Wavelan patch for 2.0.30

Jean Tourrilhes (jt@hplb.hpl.hp.com)
Fri, 18 Apr 1997 11:17:26 +0100 (BST)


Hi everybody...

After the big patch included in 2.0.30, you were probably
wondering if there was anything else to patch in the Wavelan
driver. Don't worry, I try very hard to pretend I'm working on the
driver (especially that these patches are not from me !).
What it does :
o Hardware encryption setting support <Brent Elphick>
o Fixes for Alpha architecture <Stanislav Sinyagin>
o cleanup the docs <me>

I don't think that this patch will go to 2.0.31. I've already
abused too much of the kindness of Linus and David with 2.0.30, and
those changes are not really fundamental.

To take advantage of encryption setting, you will need to
upgrade your wireless tools to version 16. See at :
ftp://hyper.stanford.edu/pub/pcmcia/contrib

For the Alpha architecture, there is still one problem. It
seem that when compiling the pcmcia driver, function 'insb' and
'outsb' are not linked with the driver module. The include is ok, and
a quick look in the alpha tree indicate that the function exists. I
don't have an Alpha (being at HP...), so if someone could compile the
pcmcia package and give me a clue...

Jean

P.S. : For constructive comments and flame, allow me a delay because
I'm only reading the digest...

-----------------------------------------------------

diff -u -p --recursive --new-file kernel-source-2.0.30b/Documentation/Configure.help linux/Documentation/Configure.help
--- kernel-source-2.0.30b/Documentation/Configure.help Thu Apr 17 21:50:44 1997
+++ linux/Documentation/Configure.help Thu Apr 17 21:41:42 1997
@@ -2417,19 +2417,18 @@ CONFIG_PT

AT&T WaveLAN & DEC RoamAbout DS support
CONFIG_WAVELAN
- These are cards for wireless ethernet-like networking. Supported are
- AT&T GIS and NCR WaveLAN cards. If you want to use a card of this
- type under Linux, say Y and read the Ethernet-HOWTO, available via
- ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Some
- more specific information is contained in
- drivers/net/README.wavelan. 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 as well as
- Documentation/networking/net-modules.txt. If you plan to use more
- than one network card under linux, read the
- Multiple-Ethernet-mini-HOWTO, available from
- sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
+ The Lucent Wavelan (formerly NCR and AT&T ; or DEC RoamAbout DS)
+ is a Radio LAN (wireless ethernet-like) at 900 MHz and 2.4 GHz.
+ This driver support the ISA version of the Wavelan. A driver for
+ the pcmcia hardware is available in David Hinds's pcmcia package.
+ This driver is fairly stable and may be compiled as a module
+ (wavelan.o). It implements many nice feature and the Wireless
+ Extensions (you must get the Wireless tools from the net).
+ For documentation, refer to :
+ o the wavelan man page, wireless tools man pages
+ o wavelan.p.h and the source code
+ o Ethernet-HOWTO, Multiple-Ethernet-mini-HOWTO, Module-HOWTO
+ o More documentation to come when I will have the time :-)

HP PCLAN+ (27247B and 27252A) support
CONFIG_HPLAN_PLUS
diff -u -p --recursive --new-file kernel-source-2.0.30b/include/linux/wireless.h linux/include/linux/wireless.h
--- kernel-source-2.0.30b/include/linux/wireless.h Thu Apr 17 21:50:52 1997
+++ linux/include/linux/wireless.h Thu Apr 17 21:38:22 1997
@@ -63,20 +63,25 @@
* (there is some stuff that will be added in the future...)
* I just plan to increment with each new version.
*/
-#define WIRELESS_EXT 4
+#define WIRELESS_EXT 5

/*
* Changes :
*
* V2 to V3
* --------
- * Alan Cox start some imcompatibles changes. I've integrated a bit more.
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
* - Encryption renamed to Encode to avoid US regulation problems
* - Frequency changed from float to struct to avoid problems on old 386
*
* V3 to V4
* --------
* - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
*/

/* -------------------------- IOCTL LIST -------------------------- */
@@ -103,11 +108,16 @@
#define SIOCSIWSPY 0x8B10 /* set spy addresses */
#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */

+/* Access Point manipulation */
+#define SIOCSIWAP 0x8B14 /* set access point hardware addresses */
+#define SIOCGIWAP 0x8B15 /* get access point hardware addresses */
+#define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */
+
/* ------------------------- IOCTL STUFF ------------------------- */

/* The first and the last (range) */
#define SIOCIWFIRST 0x8B00
-#define SIOCIWLAST 0x8B13
+#define SIOCIWLAST 0x8B17

/* Even : get (world access), odd : set (root access) */
#define IW_IS_SET(cmd) (!((cmd) & 0x1))
@@ -185,6 +195,17 @@ struct iw_discarded
__u32 misc; /* Others cases */
};

+/*
+ * Encoding information (setting and so on)
+ * Encoding might be hardware encryption, scrambing or others
+ */
+struct iw_encoding
+{
+ __u8 method; /* Algorithm number / key used */
+ __u64 code; /* Data/key used for algorithm */
+};
+
+
/* ------------------------ WIRELESS STATS ------------------------ */
/*
* Wireless statistics (used for /proc/net/wireless)
@@ -234,13 +255,11 @@ struct iwreq
* 0-1000 = channel
* > 1000 = frequency in Hz */

- struct /* Encoding stuff */
- {
- __u8 method; /* Algorithm number / off */
- __u64 code; /* Data used for algorithm */
- } encoding;
+ struct iw_encoding encoding; /* Encoding stuff */

- __u32 sensitivity; /* signal level threshold */
+ __u32 sensitivity; /* signal level threshold */
+
+ struct sockaddr ap_addr; /* Access point address */

struct /* For all data bigger than 16 octets */
{
@@ -275,16 +294,16 @@ struct iw_range
__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 */

- /* Encoder stuff */
-
/* signal level threshold range */
__u32 sensitivity;

/* Quality of link & SNR stuff */
struct iw_quality max_qual; /* Quality of the link */
+
+ /* Encoder stuff */
+ struct iw_encoding max_encoding; /* Encoding max range */
};

/*
diff -u -p --recursive --new-file kernel-source-2.0.30b/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h
--- kernel-source-2.0.30b/drivers/net/wavelan.p.h Thu Apr 17 21:50:47 1997
+++ linux/drivers/net/wavelan.p.h Thu Apr 17 21:45:19 1997
@@ -35,6 +35,12 @@

/* ------------------------ SPECIFIC NOTES ------------------------ */
/*
+ * wavelan.o is darn too big
+ * -------------------------
+ * That's true ! There is a very simple way to reduce the driver
+ * object by 33% (yes !). Comment out the following line :
+ * #include <linux/wireless.h>
+ *
* MAC address and hardware detection :
* ----------------------------------
* The detection code of the wavelan chech that the first 3
@@ -80,14 +86,12 @@
* caracteristics of the hardware in a standard way and support for
* applications for taking advantage of it (like Mobile IP).
*
- * By default, these wireless extensions are disabled, because they
- * need a patch to the Linux Kernel. This simple patch may be found
- * with the driver + some utilities to access those wireless
- * extensions (iwconfig...). Hopefully, those wireless extensions will
- * make their way in the kernel someday.
+ * You will need to enable the CONFIG_NET_RADIO define in the kernel
+ * configuration to enable the wireless extensions (this is the one
+ * giving access to the radio network device choice).
*
- * You also will need to enable the CONFIG_NET_RADIO in the kernel
- * configuration to enable the wireless extensions.
+ * It might also be a good idea as well to fetch the wireless tools to
+ * configure the device and play a bit.
*/

/* ---------------------------- FILES ---------------------------- */
@@ -161,6 +165,7 @@
* Ajay Bakre (bakre@paul.rutgers.edu),
* Donald Becker (becker@cesdis.gsfc.nasa.gov),
* Loeke Brederveld (Loeke.Brederveld@Utrecht.NCR.com),
+ * Brent Elphick <belphick@uwaterloo.ca>,
* Anders Klemets (klemets@it.kth.se),
* Vladimir V. Kolpakov (w@stier.koenig.ru),
* Marc Meertens (Marc.Meertens@Utrecht.NCR.com),
@@ -185,6 +190,7 @@
* John Rosenberg (johnr@cs.usyd.edu.au),
* George Rossi (george@phm.gov.au),
* Arthur Scott (arthur@cs.usyd.edu.au),
+ * Stanislav Sinyagin <stas@isf.ru>
* Peter Storey,
* for their assistance and advice.
*
@@ -260,9 +266,13 @@
* - Remove extern kerword for wavelan_probe()
* - Level threshold is now a standard wireless extension (version 4 !)
*
+ * Changes made for release in 2.1.36 :
+ * ----------------------------------
+ * - Encryption setting from Brent Elphick (thanks a lot !)
+ * - 'ioaddr' to 'u_long' for the Alpha (thanks to Stanislav Sinyagin)
+ *
* Wishes & dreams :
* ---------------
- * - Encryption stuff
* - Roaming
*/

@@ -345,7 +355,7 @@
/************************ CONSTANTS & MACROS ************************/

#ifdef DEBUG_VERSION_SHOW
-static const char *version = "wavelan.c : v15 (wireless extensions) 12/2/97\n";
+static const char *version = "wavelan.c : v16 (wireless extensions) 17/4/97\n";
#endif

/* Watchdog temporisation */
@@ -442,69 +452,65 @@ static int
wv_psa_to_irq(u_char);
/* ------------------- HOST ADAPTER SUBROUTINES ------------------- */
static inline u_short /* data */
- hasr_read(u_short); /* Read the host interface : base address */
+ hasr_read(u_long); /* Read the host interface : base address */
static inline void
- hacr_write(u_short, /* Write to host interface : base address */
+ hacr_write(u_long, /* Write to host interface : base address */
u_short), /* data */
- hacr_write_slow(u_short,
+ hacr_write_slow(u_long,
u_short),
- set_chan_attn(u_short, /* ioaddr */
+ set_chan_attn(u_long, /* ioaddr */
u_short), /* hacr */
- wv_hacr_reset(u_short), /* ioaddr */
- wv_16_off(u_short, /* ioaddr */
+ wv_hacr_reset(u_long), /* ioaddr */
+ wv_16_off(u_long, /* ioaddr */
u_short), /* hacr */
- wv_16_on(u_short, /* ioaddr */
+ wv_16_on(u_long, /* ioaddr */
u_short), /* hacr */
wv_ints_off(device *),
wv_ints_on(device *);
/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
static void
- psa_read(u_short, /* Read the Parameter Storage Area */
+ psa_read(u_long, /* Read the Parameter Storage Area */
u_short, /* hacr */
int, /* offset in PSA */
u_char *, /* buffer to fill */
int), /* size to read */
- psa_write(u_short, /* Write to the PSA */
+ psa_write(u_long, /* Write to the PSA */
u_short, /* hacr */
int, /* Offset in psa */
u_char *, /* Buffer in memory */
int); /* Length of buffer */
static inline void
- mmc_out(u_short, /* Write 1 byte to the Modem Manag Control */
+ mmc_out(u_long, /* Write 1 byte to the Modem Manag Control */
u_short,
u_char),
- mmc_write(u_short, /* Write n bytes to the MMC */
+ mmc_write(u_long, /* Write n bytes to the MMC */
u_char,
u_char *,
int);
static inline u_char /* Read 1 byte from the MMC */
- mmc_in(u_short,
+ mmc_in(u_long,
u_short);
static inline void
- mmc_read(u_short, /* Read n bytes from the MMC */
+ mmc_read(u_long, /* Read n bytes from the MMC */
u_char,
u_char *,
int),
- fee_wait(u_short, /* Wait for frequency EEprom : base address */
+ fee_wait(u_long, /* Wait for frequency EEprom : base address */
int, /* Base delay to wait for */
int); /* Number of time to wait */
static void
- fee_read(u_short, /* Read the frequency EEprom : base address */
+ fee_read(u_long, /* Read the frequency EEprom : base address */
u_short, /* destination offset */
u_short *, /* data buffer */
- int), /* number of registers */
- fee_write(u_short, /* Write to frequency EEprom : base address */
- u_short, /* destination offset */
- u_short *, /* data buffer */
- int); /* number of registers */
+ int); /* number of registers */
/* ---------------------- I82586 SUBROUTINES ----------------------- */
static /*inline*/ void
- obram_read(u_short, /* ioaddr */
+ obram_read(u_long, /* ioaddr */
u_short, /* o */
u_char *, /* b */
int); /* n */
static inline void
- obram_write(u_short, /* ioaddr */
+ obram_write(u_long, /* ioaddr */
u_short, /* o */
u_char *, /* b */
int); /* n */
@@ -514,11 +520,11 @@ static inline int
wv_synchronous_cmd(device *,
const char *),
wv_config_complete(device *,
- u_short,
+ u_long,
net_local *);
static int
wv_complete(device *,
- u_short,
+ u_long,
net_local *);
static inline void
wv_82586_reconfig(device *);
@@ -560,7 +566,7 @@ static inline void
wv_82586_stop(device *);
static int
wv_hw_reset(device *), /* Reset the wavelan hardware */
- wv_check_ioaddr(u_short, /* ioaddr */
+ wv_check_ioaddr(u_long, /* ioaddr */
u_char *); /* mac address (read) */
/* ---------------------- INTERRUPT HANDLING ---------------------- */
static void
diff -u -p --recursive --new-file kernel-source-2.0.30b/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- kernel-source-2.0.30b/drivers/net/wavelan.c Thu Apr 17 21:50:47 1997
+++ linux/drivers/net/wavelan.c Thu Apr 17 21:53:08 1997
@@ -112,7 +112,7 @@ wv_struct_check(void)
* Read from card's Host Adaptor Status Register.
*/
static inline u_short
-hasr_read(u_short ioaddr)
+hasr_read(u_long ioaddr)
{
return(inw(HASR(ioaddr)));
} /* hasr_read */
@@ -122,7 +122,7 @@ hasr_read(u_short ioaddr)
* Write to card's Host Adapter Command Register.
*/
static inline void
-hacr_write(u_short ioaddr,
+hacr_write(u_long ioaddr,
u_short hacr)
{
outw(hacr, HACR(ioaddr));
@@ -134,7 +134,7 @@ hacr_write(u_short ioaddr,
* those times when it is needed.
*/
static inline void
-hacr_write_slow(u_short ioaddr,
+hacr_write_slow(u_long ioaddr,
u_short hacr)
{
hacr_write(ioaddr, hacr);
@@ -147,7 +147,7 @@ hacr_write_slow(u_short ioaddr,
* Set the channel attention bit.
*/
static inline void
-set_chan_attn(u_short ioaddr,
+set_chan_attn(u_long ioaddr,
u_short hacr)
{
hacr_write(ioaddr, hacr | HACR_CA);
@@ -158,7 +158,7 @@ set_chan_attn(u_short ioaddr,
* Reset, and then set host adaptor into default mode.
*/
static inline void
-wv_hacr_reset(u_short ioaddr)
+wv_hacr_reset(u_long ioaddr)
{
hacr_write_slow(ioaddr, HACR_RESET);
hacr_write(ioaddr, HACR_DEFAULT);
@@ -169,7 +169,7 @@ wv_hacr_reset(u_short ioaddr)
* Set the i/o transfer over the ISA bus to 8 bits mode
*/
static inline void
-wv_16_off(u_short ioaddr,
+wv_16_off(u_long ioaddr,
u_short hacr)
{
hacr &= ~HACR_16BITS;
@@ -181,7 +181,7 @@ wv_16_off(u_short ioaddr,
* Set the i/o transfer over the ISA bus to 8 bits mode
*/
static inline void
-wv_16_on(u_short ioaddr,
+wv_16_on(u_long ioaddr,
u_short hacr)
{
hacr |= HACR_16BITS;
@@ -196,7 +196,7 @@ static inline void
wv_ints_off(device * dev)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_long x;

x = wv_splhi();
@@ -215,7 +215,7 @@ static inline void
wv_ints_on(device * dev)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_long x;

x = wv_splhi();
@@ -239,7 +239,7 @@ wv_ints_on(device * dev)
* Read bytes from the PSA.
*/
static void
-psa_read(u_short ioaddr,
+psa_read(u_long ioaddr,
u_short hacr,
int o, /* offset in PSA */
u_char * b, /* buffer to fill */
@@ -262,7 +262,7 @@ psa_read(u_short ioaddr,
* Write the Paramter Storage Area to the WaveLAN card's memory
*/
static void
-psa_write(u_short ioaddr,
+psa_write(u_long ioaddr,
u_short hacr,
int o, /* Offset in psa */
u_char * b, /* Buffer in memory */
@@ -329,7 +329,7 @@ psa_crc(u_short * psa, /* The PSA */
* Write 1 byte to the MMC.
*/
static inline void
-mmc_out(u_short ioaddr,
+mmc_out(u_long ioaddr,
u_short o,
u_char d)
{
@@ -347,7 +347,7 @@ mmc_out(u_short ioaddr,
* We start by the end because it is the way it should be !
*/
static inline void
-mmc_write(u_short ioaddr,
+mmc_write(u_long ioaddr,
u_char o,
u_char * b,
int n)
@@ -365,7 +365,7 @@ mmc_write(u_short ioaddr,
* Optimised version for 1 byte, avoid using memory...
*/
static inline u_char
-mmc_in(u_short ioaddr,
+mmc_in(u_long ioaddr,
u_short o)
{
while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
@@ -386,7 +386,7 @@ mmc_in(u_short ioaddr,
* We start by the end because it is the way it should be !
*/
static inline void
-mmc_read(u_short ioaddr,
+mmc_read(u_long ioaddr,
u_char o,
u_char * b,
int n)
@@ -400,11 +400,27 @@ mmc_read(u_short ioaddr,

/*------------------------------------------------------------------*/
/*
+ * Get the type of encryption available...
+ */
+static inline int
+mmc_encr(u_long ioaddr) /* i/o port of the card */
+{
+ int temp;
+
+ temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));
+ if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))
+ return 0;
+ else
+ return temp;
+}
+
+/*------------------------------------------------------------------*/
+/*
* Wait for the frequency EEprom to complete a command...
* I hope this one will be optimally inlined...
*/
static inline void
-fee_wait(u_short ioaddr, /* i/o port of the card */
+fee_wait(u_long ioaddr, /* i/o port of the card */
int delay, /* Base delay to wait for */
int number) /* Number of time to wait */
{
@@ -420,7 +436,7 @@ fee_wait(u_short ioaddr, /* i/o port of
* Read bytes from the Frequency EEprom (frequency select cards).
*/
static void
-fee_read(u_short ioaddr, /* i/o port of the card */
+fee_read(u_long ioaddr, /* i/o port of the card */
u_short o, /* destination offset */
u_short * b, /* data buffer */
int n) /* number of registers */
@@ -445,6 +461,8 @@ fee_read(u_short ioaddr, /* i/o port of
}
}

+#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
+
/*------------------------------------------------------------------*/
/*
* Write bytes from the Frequency EEprom (frequency select cards).
@@ -453,7 +471,7 @@ fee_read(u_short ioaddr, /* i/o port of
* Jean II
*/
static void
-fee_write(u_short ioaddr, /* i/o port of the card */
+fee_write(u_long ioaddr, /* i/o port of the card */
u_short o, /* destination offset */
u_short * b, /* data buffer */
int n) /* number of registers */
@@ -528,6 +546,7 @@ fee_write(u_short ioaddr, /* i/o port of
fee_wait(ioaddr, 10, 100);
#endif /* EEPROM_IS_PROTECTED */
}
+#endif /* WIRELESS_EXT */

/************************ I82586 SUBROUTINES *************************/
/*
@@ -540,7 +559,7 @@ fee_write(u_short ioaddr, /* i/o port of
* Why inlining this function make it fail ???
*/
static /*inline*/ void
-obram_read(u_short ioaddr,
+obram_read(u_long ioaddr,
u_short o,
u_char * b,
int n)
@@ -554,7 +573,7 @@ obram_read(u_short ioaddr,
* Write bytes to the on-board RAM.
*/
static inline void
-obram_write(u_short ioaddr,
+obram_write(u_long ioaddr,
u_short o,
u_char * b,
int n)
@@ -571,7 +590,7 @@ static void
wv_ack(device * dev)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_short scb_cs;
int i;

@@ -614,7 +633,7 @@ wv_synchronous_cmd(device * dev,
const char * str)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_short scb_cmd;
ach_t cb;
int i;
@@ -660,7 +679,7 @@ wv_synchronous_cmd(device * dev,
*/
static inline int
wv_config_complete(device * dev,
- u_short ioaddr,
+ u_long ioaddr,
net_local * lp)
{
unsigned short mcs_addr;
@@ -722,7 +741,7 @@ wv_config_complete(device * dev,
*/
static int
wv_complete(device * dev,
- u_short ioaddr,
+ u_long ioaddr,
net_local * lp)
{
int nreaped = 0;
@@ -992,7 +1011,7 @@ wv_psa_show(psa_t * p)
static void
wv_mmc_show(device * dev)
{
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *)dev->priv;
mmr_t m;

@@ -1077,7 +1096,7 @@ wv_mmc_show(device * dev)
* Print the last block of the i82586 memory
*/
static void
-wv_scb_show(unsigned short ioaddr)
+wv_scb_show(u_long ioaddr)
{
scb_t scb;

@@ -1162,7 +1181,7 @@ wv_cu_show_one(device * dev,
int i,
u_short p)
{
- unsigned short ioaddr;
+ u_long ioaddr;
ac_tx_t actx;

ioaddr = dev->base_addr;
@@ -1529,7 +1548,7 @@ wavelan_set_mac_address(device * dev,
* (called in wavelan_ioctl)
*/
static inline int
-wv_set_frequency(u_short ioaddr, /* i/o port of the card */
+wv_set_frequency(u_long ioaddr, /* i/o port of the card */
iw_freq * frequency)
{
const int BAND_NUM = 10; /* Number of bands */
@@ -1550,7 +1569,7 @@ wv_set_frequency(u_short ioaddr, /* i/o
}

/* Setting by channel (same as wfreqsel) */
- /* Warning : each channel is 11MHz wide, so some of the channels
+ /* Warning : each channel is 22MHz wide, so some of the channels
* will interfere... */
if((frequency->e == 0) &&
(frequency->m >= 0) && (frequency->m < BAND_NUM))
@@ -1729,7 +1748,7 @@ wv_set_frequency(u_short ioaddr, /* i/o
* Give the list of available frequencies
*/
static inline int
-wv_frequency_list(u_short ioaddr, /* i/o port of the card */
+wv_frequency_list(u_long ioaddr, /* i/o port of the card */
iw_freq * list, /* List of frequency to fill */
int max) /* Maximum number of frequencies */
{
@@ -1826,7 +1845,7 @@ wavelan_ioctl(struct device * dev, /* De
struct ifreq * rq, /* Data passed */
int cmd) /* Ioctl number */
{
- unsigned short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *)dev->priv; /* lp is not unused */
struct iwreq * wrq = (struct iwreq *) rq;
psa_t psa;
@@ -1866,9 +1885,7 @@ wavelan_ioctl(struct device * dev, /* De
m.w.mmw_netw_id_h = (wrq->u.nwid.nwid & 0xFF00) >> 8;
mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m,
(unsigned char *)&m.w.mmw_netw_id_l, 2);
- m.w.mmw_loopt_sel = 0x00;
- mmc_write(ioaddr, (char *)&m.w.mmw_loopt_sel - (char *)&m,
- (unsigned char *)&m.w.mmw_loopt_sel, 1);
+ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
}
else
{
@@ -1878,10 +1895,8 @@ wavelan_ioctl(struct device * dev, /* De
(char *)&psa.psa_nwid_select - (char *)&psa,
(unsigned char *)&psa.psa_nwid_select, 1);

- /* Disable nwid in the mmc (no check) */
- m.w.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
- mmc_write(ioaddr, (char *)&m.w.mmw_loopt_sel - (char *)&m,
- (unsigned char *)&m.w.mmw_loopt_sel, 1);
+ /* Disable nwid in the mmc (no filtering) */
+ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
}
break;

@@ -1950,6 +1965,82 @@ wavelan_ioctl(struct device * dev, /* De
wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
break;

+ case SIOCSIWENCODE:
+ /* Set encryption key */
+ if(!mmc_encr(ioaddr))
+ {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if(wrq->u.encoding.method)
+ { /* enable encryption */
+ int i;
+ long long key = wrq->u.encoding.code;
+
+ for(i = 7; i >= 0; i--)
+ {
+ psa.psa_encryption_key[i] = key & 0xFF;
+ key >>= 8;
+ }
+ psa.psa_encryption_select = 1;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select - (char *) &psa,
+ (unsigned char *) &psa.psa_encryption_select, 8+1);
+
+ mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),
+ MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
+ mmc_write(ioaddr, mmwoff(0, mmw_encr_key),
+ (unsigned char *) &psa.psa_encryption_key, 8);
+ }
+ else
+ { /* disable encryption */
+ psa.psa_encryption_select = 0;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select - (char *) &psa,
+ (unsigned char *) &psa.psa_encryption_select, 1);
+
+ mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
+ }
+ break;
+
+ case SIOCGIWENCODE:
+ /* Read the encryption key */
+ if(!mmc_encr(ioaddr))
+ {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ /* only super-user can see encryption key */
+ if(!suser())
+ {
+ ret = -EPERM;
+ break;
+ }
+ else
+ {
+ int i;
+ long long key = 0;
+
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select - (char *) &psa,
+ (unsigned char *) &psa.psa_encryption_select, 1+8);
+ for(i = 0; i < 8; i++)
+ {
+ key <<= 8;
+ key += psa.psa_encryption_key[i];
+ }
+ wrq->u.encoding.code = key;
+
+ /* encryption is enabled */
+ if(psa.psa_encryption_select)
+ wrq->u.encoding.method = mmc_encr(ioaddr);
+ else
+ wrq->u.encoding.method = 0;
+ }
+ break;
+
case SIOCGIWRANGE:
/* Basic checking... */
if(wrq->u.data.pointer != (caddr_t) 0)
@@ -2207,7 +2298,7 @@ wavelan_ioctl(struct device * dev, /* De
static iw_stats *
wavelan_get_wireless_stats(device * dev)
{
- unsigned short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *) dev->priv;
mmr_t m;
iw_stats * wstats;
@@ -2281,7 +2372,7 @@ wv_packet_read(device * dev,
int sksize)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
struct sk_buff * skb;

#ifdef DEBUG_RX_TRACE
@@ -2369,7 +2460,7 @@ wv_packet_read(device * dev,
static inline void
wv_receive(device * dev)
{
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *)dev->priv;
int nreaped = 0;

@@ -2555,7 +2646,7 @@ wv_packet_write(device * dev,
short length)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
unsigned short txblock;
unsigned short txpred;
unsigned short tx_addr;
@@ -2760,7 +2851,7 @@ wavelan_packet_xmit(struct sk_buff * skb
static inline int
wv_mmc_init(device * dev)
{
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
net_local * lp = (net_local *)dev->priv;
psa_t psa;
mmw_t m;
@@ -2789,6 +2880,9 @@ wv_mmc_init(device * dev)
/* As NWID is not set : no NWID checking */
psa.psa_nwid_select = 0;

+ /* Disable encryption */
+ psa.psa_encryption_select = 0;
+
/* Set to standard values
* 0x04 for AT,
* 0x01 for MCA,
@@ -2806,7 +2900,7 @@ wv_mmc_init(device * dev)
#ifdef USE_PSA_CONFIG
/* Write the psa */
psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
- (unsigned char *)psa.psa_nwid, 3);
+ (unsigned char *)psa.psa_nwid, 4);
psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
(unsigned char *)&psa.psa_thr_pre_set, 1);
psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
@@ -2828,6 +2922,14 @@ wv_mmc_init(device * dev)
else
m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;

+ memcpy(&m.mmw_encr_key, &psa.psa_encryption_key,
+ sizeof(m.mmw_encr_key));
+
+ if(psa.psa_encryption_select)
+ m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE;
+ else
+ m.mmw_encr_enable = 0;
+
m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;

@@ -2919,7 +3021,7 @@ static inline int
wv_ru_start(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_short scb_cs;
fd_t fd;
rbd_t rbd;
@@ -3013,7 +3115,7 @@ static inline int
wv_cu_start(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
int i;
u_short txblock;
u_short first_nop;
@@ -3114,7 +3216,7 @@ static inline int
wv_82586_start(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
scp_t scp; /* system configuration pointer */
iscp_t iscp; /* intermediate scp */
scb_t scb; /* system control block */
@@ -3244,7 +3346,7 @@ static void
wv_82586_config(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
unsigned short txblock;
unsigned short txpred;
unsigned short tx_addr;
@@ -3440,7 +3542,7 @@ static inline void
wv_82586_stop(device * dev)
{
net_local * lp = (net_local *) dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_short scb_cmd;

#ifdef DEBUG_CONFIG_TRACE
@@ -3475,7 +3577,7 @@ static int
wv_hw_reset(device * dev)
{
net_local * lp = (net_local *)dev->priv;
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;

#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name,
@@ -3520,7 +3622,7 @@ wv_hw_reset(device * dev)
* (called in wavelan_probe() and init_module())
*/
static int
-wv_check_ioaddr(u_short ioaddr,
+wv_check_ioaddr(u_long ioaddr,
u_char * mac)
{
int i; /* Loop counter */
@@ -3567,7 +3669,7 @@ wavelan_interrupt(int irq,
struct pt_regs * regs)
{
device * dev;
- u_short ioaddr;
+ u_long ioaddr;
net_local * lp;
u_short hasr;
u_short status;
@@ -3714,7 +3816,7 @@ wavelan_watchdog(u_long a)
{
device * dev;
net_local * lp;
- unsigned short ioaddr;
+ u_long ioaddr;
unsigned long x;
unsigned int nreaped;

@@ -3909,7 +4011,7 @@ wavelan_close(device * dev)
static int
wavelan_config(device * dev)
{
- u_short ioaddr = dev->base_addr;
+ u_long ioaddr = dev->base_addr;
u_char irq_mask;
int irq;
net_local * lp;