aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/Kconfig4
-rw-r--r--drivers/staging/Makefile2
-rw-r--r--drivers/staging/agnx/Kconfig5
-rw-r--r--drivers/staging/agnx/Makefile8
-rw-r--r--drivers/staging/agnx/TODO22
-rw-r--r--drivers/staging/agnx/agnx.h156
-rw-r--r--drivers/staging/agnx/debug.h416
-rw-r--r--drivers/staging/agnx/pci.c635
-rw-r--r--drivers/staging/agnx/phy.c960
-rw-r--r--drivers/staging/agnx/phy.h409
-rw-r--r--drivers/staging/agnx/rf.c893
-rw-r--r--drivers/staging/agnx/sta.c218
-rw-r--r--drivers/staging/agnx/sta.h222
-rw-r--r--drivers/staging/agnx/table.c168
-rw-r--r--drivers/staging/agnx/table.h10
-rw-r--r--drivers/staging/agnx/xmit.c836
-rw-r--r--drivers/staging/agnx/xmit.h250
-rw-r--r--drivers/staging/comedi/Kconfig2
-rw-r--r--drivers/staging/comedi/comedi_fops.c2
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidio.c8
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c18
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c12
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c22
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/s526.c109
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c1
-rw-r--r--drivers/staging/cowloop/Kconfig16
-rw-r--r--drivers/staging/cowloop/Makefile1
-rw-r--r--drivers/staging/cowloop/TODO11
-rw-r--r--drivers/staging/cowloop/cowloop.c2842
-rw-r--r--drivers/staging/cowloop/cowloop.h66
-rw-r--r--drivers/staging/iio/Kconfig1
-rw-r--r--drivers/staging/p9auth/p9auth.c14
-rw-r--r--drivers/staging/rtl8192e/r8192E_core.c1
-rw-r--r--drivers/staging/winbond/wbusb.c44
40 files changed, 148 insertions, 8248 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 9a4dd5992f65..7df3ba4f1f4d 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -59,8 +59,6 @@ source "drivers/staging/echo/Kconfig"
59 59
60source "drivers/staging/poch/Kconfig" 60source "drivers/staging/poch/Kconfig"
61 61
62source "drivers/staging/agnx/Kconfig"
63
64source "drivers/staging/otus/Kconfig" 62source "drivers/staging/otus/Kconfig"
65 63
66source "drivers/staging/rt2860/Kconfig" 64source "drivers/staging/rt2860/Kconfig"
@@ -129,7 +127,5 @@ source "drivers/staging/sep/Kconfig"
129 127
130source "drivers/staging/iio/Kconfig" 128source "drivers/staging/iio/Kconfig"
131 129
132source "drivers/staging/cowloop/Kconfig"
133
134endif # !STAGING_EXCLUDE_BUILD 130endif # !STAGING_EXCLUDE_BUILD
135endif # STAGING 131endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 104f2f8897ec..747571172269 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_W35UND) += winbond/
12obj-$(CONFIG_PRISM2_USB) += wlan-ng/ 12obj-$(CONFIG_PRISM2_USB) += wlan-ng/
13obj-$(CONFIG_ECHO) += echo/ 13obj-$(CONFIG_ECHO) += echo/
14obj-$(CONFIG_POCH) += poch/ 14obj-$(CONFIG_POCH) += poch/
15obj-$(CONFIG_AGNX) += agnx/
16obj-$(CONFIG_OTUS) += otus/ 15obj-$(CONFIG_OTUS) += otus/
17obj-$(CONFIG_RT2860) += rt2860/ 16obj-$(CONFIG_RT2860) += rt2860/
18obj-$(CONFIG_RT2870) += rt2870/ 17obj-$(CONFIG_RT2870) += rt2870/
@@ -46,4 +45,3 @@ obj-$(CONFIG_VME_BUS) += vme/
46obj-$(CONFIG_RAR_REGISTER) += rar/ 45obj-$(CONFIG_RAR_REGISTER) += rar/
47obj-$(CONFIG_DX_SEP) += sep/ 46obj-$(CONFIG_DX_SEP) += sep/
48obj-$(CONFIG_IIO) += iio/ 47obj-$(CONFIG_IIO) += iio/
49obj-$(CONFIG_COWLOOP) += cowloop/
diff --git a/drivers/staging/agnx/Kconfig b/drivers/staging/agnx/Kconfig
deleted file mode 100644
index 7f43549e36dd..000000000000
--- a/drivers/staging/agnx/Kconfig
+++ /dev/null
@@ -1,5 +0,0 @@
1config AGNX
2 tristate "Wireless Airgo AGNX support"
3 depends on WLAN_80211 && MAC80211
4 ---help---
5 This is an experimental driver for Airgo AGNX00 wireless chip.
diff --git a/drivers/staging/agnx/Makefile b/drivers/staging/agnx/Makefile
deleted file mode 100644
index 1216564a312d..000000000000
--- a/drivers/staging/agnx/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
1obj-$(CONFIG_AGNX) += agnx.o
2
3agnx-objs := rf.o \
4 pci.o \
5 xmit.o \
6 table.o \
7 sta.o \
8 phy.o
diff --git a/drivers/staging/agnx/TODO b/drivers/staging/agnx/TODO
deleted file mode 100644
index 89bec74318aa..000000000000
--- a/drivers/staging/agnx/TODO
+++ /dev/null
@@ -1,22 +0,0 @@
12008 7/18
2
3The RX has can't receive OFDM packet correctly,
4Guess it need be do RX calibrate.
5
6
7before 2008 3/1
8
91: The RX get too much "CRC failed" pakets, it make the card work very unstable,
102: After running a while, the card will get infinity "RX Frame" and "Error"
11interrupt, not know the root reason so far, try to fix it
123: Using two tx queue txd and txm but not only txm.
134: Set the hdr correctly.
145: Try to do recalibrate correvtly
156: To support G mode in future
167: Fix the mac address can't be readed and set correctly in BE machine.
178: Fix include and exclude FCS in promisous mode and manage mode
189: Using sta_notify to notice sta change
1910: Turn on frame reception at the end of start
2011: Guess the card support HW_MULTICAST_FILTER
2112: The tx process should be implment atomic?
2213: Using mac80211 function to control the TX&RX LED.
diff --git a/drivers/staging/agnx/agnx.h b/drivers/staging/agnx/agnx.h
deleted file mode 100644
index 3963d2597a11..000000000000
--- a/drivers/staging/agnx/agnx.h
+++ /dev/null
@@ -1,156 +0,0 @@
1#ifndef AGNX_H_
2#define AGNX_H_
3
4#include <linux/io.h>
5
6#include "xmit.h"
7
8#define PFX KBUILD_MODNAME ": "
9
10static inline u32 agnx_read32(void __iomem *mem_region, u32 offset)
11{
12 return ioread32(mem_region + offset);
13}
14
15static inline void agnx_write32(void __iomem *mem_region, u32 offset, u32 val)
16{
17 iowrite32(val, mem_region + offset);
18}
19
20/* static const struct ieee80211_rate agnx_rates_80211b[] = { */
21/* { .rate = 10, */
22/* .val = 0xa, */
23/* .flags = IEEE80211_RATE_CCK }, */
24/* { .rate = 20, */
25/* .val = 0x14, */
26/* .hw_value = -0x14, */
27/* .flags = IEEE80211_RATE_CCK_2 }, */
28/* { .rate = 55, */
29/* .val = 0x37, */
30/* .val2 = -0x37, */
31/* .flags = IEEE80211_RATE_CCK_2 }, */
32/* { .rate = 110, */
33/* .val = 0x6e, */
34/* .val2 = -0x6e, */
35/* .flags = IEEE80211_RATE_CCK_2 } */
36/* }; */
37
38
39static const struct ieee80211_rate agnx_rates_80211g[] = {
40/* { .bitrate = 10, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
41/* { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
42/* { .bitrate = 55, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
43/* { .bitrate = 110, .hw_value = 4, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
44 { .bitrate = 10, .hw_value = 1, },
45 { .bitrate = 20, .hw_value = 2, },
46 { .bitrate = 55, .hw_value = 3, },
47 { .bitrate = 110, .hw_value = 4,},
48
49 { .bitrate = 60, .hw_value = 0xB, },
50 { .bitrate = 90, .hw_value = 0xF, },
51 { .bitrate = 120, .hw_value = 0xA },
52 { .bitrate = 180, .hw_value = 0xE, },
53/* { .bitrate = 240, .hw_value = 0xd, }, */
54 { .bitrate = 360, .hw_value = 0xD, },
55 { .bitrate = 480, .hw_value = 0x8, },
56 { .bitrate = 540, .hw_value = 0xC, },
57};
58
59static const struct ieee80211_channel agnx_channels[] = {
60 { .center_freq = 2412, .hw_value = 1, },
61 { .center_freq = 2417, .hw_value = 2, },
62 { .center_freq = 2422, .hw_value = 3, },
63 { .center_freq = 2427, .hw_value = 4, },
64 { .center_freq = 2432, .hw_value = 5, },
65 { .center_freq = 2437, .hw_value = 6, },
66 { .center_freq = 2442, .hw_value = 7, },
67 { .center_freq = 2447, .hw_value = 8, },
68 { .center_freq = 2452, .hw_value = 9, },
69 { .center_freq = 2457, .hw_value = 10, },
70 { .center_freq = 2462, .hw_value = 11, },
71 { .center_freq = 2467, .hw_value = 12, },
72 { .center_freq = 2472, .hw_value = 13, },
73 { .center_freq = 2484, .hw_value = 14, },
74};
75
76#define NUM_DRIVE_MODES 2
77/* Agnx operate mode */
78enum {
79 AGNX_MODE_80211A,
80 AGNX_MODE_80211A_OOB,
81 AGNX_MODE_80211A_MIMO,
82 AGNX_MODE_80211B_SHORT,
83 AGNX_MODE_80211B_LONG,
84 AGNX_MODE_80211G,
85 AGNX_MODE_80211G_OOB,
86 AGNX_MODE_80211G_MIMO,
87};
88
89enum {
90 AGNX_UNINIT,
91 AGNX_START,
92 AGNX_STOP,
93};
94
95struct agnx_priv {
96 struct pci_dev *pdev;
97 struct ieee80211_hw *hw;
98
99 spinlock_t lock;
100 struct mutex mutex;
101 unsigned int init_status;
102
103 void __iomem *ctl; /* pointer to base ram address */
104 void __iomem *data; /* pointer to mem region #2 */
105
106 struct agnx_ring rx;
107 struct agnx_ring txm;
108 struct agnx_ring txd;
109
110 /* Need volatile? */
111 u32 irq_status;
112
113 struct delayed_work periodic_work; /* Periodic tasks like recalibrate */
114 struct ieee80211_low_level_stats stats;
115
116 /* unsigned int phymode; */
117 int mode;
118 int channel;
119 u8 bssid[ETH_ALEN];
120
121 u8 mac_addr[ETH_ALEN];
122 u8 revid;
123
124 struct ieee80211_supported_band band;
125};
126
127
128#define AGNX_CHAINS_MAX 6
129#define AGNX_PERIODIC_DELAY 60000 /* unit: ms */
130#define LOCAL_STAID 0 /* the station entry for the card itself */
131#define BSSID_STAID 1 /* the station entry for the bsssid AP */
132#define spi_delay() udelay(40)
133#define eeprom_delay() udelay(40)
134#define routing_table_delay() udelay(50)
135
136/* PDU pool MEM region #2 */
137#define AGNX_PDUPOOL 0x40000 /* PDU pool */
138#define AGNX_PDUPOOL_SIZE 0x8000 /* PDU pool size*/
139#define AGNX_PDU_TX_WQ 0x41000 /* PDU list TX workqueue */
140#define AGNX_PDU_FREE 0x41800 /* Free Pool */
141#define PDU_SIZE 0x80 /* Free Pool node size */
142#define PDU_FREE_CNT 0xd0 /* Free pool node count */
143
144
145/* RF stuffs */
146extern void rf_chips_init(struct agnx_priv *priv);
147extern void spi_rc_write(void __iomem *mem_region, u32 chip_ids, u32 sw);
148extern void calibrate_oscillator(struct agnx_priv *priv);
149extern void do_calibration(struct agnx_priv *priv);
150extern void antenna_calibrate(struct agnx_priv *priv);
151extern void __antenna_calibrate(struct agnx_priv *priv);
152extern void print_offsets(struct agnx_priv *priv);
153extern int agnx_set_channel(struct agnx_priv *priv, unsigned int channel);
154
155
156#endif /* AGNX_H_ */
diff --git a/drivers/staging/agnx/debug.h b/drivers/staging/agnx/debug.h
deleted file mode 100644
index 7947f327a214..000000000000
--- a/drivers/staging/agnx/debug.h
+++ /dev/null
@@ -1,416 +0,0 @@
1#ifndef AGNX_DEBUG_H_
2#define AGNX_DEBUG_H_
3
4#include "agnx.h"
5#include "phy.h"
6#include "sta.h"
7#include "xmit.h"
8
9#define AGNX_TRACE printk(KERN_ERR PFX "function:%s line:%d\n", __func__, __LINE__)
10
11#define PRINTK_LE16(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", le16_to_cpu(var))
12#define PRINTK_LE32(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", le32_to_cpu(var))
13#define PRINTK_U8(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.2x\n", var)
14#define PRINTK_BE16(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", be16_to_cpu(var))
15#define PRINTK_BE32(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", be32_to_cpu(var))
16#define PRINTK_BITS(prefix, field) printk(KERN_DEBUG PFX #prefix ": " #field ": 0x%x\n", (reg & field) >> field##_SHIFT)
17
18static inline void agnx_bug(char *reason)
19{
20 printk(KERN_ERR PFX "%s\n", reason);
21 BUG();
22}
23
24static inline void agnx_print_desc(struct agnx_desc *desc)
25{
26 u32 reg = be32_to_cpu(desc->frag);
27
28 PRINTK_BITS(DESC, PACKET_LEN);
29
30 if (reg & FIRST_FRAG) {
31 PRINTK_BITS(DESC, FIRST_PACKET_MASK);
32 PRINTK_BITS(DESC, FIRST_RESERV2);
33 PRINTK_BITS(DESC, FIRST_TKIP_ERROR);
34 PRINTK_BITS(DESC, FIRST_TKIP_PACKET);
35 PRINTK_BITS(DESC, FIRST_RESERV1);
36 PRINTK_BITS(DESC, FIRST_FRAG_LEN);
37 } else {
38 PRINTK_BITS(DESC, SUB_RESERV2);
39 PRINTK_BITS(DESC, SUB_TKIP_ERROR);
40 PRINTK_BITS(DESC, SUB_TKIP_PACKET);
41 PRINTK_BITS(DESC, SUB_RESERV1);
42 PRINTK_BITS(DESC, SUB_FRAG_LEN);
43 }
44
45 PRINTK_BITS(DESC, FIRST_FRAG);
46 PRINTK_BITS(DESC, LAST_FRAG);
47 PRINTK_BITS(DESC, OWNER);
48}
49
50
51static inline void dump_ieee80211b_phy_hdr(__be32 _11b0, __be32 _11b1)
52{
53
54}
55
56static inline void agnx_print_hdr(struct agnx_hdr *hdr)
57{
58 u32 reg;
59 int i;
60
61 reg = be32_to_cpu(hdr->reg0);
62 PRINTK_BITS(HDR, RTS);
63 PRINTK_BITS(HDR, MULTICAST);
64 PRINTK_BITS(HDR, ACK);
65 PRINTK_BITS(HDR, TM);
66 PRINTK_BITS(HDR, RELAY);
67 PRINTK_BITS(HDR, REVISED_FCS);
68 PRINTK_BITS(HDR, NEXT_BUFFER_ADDR);
69
70 reg = be32_to_cpu(hdr->reg1);
71 PRINTK_BITS(HDR, MAC_HDR_LEN);
72 PRINTK_BITS(HDR, DURATION_OVERIDE);
73 PRINTK_BITS(HDR, PHY_HDR_OVERIDE);
74 PRINTK_BITS(HDR, CRC_FAIL);
75 PRINTK_BITS(HDR, SEQUENCE_NUMBER);
76 PRINTK_BITS(HDR, BUFF_HEAD_ADDR);
77
78 reg = be32_to_cpu(hdr->reg2);
79 PRINTK_BITS(HDR, PDU_COUNT);
80 PRINTK_BITS(HDR, WEP_KEY);
81 PRINTK_BITS(HDR, USES_WEP_KEY);
82 PRINTK_BITS(HDR, KEEP_ALIVE);
83 PRINTK_BITS(HDR, BUFF_TAIL_ADDR);
84
85 reg = be32_to_cpu(hdr->reg3);
86 PRINTK_BITS(HDR, CTS_11G);
87 PRINTK_BITS(HDR, RTS_11G);
88 PRINTK_BITS(HDR, FRAG_SIZE);
89 PRINTK_BITS(HDR, PAYLOAD_LEN);
90 PRINTK_BITS(HDR, FRAG_NUM);
91
92 reg = be32_to_cpu(hdr->reg4);
93 PRINTK_BITS(HDR, RELAY_STAID);
94 PRINTK_BITS(HDR, STATION_ID);
95 PRINTK_BITS(HDR, WORKQUEUE_ID);
96
97 reg = be32_to_cpu(hdr->reg5);
98 /* printf the route flag */
99 PRINTK_BITS(HDR, ROUTE_HOST);
100 PRINTK_BITS(HDR, ROUTE_CARD_CPU);
101 PRINTK_BITS(HDR, ROUTE_ENCRYPTION);
102 PRINTK_BITS(HDR, ROUTE_TX);
103 PRINTK_BITS(HDR, ROUTE_RX1);
104 PRINTK_BITS(HDR, ROUTE_RX2);
105 PRINTK_BITS(HDR, ROUTE_COMPRESSION);
106
107 PRINTK_BE32(HDR, hdr->_11g0);
108 PRINTK_BE32(HDR, hdr->_11g1);
109 PRINTK_BE32(HDR, hdr->_11b0);
110 PRINTK_BE32(HDR, hdr->_11b1);
111
112 dump_ieee80211b_phy_hdr(hdr->_11b0, hdr->_11b1);
113
114 /* Fixme */
115 for (i = 0; i < ARRAY_SIZE(hdr->mac_hdr); i++) {
116 if (i == 0)
117 printk(KERN_DEBUG PFX "IEEE80211 HDR: ");
118 printk("%.2x ", hdr->mac_hdr[i]);
119 if (i + 1 == ARRAY_SIZE(hdr->mac_hdr))
120 printk("\n");
121 }
122
123 PRINTK_BE16(HDR, hdr->rts_duration);
124 PRINTK_BE16(HDR, hdr->last_duration);
125 PRINTK_BE16(HDR, hdr->sec_last_duration);
126 PRINTK_BE16(HDR, hdr->other_duration);
127 PRINTK_BE16(HDR, hdr->tx_other_duration);
128 PRINTK_BE16(HDR, hdr->last_11g_len);
129 PRINTK_BE16(HDR, hdr->other_11g_len);
130 PRINTK_BE16(HDR, hdr->last_11b_len);
131 PRINTK_BE16(HDR, hdr->other_11b_len);
132
133 /* FIXME */
134 reg = be16_to_cpu(hdr->reg6);
135 PRINTK_BITS(HDR, MBF);
136 PRINTK_BITS(HDR, RSVD4);
137
138 PRINTK_BE16(HDR, hdr->rx_frag_stat);
139
140 PRINTK_BE32(HDR, hdr->time_stamp);
141 PRINTK_BE32(HDR, hdr->phy_stats_hi);
142 PRINTK_BE32(HDR, hdr->phy_stats_lo);
143 PRINTK_BE32(HDR, hdr->mic_key0);
144 PRINTK_BE32(HDR, hdr->mic_key1);
145} /* agnx_print_hdr */
146
147
148static inline void agnx_print_rx_hdr(struct agnx_hdr *hdr)
149{
150 agnx_print_hdr(hdr);
151
152 PRINTK_BE16(HDR, hdr->rx.rx_packet_duration);
153 PRINTK_BE16(HDR, hdr->rx.replay_cnt);
154
155 PRINTK_U8(HDR, hdr->rx_channel);
156}
157
158static inline void agnx_print_tx_hdr(struct agnx_hdr *hdr)
159{
160 agnx_print_hdr(hdr);
161
162 PRINTK_U8(HDR, hdr->tx.long_retry_limit);
163 PRINTK_U8(HDR, hdr->tx.short_retry_limit);
164 PRINTK_U8(HDR, hdr->tx.long_retry_cnt);
165 PRINTK_U8(HDR, hdr->tx.short_retry_cnt);
166
167 PRINTK_U8(HDR, hdr->rx_channel);
168}
169
170static inline void
171agnx_print_sta_power(struct agnx_priv *priv, unsigned int sta_idx)
172{
173 struct agnx_sta_power power;
174 u32 reg;
175
176 get_sta_power(priv, &power, sta_idx);
177
178 reg = le32_to_cpu(power.reg);
179 PRINTK_BITS(STA_POWER, SIGNAL);
180 PRINTK_BITS(STA_POWER, RATE);
181 PRINTK_BITS(STA_POWER, TIFS);
182 PRINTK_BITS(STA_POWER, EDCF);
183 PRINTK_BITS(STA_POWER, CHANNEL_BOND);
184 PRINTK_BITS(STA_POWER, PHY_MODE);
185 PRINTK_BITS(STA_POWER, POWER_LEVEL);
186 PRINTK_BITS(STA_POWER, NUM_TRANSMITTERS);
187}
188
189static inline void
190agnx_print_sta_tx_wq(struct agnx_priv *priv, unsigned int sta_idx, unsigned int wq_idx)
191{
192 struct agnx_sta_tx_wq tx_wq;
193 u32 reg;
194
195 get_sta_tx_wq(priv, &tx_wq, sta_idx, wq_idx);
196
197 reg = le32_to_cpu(tx_wq.reg0);
198 PRINTK_BITS(STA_TX_WQ, TAIL_POINTER);
199 PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_LOW);
200
201 reg = le32_to_cpu(tx_wq.reg3);
202 PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_HIGH);
203 PRINTK_BITS(STA_TX_WQ, ACK_POINTER_LOW);
204
205 reg = le32_to_cpu(tx_wq.reg1);
206 PRINTK_BITS(STA_TX_WQ, ACK_POINTER_HIGH);
207 PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_TAIL_PACK_CNT);
208 PRINTK_BITS(STA_TX_WQ, ACK_TIMOUT_TAIL_PACK_CNT);
209
210 reg = le32_to_cpu(tx_wq.reg2);
211 PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_BYTE_CNT);
212 PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_FRAG_CNT);
213 PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_ACK_TYPE);
214 PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_VALID);
215}
216
217static inline void agnx_print_sta_traffic(struct agnx_sta_traffic *traffic)
218{
219 u32 reg;
220
221 reg = le32_to_cpu(traffic->reg0);
222 PRINTK_BITS(STA_TRAFFIC, ACK_TIMOUT_CNT);
223 PRINTK_BITS(STA_TRAFFIC, TRAFFIC_ACK_TYPE);
224 PRINTK_BITS(STA_TRAFFIC, NEW_PACKET);
225 PRINTK_BITS(STA_TRAFFIC, TRAFFIC_VALID);
226 PRINTK_BITS(STA_TRAFFIC, RX_HDR_DESC_POINTER);
227
228 reg = le32_to_cpu(traffic->reg1);
229 PRINTK_BITS(STA_TRAFFIC, RX_PACKET_TIMESTAMP);
230 PRINTK_BITS(STA_TRAFFIC, TRAFFIC_RESERVED);
231 PRINTK_BITS(STA_TRAFFIC, SV);
232 PRINTK_BITS(STA_TRAFFIC, RX_SEQUENCE_NUM);
233
234 PRINTK_LE32(STA_TRAFFIC, traffic->tx_replay_cnt_low);
235
236 PRINTK_LE16(STA_TRAFFIC, traffic->tx_replay_cnt_high);
237 PRINTK_LE16(STA_TRAFFIC, traffic->rx_replay_cnt_high);
238
239 PRINTK_LE32(STA_TRAFFIC, traffic->rx_replay_cnt_low);
240}
241
242static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx)
243{
244 struct agnx_sta station;
245 struct agnx_sta *sta = &station;
246 u32 reg;
247 unsigned int i;
248
249 get_sta(priv, sta, sta_idx);
250
251 for (i = 0; i < 4; i++)
252 PRINTK_LE32(STA, sta->tx_session_keys[i]);
253 for (i = 0; i < 4; i++)
254 PRINTK_LE32(STA, sta->rx_session_keys[i]);
255
256 reg = le32_to_cpu(sta->reg);
257 PRINTK_BITS(STA, ID_1);
258 PRINTK_BITS(STA, ID_0);
259 PRINTK_BITS(STA, ENABLE_CONCATENATION);
260 PRINTK_BITS(STA, ENABLE_DECOMPRESSION);
261 PRINTK_BITS(STA, STA_RESERVED);
262 PRINTK_BITS(STA, EAP);
263 PRINTK_BITS(STA, ED_NULL);
264 PRINTK_BITS(STA, ENCRYPTION_POLICY);
265 PRINTK_BITS(STA, DEFINED_KEY_ID);
266 PRINTK_BITS(STA, FIXED_KEY);
267 PRINTK_BITS(STA, KEY_VALID);
268 PRINTK_BITS(STA, STATION_VALID);
269
270 PRINTK_LE32(STA, sta->tx_aes_blks_unicast);
271 PRINTK_LE32(STA, sta->rx_aes_blks_unicast);
272
273 PRINTK_LE16(STA, sta->aes_format_err_unicast_cnt);
274 PRINTK_LE16(STA, sta->aes_replay_unicast);
275
276 PRINTK_LE16(STA, sta->aes_decrypt_err_unicast);
277 PRINTK_LE16(STA, sta->aes_decrypt_err_default);
278
279 PRINTK_LE16(STA, sta->single_retry_packets);
280 PRINTK_LE16(STA, sta->failed_tx_packets);
281
282 PRINTK_LE16(STA, sta->muti_retry_packets);
283 PRINTK_LE16(STA, sta->ack_timeouts);
284
285 PRINTK_LE16(STA, sta->frag_tx_cnt);
286 PRINTK_LE16(STA, sta->rts_brq_sent);
287
288 PRINTK_LE16(STA, sta->tx_packets);
289 PRINTK_LE16(STA, sta->cts_back_timeout);
290
291 PRINTK_LE32(STA, sta->phy_stats_high);
292 PRINTK_LE32(STA, sta->phy_stats_low);
293
294 /* for (i = 0; i < 8; i++) */
295 agnx_print_sta_traffic(sta->traffic + 0);
296
297 PRINTK_LE16(STA, sta->traffic_class0_frag_success);
298 PRINTK_LE16(STA, sta->traffic_class1_frag_success);
299 PRINTK_LE16(STA, sta->traffic_class2_frag_success);
300 PRINTK_LE16(STA, sta->traffic_class3_frag_success);
301 PRINTK_LE16(STA, sta->traffic_class4_frag_success);
302 PRINTK_LE16(STA, sta->traffic_class5_frag_success);
303 PRINTK_LE16(STA, sta->traffic_class6_frag_success);
304 PRINTK_LE16(STA, sta->traffic_class7_frag_success);
305
306 PRINTK_LE16(STA, sta->num_frag_non_prime_rates);
307 PRINTK_LE16(STA, sta->ack_timeout_non_prime_rates);
308}
309
310
311static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
312{
313 u16 fctl;
314 int hdrlen;
315
316 fctl = le16_to_cpu(hdr->frame_control);
317 switch (fctl & IEEE80211_FCTL_FTYPE) {
318 case IEEE80211_FTYPE_DATA:
319 printk(PFX "%s DATA ", tag);
320 break;
321 case IEEE80211_FTYPE_CTL:
322 printk(PFX "%s CTL ", tag);
323 break;
324 case IEEE80211_FTYPE_MGMT:
325 printk(PFX "%s MGMT ", tag);
326 switch (fctl & IEEE80211_FCTL_STYPE) {
327 case IEEE80211_STYPE_ASSOC_REQ:
328 printk("SubType: ASSOC_REQ ");
329 break;
330 case IEEE80211_STYPE_ASSOC_RESP:
331 printk("SubType: ASSOC_RESP ");
332 break;
333 case IEEE80211_STYPE_REASSOC_REQ:
334 printk("SubType: REASSOC_REQ ");
335 break;
336 case IEEE80211_STYPE_REASSOC_RESP:
337 printk("SubType: REASSOC_RESP ");
338 break;
339 case IEEE80211_STYPE_PROBE_REQ:
340 printk("SubType: PROBE_REQ ");
341 break;
342 case IEEE80211_STYPE_PROBE_RESP:
343 printk("SubType: PROBE_RESP ");
344 break;
345 case IEEE80211_STYPE_BEACON:
346 printk("SubType: BEACON ");
347 break;
348 case IEEE80211_STYPE_ATIM:
349 printk("SubType: ATIM ");
350 break;
351 case IEEE80211_STYPE_DISASSOC:
352 printk("SubType: DISASSOC ");
353 break;
354 case IEEE80211_STYPE_AUTH:
355 printk("SubType: AUTH ");
356 break;
357 case IEEE80211_STYPE_DEAUTH:
358 printk("SubType: DEAUTH ");
359 break;
360 case IEEE80211_STYPE_ACTION:
361 printk("SubType: ACTION ");
362 break;
363 default:
364 printk("SubType: Unknow\n");
365 }
366 break;
367 default:
368 printk(PFX "%s Packet type: Unknow\n", tag);
369 }
370
371 hdrlen = ieee80211_hdrlen(fctl);
372
373 if (hdrlen >= 4)
374 printk("FC=0x%04x DUR=0x%04x",
375 fctl, le16_to_cpu(hdr->duration_id));
376 if (hdrlen >= 10)
377 printk(" A1=%pM", hdr->addr1);
378 if (hdrlen >= 16)
379 printk(" A2=%pM", hdr->addr2);
380 if (hdrlen >= 24)
381 printk(" A3=%pM", hdr->addr3);
382 if (hdrlen >= 30)
383 printk(" A4=%pM", hdr->addr4);
384 printk("\n");
385}
386
387static inline void dump_txm_registers(struct agnx_priv *priv)
388{
389 void __iomem *ctl = priv->ctl;
390 int i;
391 for (i = 0; i <= 0x1e8; i += 4)
392 printk(KERN_DEBUG PFX "TXM: %x---> 0x%.8x\n", i, ioread32(ctl + i));
393}
394static inline void dump_rxm_registers(struct agnx_priv *priv)
395{
396 void __iomem *ctl = priv->ctl;
397 int i;
398 for (i = 0; i <= 0x108; i += 4)
399 printk(KERN_DEBUG PFX "RXM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2000 + i));
400}
401static inline void dump_bm_registers(struct agnx_priv *priv)
402{
403 void __iomem *ctl = priv->ctl;
404 int i;
405 for (i = 0; i <= 0x90; i += 4)
406 printk(KERN_DEBUG PFX "BM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2c00 + i));
407}
408static inline void dump_cir_registers(struct agnx_priv *priv)
409{
410 void __iomem *ctl = priv->ctl;
411 int i;
412 for (i = 0; i <= 0xb8; i += 4)
413 printk(KERN_DEBUG PFX "CIR: %x---> 0x%.8x\n", i, ioread32(ctl + 0x3000 + i));
414}
415
416#endif /* AGNX_DEBUG_H_ */
diff --git a/drivers/staging/agnx/pci.c b/drivers/staging/agnx/pci.c
deleted file mode 100644
index 32b5489456a8..000000000000
--- a/drivers/staging/agnx/pci.c
+++ /dev/null
@@ -1,635 +0,0 @@
1/**
2 * Airgo MIMO wireless driver
3 *
4 * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
5
6 * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
7 * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
8
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/init.h>
15#include <linux/etherdevice.h>
16#include <linux/pci.h>
17#include <linux/delay.h>
18
19#include "agnx.h"
20#include "debug.h"
21#include "xmit.h"
22#include "phy.h"
23
24MODULE_AUTHOR("Li YanBo <dreamfly281@gmail.com>");
25MODULE_DESCRIPTION("Airgo MIMO PCI wireless driver");
26MODULE_LICENSE("GPL");
27
28static struct pci_device_id agnx_pci_id_tbl[] __devinitdata = {
29 { PCI_DEVICE(0x17cb, 0x0001) }, /* Beklin F5d8010, Netgear WGM511 etc */
30 { PCI_DEVICE(0x17cb, 0x0002) }, /* Netgear Wpnt511 */
31 { 0 }
32};
33
34MODULE_DEVICE_TABLE(pci, agnx_pci_id_tbl);
35
36
37static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason)
38{
39 void __iomem *ctl = priv->ctl;
40 u32 reg;
41
42 if (*reason & AGNX_STAT_RX) {
43 /* Mark complete RX */
44 reg = ioread32(ctl + AGNX_CIR_RXCTL);
45 reg |= 0x4;
46 iowrite32(reg, ctl + AGNX_CIR_RXCTL);
47 /* disable Rx interrupt */
48 }
49 if (*reason & AGNX_STAT_TX) {
50 reg = ioread32(ctl + AGNX_CIR_TXDCTL);
51 if (reg & 0x4) {
52 iowrite32(reg, ctl + AGNX_CIR_TXDCTL);
53 *reason |= AGNX_STAT_TXD;
54 }
55 reg = ioread32(ctl + AGNX_CIR_TXMCTL);
56 if (reg & 0x4) {
57 iowrite32(reg, ctl + AGNX_CIR_TXMCTL);
58 *reason |= AGNX_STAT_TXM;
59 }
60 }
61#if 0
62 if (*reason & AGNX_STAT_X) {
63 reg = ioread32(ctl + AGNX_INT_STAT);
64 iowrite32(reg, ctl + AGNX_INT_STAT);
65 /* FIXME reinit interrupt mask */
66 reg = 0xc390bf9 & ~IRQ_TX_BEACON;
67 reg &= ~IRQ_TX_DISABLE;
68 iowrite32(reg, ctl + AGNX_INT_MASK);
69 iowrite32(0x800, ctl + AGNX_CIR_BLKCTL);
70 }
71#endif
72} /* agnx_interrupt_ack */
73
74static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
75{
76 struct ieee80211_hw *dev = dev_id;
77 struct agnx_priv *priv = dev->priv;
78 void __iomem *ctl = priv->ctl;
79 irqreturn_t ret = IRQ_NONE;
80 u32 irq_reason;
81
82 spin_lock(&priv->lock);
83
84/* printk(KERN_ERR PFX "Get a interrupt %s\n", __func__); */
85
86 if (priv->init_status != AGNX_START)
87 goto out;
88
89 /* FiXME Here has no lock, Is this will lead to race? */
90 irq_reason = ioread32(ctl + AGNX_CIR_BLKCTL);
91 if (!(irq_reason & 0x7))
92 goto out;
93
94 ret = IRQ_HANDLED;
95 priv->irq_status = ioread32(ctl + AGNX_INT_STAT);
96
97/* printk(PFX "Interrupt reason is 0x%x\n", irq_reason); */
98 /* Make sure the txm and txd flags don't conflict with other unknown
99 interrupt flag, maybe is not necessary */
100 irq_reason &= 0xF;
101
102 disable_rx_interrupt(priv);
103 /* TODO Make sure the card finished initialized */
104 agnx_interrupt_ack(priv, &irq_reason);
105
106 if (irq_reason & AGNX_STAT_RX)
107 handle_rx_irq(priv);
108 if (irq_reason & AGNX_STAT_TXD)
109 handle_txd_irq(priv);
110 if (irq_reason & AGNX_STAT_TXM)
111 handle_txm_irq(priv);
112 if (irq_reason & AGNX_STAT_X)
113 handle_other_irq(priv);
114
115 enable_rx_interrupt(priv);
116out:
117 spin_unlock(&priv->lock);
118 return ret;
119} /* agnx_interrupt_handler */
120
121
122/* FIXME */
123static int agnx_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
124{
125 AGNX_TRACE;
126 return _agnx_tx(dev->priv, skb);
127} /* agnx_tx */
128
129
130static int agnx_get_mac_address(struct agnx_priv *priv)
131{
132 void __iomem *ctl = priv->ctl;
133 u32 reg;
134 AGNX_TRACE;
135
136 /* Attention! directly read the MAC or other date from EEPROM will
137 lead to cardbus(WGM511) lock up when write to PM PLL register */
138 reg = agnx_read32(ctl, 0x3544);
139 udelay(40);
140 reg = agnx_read32(ctl, 0x354c);
141 udelay(50);
142 /* Get the mac address */
143 reg = agnx_read32(ctl, 0x3544);
144 udelay(40);
145
146 /* HACK */
147 reg = cpu_to_le32(reg);
148 priv->mac_addr[0] = ((u8 *)&reg)[2];
149 priv->mac_addr[1] = ((u8 *)&reg)[3];
150 reg = agnx_read32(ctl, 0x3548);
151 udelay(50);
152 *((u32 *)(priv->mac_addr + 2)) = cpu_to_le32(reg);
153
154 if (!is_valid_ether_addr(priv->mac_addr)) {
155 printk(KERN_WARNING PFX "read mac %pM\n", priv->mac_addr);
156 printk(KERN_WARNING PFX "Invalid hwaddr! Using random hwaddr\n");
157 random_ether_addr(priv->mac_addr);
158 }
159
160 return 0;
161} /* agnx_get_mac_address */
162
163static int agnx_alloc_rings(struct agnx_priv *priv)
164{
165 unsigned int len;
166 AGNX_TRACE;
167
168 /* Allocate RX/TXM/TXD rings info */
169 priv->rx.size = AGNX_RX_RING_SIZE;
170 priv->txm.size = AGNX_TXM_RING_SIZE;
171 priv->txd.size = AGNX_TXD_RING_SIZE;
172
173 len = priv->rx.size + priv->txm.size + priv->txd.size;
174
175/* priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL); */
176 priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_ATOMIC);
177 if (!priv->rx.info)
178 return -ENOMEM;
179 priv->txm.info = priv->rx.info + priv->rx.size;
180 priv->txd.info = priv->txm.info + priv->txm.size;
181
182 /* Allocate RX/TXM/TXD descriptors */
183 priv->rx.desc = pci_alloc_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
184 &priv->rx.dma);
185 if (!priv->rx.desc) {
186 kfree(priv->rx.info);
187 return -ENOMEM;
188 }
189
190 priv->txm.desc = priv->rx.desc + priv->rx.size;
191 priv->txm.dma = priv->rx.dma + sizeof(struct agnx_desc) * priv->rx.size;
192 priv->txd.desc = priv->txm.desc + priv->txm.size;
193 priv->txd.dma = priv->txm.dma + sizeof(struct agnx_desc) * priv->txm.size;
194
195 return 0;
196} /* agnx_alloc_rings */
197
198static void rings_free(struct agnx_priv *priv)
199{
200 unsigned int len = priv->rx.size + priv->txm.size + priv->txd.size;
201 unsigned long flags;
202 AGNX_TRACE;
203
204 spin_lock_irqsave(&priv->lock, flags);
205 kfree(priv->rx.info);
206 pci_free_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
207 priv->rx.desc, priv->rx.dma);
208 spin_unlock_irqrestore(&priv->lock, flags);
209}
210
211#if 0
212static void agnx_periodic_work_handler(struct work_struct *work)
213{
214 struct agnx_priv *priv = container_of(work, struct agnx_priv, periodic_work.work);
215/* unsigned long flags; */
216 unsigned long delay;
217
218 /* fixme: using mutex?? */
219/* spin_lock_irqsave(&priv->lock, flags); */
220
221 /* TODO Recalibrate*/
222/* calibrate_oscillator(priv); */
223/* antenna_calibrate(priv); */
224/* agnx_send_packet(priv, 997); */
225 /* FIXME */
226/* if (debug == 3) */
227/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
228/* else */
229 delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY);
230/* delay = round_jiffies(HZ * 15); */
231
232 queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay);
233
234/* spin_unlock_irqrestore(&priv->lock, flags); */
235}
236#endif
237
238static int agnx_start(struct ieee80211_hw *dev)
239{
240 struct agnx_priv *priv = dev->priv;
241 /* unsigned long delay; */
242 int err = 0;
243 AGNX_TRACE;
244
245 err = agnx_alloc_rings(priv);
246 if (err) {
247 printk(KERN_ERR PFX "Can't alloc RX/TXM/TXD rings\n");
248 goto out;
249 }
250 err = request_irq(priv->pdev->irq, &agnx_interrupt_handler,
251 IRQF_SHARED, "agnx_pci", dev);
252 if (err) {
253 printk(KERN_ERR PFX "Failed to register IRQ handler\n");
254 rings_free(priv);
255 goto out;
256 }
257
258/* mdelay(500); */
259
260 might_sleep();
261 agnx_hw_init(priv);
262
263/* mdelay(500); */
264 might_sleep();
265
266 priv->init_status = AGNX_START;
267/* INIT_DELAYED_WORK(&priv->periodic_work, agnx_periodic_work_handler); */
268/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
269/* queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay); */
270out:
271 return err;
272} /* agnx_start */
273
274static void agnx_stop(struct ieee80211_hw *dev)
275{
276 struct agnx_priv *priv = dev->priv;
277 AGNX_TRACE;
278
279 priv->init_status = AGNX_STOP;
280 /* make sure hardware will not generate irq */
281 agnx_hw_reset(priv);
282 free_irq(priv->pdev->irq, dev);
283/* flush_workqueue(priv->hw->workqueue); */
284/* cancel_delayed_work_sync(&priv->periodic_work); */
285 unfill_rings(priv);
286 rings_free(priv);
287}
288
289static int agnx_config(struct ieee80211_hw *dev, u32 changed)
290{
291 struct agnx_priv *priv = dev->priv;
292 struct ieee80211_conf *conf = &dev->conf;
293 int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
294 AGNX_TRACE;
295
296 spin_lock(&priv->lock);
297 /* FIXME need priv lock? */
298 if (channel != priv->channel) {
299 priv->channel = channel;
300 agnx_set_channel(priv, priv->channel);
301 }
302
303 spin_unlock(&priv->lock);
304 return 0;
305}
306
307static void agnx_bss_info_changed(struct ieee80211_hw *dev,
308 struct ieee80211_vif *vif,
309 struct ieee80211_bss_conf *conf,
310 u32 changed)
311{
312 struct agnx_priv *priv = dev->priv;
313 void __iomem *ctl = priv->ctl;
314 AGNX_TRACE;
315
316 if (!(changed & BSS_CHANGED_BSSID))
317 return;
318
319 spin_lock(&priv->lock);
320
321 if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
322 agnx_set_bssid(priv, conf->bssid);
323 memcpy(priv->bssid, conf->bssid, ETH_ALEN);
324 hash_write(priv, conf->bssid, BSSID_STAID);
325 sta_init(priv, BSSID_STAID);
326 /* FIXME needed? */
327 sta_power_init(priv, BSSID_STAID);
328 agnx_write32(ctl, AGNX_BM_MTSM, 0xff & ~0x1);
329 }
330 spin_unlock(&priv->lock);
331} /* agnx_bss_info_changed */
332
333
334static void agnx_configure_filter(struct ieee80211_hw *dev,
335 unsigned int changed_flags,
336 unsigned int *total_flags,
337 int mc_count, struct dev_mc_list *mclist)
338{
339 unsigned int new_flags = 0;
340
341 *total_flags = new_flags;
342 /* TODO */
343}
344
345static int agnx_add_interface(struct ieee80211_hw *dev,
346 struct ieee80211_if_init_conf *conf)
347{
348 struct agnx_priv *priv = dev->priv;
349 AGNX_TRACE;
350
351 spin_lock(&priv->lock);
352 /* FIXME */
353 if (priv->mode != NL80211_IFTYPE_MONITOR)
354 return -EOPNOTSUPP;
355
356 switch (conf->type) {
357 case NL80211_IFTYPE_STATION:
358 priv->mode = conf->type;
359 break;
360 default:
361 return -EOPNOTSUPP;
362 }
363
364 spin_unlock(&priv->lock);
365
366 return 0;
367}
368
369static void agnx_remove_interface(struct ieee80211_hw *dev,
370 struct ieee80211_if_init_conf *conf)
371{
372 struct agnx_priv *priv = dev->priv;
373 AGNX_TRACE;
374
375 /* TODO */
376 priv->mode = NL80211_IFTYPE_MONITOR;
377}
378
379static int agnx_get_stats(struct ieee80211_hw *dev,
380 struct ieee80211_low_level_stats *stats)
381{
382 struct agnx_priv *priv = dev->priv;
383 AGNX_TRACE;
384 spin_lock(&priv->lock);
385 /* TODO !! */
386 memcpy(stats, &priv->stats, sizeof(*stats));
387 spin_unlock(&priv->lock);
388
389 return 0;
390}
391
392static u64 agnx_get_tsft(struct ieee80211_hw *dev)
393{
394 void __iomem *ctl = ((struct agnx_priv *)dev->priv)->ctl;
395 u32 tsftl;
396 u64 tsft;
397 AGNX_TRACE;
398
399 /* FIXME */
400 tsftl = ioread32(ctl + AGNX_TXM_TIMESTAMPLO);
401 tsft = ioread32(ctl + AGNX_TXM_TIMESTAMPHI);
402 tsft <<= 32;
403 tsft |= tsftl;
404
405 return tsft;
406}
407
408static int agnx_get_tx_stats(struct ieee80211_hw *dev,
409 struct ieee80211_tx_queue_stats *stats)
410{
411 struct agnx_priv *priv = dev->priv;
412 AGNX_TRACE;
413
414 /* FIXME now we just using txd queue, but should using txm queue too */
415 stats[0].len = (priv->txd.idx - priv->txd.idx_sent) / 2;
416 stats[0].limit = priv->txd.size - 2;
417 stats[0].count = priv->txd.idx / 2;
418
419 return 0;
420}
421
422static struct ieee80211_ops agnx_ops = {
423 .tx = agnx_tx,
424 .start = agnx_start,
425 .stop = agnx_stop,
426 .add_interface = agnx_add_interface,
427 .remove_interface = agnx_remove_interface,
428 .config = agnx_config,
429 .bss_info_changed = agnx_bss_info_changed,
430 .configure_filter = agnx_configure_filter,
431 .get_stats = agnx_get_stats,
432 .get_tx_stats = agnx_get_tx_stats,
433 .get_tsf = agnx_get_tsft
434};
435
436static void __devexit agnx_pci_remove(struct pci_dev *pdev)
437{
438 struct ieee80211_hw *dev = pci_get_drvdata(pdev);
439 struct agnx_priv *priv;
440 AGNX_TRACE;
441
442 if (!dev)
443 return;
444 priv = dev->priv;
445 ieee80211_unregister_hw(dev);
446 pci_iounmap(pdev, priv->ctl);
447 pci_iounmap(pdev, priv->data);
448 pci_release_regions(pdev);
449 pci_disable_device(pdev);
450
451 ieee80211_free_hw(dev);
452}
453
454static int __devinit agnx_pci_probe(struct pci_dev *pdev,
455 const struct pci_device_id *id)
456{
457 struct ieee80211_hw *dev;
458 struct agnx_priv *priv;
459 int err;
460
461 err = pci_enable_device(pdev);
462 if (err) {
463 dev_err(&pdev->dev, "can't enable pci device\n");
464 return err;
465 }
466
467 err = pci_request_regions(pdev, "agnx-pci");
468 if (err) {
469 dev_err(&pdev->dev, "can't reserve PCI resources\n");
470 return err;
471 }
472
473 if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) ||
474 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
475 dev_err(&pdev->dev, "no suitable DMA available\n");
476 err = -EIO;
477 goto err_free_reg;
478 }
479
480 pci_set_master(pdev);
481
482 dev = ieee80211_alloc_hw(sizeof(*priv), &agnx_ops);
483 if (!dev) {
484 dev_err(&pdev->dev, "ieee80211 alloc failed\n");
485 err = -ENOMEM;
486 goto err_free_reg;
487 }
488 priv = dev->priv;
489 memset(priv, 0, sizeof(*priv));
490 priv->mode = NL80211_IFTYPE_MONITOR;
491 priv->pdev = pdev;
492 priv->hw = dev;
493 spin_lock_init(&priv->lock);
494 priv->init_status = AGNX_UNINIT;
495
496 priv->ctl = pci_iomap(pdev, 0, 0);
497/* dev_dbg(&pdev->dev, "MEM1 mapped address is 0x%p\n", priv->ctl); */
498 if (!priv->ctl) {
499 dev_err(&pdev->dev, "can't map device memory\n");
500 err = -ENOMEM;
501 goto err_free_dev;
502 }
503 priv->data = pci_iomap(pdev, 1, 0);
504 if (!priv->data) {
505 dev_err(&pdev->dev, "can't map device memory\n");
506 err = -ENOMEM;
507 goto err_iounmap2;
508 }
509
510 pci_read_config_byte(pdev, PCI_REVISION_ID, &priv->revid);
511
512 priv->band.channels = (struct ieee80211_channel *)agnx_channels;
513 priv->band.n_channels = ARRAY_SIZE(agnx_channels);
514 priv->band.bitrates = (struct ieee80211_rate *)agnx_rates_80211g;
515 priv->band.n_bitrates = ARRAY_SIZE(agnx_rates_80211g);
516
517 /* Init ieee802.11 dev */
518 SET_IEEE80211_DEV(dev, &pdev->dev);
519 pci_set_drvdata(pdev, dev);
520 dev->extra_tx_headroom = sizeof(struct agnx_hdr);
521
522 /* FIXME It only include FCS in promious mode but not manage mode */
523/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS; */
524 dev->channel_change_time = 5000;
525 dev->max_signal = 100;
526 /* FIXME */
527 dev->queues = 1;
528
529 agnx_get_mac_address(priv);
530
531 SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr);
532
533/* /\* FIXME *\/ */
534/* for (i = 1; i < NUM_DRIVE_MODES; i++) { */
535/* err = ieee80211_register_hwmode(dev, &priv->modes[i]); */
536/* if (err) { */
537/* printk(KERN_ERR PFX "Can't register hwmode\n"); */
538/* goto err_iounmap; */
539/* } */
540/* } */
541
542 priv->channel = 1;
543 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
544
545 err = ieee80211_register_hw(dev);
546 if (err) {
547 dev_err(&pdev->dev, "can't register hardware\n");
548 goto err_iounmap;
549 }
550
551 agnx_hw_reset(priv);
552
553 dev_info(&pdev->dev, "%s: hwaddr %pM, Rev 0x%02x\n",
554 wiphy_name(dev->wiphy),
555 dev->wiphy->perm_addr, priv->revid);
556 return 0;
557
558 err_iounmap:
559 pci_iounmap(pdev, priv->data);
560
561 err_iounmap2:
562 pci_iounmap(pdev, priv->ctl);
563
564 err_free_dev:
565 pci_set_drvdata(pdev, NULL);
566 ieee80211_free_hw(dev);
567
568 err_free_reg:
569 pci_release_regions(pdev);
570
571 pci_disable_device(pdev);
572 return err;
573} /* agnx_pci_probe*/
574
575#ifdef CONFIG_PM
576
577static int agnx_pci_suspend(struct pci_dev *pdev, pm_message_t state)
578{
579 struct ieee80211_hw *dev = pci_get_drvdata(pdev);
580 AGNX_TRACE;
581
582 ieee80211_stop_queues(dev);
583 agnx_stop(dev);
584
585 pci_save_state(pdev);
586 pci_set_power_state(pdev, pci_choose_state(pdev, state));
587 return 0;
588}
589
590static int agnx_pci_resume(struct pci_dev *pdev)
591{
592 struct ieee80211_hw *dev = pci_get_drvdata(pdev);
593 AGNX_TRACE;
594
595 pci_set_power_state(pdev, PCI_D0);
596 pci_restore_state(pdev);
597
598 agnx_start(dev);
599 ieee80211_wake_queues(dev);
600
601 return 0;
602}
603
604#else
605
606#define agnx_pci_suspend NULL
607#define agnx_pci_resume NULL
608
609#endif /* CONFIG_PM */
610
611
612static struct pci_driver agnx_pci_driver = {
613 .name = "agnx-pci",
614 .id_table = agnx_pci_id_tbl,
615 .probe = agnx_pci_probe,
616 .remove = __devexit_p(agnx_pci_remove),
617 .suspend = agnx_pci_suspend,
618 .resume = agnx_pci_resume,
619};
620
621static int __init agnx_pci_init(void)
622{
623 AGNX_TRACE;
624 return pci_register_driver(&agnx_pci_driver);
625}
626
627static void __exit agnx_pci_exit(void)
628{
629 AGNX_TRACE;
630 pci_unregister_driver(&agnx_pci_driver);
631}
632
633
634module_init(agnx_pci_init);
635module_exit(agnx_pci_exit);
diff --git a/drivers/staging/agnx/phy.c b/drivers/staging/agnx/phy.c
deleted file mode 100644
index ec1ca86fa0c4..000000000000
--- a/drivers/staging/agnx/phy.c
+++ /dev/null
@@ -1,960 +0,0 @@
1/**
2 * Airgo MIMO wireless driver
3 *
4 * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
5
6 * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
7 * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
8
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/init.h>
15#include <linux/etherdevice.h>
16#include <linux/pci.h>
17#include <linux/delay.h>
18#include "agnx.h"
19#include "debug.h"
20#include "phy.h"
21#include "table.h"
22#include "sta.h"
23#include "xmit.h"
24
25u8 read_from_eeprom(struct agnx_priv *priv, u16 address)
26{
27 void __iomem *ctl = priv->ctl;
28 struct agnx_eeprom cmd;
29 u32 reg;
30
31 memset(&cmd, 0, sizeof(cmd));
32 cmd.cmd = EEPROM_CMD_READ << AGNX_EEPROM_COMMAND_SHIFT;
33 cmd.address = address;
34 /* Verify that the Status bit is clear */
35 /* Read Command and Address are written to the Serial Interface */
36 iowrite32(*(__le32 *)&cmd, ctl + AGNX_CIR_SERIALITF);
37 /* Wait for the Status bit to clear again */
38 eeprom_delay();
39 /* Read from Data */
40 reg = ioread32(ctl + AGNX_CIR_SERIALITF);
41
42 cmd = *(struct agnx_eeprom *)&reg;
43
44 return cmd.data;
45}
46
47static int card_full_reset(struct agnx_priv *priv)
48{
49 void __iomem *ctl = priv->ctl;
50 u32 reg;
51 AGNX_TRACE;
52
53 reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
54 agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x80);
55 reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
56 return 0;
57}
58
59inline void enable_power_saving(struct agnx_priv *priv)
60{
61 void __iomem *ctl = priv->ctl;
62 u32 reg;
63
64 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
65 reg &= ~0x8;
66 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
67}
68
69inline void disable_power_saving(struct agnx_priv *priv)
70{
71 void __iomem *ctl = priv->ctl;
72 u32 reg;
73
74 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
75 reg |= 0x8;
76 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
77}
78
79
80void disable_receiver(struct agnx_priv *priv)
81{
82 void __iomem *ctl = priv->ctl;
83 AGNX_TRACE;
84
85 /* FIXME Disable the receiver */
86 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
87 /* Set gain control reset */
88 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
89 /* Reset gain control reset */
90 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
91}
92
93
94/* Fixme this shoule be disable RX, above is enable RX */
95void enable_receiver(struct agnx_priv *priv)
96{
97 void __iomem *ctl = priv->ctl;
98 AGNX_TRACE;
99
100 /* Set adaptive gain control discovery mode */
101 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
102 /* Set gain control reset */
103 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
104 /* Clear gain control reset */
105 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
106}
107
108static void mac_address_set(struct agnx_priv *priv)
109{
110 void __iomem *ctl = priv->ctl;
111 u8 *mac_addr = priv->mac_addr;
112 u32 reg;
113
114 /* FIXME */
115 reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];
116 iowrite32(reg, ctl + AGNX_RXM_MACHI);
117 reg = (mac_addr[4] << 8) | mac_addr[5];
118 iowrite32(reg, ctl + AGNX_RXM_MACLO);
119}
120
121static void receiver_bssid_set(struct agnx_priv *priv, const u8 *bssid)
122{
123 void __iomem *ctl = priv->ctl;
124 u32 reg;
125
126 disable_receiver(priv);
127 /* FIXME */
128 reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];
129 iowrite32(reg, ctl + AGNX_RXM_BSSIDHI);
130 reg = (bssid[4] << 8) | bssid[5];
131 iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);
132
133 /* Enable the receiver */
134 enable_receiver(priv);
135
136 /* Clear the TSF */
137/* agnx_write32(ctl, AGNX_TXM_TSFLO, 0x0); */
138/* agnx_write32(ctl, AGNX_TXM_TSFHI, 0x0); */
139 /* Clear the TBTT */
140 agnx_write32(ctl, AGNX_TXM_TBTTLO, 0x0);
141 agnx_write32(ctl, AGNX_TXM_TBTTHI, 0x0);
142 disable_receiver(priv);
143} /* receiver_bssid_set */
144
145static void band_management_init(struct agnx_priv *priv)
146{
147 void __iomem *ctl = priv->ctl;
148 void __iomem *data = priv->data;
149 u32 reg;
150 int i;
151 AGNX_TRACE;
152
153 agnx_write32(ctl, AGNX_BM_TXWADDR, AGNX_PDU_TX_WQ);
154 agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);
155 memset_io(data + AGNX_PDUPOOL, 0x0, AGNX_PDUPOOL_SIZE);
156 agnx_write32(ctl, AGNX_BM_BMCTL, 0x200);
157
158 agnx_write32(ctl, AGNX_BM_CIPDUWCNT, 0x40);
159 agnx_write32(ctl, AGNX_BM_SPPDUWCNT, 0x2);
160 agnx_write32(ctl, AGNX_BM_RFPPDUWCNT, 0x0);
161 agnx_write32(ctl, AGNX_BM_RHPPDUWCNT, 0x22);
162
163 /* FIXME Initialize the Free Pool Linked List */
164 /* 1. Write the Address of the Next Node ((0x41800 + node*size)/size)
165 to the first word of each node. */
166 for (i = 0; i < PDU_FREE_CNT; i++) {
167 iowrite32((AGNX_PDU_FREE + (i+1)*PDU_SIZE)/PDU_SIZE,
168 data + AGNX_PDU_FREE + (PDU_SIZE * i));
169 /* The last node should be set to 0x0 */
170 if ((i + 1) == PDU_FREE_CNT)
171 memset_io(data + AGNX_PDU_FREE + (PDU_SIZE * i),
172 0x0, PDU_SIZE);
173 }
174
175 /* Head is First Pool address (0x41800) / size (0x80) */
176 agnx_write32(ctl, AGNX_BM_FPLHP, AGNX_PDU_FREE/PDU_SIZE);
177 /* Tail is Last Pool Address (0x47f80) / size (0x80) */
178 agnx_write32(ctl, AGNX_BM_FPLTP, 0x47f80/PDU_SIZE);
179 /* Count is Number of Nodes in the Pool (0xd0) */
180 agnx_write32(ctl, AGNX_BM_FPCNT, PDU_FREE_CNT);
181
182 /* Start all workqueue */
183 agnx_write32(ctl, AGNX_BM_CIWQCTL, 0x80000);
184 agnx_write32(ctl, AGNX_BM_CPULWCTL, 0x80000);
185 agnx_write32(ctl, AGNX_BM_CPUHWCTL, 0x80000);
186 agnx_write32(ctl, AGNX_BM_CPUTXWCTL, 0x80000);
187 agnx_write32(ctl, AGNX_BM_CPURXWCTL, 0x80000);
188 agnx_write32(ctl, AGNX_BM_SPRXWCTL, 0x80000);
189 agnx_write32(ctl, AGNX_BM_SPTXWCTL, 0x80000);
190 agnx_write32(ctl, AGNX_BM_RFPWCTL, 0x80000);
191
192 /* Enable the Band Management */
193 reg = agnx_read32(ctl, AGNX_BM_BMCTL);
194 reg |= 0x1;
195 agnx_write32(ctl, AGNX_BM_BMCTL, reg);
196} /* band_managment_init */
197
198
199static void system_itf_init(struct agnx_priv *priv)
200{
201 void __iomem *ctl = priv->ctl;
202 u32 reg;
203 AGNX_TRACE;
204
205 agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x0);
206 agnx_write32(ctl, AGNX_PM_TESTPHY, 0x11e143a);
207
208 if (priv->revid == 0) {
209 reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);
210 reg |= 0x11;
211 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);
212 }
213 /* ??? What is that means? it should difference for differice type
214 of cards */
215 agnx_write32(ctl, AGNX_CIR_SERIALITF, 0xfff81006);
216
217 agnx_write32(ctl, AGNX_SYSITF_GPIOIN, 0x1f0000);
218 agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
219 reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);
220}
221
222static void encryption_init(struct agnx_priv *priv)
223{
224 void __iomem *ctl = priv->ctl;
225 AGNX_TRACE;
226
227 agnx_write32(ctl, AGNX_ENCRY_WEPKEY0, 0x0);
228 agnx_write32(ctl, AGNX_ENCRY_WEPKEY1, 0x0);
229 agnx_write32(ctl, AGNX_ENCRY_WEPKEY2, 0x0);
230 agnx_write32(ctl, AGNX_ENCRY_WEPKEY3, 0x0);
231 agnx_write32(ctl, AGNX_ENCRY_CCMRECTL, 0x8);
232}
233
234static void tx_management_init(struct agnx_priv *priv)
235{
236 void __iomem *ctl = priv->ctl;
237 void __iomem *data = priv->data;
238 u32 reg;
239 AGNX_TRACE;
240
241 /* Fill out the ComputationalEngineLookupTable
242 * starting at memory #2 offset 0x800
243 */
244 tx_engine_lookup_tbl_init(priv);
245 memset_io(data + 0x1000, 0, 0xfe0);
246 /* Enable Transmission Management Functions */
247 agnx_write32(ctl, AGNX_TXM_ETMF, 0x3ff);
248 /* Write 0x3f to Transmission Template */
249 agnx_write32(ctl, AGNX_TXM_TXTEMP, 0x3f);
250
251 if (priv->revid >= 2)
252 agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e140a0b);
253 else
254 agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e190a0b);
255
256 reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
257 reg &= 0xff00;
258 reg |= 0xb;
259 agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
260 reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
261 reg &= 0xffff00ff;
262 reg |= 0xa00;
263 agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
264 /* Enable TIFS */
265 agnx_write32(ctl, AGNX_TXM_CTL, 0x40000);
266
267 reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
268 reg &= 0xff00ffff;
269 reg |= 0x510000;
270 agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
271 reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
272 reg &= 0xff00ffff;
273 agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
274 reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
275 reg &= 0x00ffffff;
276 reg |= 0x1c000000;
277 agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
278 reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
279 reg &= 0x00ffffff;
280 reg |= 0x01000000;
281 agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
282
283 /* # Set DIF 0-1,2-3,4-5,6-7 to defaults */
284 agnx_write32(ctl, AGNX_TXM_DIF01, 0x321d321d);
285 agnx_write32(ctl, AGNX_TXM_DIF23, 0x321d321d);
286 agnx_write32(ctl, AGNX_TXM_DIF45, 0x321d321d);
287 agnx_write32(ctl, AGNX_TXM_DIF67, 0x321d321d);
288
289 /* Max Ack timeout limit */
290 agnx_write32(ctl, AGNX_TXM_MAXACKTIM, 0x1e19);
291 /* Max RX Data Timeout count, */
292 reg = agnx_read32(ctl, AGNX_TXM_MAXRXTIME);
293 reg &= 0xffff0000;
294 reg |= 0xff;
295 agnx_write32(ctl, AGNX_TXM_MAXRXTIME, reg);
296
297 /* CF poll RX Timeout count */
298 reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
299 reg &= 0xffff;
300 reg |= 0xff0000;
301 agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
302
303 /* Max Timeout Exceeded count, */
304 reg = agnx_read32(ctl, AGNX_TXM_MAXTIMOUT);
305 reg &= 0xff00ffff;
306 reg |= 0x190000;
307 agnx_write32(ctl, AGNX_TXM_MAXTIMOUT, reg);
308
309 /* CF ack timeout limit for 11b */
310 reg = agnx_read32(ctl, AGNX_TXM_CFACKT11B);
311 reg &= 0xff00;
312 reg |= 0x1e;
313 agnx_write32(ctl, AGNX_TXM_CFACKT11B, reg);
314
315 /* Max CF Poll Timeout Count */
316 reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
317 reg &= 0xffff0000;
318 reg |= 0x19;
319 agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
320 /* CF Poll RX Timeout Count */
321 reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
322 reg &= 0xffff0000;
323 reg |= 0x1e;
324 agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
325
326 /* # write default to */
327 /* 1. Schedule Empty Count */
328 agnx_write32(ctl, AGNX_TXM_SCHEMPCNT, 0x5);
329 /* 2. CFP Period Count */
330 agnx_write32(ctl, AGNX_TXM_CFPERCNT, 0x1);
331 /* 3. CFP MDV */
332 agnx_write32(ctl, AGNX_TXM_CFPMDV, 0x10000);
333
334 /* Probe Delay */
335 reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
336 reg &= 0xffff0000;
337 reg |= 0x400;
338 agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
339
340 /* Max CCA count Slot */
341 reg = agnx_read32(ctl, AGNX_TXM_MAXCCACNTSLOT);
342 reg &= 0xffff00ff;
343 reg |= 0x900;
344 agnx_write32(ctl, AGNX_TXM_MAXCCACNTSLOT, reg);
345
346 /* Slot limit/1 msec Limit */
347 reg = agnx_read32(ctl, AGNX_TXM_SLOTLIMIT);
348 reg &= 0xff00ffff;
349 reg |= 0x140077;
350 agnx_write32(ctl, AGNX_TXM_SLOTLIMIT, reg);
351
352 /* # Set CW #(0-7) to default */
353 agnx_write32(ctl, AGNX_TXM_CW0, 0xff0007);
354 agnx_write32(ctl, AGNX_TXM_CW1, 0xff0007);
355 agnx_write32(ctl, AGNX_TXM_CW2, 0xff0007);
356 agnx_write32(ctl, AGNX_TXM_CW3, 0xff0007);
357 agnx_write32(ctl, AGNX_TXM_CW4, 0xff0007);
358 agnx_write32(ctl, AGNX_TXM_CW5, 0xff0007);
359 agnx_write32(ctl, AGNX_TXM_CW6, 0xff0007);
360 agnx_write32(ctl, AGNX_TXM_CW7, 0xff0007);
361
362 /* # Set Short/Long limit #(0-7) to default */
363 agnx_write32(ctl, AGNX_TXM_SLBEALIM0, 0xa000a);
364 agnx_write32(ctl, AGNX_TXM_SLBEALIM1, 0xa000a);
365 agnx_write32(ctl, AGNX_TXM_SLBEALIM2, 0xa000a);
366 agnx_write32(ctl, AGNX_TXM_SLBEALIM3, 0xa000a);
367 agnx_write32(ctl, AGNX_TXM_SLBEALIM4, 0xa000a);
368 agnx_write32(ctl, AGNX_TXM_SLBEALIM5, 0xa000a);
369 agnx_write32(ctl, AGNX_TXM_SLBEALIM6, 0xa000a);
370 agnx_write32(ctl, AGNX_TXM_SLBEALIM7, 0xa000a);
371
372 reg = agnx_read32(ctl, AGNX_TXM_CTL);
373 reg |= 0x1400;
374 agnx_write32(ctl, AGNX_TXM_CTL, reg);
375 /* Wait for bit 0 in Control Reg to clear */
376 udelay(80);
377 reg = agnx_read32(ctl, AGNX_TXM_CTL);
378 /* Or 0x18000 to Control reg */
379 reg = agnx_read32(ctl, AGNX_TXM_CTL);
380 reg |= 0x18000;
381 agnx_write32(ctl, AGNX_TXM_CTL, reg);
382 /* Wait for bit 0 in Control Reg to clear */
383 udelay(80);
384 reg = agnx_read32(ctl, AGNX_TXM_CTL);
385
386 /* Set Listen Interval Count to default */
387 agnx_write32(ctl, AGNX_TXM_LISINTERCNT, 0x1);
388 /* Set DTIM period count to default */
389 agnx_write32(ctl, AGNX_TXM_DTIMPERICNT, 0x2000);
390} /* tx_management_init */
391
392static void rx_management_init(struct agnx_priv *priv)
393{
394 void __iomem *ctl = priv->ctl;
395 AGNX_TRACE;
396
397 /* Initialize the Routing Table */
398 routing_table_init(priv);
399
400 if (priv->revid >= 3) {
401 agnx_write32(ctl, 0x2074, 0x1f171710);
402 agnx_write32(ctl, 0x2078, 0x10100d0d);
403 agnx_write32(ctl, 0x207c, 0x11111010);
404 } else {
405 agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0);
406 }
407 agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00);
408}
409
410
411static void agnx_timer_init(struct agnx_priv *priv)
412{
413 void __iomem *ctl = priv->ctl;
414 AGNX_TRACE;
415
416/* /\* Write 0x249f00 (tick duration?) to Timer 1 *\/ */
417/* agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x249f00); */
418/* /\* Write 0xe2 to Timer 1 Control *\/ */
419/* agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0xe2); */
420
421 /* Write 0x249f00 (tick duration?) to Timer 1 */
422 agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x0);
423 /* Write 0xe2 to Timer 1 Control */
424 agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0x0);
425
426 iowrite32(0xFFFFFFFF, priv->ctl + AGNX_TXM_BEACON_CTL);
427}
428
429static void power_manage_init(struct agnx_priv *priv)
430{
431 void __iomem *ctl = priv->ctl;
432 u32 reg;
433 AGNX_TRACE;
434
435 agnx_write32(ctl, AGNX_PM_MACMSW, 0x1f);
436 agnx_write32(ctl, AGNX_PM_RFCTL, 0x1f);
437
438 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
439 reg &= 0xf00f;
440 reg |= 0xa0;
441 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
442
443 if (priv->revid >= 3) {
444 reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
445 reg |= 0x18;
446 agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
447 }
448} /* power_manage_init */
449
450
451static void gain_ctlcnt_init(struct agnx_priv *priv)
452{
453 void __iomem *ctl = priv->ctl;
454 u32 reg;
455 AGNX_TRACE;
456
457 agnx_write32(ctl, AGNX_GCR_TRACNT5, 0x119);
458 agnx_write32(ctl, AGNX_GCR_TRACNT6, 0x118);
459 agnx_write32(ctl, AGNX_GCR_TRACNT7, 0x117);
460
461 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
462 reg |= 0x8;
463 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
464
465 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
466 reg &= ~0x8;
467 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
468
469 agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);
470
471 /* FIXME Write the initial Station Descriptor for the card */
472 sta_init(priv, LOCAL_STAID);
473 sta_init(priv, BSSID_STAID);
474
475 /* Enable staion 0 and 1 can do TX */
476 /* It seemed if we set other bit to 1 the bit 0 will
477 be auto change to 0 */
478 agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1);
479/* agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1); */
480} /* gain_ctlcnt_init */
481
482
483static void phy_init(struct agnx_priv *priv)
484{
485 void __iomem *ctl = priv->ctl;
486 void __iomem *data = priv->data;
487 u32 reg;
488 AGNX_TRACE;
489
490 /* Load InitialGainTable */
491 gain_table_init(priv);
492
493 agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000);
494
495 /* Clear the following offsets in Memory Range #2: */
496 memset_io(data + 0x5040, 0, 0xa * 4);
497 memset_io(data + 0x5080, 0, 0xa * 4);
498 memset_io(data + 0x50c0, 0, 0xa * 4);
499 memset_io(data + 0x5400, 0, 0x80 * 4);
500 memset_io(data + 0x6000, 0, 0x280 * 4);
501 memset_io(data + 0x7000, 0, 0x280 * 4);
502 memset_io(data + 0x8000, 0, 0x280 * 4);
503
504 /* Initialize the Following Registers According to PCI Revision ID */
505 if (priv->revid == 0) {
506 /* fixme the part hasn't been update but below has been update
507 based on WGM511 */
508 agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
509 agnx_write32(ctl, AGNX_ACI_TIMER1, 0x1d);
510 agnx_write32(ctl, AGNX_ACI_TIMER2, 0x3);
511 agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11);
512 agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0);
513 agnx_write32(ctl, AGNX_GCR_THD0A, 0x64);
514 agnx_write32(ctl, AGNX_GCR_THD0AL, 0x4b);
515 agnx_write32(ctl, AGNX_GCR_THD0B, 0x4b);
516 agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14);
517 agnx_write32(ctl, AGNX_GCR_DSAT, 0x24);
518 agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8);
519 agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a);
520 agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3);
521 agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd);
522 agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1);
523 agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7);
524 agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28);
525 agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
526 reg = agnx_read32(ctl, AGNX_GCR_CWDETEC);
527 reg |= 0x1;
528 agnx_write32(ctl, AGNX_GCR_CWDETEC, reg);
529 agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
530 agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);
531 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
532 agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3);
533 agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3);
534 agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3);
535 agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3);
536 agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x0);
537 agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x0);
538 agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x0);
539 agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x0);
540 agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10);
541 agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1);
542 agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0x1);
543 agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190);
544 agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x78);
545 agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x1c);
546 agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0);
547 agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
548 agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x1);
549 agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0);
550 agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f);
551 agnx_write32(ctl, AGNX_GCR_THJUMP, 0x14);
552 agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0);
553 agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x30);
554 agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x32);
555 agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19);
556 agnx_write32(ctl, AGNX_GCR_0X14c, 0x0);
557 agnx_write32(ctl, AGNX_GCR_0X150, 0x0);
558 agnx_write32(ctl, 0x9400, 0x0);
559 agnx_write32(ctl, 0x940c, 0x6ff);
560 agnx_write32(ctl, 0x9428, 0xa0);
561 agnx_write32(ctl, 0x9434, 0x0);
562 agnx_write32(ctl, 0x9c04, 0x15);
563 agnx_write32(ctl, 0x9c0c, 0x7f);
564 agnx_write32(ctl, 0x9c34, 0x0);
565 agnx_write32(ctl, 0xc000, 0x38d);
566 agnx_write32(ctl, 0x14018, 0x0);
567 agnx_write32(ctl, 0x16000, 0x1);
568 agnx_write32(ctl, 0x11004, 0x0);
569 agnx_write32(ctl, 0xec54, 0xa);
570 agnx_write32(ctl, 0xec1c, 0x5);
571 } else if (priv->revid > 0) {
572 agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
573 agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
574 agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
575 agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11);
576 agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0);
577 agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14);
578 agnx_write32(ctl, AGNX_GCR_DSAT, 0x24);
579 agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8);
580 agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a);
581 agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3);
582 agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd);
583 agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1);
584 agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7);
585 agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28);
586 agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
587 agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0);
588 agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
589/* agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);*/
590 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
591
592 agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x32);
593 agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x32);
594 agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x32);
595 agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x32);
596 agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10);
597 agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1ad);
598 agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0xa10);
599 agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190);
600 agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0);
601 agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
602 agnx_write32(ctl, AGNX_GCR_THCS, 0x0);
603 agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x4);
604 agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0);
605 agnx_write32(ctl, AGNX_GCR_THJUMP, 0x1e);
606 agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0);
607 agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x2a);
608 agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c);
609 agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19);
610 agnx_write32(ctl, AGNX_GCR_0X14c, 0x0);
611 agnx_write32(ctl, AGNX_GCR_0X150, 0x0);
612 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
613 agnx_write32(ctl, AGNX_GCR_WATCHDOG, 0x37);
614 agnx_write32(ctl, 0x9400, 0x0);
615 agnx_write32(ctl, 0x940c, 0x6ff);
616 agnx_write32(ctl, 0x9428, 0xa0);
617 agnx_write32(ctl, 0x9434, 0x0);
618 agnx_write32(ctl, 0x9c04, 0x15);
619 agnx_write32(ctl, 0x9c0c, 0x7f);
620 agnx_write32(ctl, 0x9c34, 0x0);
621 agnx_write32(ctl, 0xc000, 0x38d);
622 agnx_write32(ctl, 0x14014, 0x1000);
623 agnx_write32(ctl, 0x14018, 0x0);
624 agnx_write32(ctl, 0x16000, 0x1);
625 agnx_write32(ctl, 0x11004, 0x0);
626 agnx_write32(ctl, 0xec54, 0xa);
627 agnx_write32(ctl, 0xec1c, 0x50);
628 } else if (priv->revid > 1) {
629 reg = agnx_read32(ctl, 0xec18);
630 reg |= 0x8;
631 agnx_write32(ctl, 0xec18, reg);
632 }
633
634 /* Write the TX Fir Coefficient Table */
635 tx_fir_table_init(priv);
636
637 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
638 reg &= ~0x8;
639 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
640 reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
641 reg |= 0x1;
642 agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
643
644/* reg = agnx_read32(ctl, 0x1a030); */
645/* reg &= ~0x4; */
646/* agnx_write32(ctl, 0x1a030, reg); */
647
648 agnx_write32(ctl, AGNX_GCR_TRACNT4, 0x113);
649} /* phy_init */
650
651static void chip_init(struct agnx_priv *priv)
652{
653 void __iomem *ctl = priv->ctl;
654 u32 reg;
655 AGNX_TRACE;
656
657 band_management_init(priv);
658
659 rf_chips_init(priv);
660
661 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
662 reg |= 0x8;
663 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
664
665 /* Initialize the PHY */
666 phy_init(priv);
667
668 encryption_init(priv);
669
670 tx_management_init(priv);
671
672 rx_management_init(priv);
673
674 power_manage_init(priv);
675
676 /* Initialize the Timers */
677 agnx_timer_init(priv);
678
679 /* Write 0xc390bf9 to Interrupt Mask (Disable TX) */
680 reg = 0xc390bf9 & ~IRQ_TX_BEACON;
681 reg &= ~IRQ_TX_DISABLE;
682 agnx_write32(ctl, AGNX_INT_MASK, reg);
683
684 reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
685 reg |= 0x800;
686 agnx_write32(ctl, AGNX_CIR_BLKCTL, reg);
687
688 /* set it when need get multicast enable? */
689 agnx_write32(ctl, AGNX_BM_MTSM, 0xff);
690} /* chip_init */
691
692
693static inline void set_promis_and_managed(struct agnx_priv *priv)
694{
695 void __iomem *ctl = priv->ctl;
696 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2);
697 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2);
698}
699static inline void set_learn_mode(struct agnx_priv *priv)
700{
701 void __iomem *ctl = priv->ctl;
702 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x8);
703}
704static inline void set_scan_mode(struct agnx_priv *priv)
705{
706 void __iomem *ctl = priv->ctl;
707 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x20);
708}
709static inline void set_promiscuous_mode(struct agnx_priv *priv)
710{
711 void __iomem *ctl = priv->ctl;
712 /* agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x210);*/
713 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10);
714}
715static inline void set_managed_mode(struct agnx_priv *priv)
716{
717 void __iomem *ctl = priv->ctl;
718 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x2);
719}
720static inline void set_adhoc_mode(struct agnx_priv *priv)
721{
722 void __iomem *ctl = priv->ctl;
723 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x0);
724}
725
726#if 0
727static void unknow_register_write(struct agnx_priv *priv)
728{
729 void __iomem *ctl = priv->ctl;
730
731 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x0, 0x3e);
732 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4, 0xb2);
733 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x8, 0x140);
734 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0xc, 0x1C0);
735 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x10, 0x1FF);
736 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x14, 0x1DD);
737 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x18, 0x15F);
738 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x1c, 0xA1);
739 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x20, 0x3E7);
740 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x24, 0x36B);
741 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x28, 0x348);
742 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x2c, 0x37D);
743 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x30, 0x3DE);
744 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x34, 0x36);
745 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x38, 0x64);
746 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x3c, 0x57);
747 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x40, 0x23);
748 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x44, 0x3ED);
749 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x48, 0x3C9);
750 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4c, 0x3CA);
751 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x50, 0x3E7);
752 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x54, 0x8);
753 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x58, 0x1F);
754 agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x5c, 0x1a);
755}
756#endif
757
758static void card_interface_init(struct agnx_priv *priv)
759{
760 void __iomem *ctl = priv->ctl;
761 u8 bssid[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
762 u32 reg;
763 unsigned int i;
764 AGNX_TRACE;
765
766 might_sleep();
767 /* Clear RX Control and Enable RX queues */
768 agnx_write32(ctl, AGNX_CIR_RXCTL, 0x8);
769
770 might_sleep();
771 /* Do a full reset of the card */
772 card_full_reset(priv);
773 might_sleep();
774
775 /* Check and set Card Endianness */
776 reg = ioread32(priv->ctl + AGNX_CIR_ENDIAN);
777 /* TODO If not 0xB3B2B1B0 set to 0xB3B2B1B0 */
778 printk(KERN_INFO PFX "CIR_ENDIAN is %x\n", reg);
779
780
781 /* Config the eeprom */
782 agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x7000086);
783 udelay(10);
784 reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
785
786
787 agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033);
788 reg = agnx_read32(ctl, 0xec50);
789 reg |= 0xf;
790 agnx_write32(ctl, 0xec50, reg);
791 agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
792
793
794 reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);
795 udelay(10);
796 reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
797
798 /* Dump the eeprom */
799 do {
800 char eeprom[0x100000/0x100];
801
802 for (i = 0; i < 0x100000; i += 0x100) {
803 agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x3000000 + i);
804 udelay(13);
805 reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
806 udelay(70);
807 reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
808 eeprom[i/0x100] = reg & 0xFF;
809 udelay(10);
810 }
811 print_hex_dump_bytes(PFX "EEPROM: ", DUMP_PREFIX_NONE, eeprom,
812 ARRAY_SIZE(eeprom));
813 } while (0);
814
815 spi_rc_write(ctl, RF_CHIP0, 0x26);
816 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
817
818 /* Initialize the system interface */
819 system_itf_init(priv);
820
821 might_sleep();
822 /* Chip Initialization (Polaris) */
823 chip_init(priv);
824 might_sleep();
825
826 /* Calibrate the antennae */
827 antenna_calibrate(priv);
828
829 reg = agnx_read32(ctl, 0xec50);
830 reg &= ~0x40;
831 agnx_write32(ctl, 0xec50, reg);
832 agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
833 agnx_write32(ctl, AGNX_PM_PLLCTL, 0x1);
834
835 reg = agnx_read32(ctl, AGNX_BM_BMCTL);
836 reg |= 0x8000;
837 agnx_write32(ctl, AGNX_BM_BMCTL, reg);
838 enable_receiver(priv);
839 reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);
840 reg |= 0x200;
841 agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);
842 enable_receiver(priv);
843
844 might_sleep();
845 /* Initialize Gain Control Counts */
846 gain_ctlcnt_init(priv);
847
848 /* Write Initial Station Power Template for this station(#0) */
849 sta_power_init(priv, LOCAL_STAID);
850
851 might_sleep();
852 /* Initialize the rx,td,tm rings, for each node in the ring */
853 fill_rings(priv);
854
855 might_sleep();
856
857
858 agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033);
859 agnx_write32(ctl, 0xec50, 0xc);
860 agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
861
862 /* FIXME Initialize the transmit control register */
863 agnx_write32(ctl, AGNX_TXM_CTL, 0x194c1);
864
865 enable_receiver(priv);
866
867 might_sleep();
868 /* FIXME Set the Receive Control Mac Address to card address */
869 mac_address_set(priv);
870 enable_receiver(priv);
871 might_sleep();
872
873 /* Set the recieve request rate */
874 /* FIXME Enable the request */
875 /* Check packet length */
876 /* Set maximum packet length */
877/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
878/* enable_receiver(priv); */
879
880 /* Set the Receiver BSSID */
881 receiver_bssid_set(priv, bssid);
882
883 /* FIXME Set to managed mode */
884 set_managed_mode(priv);
885/* set_promiscuous_mode(priv); */
886/* set_scan_mode(priv); */
887/* set_learn_mode(priv); */
888/* set_promis_and_managed(priv); */
889/* set_adhoc_mode(priv); */
890
891 /* Set the recieve request rate */
892 /* Check packet length */
893 agnx_write32(ctl, AGNX_RXM_REQRATE, 0x08000000);
894 reg = agnx_read32(ctl, AGNX_RXM_REQRATE);
895 /* Set maximum packet length */
896 reg |= 0x00195e00;
897 agnx_write32(ctl, AGNX_RXM_REQRATE, reg);
898
899 /* Configure the RX and TX interrupt */
900 reg = ENABLE_RX_INTERRUPT | RX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE;
901 agnx_write32(ctl, AGNX_CIR_RXCFG, reg);
902 /* FIXME */
903 reg = ENABLE_TX_INTERRUPT | TX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE;
904 agnx_write32(ctl, AGNX_CIR_TXCFG, reg);
905
906 /* Enable RX TX Interrupts */
907 agnx_write32(ctl, AGNX_CIR_RXCTL, 0x80);
908 agnx_write32(ctl, AGNX_CIR_TXMCTL, 0x80);
909 agnx_write32(ctl, AGNX_CIR_TXDCTL, 0x80);
910
911 /* FIXME Set the master control interrupt in block control */
912 agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x800);
913
914 /* Enable RX and TX queues */
915 reg = agnx_read32(ctl, AGNX_CIR_RXCTL);
916 reg |= 0x8;
917 agnx_write32(ctl, AGNX_CIR_RXCTL, reg);
918 reg = agnx_read32(ctl, AGNX_CIR_TXMCTL);
919 reg |= 0x8;
920 agnx_write32(ctl, AGNX_CIR_TXMCTL, reg);
921 reg = agnx_read32(ctl, AGNX_CIR_TXDCTL);
922 reg |= 0x8;
923 agnx_write32(ctl, AGNX_CIR_TXDCTL, reg);
924
925 agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
926 /* FIXME */
927 /* unknow_register_write(priv); */
928 /* Update local card hash entry */
929 hash_write(priv, priv->mac_addr, LOCAL_STAID);
930
931 might_sleep();
932
933 /* FIXME */
934 agnx_set_channel(priv, 1);
935 might_sleep();
936} /* agnx_card_interface_init */
937
938
939void agnx_hw_init(struct agnx_priv *priv)
940{
941 AGNX_TRACE;
942 might_sleep();
943 card_interface_init(priv);
944}
945
946int agnx_hw_reset(struct agnx_priv *priv)
947{
948 return card_full_reset(priv);
949}
950
951int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len)
952{
953 AGNX_TRACE;
954 return 0;
955}
956
957void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid)
958{
959 receiver_bssid_set(priv, bssid);
960}
diff --git a/drivers/staging/agnx/phy.h b/drivers/staging/agnx/phy.h
deleted file mode 100644
index a955f05361e7..000000000000
--- a/drivers/staging/agnx/phy.h
+++ /dev/null
@@ -1,409 +0,0 @@
1#ifndef AGNX_PHY_H_
2#define AGNX_PHY_H_
3
4#include "agnx.h"
5
6/* Transmission Managment Registers */
7#define AGNX_TXM_BASE 0x0000
8#define AGNX_TXM_CTL 0x0000 /* control register */
9#define AGNX_TXM_ETMF 0x0004 /* enable transmission management functions */
10#define AGNX_TXM_TXTEMP 0x0008 /* transmission template */
11#define AGNX_TXM_RETRYSTAID 0x000c /* Retry Station ID */
12#define AGNX_TXM_TIMESTAMPLO 0x0010 /* Timestamp Lo */
13#define AGNX_TXM_TIMESTAMPHI 0x0014 /* Timestamp Hi */
14#define AGNX_TXM_TXDELAY 0x0018 /* tx delay */
15#define AGNX_TXM_TBTTLO 0x0020 /* tbtt Lo */
16#define AGNX_TXM_TBTTHI 0x0024 /* tbtt Hi */
17#define AGNX_TXM_BEAINTER 0x0028 /* Beacon Interval */
18#define AGNX_TXM_NAV 0x0030 /* NAV */
19#define AGNX_TXM_CFPMDV 0x0034 /* CFP MDV */
20#define AGNX_TXM_CFPERCNT 0x0038 /* CFP period count */
21#define AGNX_TXM_PROBDELAY 0x003c /* probe delay */
22#define AGNX_TXM_LISINTERCNT 0x0040 /* listen interval count */
23#define AGNX_TXM_DTIMPERICNT 0x004c /* DTIM period count */
24
25#define AGNX_TXM_BEACON_CTL 0x005c /* beacon control */
26
27#define AGNX_TXM_SCHEMPCNT 0x007c /* schedule empty count */
28#define AGNX_TXM_MAXTIMOUT 0x0084 /* max timeout exceed count */
29#define AGNX_TXM_MAXCFPTIM 0x0088 /* max CF poll timeout count */
30#define AGNX_TXM_MAXRXTIME 0x008c /* max RX timeout count */
31#define AGNX_TXM_MAXACKTIM 0x0090 /* max ACK timeout count */
32#define AGNX_TXM_DIF01 0x00a0 /* DIF 0-1 */
33#define AGNX_TXM_DIF23 0x00a4 /* DIF 2-3 */
34#define AGNX_TXM_DIF45 0x00a8 /* DIF 4-5 */
35#define AGNX_TXM_DIF67 0x00ac /* DIF 6-7 */
36#define AGNX_TXM_SIFSPIFS 0x00b0 /* SIFS/PIFS */
37#define AGNX_TXM_TIFSEIFS 0x00b4 /* TIFS/EIFS */
38#define AGNX_TXM_MAXCCACNTSLOT 0x00b8 /* max CCA count slot */
39#define AGNX_TXM_SLOTLIMIT 0x00bc /* slot limit/1 msec limit */
40#define AGNX_TXM_CFPOLLRXTIM 0x00f0 /* CF poll RX timeout count */
41#define AGNX_TXM_CFACKT11B 0x00f4 /* CF ack timeout limit for 11b */
42#define AGNX_TXM_CW0 0x0100 /* CW 0 */
43#define AGNX_TXM_SLBEALIM0 0x0108 /* short/long beacon limit 0 */
44#define AGNX_TXM_CW1 0x0120 /* CW 1 */
45#define AGNX_TXM_SLBEALIM1 0x0128 /* short/long beacon limit 1 */
46#define AGNX_TXM_CW2 0x0140 /* CW 2 */
47#define AGNX_TXM_SLBEALIM2 0x0148 /* short/long beacon limit 2 */
48#define AGNX_TXM_CW3 0x0160 /* CW 3 */
49#define AGNX_TXM_SLBEALIM3 0x0168 /* short/long beacon limit 3 */
50#define AGNX_TXM_CW4 0x0180 /* CW 4 */
51#define AGNX_TXM_SLBEALIM4 0x0188 /* short/long beacon limit 4 */
52#define AGNX_TXM_CW5 0x01a0 /* CW 5 */
53#define AGNX_TXM_SLBEALIM5 0x01a8 /* short/long beacon limit 5 */
54#define AGNX_TXM_CW6 0x01c0 /* CW 6 */
55#define AGNX_TXM_SLBEALIM6 0x01c8 /* short/long beacon limit 6 */
56#define AGNX_TXM_CW7 0x01e0 /* CW 7 */
57#define AGNX_TXM_SLBEALIM7 0x01e8 /* short/long beacon limit 7 */
58#define AGNX_TXM_BEACONTEMP 0x1000 /* beacon template */
59#define AGNX_TXM_STAPOWTEMP 0x1a00 /* Station Power Template */
60
61/* Receive Management Control Registers */
62#define AGNX_RXM_BASE 0x2000
63#define AGNX_RXM_REQRATE 0x2000 /* requested rate */
64#define AGNX_RXM_MACHI 0x2004 /* first 4 bytes of mac address */
65#define AGNX_RXM_MACLO 0x2008 /* last 2 bytes of mac address */
66#define AGNX_RXM_BSSIDHI 0x200c /* bssid hi */
67#define AGNX_RXM_BSSIDLO 0x2010 /* bssid lo */
68#define AGNX_RXM_HASH_CMD_FLAG 0x2014 /* Flags for the RX Hash Command Default:0 */
69#define AGNX_RXM_HASH_CMD_HIGH 0x2018 /* The High half of the Hash Command */
70#define AGNX_RXM_HASH_CMD_LOW 0x201c /* The Low half of the Hash Command */
71#define AGNX_RXM_ROUTAB 0x2020 /* routing table */
72#define ROUTAB_SUBTYPE_SHIFT 24
73#define ROUTAB_TYPE_SHIFT 28
74#define ROUTAB_STATUS_SHIFT 30
75#define ROUTAB_RW_SHIFT 31
76#define ROUTAB_ROUTE_DROP 0xf00000 /* Drop */
77#define ROUTAB_ROUTE_CPU 0x400000 /* CPU */
78#define ROUTAB_ROUTE_ENCRY 0x500800 /* Encryption */
79#define ROUTAB_ROUTE_RFP 0x800000 /* RFP */
80
81#define ROUTAB_TYPE_MANAG 0x0 /* Management */
82#define ROUTAB_TYPE_CTL 0x1 /* Control */
83#define ROUTAB_TYPE_DATA 0x2 /* Data */
84
85#define ROUTAB_SUBTYPE_DATA 0x0
86#define ROUTAB_SUBTYPE_DATAACK 0x1
87#define ROUTAB_SUBTYPE_DATAPOLL 0x2
88#define ROUTAB_SUBTYPE_DATAPOLLACK 0x3
89#define ROUTAB_SUBTYPE_NULL 0x4 /* NULL */
90#define ROUTAB_SUBTYPE_NULLACK 0x5
91#define ROUTAB_SUBTYPE_NULLPOLL 0x6
92#define ROUTAB_SUBTYPE_NULLPOLLACK 0x7
93#define ROUTAB_SUBTYPE_QOSDATA 0x8 /* QOS DATA */
94#define ROUTAB_SUBTYPE_QOSDATAACK 0x9
95#define ROUTAB_SUBTYPE_QOSDATAPOLL 0xa
96#define ROUTAB_SUBTYPE_QOSDATAACKPOLL 0xb
97#define ROUTAB_SUBTYPE_QOSNULL 0xc
98#define ROUTAB_SUBTYPE_QOSNULLACK 0xd
99#define ROUTAB_SUBTYPE_QOSNULLPOLL 0xe
100#define ROUTAB_SUBTYPE_QOSNULLPOLLACK 0xf
101#define AGNX_RXM_DELAY11 0x2024 /* delay 11(AB) */
102#define AGNX_RXM_SOF_CNT 0x2028 /* SOF Count */
103#define AGNX_RXM_FRAG_CNT 0x202c /* Fragment Count*/
104#define AGNX_RXM_FCS_CNT 0x2030 /* FCS Count */
105#define AGNX_RXM_BSSID_MISS_CNT 0x2034 /* BSSID Miss Count */
106#define AGNX_RXM_PDU_ERR_CNT 0x2038 /* PDU Error Count */
107#define AGNX_RXM_DEST_MISS_CNT 0x203C /* Destination Miss Count */
108#define AGNX_RXM_DROP_CNT 0x2040 /* Drop Count */
109#define AGNX_RXM_ABORT_CNT 0x2044 /* Abort Count */
110#define AGNX_RXM_RELAY_CNT 0x2048 /* Relay Count */
111#define AGNX_RXM_HASH_MISS_CNT 0x204c /* Hash Miss Count */
112#define AGNX_RXM_SA_HI 0x2050 /* Address of received packet Hi */
113#define AGNX_RXM_SA_LO 0x2054 /* Address of received packet Lo */
114#define AGNX_RXM_HASH_DUMP_LST 0x2100 /* Contains Hash Data */
115#define AGNX_RXM_HASH_DUMP_MST 0x2104 /* Contains Hash Data */
116#define AGNX_RXM_HASH_DUMP_DATA 0x2108 /* The Station ID to dump */
117
118
119/* Encryption Managment */
120#define AGNX_ENCRY_BASE 0x2400
121#define AGNX_ENCRY_WEPKEY0 0x2440 /* wep key #0 */
122#define AGNX_ENCRY_WEPKEY1 0x2444 /* wep key #1 */
123#define AGNX_ENCRY_WEPKEY2 0x2448 /* wep key #2 */
124#define AGNX_ENCRY_WEPKEY3 0x244c /* wep key #3 */
125#define AGNX_ENCRY_CCMRECTL 0x2460 /* ccm replay control */
126
127
128/* Band Management Registers */
129#define AGNX_BM_BASE 0x2c00
130#define AGNX_BM_BMCTL 0x2c00 /* band management control */
131#define AGNX_BM_TXWADDR 0x2c18 /* tx workqueue address start */
132#define AGNX_BM_TXTOPEER 0x2c24 /* transmit to peers */
133#define AGNX_BM_FPLHP 0x2c2c /* free pool list head pointer */
134#define AGNX_BM_FPLTP 0x2c30 /* free pool list tail pointer */
135#define AGNX_BM_FPCNT 0x2c34 /* free pool count */
136#define AGNX_BM_CIPDUWCNT 0x2c38 /* card interface pdu workqueue count */
137#define AGNX_BM_SPPDUWCNT 0x2c3c /* sp pdu workqueue count */
138#define AGNX_BM_RFPPDUWCNT 0x2c40 /* rfp pdu workqueue count */
139#define AGNX_BM_RHPPDUWCNT 0x2c44 /* rhp pdu workqueue count */
140#define AGNX_BM_CIWQCTL 0x2c48 /* Card Interface WorkQueue Control */
141#define AGNX_BM_CPUTXWCTL 0x2c50 /* cpu tx workqueue control */
142#define AGNX_BM_CPURXWCTL 0x2c58 /* cpu rx workqueue control */
143#define AGNX_BM_CPULWCTL 0x2c60 /* cpu low workqueue control */
144#define AGNX_BM_CPUHWCTL 0x2c68 /* cpu high workqueue control */
145#define AGNX_BM_SPTXWCTL 0x2c70 /* sp tx workqueue control */
146#define AGNX_BM_SPRXWCTL 0x2c78 /* sp rx workqueue control */
147#define AGNX_BM_RFPWCTL 0x2c80 /* RFP workqueue control */
148#define AGNX_BM_MTSM 0x2c90 /* Multicast Transmit Station Mask */
149
150/* Card Interface Registers (32bits) */
151#define AGNX_CIR_BASE 0x3000
152#define AGNX_CIR_BLKCTL 0x3000 /* block control*/
153#define AGNX_STAT_TX 0x1
154#define AGNX_STAT_RX 0x2
155#define AGNX_STAT_X 0x4
156/* Below two interrupt flags will be set by our but not CPU or the card */
157#define AGNX_STAT_TXD 0x10
158#define AGNX_STAT_TXM 0x20
159
160#define AGNX_CIR_ADDRWIN 0x3004 /* Addressable Windows*/
161#define AGNX_CIR_ENDIAN 0x3008 /* card endianness */
162#define AGNX_CIR_SERIALITF 0x3020 /* serial interface */
163#define AGNX_CIR_RXCFG 0x3040 /* receive config */
164#define ENABLE_RX_INTERRUPT 0x20
165#define RX_CACHE_LINE 0x8
166/* the RX fragment length */
167#define FRAG_LEN_256 0x0 /* 256B */
168#define FRAG_LEN_512 0x1
169#define FRAG_LEN_1024 0x2
170#define FRAG_LEN_2048 0x3
171#define FRAG_BE 0x10
172#define AGNX_CIR_RXCTL 0x3050 /* receive control */
173/* memory address, chipside */
174#define AGNX_CIR_RXCMSTART 0x3054 /* receive client memory start */
175#define AGNX_CIR_RXCMEND 0x3058 /* receive client memory end */
176/* memory address, pci */
177#define AGNX_CIR_RXHOSTADDR 0x3060 /* receive hostside address */
178/* memory address, chipside */
179#define AGNX_CIR_RXCLIADDR 0x3064 /* receive clientside address */
180#define AGNX_CIR_RXDMACTL 0x3068 /* receive dma control */
181#define AGNX_CIR_TXCFG 0x3080 /* transmit config */
182#define AGNX_CIR_TXMCTL 0x3090 /* Transmit Management Control */
183#define ENABLE_TX_INTERRUPT 0x20
184#define TX_CACHE_LINE 0x8
185#define AGNX_CIR_TXMSTART 0x3094 /* Transmit Management Start */
186#define AGNX_CIR_TXMEND 0x3098 /* Transmit Management End */
187#define AGNX_CIR_TXDCTL 0x30a0 /* transmit data control */
188/* memeory address, chipset */
189#define AGNX_CIR_TXDSTART 0x30a4 /* transmit data start */
190#define AGNX_CIR_TXDEND 0x30a8 /* transmit data end */
191#define AGNX_CIR_TXMHADDR 0x30b0 /* Transmit Management Hostside Address */
192#define AGNX_CIR_TXMCADDR 0x30b4 /* Transmit Management Clientside Address */
193#define AGNX_CIR_TXDMACTL 0x30b8 /* transmit dma control */
194
195
196/* Power Managment Unit */
197#define AGNX_PM_BASE 0x3c00
198#define AGNX_PM_PMCTL 0x3c00 /* PM Control*/
199#define AGNX_PM_MACMSW 0x3c08 /* MAC Manual Slow Work Enable */
200#define AGNX_PM_RFCTL 0x3c0c /* RF Control */
201#define AGNX_PM_PHYMW 0x3c14 /* Phy Mannal Work */
202#define AGNX_PM_SOFTRST 0x3c18 /* PMU Soft Reset */
203#define AGNX_PM_PLLCTL 0x3c1c /* PMU PLL control*/
204#define AGNX_PM_TESTPHY 0x3c24 /* PMU Test Phy */
205
206
207/* Interrupt Control interface */
208#define AGNX_INT_BASE 0x4000
209#define AGNX_INT_STAT 0x4000 /* interrupt status */
210#define AGNX_INT_MASK 0x400c /* interrupt mask */
211/* FIXME */
212#define IRQ_TX_BEACON 0x1 /* TX Beacon */
213#define IRQ_TX_RETRY 0x8 /* TX Retry Interrupt */
214#define IRQ_TX_ACTIVITY 0x10 /* TX Activity */
215#define IRQ_RX_ACTIVITY 0x20 /* RX Activity */
216/* FIXME I guess that instead RX a none exist staion's packet or
217 the station hasn't been init */
218#define IRQ_RX_X 0x40
219#define IRQ_RX_Y 0x80 /* RX ? */
220#define IRQ_RX_HASHHIT 0x100 /* RX Hash Hit */
221#define IRQ_RX_FRAME 0x200 /* RX Frame */
222#define IRQ_ERR_INT 0x400 /* Error Interrupt */
223#define IRQ_TX_QUE_FULL 0x800 /* TX Workqueue Full */
224#define IRQ_BANDMAN_ERR 0x10000 /* Bandwidth Management Error */
225#define IRQ_TX_DISABLE 0x20000 /* TX Disable */
226#define IRQ_RX_IVASESKEY 0x80000 /* RX Invalid Session Key */
227#define IRQ_RX_KEYIDMIS 0x100000 /* RX key ID Mismatch */
228#define IRQ_REP_THHIT 0x200000 /* Replay Threshold Hit */
229#define IRQ_TIMER1 0x4000000 /* Timer1 */
230#define IRQ_TIMER_CNT 0x10000000 /* Timer Count */
231#define IRQ_PHY_FASTINT 0x20000000 /* Phy Fast Interrupt */
232#define IRQ_PHY_SLOWINT 0x40000000 /* Phy Slow Interrupt */
233#define IRQ_OTHER 0x80000000 /* Unknow interrupt */
234#define AGNX_IRQ_ALL 0xffffffff
235
236/* System Interface */
237#define AGNX_SYSITF_BASE 0x4400
238#define AGNX_SYSITF_SYSMODE 0x4400 /* system mode */
239#define AGNX_SYSITF_GPIOIN 0x4410 /* GPIO In */
240/* PIN lines for leds? */
241#define AGNX_SYSITF_GPIOUT 0x4414 /* GPIO Out */
242
243/* Timer Control */
244#define AGNX_TIMCTL_TIMER1 0x4800 /* Timer 1 */
245#define AGNX_TIMCTL_TIM1CTL 0x4808 /* Timer 1 Control */
246
247
248/* Antenna Calibration Interface */
249#define AGNX_ACI_BASE 0x5000
250#define AGNX_ACI_MODE 0x5000 /* Mode */
251#define AGNX_ACI_MEASURE 0x5004 /* Measure */
252#define AGNX_ACI_SELCHAIN 0x5008 /* Select Chain */
253#define AGNX_ACI_LEN 0x500c /* Length */
254#define AGNX_ACI_TIMER1 0x5018 /* Timer 1 */
255#define AGNX_ACI_TIMER2 0x501c /* Timer 2 */
256#define AGNX_ACI_OFFSET 0x5020 /* Offset */
257#define AGNX_ACI_STATUS 0x5030 /* Status */
258#define CALI_IDLE 0x0
259#define CALI_DONE 0x1
260#define CALI_BUSY 0x2
261#define CALI_ERR 0x3
262#define AGNX_ACI_AICCHA0OVE 0x5034 /* AIC Channel 0 Override */
263#define AGNX_ACI_AICCHA1OVE 0x5038 /* AIC Channel 1 Override */
264
265/* Gain Control Registers */
266#define AGNX_GCR_BASE 0x9000
267/* threshold of primary antenna */
268#define AGNX_GCR_THD0A 0x9000 /* threshold? D0 A */
269/* low threshold of primary antenna */
270#define AGNX_GCR_THD0AL 0x9004 /* threshold? D0 A low */
271/* threshold of secondary antenna */
272#define AGNX_GCR_THD0B 0x9008 /* threshold? D0_B */
273#define AGNX_GCR_DUNSAT 0x900c /* d unsaturated */
274#define AGNX_GCR_DSAT 0x9010 /* d saturated */
275#define AGNX_GCR_DFIRCAL 0x9014 /* D Fir/Cal */
276#define AGNX_GCR_DGCTL11A 0x9018 /* d gain control 11a */
277#define AGNX_GCR_DGCTL11B 0x901c /* d gain control 11b */
278/* strength of gain */
279#define AGNX_GCR_GAININIT 0x9020 /* gain initialization */
280#define AGNX_GCR_THNOSIG 0x9024 /* threhold no signal */
281#define AGNX_GCR_COARSTEP 0x9028 /* coarse stepping */
282#define AGNX_GCR_SIFST11A 0x902c /* sifx time 11a */
283#define AGNX_GCR_SIFST11B 0x9030 /* sifx time 11b */
284#define AGNX_GCR_CWDETEC 0x9034 /* cw detection */
285#define AGNX_GCR_0X38 0x9038 /* ???? */
286#define AGNX_GCR_BOACT 0x903c /* BO Active */
287#define AGNX_GCR_BOINACT 0x9040 /* BO Inactive */
288#define AGNX_GCR_BODYNA 0x9044 /* BO dynamic */
289/* 802.11 mode(a,b,g) */
290#define AGNX_GCR_DISCOVMOD 0x9048 /* discovery mode */
291#define AGNX_GCR_NLISTANT 0x904c /* number of listening antenna */
292#define AGNX_GCR_NACTIANT 0x9050 /* number of active antenna */
293#define AGNX_GCR_NMEASANT 0x9054 /* number of measuring antenna */
294#define AGNX_GCR_NCAPTANT 0x9058 /* number of capture antenna */
295#define AGNX_GCR_THCAP11A 0x905c /* threshold capture 11a */
296#define AGNX_GCR_THCAP11B 0x9060 /* threshold capture 11b */
297#define AGNX_GCR_THCAPRX11A 0x9064 /* threshold capture rx 11a */
298#define AGNX_GCR_THCAPRX11B 0x9068 /* threshold capture rx 11b */
299#define AGNX_GCR_THLEVDRO 0x906c /* threshold level drop */
300#define AGNX_GCR_GAINSET0 0x9070 /* Gainset 0 */
301#define AGNX_GCR_GAINSET1 0x9074 /* Gainset 1 */
302#define AGNX_GCR_GAINSET2 0x9078 /* Gainset 2 */
303#define AGNX_GCR_MAXRXTIME11A 0x907c /* maximum rx time 11a */
304#define AGNX_GCR_MAXRXTIME11B 0x9080 /* maximum rx time 11b */
305#define AGNX_GCR_CORRTIME 0x9084 /* correction time */
306/* reset the subsystem, 0 = disable, 1 = enable */
307#define AGNX_GCR_RSTGCTL 0x9088 /* reset gain control */
308/* channel receiving */
309#define AGNX_GCR_RXCHANEL 0x908c /* receive channel */
310#define AGNX_GCR_NOISE0 0x9090 /* Noise 0 */
311#define AGNX_GCR_NOISE1 0x9094 /* Noise 1 */
312#define AGNX_GCR_NOISE2 0x9098 /* Noise 2 */
313#define AGNX_GCR_SIGHTH 0x909c /* Signal High Threshold */
314#define AGNX_GCR_SIGLTH 0x90a0 /* Signal Low Threshold */
315#define AGNX_GCR_CORRDROP 0x90a4 /* correction drop */
316/* threshold of tertiay antenna */
317#define AGNX_GCR_THCD 0x90a8 /* threshold? CD */
318#define AGNX_GCR_THCS 0x90ac /* threshold? CS */
319#define AGNX_GCR_MAXPOWDIFF 0x90b8 /* maximum power difference */
320#define AGNX_GCR_TRACNT4 0x90ec /* Transition Count 4 */
321#define AGNX_GCR_TRACNT5 0x90f0 /* transition count 5 */
322#define AGNX_GCR_TRACNT6 0x90f4 /* transition count 6 */
323#define AGNX_GCR_TRACNT7 0x90f8 /* transition coutn 7 */
324#define AGNX_GCR_TESTBUS 0x911c /* test bus */
325#define AGNX_GCR_CHAINNUM 0x9120 /* Number of Chains */
326#define AGNX_GCR_ANTCFG 0x9124 /* Antenna Config */
327#define AGNX_GCR_THJUMP 0x912c /* threhold jump */
328#define AGNX_GCR_THPOWER 0x9130 /* threshold power */
329#define AGNX_GCR_THPOWCLIP 0x9134 /* threshold power clip*/
330#define AGNX_GCR_FORCECTLCLK 0x9138 /* Force Gain Control Clock */
331#define AGNX_GCR_GAINSETWRITE 0x913c /* Gainset Write */
332#define AGNX_GCR_THD0BTFEST 0x9140 /* threshold d0 b tf estimate */
333#define AGNX_GCR_THRX11BPOWMIN 0x9144 /* threshold rx 11b power minimum */
334#define AGNX_GCR_0X14c 0x914c /* ?? */
335#define AGNX_GCR_0X150 0x9150 /* ?? */
336#define AGNX_GCR_RXOVERIDE 0x9194 /* recieve override */
337#define AGNX_GCR_WATCHDOG 0x91b0 /* watchdog timeout */
338
339
340/* Spi Interface */
341#define AGNX_SPI_BASE 0xdc00
342#define AGNX_SPI_CFG 0xdc00 /* spi configuration */
343/* Only accept 16 bits */
344#define AGNX_SPI_WMSW 0xdc04 /* write most significant word */
345/* Only accept 16 bits */
346#define AGNX_SPI_WLSW 0xdc08 /* write least significant word */
347#define AGNX_SPI_CTL 0xdc0c /* spi control */
348#define AGNX_SPI_RMSW 0xdc10 /* read most significant word */
349#define AGNX_SPI_RLSW 0xdc14 /* read least significant word */
350/* SPI Control Mask */
351#define SPI_READ_CTL 0x4000 /* read control */
352#define SPI_BUSY_CTL 0x8000 /* busy control */
353/* RF and synth chips in spi */
354#define RF_CHIP0 0x400
355#define RF_CHIP1 0x800
356#define RF_CHIP2 0x1000
357#define SYNTH_CHIP 0x2000
358
359/* Unknown register */
360#define AGNX_UNKNOWN_BASE 0x7800
361
362/* FIXME MonitorGain */
363#define AGNX_MONGCR_BASE 0x12000
364
365/* Gain Table */
366#define AGNX_GAIN_TABLE 0x12400
367
368/* The initial FIR coefficient table */
369#define AGNX_FIR_BASE 0x19804
370
371#define AGNX_ENGINE_LOOKUP_TBL 0x800
372
373/* eeprom commands */
374#define EEPROM_CMD_NULL 0x0 /* NULL */
375#define EEPROM_CMD_WRITE 0x2 /* write */
376#define EEPROM_CMD_READ 0x3 /* read */
377#define EEPROM_CMD_STATUSREAD 0x5 /* status register read */
378#define EEPROM_CMD_WRITEENABLE 0x6 /* write enable */
379#define EEPROM_CMD_CONFIGURE 0x7 /* configure */
380
381#define EEPROM_DATAFORCOFIGURE 0x6 /* ??? */
382
383/* eeprom address */
384#define EEPROM_ADDR_SUBVID 0x0 /* Sub Vendor ID */
385#define EEPROM_ADDR_SUBSID 0x2 /* Sub System ID */
386#define EEPROM_ADDR_MACADDR 0x146 /* MAC Address */
387#define EEPROM_ADDR_LOTYPE 0x14f /* LO type */
388
389struct agnx_eeprom {
390 u8 data; /* date */
391 u16 address; /* address in EEPROM */
392 u8 cmd; /* command, unknown, status */
393} __attribute__((__packed__));
394
395#define AGNX_EEPROM_COMMAND_SHIFT 5
396#define AGNX_EEPROM_COMMAND_STAT 0x01
397
398void disable_receiver(struct agnx_priv *priv);
399void enable_receiver(struct agnx_priv *priv);
400u8 read_from_eeprom(struct agnx_priv *priv, u16 address);
401void agnx_hw_init(struct agnx_priv *priv);
402int agnx_hw_reset(struct agnx_priv *priv);
403int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len);
404void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid);
405void enable_power_saving(struct agnx_priv *priv);
406void disable_power_saving(struct agnx_priv *priv);
407void calibrate_antenna_period(unsigned long data);
408
409#endif /* AGNX_PHY_H_ */
diff --git a/drivers/staging/agnx/rf.c b/drivers/staging/agnx/rf.c
deleted file mode 100644
index 42e457a1844f..000000000000
--- a/drivers/staging/agnx/rf.c
+++ /dev/null
@@ -1,893 +0,0 @@
1/**
2 * Airgo MIMO wireless driver
3 *
4 * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
5
6 * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
7 * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
8
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation;
12 */
13
14#include <linux/pci.h>
15#include <linux/delay.h>
16#include "agnx.h"
17#include "debug.h"
18#include "phy.h"
19#include "table.h"
20
21/* FIXME! */
22static inline void spi_write(void __iomem *region, u32 chip_ids, u32 sw,
23 u16 size, u32 control)
24{
25 u32 reg;
26 u32 lsw = sw & 0xffff; /* lower 16 bits of sw*/
27 u32 msw = sw >> 16; /* high 16 bits of sw */
28
29 /* FIXME Write Most Significant Word of the 32bit data to MSW */
30 /* FIXME And Least Significant Word to LSW */
31 iowrite32((lsw), region + AGNX_SPI_WLSW);
32 iowrite32((msw), region + AGNX_SPI_WMSW);
33 reg = chip_ids | size | control;
34 /* Write chip id(s), write size and busy control to Control Register */
35 iowrite32((reg), region + AGNX_SPI_CTL);
36 /* Wait for Busy control to clear */
37 spi_delay();
38}
39
40/*
41 * Write to SPI Synth register
42 */
43static inline void spi_sy_write(void __iomem *region, u32 chip_ids, u32 sw)
44{
45 /* FIXME the size 0x15 is a magic value*/
46 spi_write(region, chip_ids, sw, 0x15, SPI_BUSY_CTL);
47}
48
49/*
50 * Write to SPI RF register
51 */
52static inline void spi_rf_write(void __iomem *region, u32 chip_ids, u32 sw)
53{
54 /* FIXME the size 0xd is a magic value*/
55 spi_write(region, chip_ids, sw, 0xd, SPI_BUSY_CTL);
56} /* spi_rf_write */
57
58/*
59 * Write to SPI with Read Control bit set
60 */
61inline void spi_rc_write(void __iomem *region, u32 chip_ids, u32 sw)
62{
63 /* FIXME the size 0xe5 is a magic value */
64 spi_write(region, chip_ids, sw, 0xe5, SPI_BUSY_CTL|SPI_READ_CTL);
65}
66
67/* Get the active chains's count */
68static int get_active_chains(struct agnx_priv *priv)
69{
70 void __iomem *ctl = priv->ctl;
71 int num = 0;
72 u32 reg;
73 AGNX_TRACE;
74
75 spi_rc_write(ctl, RF_CHIP0, 0x21);
76 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
77 if (reg == 1)
78 num++;
79
80 spi_rc_write(ctl, RF_CHIP1, 0x21);
81 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
82 if (reg == 1)
83 num++;
84
85 spi_rc_write(ctl, RF_CHIP2, 0x21);
86 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
87 if (reg == 1)
88 num++;
89
90 spi_rc_write(ctl, RF_CHIP0, 0x26);
91 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
92 if (0x33 != reg)
93 printk(KERN_WARNING PFX "Unmatched rf chips result\n");
94
95 return num;
96} /* get_active_chains */
97
98void rf_chips_init(struct agnx_priv *priv)
99{
100 void __iomem *ctl = priv->ctl;
101 u32 reg;
102 int num;
103 AGNX_TRACE;
104
105 if (priv->revid == 1) {
106 reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
107 reg |= 0x8;
108 agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
109 }
110
111 /* Set SPI clock speed to 200NS */
112 reg = agnx_read32(ctl, AGNX_SPI_CFG);
113 reg &= ~0xF;
114 reg |= 0x3;
115 agnx_write32(ctl, AGNX_SPI_CFG, reg);
116
117 /* Set SPI clock speed to 50NS */
118 reg = agnx_read32(ctl, AGNX_SPI_CFG);
119 reg &= ~0xF;
120 reg |= 0x1;
121 agnx_write32(ctl, AGNX_SPI_CFG, reg);
122
123 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1101);
124
125 num = get_active_chains(priv);
126 printk(KERN_INFO PFX "Active chains are %d\n", num);
127
128 reg = agnx_read32(ctl, AGNX_SPI_CFG);
129 reg &= ~0xF;
130 agnx_write32(ctl, AGNX_SPI_CFG, reg);
131
132 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1908);
133} /* rf_chips_init */
134
135
136static u32 channel_tbl[15][9] = {
137 {0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
138 {1, 0x00, 0x00, 0x624, 0x00, 0x1a4, 0x28, 0x00, 0x1e},
139 {2, 0x00, 0x00, 0x615, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
140 {3, 0x00, 0x00, 0x61a, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
141 {4, 0x00, 0x00, 0x61f, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
142 {5, 0x00, 0x00, 0x624, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
143 {6, 0x00, 0x00, 0x61f, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
144 {7, 0x00, 0x00, 0x624, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
145 {8, 0x00, 0x00, 0x629, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
146 {9, 0x00, 0x00, 0x624, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
147 {10, 0x00, 0x00, 0x629, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
148 {11, 0x00, 0x00, 0x62e, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
149 {12, 0x00, 0x00, 0x633, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
150 {13, 0x00, 0x00, 0x628, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
151 {14, 0x00, 0x00, 0x644, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
152};
153
154
155static inline void
156channel_tbl_write(struct agnx_priv *priv, unsigned int channel, unsigned int reg_num)
157{
158 void __iomem *ctl = priv->ctl;
159 u32 reg;
160
161 reg = channel_tbl[channel][reg_num];
162 reg <<= 4;
163 reg |= reg_num;
164 spi_sy_write(ctl, SYNTH_CHIP, reg);
165}
166
167static void synth_freq_set(struct agnx_priv *priv, unsigned int channel)
168{
169 void __iomem *ctl = priv->ctl;
170 u32 reg;
171 AGNX_TRACE;
172
173 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
174
175 /* Set the Clock bits to 50NS */
176 reg = agnx_read32(ctl, AGNX_SPI_CFG);
177 reg &= ~0xF;
178 reg |= 0x1;
179 agnx_write32(ctl, AGNX_SPI_CFG, reg);
180
181 /* Write 0x00c0 to LSW and 0x3 to MSW of Synth Chip */
182 spi_sy_write(ctl, SYNTH_CHIP, 0x300c0);
183
184 spi_sy_write(ctl, SYNTH_CHIP, 0x32);
185
186 /* # Write to Register 1 on the Synth Chip */
187 channel_tbl_write(priv, channel, 1);
188 /* # Write to Register 3 on the Synth Chip */
189 channel_tbl_write(priv, channel, 3);
190 /* # Write to Register 6 on the Synth Chip */
191 channel_tbl_write(priv, channel, 6);
192 /* # Write to Register 5 on the Synth Chip */
193 channel_tbl_write(priv, channel, 5);
194 /* # Write to register 8 on the Synth Chip */
195 channel_tbl_write(priv, channel, 8);
196
197 /* FIXME Clear the clock bits */
198 reg = agnx_read32(ctl, AGNX_SPI_CFG);
199 reg &= ~0xf;
200 agnx_write32(ctl, AGNX_SPI_CFG, reg);
201} /* synth_chip_init */
202
203
204static void antenna_init(struct agnx_priv *priv, int num_antenna)
205{
206 void __iomem *ctl = priv->ctl;
207
208 switch (num_antenna) {
209 case 1:
210 agnx_write32(ctl, AGNX_GCR_NLISTANT, 1);
211 agnx_write32(ctl, AGNX_GCR_NMEASANT, 1);
212 agnx_write32(ctl, AGNX_GCR_NACTIANT, 1);
213 agnx_write32(ctl, AGNX_GCR_NCAPTANT, 1);
214
215 agnx_write32(ctl, AGNX_GCR_ANTCFG, 7);
216 agnx_write32(ctl, AGNX_GCR_BOACT, 34);
217 agnx_write32(ctl, AGNX_GCR_BOINACT, 34);
218 agnx_write32(ctl, AGNX_GCR_BODYNA, 30);
219
220 agnx_write32(ctl, AGNX_GCR_THD0A, 125);
221 agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
222 agnx_write32(ctl, AGNX_GCR_THD0B, 90);
223
224 agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 80);
225 agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
226 agnx_write32(ctl, AGNX_GCR_SIGLTH, 16);
227 break;
228 case 2:
229 agnx_write32(ctl, AGNX_GCR_NLISTANT, 2);
230 agnx_write32(ctl, AGNX_GCR_NMEASANT, 2);
231 agnx_write32(ctl, AGNX_GCR_NACTIANT, 2);
232 agnx_write32(ctl, AGNX_GCR_NCAPTANT, 2);
233 agnx_write32(ctl, AGNX_GCR_ANTCFG, 15);
234 agnx_write32(ctl, AGNX_GCR_BOACT, 36);
235 agnx_write32(ctl, AGNX_GCR_BOINACT, 36);
236 agnx_write32(ctl, AGNX_GCR_BODYNA, 32);
237 agnx_write32(ctl, AGNX_GCR_THD0A, 120);
238 agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
239 agnx_write32(ctl, AGNX_GCR_THD0B, 80);
240 agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
241 agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
242 agnx_write32(ctl, AGNX_GCR_SIGLTH, 32);
243 break;
244 case 3:
245 agnx_write32(ctl, AGNX_GCR_NLISTANT, 3);
246 agnx_write32(ctl, AGNX_GCR_NMEASANT, 3);
247 agnx_write32(ctl, AGNX_GCR_NACTIANT, 3);
248 agnx_write32(ctl, AGNX_GCR_NCAPTANT, 3);
249 agnx_write32(ctl, AGNX_GCR_ANTCFG, 31);
250 agnx_write32(ctl, AGNX_GCR_BOACT, 36);
251 agnx_write32(ctl, AGNX_GCR_BOINACT, 36);
252 agnx_write32(ctl, AGNX_GCR_BODYNA, 32);
253 agnx_write32(ctl, AGNX_GCR_THD0A, 100);
254 agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
255 agnx_write32(ctl, AGNX_GCR_THD0B, 70);
256 agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
257 agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
258 agnx_write32(ctl, AGNX_GCR_SIGLTH, 48);
259/* agnx_write32(ctl, AGNX_GCR_SIGLTH, 16); */
260 break;
261 default:
262 printk(KERN_WARNING PFX "Unknow antenna number\n");
263 }
264} /* antenna_init */
265
266static void chain_update(struct agnx_priv *priv, u32 chain)
267{
268 void __iomem *ctl = priv->ctl;
269 u32 reg;
270 AGNX_TRACE;
271
272 spi_rc_write(ctl, RF_CHIP0, 0x20);
273 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
274
275 if (reg == 0x4)
276 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
277 else if (reg != 0x0)
278 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
279 else {
280 if (chain == 3 || chain == 6) {
281 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
282 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
283 } else if (chain == 2 || chain == 4) {
284 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
285 spi_rf_write(ctl, RF_CHIP2, 0x1005);
286 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x824);
287 } else if (chain == 1) {
288 spi_rf_write(ctl, RF_CHIP0, reg|0x1000);
289 spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1004);
290 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xc36);
291 }
292 }
293
294 spi_rc_write(ctl, RF_CHIP0, 0x22);
295 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
296
297 switch (reg) {
298 case 0:
299 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1005);
300 break;
301 case 1:
302 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
303 break;
304 case 2:
305 if (chain == 6 || chain == 4) {
306 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1202);
307 spi_rf_write(ctl, RF_CHIP2, 0x1005);
308 } else if (chain < 3) {
309 spi_rf_write(ctl, RF_CHIP0, 0x1202);
310 spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1005);
311 }
312 break;
313 default:
314 if (chain == 3) {
315 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
316 spi_rf_write(ctl, RF_CHIP2, 0x1201);
317 } else if (chain == 2) {
318 spi_rf_write(ctl, RF_CHIP0, 0x1203);
319 spi_rf_write(ctl, RF_CHIP2, 0x1200);
320 spi_rf_write(ctl, RF_CHIP1, 0x1201);
321 } else if (chain == 1) {
322 spi_rf_write(ctl, RF_CHIP0, 0x1203);
323 spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1200);
324 } else if (chain == 4) {
325 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
326 spi_rf_write(ctl, RF_CHIP2, 0x1201);
327 } else {
328 spi_rf_write(ctl, RF_CHIP0, 0x1203);
329 spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1201);
330 }
331 }
332} /* chain_update */
333
334static void antenna_config(struct agnx_priv *priv)
335{
336 void __iomem *ctl = priv->ctl;
337 u32 reg;
338 AGNX_TRACE;
339
340 /* Write 0x0 to the TX Management Control Register Enable bit */
341 reg = agnx_read32(ctl, AGNX_TXM_CTL);
342 reg &= ~0x1;
343 agnx_write32(ctl, AGNX_TXM_CTL, reg);
344
345 /* FIXME */
346 /* Set initial value based on number of Antennae */
347 antenna_init(priv, 3);
348
349 /* FIXME Update Power Templates for current valid Stations */
350 /* sta_power_init(priv, 0);*/
351
352 /* FIXME the number of chains should get from eeprom*/
353 chain_update(priv, AGNX_CHAINS_MAX);
354} /* antenna_config */
355
356void calibrate_oscillator(struct agnx_priv *priv)
357{
358 void __iomem *ctl = priv->ctl;
359 u32 reg;
360 AGNX_TRACE;
361
362 spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
363 reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
364 reg |= 0x10;
365 agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
366
367 agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 1);
368 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 1);
369
370 agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
371
372 agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
373 agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
374 /* (Residual DC Calibration) to Calibration Mode */
375 agnx_write32(ctl, AGNX_ACI_MODE, 0x2);
376
377 spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x1004);
378 agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
379 /* (TX LO Calibration) to Calibration Mode */
380 agnx_write32(ctl, AGNX_ACI_MODE, 0x4);
381
382 do {
383 u32 reg1, reg2, reg3;
384 /* Enable Power Saving Control */
385 enable_power_saving(priv);
386 /* Save the following registers to restore */
387 reg1 = ioread32(ctl + 0x11000);
388 reg2 = ioread32(ctl + 0xec50);
389 reg3 = ioread32(ctl + 0xec54);
390 wmb();
391
392 agnx_write32(ctl, 0x11000, 0xcfdf);
393 agnx_write32(ctl, 0xec50, 0x70);
394 /* Restore the registers */
395 agnx_write32(ctl, 0x11000, reg1);
396 agnx_write32(ctl, 0xec50, reg2);
397 agnx_write32(ctl, 0xec54, reg3);
398 /* Disable Power Saving Control */
399 disable_power_saving(priv);
400 } while (0);
401
402 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0);
403} /* calibrate_oscillator */
404
405
406static void radio_channel_set(struct agnx_priv *priv, unsigned int channel)
407{
408 void __iomem *ctl = priv->ctl;
409 unsigned int freq = priv->band.channels[channel - 1].center_freq;
410 u32 reg;
411 AGNX_TRACE;
412
413 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
414 /* Set SPI Clock to 50 Ns */
415 reg = agnx_read32(ctl, AGNX_SPI_CFG);
416 reg &= ~0xF;
417 reg |= 0x1;
418 agnx_write32(ctl, AGNX_SPI_CFG, reg);
419
420 /* Clear the Disable Tx interrupt bit in Interrupt Mask */
421/* reg = agnx_read32(ctl, AGNX_INT_MASK); */
422/* reg &= ~IRQ_TX_DISABLE; */
423/* agnx_write32(ctl, AGNX_INT_MASK, reg); */
424
425 /* Band Selection */
426 reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
427 reg |= 0x8;
428 agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
429
430 /* FIXME Set the SiLabs Chip Frequency */
431 synth_freq_set(priv, channel);
432
433 reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
434 reg |= 0x80100030;
435 agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
436 reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
437 reg |= 0x20009;
438 agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
439
440 agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
441
442 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1100);
443
444 /* Load the MonitorGain Table */
445 monitor_gain_table_init(priv);
446
447 /* Load the TX Fir table */
448 tx_fir_table_init(priv);
449
450 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
451 reg |= 0x8;
452 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
453
454 spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x22);
455 udelay(80);
456 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
457
458
459 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xff);
460 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
461
462 reg = agnx_read32(ctl, 0xec50);
463 reg |= 0x4f;
464 agnx_write32(ctl, 0xec50, reg);
465
466 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
467 agnx_write32(ctl, 0x11008, 0x1);
468 agnx_write32(ctl, 0x1100c, 0x0);
469 agnx_write32(ctl, 0x11008, 0x0);
470 agnx_write32(ctl, 0xec50, 0xc);
471
472 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
473 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
474 agnx_write32(ctl, 0x11010, 0x6e);
475 agnx_write32(ctl, 0x11014, 0x6c);
476
477 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
478
479 /* Calibrate the Antenna */
480 /* antenna_calibrate(priv); */
481 /* Calibrate the TxLocalOscillator */
482 calibrate_oscillator(priv);
483
484 reg = agnx_read32(ctl, AGNX_PM_PMCTL);
485 reg &= ~0x8;
486 agnx_write32(ctl, AGNX_PM_PMCTL, reg);
487 agnx_write32(ctl, AGNX_GCR_GAININIT, 0xa);
488 agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
489
490 agnx_write32(ctl, 0x11018, 0xb);
491 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
492
493 /* Write Frequency to Gain Control Channel */
494 agnx_write32(ctl, AGNX_GCR_RXCHANEL, freq);
495 /* Write 0x140000/Freq to 0x9c08 */
496 reg = 0x140000/freq;
497 agnx_write32(ctl, 0x9c08, reg);
498
499 reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
500 reg &= ~0x80100030;
501 agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
502
503 reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
504 reg &= ~0x20009;
505 reg |= 0x1;
506 agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
507
508 agnx_write32(ctl, AGNX_ACI_MODE, 0x0);
509
510/* FIXME According to Number of Chains: */
511
512/* 1. 1: */
513/* 1. Write 0x1203 to RF Chip 0 */
514/* 2. Write 0x1200 to RF Chips 1 +2 */
515/* 2. 2: */
516/* 1. Write 0x1203 to RF Chip 0 */
517/* 2. Write 0x1200 to RF Chip 2 */
518/* 3. Write 0x1201 to RF Chip 1 */
519/* 3. 3: */
520/* 1. Write 0x1203 to RF Chip 0 */
521/* 2. Write 0x1201 to RF Chip 1 + 2 */
522/* 4. 4: */
523/* 1. Write 0x1203 to RF Chip 0 + 1 */
524/* 2. Write 0x1200 to RF Chip 2 */
525
526/* 5. 6: */
527 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
528 spi_rf_write(ctl, RF_CHIP2, 0x1201);
529
530 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1000);
531 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
532
533 /* FIXME Set the Disable Tx interrupt bit in Interrupt Mask
534 (Or 0x20000 to Interrupt Mask) */
535/* reg = agnx_read32(ctl, AGNX_INT_MASK); */
536/* reg |= IRQ_TX_DISABLE; */
537/* agnx_write32(ctl, AGNX_INT_MASK, reg); */
538
539 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
540 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
541
542 /* Configure the Antenna */
543 antenna_config(priv);
544
545 /* Write 0x0 to Discovery Mode Enable detect G, B, A packet? */
546 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0);
547
548 reg = agnx_read32(ctl, AGNX_RXM_REQRATE);
549 reg |= 0x80000000;
550 agnx_write32(ctl, AGNX_RXM_REQRATE, reg);
551 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
552 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
553
554 /* enable radio on and the power LED */
555 reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
556 reg &= ~0x1;
557 reg |= 0x2;
558 agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
559
560 reg = agnx_read32(ctl, AGNX_TXM_CTL);
561 reg |= 0x1;
562 agnx_write32(ctl, AGNX_TXM_CTL, reg);
563} /* radio_channel_set */
564
565static void base_band_filter_calibrate(struct agnx_priv *priv)
566{
567 void __iomem *ctl = priv->ctl;
568
569 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1700);
570 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1001);
571 agnx_write32(ctl, AGNX_GCR_FORCECTLCLK, 0x0);
572 spi_rc_write(ctl, RF_CHIP0, 0x27);
573 spi_rc_write(ctl, RF_CHIP1, 0x27);
574 spi_rc_write(ctl, RF_CHIP2, 0x27);
575 agnx_write32(ctl, AGNX_GCR_FORCECTLCLK, 0x1);
576}
577
578static void print_offset(struct agnx_priv *priv, u32 chain)
579{
580 void __iomem *ctl = priv->ctl;
581 u32 offset;
582
583 iowrite32((chain), ctl + AGNX_ACI_SELCHAIN);
584 udelay(10);
585 offset = (ioread32(ctl + AGNX_ACI_OFFSET));
586 printk(PFX "Chain is 0x%x, Offset is 0x%x\n", chain, offset);
587}
588
589void print_offsets(struct agnx_priv *priv)
590{
591 print_offset(priv, 0);
592 print_offset(priv, 4);
593 print_offset(priv, 1);
594 print_offset(priv, 5);
595 print_offset(priv, 2);
596 print_offset(priv, 6);
597}
598
599
600struct chains {
601 u32 cali; /* calibrate value*/
602
603#define NEED_CALIBRATE 0
604#define SUCCESS_CALIBRATE 1
605 int status;
606};
607
608static void chain_calibrate(struct agnx_priv *priv, struct chains *chains,
609 unsigned int num)
610{
611 void __iomem *ctl = priv->ctl;
612 u32 calibra = chains[num].cali;
613
614 if (num < 3)
615 calibra |= 0x1400;
616 else
617 calibra |= 0x1500;
618
619 switch (num) {
620 case 0:
621 case 4:
622 spi_rf_write(ctl, RF_CHIP0, calibra);
623 break;
624 case 1:
625 case 5:
626 spi_rf_write(ctl, RF_CHIP1, calibra);
627 break;
628 case 2:
629 case 6:
630 spi_rf_write(ctl, RF_CHIP2, calibra);
631 break;
632 default:
633 BUG();
634 }
635} /* chain_calibrate */
636
637static inline void get_calibrete_value(struct agnx_priv *priv, struct chains *chains,
638 unsigned int num)
639{
640 void __iomem *ctl = priv->ctl;
641 u32 offset;
642
643 iowrite32((num), ctl + AGNX_ACI_SELCHAIN);
644 /* FIXME */
645 udelay(10);
646 offset = (ioread32(ctl + AGNX_ACI_OFFSET));
647
648 if (offset < 0xf) {
649 chains[num].status = SUCCESS_CALIBRATE;
650 return;
651 }
652
653 if (num == 0 || num == 1 || num == 2) {
654 if (0 == chains[num].cali)
655 chains[num].cali = 0xff;
656 else
657 chains[num].cali--;
658 } else
659 chains[num].cali++;
660
661 chains[num].status = NEED_CALIBRATE;
662}
663
664static inline void calibra_delay(struct agnx_priv *priv)
665{
666 void __iomem *ctl = priv->ctl;
667 u32 reg;
668 unsigned int i = 100;
669
670 wmb();
671 while (--i) {
672 reg = (ioread32(ctl + AGNX_ACI_STATUS));
673 if (reg == 0x4000)
674 break;
675 udelay(10);
676 }
677 if (!i)
678 printk(PFX "calibration failed\n");
679}
680
681void do_calibration(struct agnx_priv *priv)
682{
683 void __iomem *ctl = priv->ctl;
684 struct chains chains[7];
685 unsigned int i, j;
686 AGNX_TRACE;
687
688 for (i = 0; i < 7; i++) {
689 if (i == 3)
690 continue;
691
692 chains[i].cali = 0x7f;
693 chains[i].status = NEED_CALIBRATE;
694 }
695
696 /* FIXME 0x300 is a magic number */
697 for (j = 0; j < 0x300; j++) {
698 if (chains[0].status == SUCCESS_CALIBRATE &&
699 chains[1].status == SUCCESS_CALIBRATE &&
700 chains[2].status == SUCCESS_CALIBRATE &&
701 chains[4].status == SUCCESS_CALIBRATE &&
702 chains[5].status == SUCCESS_CALIBRATE &&
703 chains[6].status == SUCCESS_CALIBRATE)
704 break;
705
706 /* Attention, there is no chain 3 */
707 for (i = 0; i < 7; i++) {
708 if (i == 3)
709 continue;
710 if (chains[i].status == NEED_CALIBRATE)
711 chain_calibrate(priv, chains, i);
712 }
713 /* Write 0x1 to Calibration Measure */
714 iowrite32((0x1), ctl + AGNX_ACI_MEASURE);
715 calibra_delay(priv);
716
717 for (i = 0; i < 7; i++) {
718 if (i == 3)
719 continue;
720
721 get_calibrete_value(priv, chains, i);
722 }
723 }
724 printk(PFX "Clibrate times is %d\n", j);
725 print_offsets(priv);
726} /* do_calibration */
727
728void antenna_calibrate(struct agnx_priv *priv)
729{
730 void __iomem *ctl = priv->ctl;
731 u32 reg;
732 AGNX_TRACE;
733
734 agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3);
735 agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3);
736 agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3);
737 agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3);
738
739 agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f);
740 agnx_write32(ctl, AGNX_GCR_BOACT, 0x24);
741 agnx_write32(ctl, AGNX_GCR_BOINACT, 0x24);
742 agnx_write32(ctl, AGNX_GCR_BODYNA, 0x20);
743 agnx_write32(ctl, AGNX_GCR_THD0A, 0x64);
744 agnx_write32(ctl, AGNX_GCR_THD0AL, 0x64);
745 agnx_write32(ctl, AGNX_GCR_THD0B, 0x46);
746 agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c);
747 agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x64);
748 agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x30);
749
750 spi_rc_write(ctl, RF_CHIP0, 0x20);
751 /* Fixme */
752 udelay(80);
753 /* 1. Should read 0x0 */
754 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
755 if (0x0 != reg)
756 printk(KERN_WARNING PFX "Unmatched rf chips result\n");
757 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1000);
758
759 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
760
761 spi_rc_write(ctl, RF_CHIP0, 0x22);
762 udelay(80);
763 reg = agnx_read32(ctl, AGNX_SPI_RLSW);
764 if (0x0 != reg)
765 printk(KERN_WARNING PFX "Unmatched rf chips result\n");
766 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1005);
767
768 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
769 agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
770
771 reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
772 reg |= 0x1c000032;
773 agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
774 reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
775 reg |= 0x0003f07;
776 agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
777
778 reg = agnx_read32(ctl, 0xec50);
779 reg |= 0x40;
780 agnx_write32(ctl, 0xec50, reg);
781
782 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xff8);
783 agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
784
785 agnx_write32(ctl, AGNX_GCR_CHAINNUM, 0x6);
786 agnx_write32(ctl, 0x19874, 0x0);
787 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1700);
788
789 /* Calibrate the BaseBandFilter */
790 base_band_filter_calibrate(priv);
791
792 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1002);
793
794 agnx_write32(ctl, AGNX_GCR_GAINSET0, 0x1d);
795 agnx_write32(ctl, AGNX_GCR_GAINSET1, 0x1d);
796 agnx_write32(ctl, AGNX_GCR_GAINSET2, 0x1d);
797 agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x1);
798
799 agnx_write32(ctl, AGNX_ACI_MODE, 0x1);
800 agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
801
802 agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
803 agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
804
805 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1400);
806 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1500);
807
808 /* Measure Calibration */
809 agnx_write32(ctl, AGNX_ACI_MEASURE, 0x1);
810 calibra_delay(priv);
811
812 /* do calibration */
813 do_calibration(priv);
814
815 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
816 agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
817 agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
818 agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
819
820 reg = agnx_read32(ctl, AGNX_GCR_GAINSET0);
821 reg &= 0xf;
822 agnx_write32(ctl, AGNX_GCR_GAINSET0, reg);
823 reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
824 reg &= 0xf;
825 agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
826 reg = agnx_read32(ctl, AGNX_GCR_GAINSET2);
827 reg &= 0xf;
828 agnx_write32(ctl, AGNX_GCR_GAINSET2, reg);
829
830 agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x0);
831 disable_receiver(priv);
832} /* antenna_calibrate */
833
834void __antenna_calibrate(struct agnx_priv *priv)
835{
836 void __iomem *ctl = priv->ctl;
837 u32 reg;
838
839 /* Calibrate the BaseBandFilter */
840 /* base_band_filter_calibrate(priv); */
841 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1002);
842
843
844 agnx_write32(ctl, AGNX_GCR_GAINSET0, 0x1d);
845 agnx_write32(ctl, AGNX_GCR_GAINSET1, 0x1d);
846 agnx_write32(ctl, AGNX_GCR_GAINSET2, 0x1d);
847
848 agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x1);
849
850 agnx_write32(ctl, AGNX_ACI_MODE, 0x1);
851 agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
852
853
854 agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
855 agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
856 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1400);
857 spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1500);
858 /* Measure Calibration */
859 agnx_write32(ctl, AGNX_ACI_MEASURE, 0x1);
860 calibra_delay(priv);
861 do_calibration(priv);
862 agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
863
864 agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
865 agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
866
867 agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
868
869 reg = agnx_read32(ctl, AGNX_GCR_GAINSET0);
870 reg &= 0xf;
871 agnx_write32(ctl, AGNX_GCR_GAINSET0, reg);
872 reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
873 reg &= 0xf;
874 agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
875 reg = agnx_read32(ctl, AGNX_GCR_GAINSET2);
876 reg &= 0xf;
877 agnx_write32(ctl, AGNX_GCR_GAINSET2, reg);
878
879
880 agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x0);
881
882 /* Write 0x3 Gain Control Discovery Mode */
883 enable_receiver(priv);
884}
885
886int agnx_set_channel(struct agnx_priv *priv, unsigned int channel)
887{
888 AGNX_TRACE;
889
890 printk(KERN_ERR PFX "Channel is %d %s\n", channel, __func__);
891 radio_channel_set(priv, channel);
892 return 0;
893}
diff --git a/drivers/staging/agnx/sta.c b/drivers/staging/agnx/sta.c
deleted file mode 100644
index 3e7db5e2811a..000000000000
--- a/drivers/staging/agnx/sta.c
+++ /dev/null
@@ -1,218 +0,0 @@
1#include <linux/delay.h>
2#include <linux/etherdevice.h>
3#include "phy.h"
4#include "sta.h"
5#include "debug.h"
6
7void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
8{
9 void __iomem *ctl = priv->ctl;
10
11 reglo &= 0xFFFF;
12 reglo |= 0x30000000;
13 reglo |= 0x40000000; /* Set status busy */
14 reglo |= sta_id << 16;
15
16 iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
17 iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
18 iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
19
20 reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
21 reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
22 printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
23}
24
25void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id)
26{
27 void __iomem *ctl = priv->ctl;
28 u32 reghi, reglo;
29
30 if (!is_valid_ether_addr(mac_addr))
31 printk(KERN_WARNING PFX "Update hash table: Invalid hwaddr!\n");
32
33 reghi = mac_addr[0] << 24 | mac_addr[1] << 16 | mac_addr[2] << 8 | mac_addr[3];
34 reglo = mac_addr[4] << 8 | mac_addr[5];
35 reglo |= 0x10000000; /* Set hash commmand */
36 reglo |= 0x40000000; /* Set status busy */
37 reglo |= sta_id << 16;
38
39 iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
40 iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
41 iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
42
43 reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
44 if (!(reglo & 0x80000000))
45 printk(KERN_WARNING PFX "Update hash table failed\n");
46}
47
48void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
49{
50 void __iomem *ctl = priv->ctl;
51
52 reglo &= 0xFFFF;
53 reglo |= 0x20000000;
54 reglo |= 0x40000000; /* Set status busy */
55 reglo |= sta_id << 16;
56
57 iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
58 iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
59 iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
60 reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
61
62 reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
63 printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
64
65}
66
67void hash_dump(struct agnx_priv *priv, u8 sta_id)
68{
69 void __iomem *ctl = priv->ctl;
70 u32 reghi, reglo;
71
72 reglo = 0x40000000; /* status bit */
73 iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
74 iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA);
75
76 udelay(80);
77
78 reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
79 reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
80 printk(PFX "hash cmd are : %.8x%.8x\n", reghi, reglo);
81 reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG);
82 printk(PFX "hash flag is : %.8x\n", reghi);
83 reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_MST);
84 reglo = ioread32(ctl + AGNX_RXM_HASH_DUMP_LST);
85 printk(PFX "hash dump mst lst: %.8x%.8x\n", reghi, reglo);
86 reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_DATA);
87 printk(PFX "hash dump data: %.8x\n", reghi);
88}
89
90void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
91{
92 void __iomem *ctl = priv->ctl;
93 memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
94 sizeof(*power));
95}
96
97inline void
98set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
99{
100 void __iomem *ctl = priv->ctl;
101 /* FIXME 2. Write Template to offset + station number */
102 memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
103 power, sizeof(*power));
104}
105
106
107void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
108 unsigned int sta_idx, unsigned int wq_idx)
109{
110 void __iomem *data = priv->data;
111 memcpy_fromio(tx_wq, data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
112 sizeof(*tx_wq) * wq_idx, sizeof(*tx_wq));
113
114}
115
116inline void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
117 unsigned int sta_idx, unsigned int wq_idx)
118{
119 void __iomem *data = priv->data;
120 memcpy_toio(data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
121 sizeof(*tx_wq) * wq_idx, tx_wq, sizeof(*tx_wq));
122}
123
124
125void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
126{
127 void __iomem *data = priv->data;
128
129 memcpy_fromio(sta, data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
130 sizeof(*sta));
131}
132
133inline void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
134{
135 void __iomem *data = priv->data;
136
137 memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
138 sta, sizeof(*sta));
139}
140
141/* FIXME */
142void sta_power_init(struct agnx_priv *priv, unsigned int sta_idx)
143{
144 struct agnx_sta_power power;
145 u32 reg;
146 AGNX_TRACE;
147
148 memset(&power, 0, sizeof(power));
149 reg = agnx_set_bits(EDCF, EDCF_SHIFT, 0x1);
150 power.reg = cpu_to_le32(reg);
151 set_sta_power(priv, &power, sta_idx);
152 udelay(40);
153} /* add_power_template */
154
155
156/* @num: The #number of station that is visible to the card */
157static void sta_tx_workqueue_init(struct agnx_priv *priv, unsigned int sta_idx)
158{
159 struct agnx_sta_tx_wq tx_wq;
160 u32 reg;
161 unsigned int i;
162
163 memset(&tx_wq, 0, sizeof(tx_wq));
164
165 reg = agnx_set_bits(WORK_QUEUE_VALID, WORK_QUEUE_VALID_SHIFT, 1);
166 reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 1);
167/* reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0); */
168 tx_wq.reg2 |= cpu_to_le32(reg);
169
170 /* Suppose all 8 traffic class are used */
171 for (i = 0; i < STA_TX_WQ_NUM; i++)
172 set_sta_tx_wq(priv, &tx_wq, sta_idx, i);
173} /* sta_tx_workqueue_init */
174
175
176static void sta_traffic_init(struct agnx_sta_traffic *traffic)
177{
178 u32 reg;
179 memset(traffic, 0, sizeof(*traffic));
180
181 reg = agnx_set_bits(NEW_PACKET, NEW_PACKET_SHIFT, 1);
182 reg |= agnx_set_bits(TRAFFIC_VALID, TRAFFIC_VALID_SHIFT, 1);
183/* reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1); */
184 traffic->reg0 = cpu_to_le32(reg);
185
186 /* 3. setting RX Sequence Number to 4095 */
187 reg = agnx_set_bits(RX_SEQUENCE_NUM, RX_SEQUENCE_NUM_SHIFT, 4095);
188 traffic->reg1 = cpu_to_le32(reg);
189}
190
191
192/* @num: The #number of station that is visible to the card */
193void sta_init(struct agnx_priv *priv, unsigned int sta_idx)
194{
195 /* FIXME the length of sta is 256 bytes Is that
196 * dangerous to stack overflow? */
197 struct agnx_sta sta;
198 u32 reg;
199 int i;
200
201 memset(&sta, 0, sizeof(sta));
202 /* Set valid to 1 */
203 reg = agnx_set_bits(STATION_VALID, STATION_VALID_SHIFT, 1);
204 /* Set Enable Concatenation to 0 (?) */
205 reg |= agnx_set_bits(ENABLE_CONCATENATION, ENABLE_CONCATENATION_SHIFT, 0);
206 /* Set Enable Decompression to 0 (?) */
207 reg |= agnx_set_bits(ENABLE_DECOMPRESSION, ENABLE_DECOMPRESSION_SHIFT, 0);
208 sta.reg = cpu_to_le32(reg);
209
210 /* Initialize each of the Traffic Class Structures by: */
211 for (i = 0; i < 8; i++)
212 sta_traffic_init(sta.traffic + i);
213
214 set_sta(priv, &sta, sta_idx);
215 sta_tx_workqueue_init(priv, sta_idx);
216} /* sta_descriptor_init */
217
218
diff --git a/drivers/staging/agnx/sta.h b/drivers/staging/agnx/sta.h
deleted file mode 100644
index fd504e3f3870..000000000000
--- a/drivers/staging/agnx/sta.h
+++ /dev/null
@@ -1,222 +0,0 @@
1#ifndef AGNX_STA_H_
2#define AGNX_STA_H_
3
4#define STA_TX_WQ_NUM 8 /* The number of TX workqueue one STA has */
5
6struct agnx_hash_cmd {
7 __be32 cmdhi;
8#define MACLO 0xFFFF0000
9#define MACLO_SHIFT 16
10#define STA_ID 0x0000FFF0
11#define STA_ID_SHIFT 4
12#define CMD 0x0000000C
13#define CMD_SHIFT 2
14#define STATUS 0x00000002
15#define STATUS_SHIFT 1
16#define PASS 0x00000001
17#define PASS_SHIFT 1
18 __be32 cmdlo;
19} __attribute__((__packed__));
20
21
22/*
23 * Station Power Template
24 * FIXME Just for agn100 yet
25 */
26struct agnx_sta_power {
27 __le32 reg;
28#define SIGNAL 0x000000FF /* signal */
29#define SIGNAL_SHIFT 0
30#define RATE 0x00000F00
31#define RATE_SHIFT 8
32#define TIFS 0x00001000
33#define TIFS_SHIFT 12
34#define EDCF 0x00002000
35#define EDCF_SHIFT 13
36#define CHANNEL_BOND 0x00004000
37#define CHANNEL_BOND_SHIFT 14
38#define PHY_MODE 0x00038000
39#define PHY_MODE_SHIFT 15
40#define POWER_LEVEL 0x007C0000
41#define POWER_LEVEL_SHIFT 18
42#define NUM_TRANSMITTERS 0x00800000
43#define NUM_TRANSMITTERS_SHIFT 23
44} __attribute__((__packed__));
45
46/*
47 * TX Workqueue Descriptor
48 */
49struct agnx_sta_tx_wq {
50 __le32 reg0;
51#define HEAD_POINTER_LOW 0xFF000000 /* Head pointer low */
52#define HEAD_POINTER_LOW_SHIFT 24
53#define TAIL_POINTER 0x00FFFFFF /* Tail pointer */
54#define TAIL_POINTER_SHIFT 0
55
56 __le32 reg3;
57#define ACK_POINTER_LOW 0xFFFF0000 /* ACK pointer low */
58#define ACK_POINTER_LOW_SHIFT 16
59#define HEAD_POINTER_HIGH 0x0000FFFF /* Head pointer high */
60#define HEAD_POINTER_HIGH_SHIFT 0
61
62 __le32 reg1;
63/* ACK timeout tail packet count */
64#define ACK_TIMOUT_TAIL_PACK_CNT 0xFFF00000
65#define ACK_TIMOUT_TAIL_PACK_CNT_SHIFT 20
66/* Head timeout tail packet count */
67#define HEAD_TIMOUT_TAIL_PACK_CNT 0x000FFF00
68#define HEAD_TIMOUT_TAIL_PACK_CNT_SHIFT 8
69#define ACK_POINTER_HIGH 0x000000FF /* ACK pointer high */
70#define ACK_POINTER_HIGH_SHIFT 0
71
72 __le32 reg2;
73#define WORK_QUEUE_VALID 0x80000000 /* valid */
74#define WORK_QUEUE_VALID_SHIFT 31
75#define WORK_QUEUE_ACK_TYPE 0x40000000 /* ACK type */
76#define WORK_QUEUE_ACK_TYPE_SHIFT 30
77/* Head timeout window limit fragmentation count */
78#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT 0x3FFF0000
79#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT_SHIFT 16
80/* Head timeout window limit byte count */
81#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT 0x0000FFFF
82#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT_SHIFT 0
83} __attribute__((__packed__));
84
85
86/*
87 * Traffic Class Structure
88 */
89struct agnx_sta_traffic {
90 __le32 reg0;
91#define ACK_TIMOUT_CNT 0xFF800000 /* ACK Timeout Counts */
92#define ACK_TIMOUT_CNT_SHIFT 23
93#define TRAFFIC_ACK_TYPE 0x00600000 /* ACK Type */
94#define TRAFFIC_ACK_TYPE_SHIFT 21
95#define NEW_PACKET 0x00100000 /* New Packet */
96#define NEW_PACKET_SHIFT 20
97#define TRAFFIC_VALID 0x00080000 /* Valid */
98#define TRAFFIC_VALID_SHIFT 19
99#define RX_HDR_DESC_POINTER 0x0007FFFF /* RX Header Descripter pointer */
100#define RX_HDR_DESC_POINTER_SHIFT 0
101
102 __le32 reg1;
103#define RX_PACKET_TIMESTAMP 0xFFFF0000 /* RX Packet Timestamp */
104#define RX_PACKET_TIMESTAMP_SHIFT 16
105#define TRAFFIC_RESERVED 0x0000E000 /* Reserved */
106#define TRAFFIC_RESERVED_SHIFT 13
107#define SV 0x00001000 /* sv */
108#define SV_SHIFT 12
109#define RX_SEQUENCE_NUM 0x00000FFF /* RX Sequence Number */
110#define RX_SEQUENCE_NUM_SHIFT 0
111
112 __le32 tx_replay_cnt_low; /* TX Replay Counter Low */
113
114 __le16 tx_replay_cnt_high; /* TX Replay Counter High */
115 __le16 rx_replay_cnt_high; /* RX Replay Counter High */
116
117 __be32 rx_replay_cnt_low; /* RX Replay Counter Low */
118} __attribute__((__packed__));
119
120/*
121 * Station Descriptors
122 */
123struct agnx_sta {
124 __le32 tx_session_keys[4]; /* Transmit Session Key (0-3) */
125 __le32 rx_session_keys[4]; /* Receive Session Key (0-3) */
126
127 __le32 reg;
128#define ID_1 0xC0000000 /* id 1 */
129#define ID_1_SHIFT 30
130#define ID_0 0x30000000 /* id 0 */
131#define ID_0_SHIFT 28
132#define ENABLE_CONCATENATION 0x0FF00000 /* Enable concatenation */
133#define ENABLE_CONCATENATION_SHIFT 20
134#define ENABLE_DECOMPRESSION 0x000FF000 /* Enable decompression */
135#define ENABLE_DECOMPRESSION_SHIFT 12
136#define STA_RESERVED 0x00000C00 /* Reserved */
137#define STA_RESERVED_SHIFT 10
138#define EAP 0x00000200 /* EAP */
139#define EAP_SHIFT 9
140#define ED_NULL 0x00000100 /* ED NULL */
141#define ED_NULL_SHIFT 8
142#define ENCRYPTION_POLICY 0x000000E0 /* Encryption Policy */
143#define ENCRYPTION_POLICY_SHIFT 5
144#define DEFINED_KEY_ID 0x00000018 /* Defined Key ID */
145#define DEFINED_KEY_ID_SHIFT 3
146#define FIXED_KEY 0x00000004 /* Fixed Key */
147#define FIXED_KEY_SHIFT 2
148#define KEY_VALID 0x00000002 /* Key Valid */
149#define KEY_VALID_SHIFT 1
150#define STATION_VALID 0x00000001 /* Station Valid */
151#define STATION_VALID_SHIFT 0
152
153 __le32 tx_aes_blks_unicast; /* TX AES Blks Unicast */
154 __le32 rx_aes_blks_unicast; /* RX AES Blks Unicast */
155
156 __le16 aes_format_err_unicast_cnt; /* AES Format Error Unicast Counts */
157 __le16 aes_replay_unicast; /* AES Replay Unicast */
158
159 __le16 aes_decrypt_err_unicast; /* AES Decrypt Error Unicast */
160 __le16 aes_decrypt_err_default; /* AES Decrypt Error default */
161
162 __le16 single_retry_packets; /* Single Retry Packets */
163 __le16 failed_tx_packets; /* Failed Tx Packets */
164
165 __le16 muti_retry_packets; /* Multiple Retry Packets */
166 __le16 ack_timeouts; /* ACK Timeouts */
167
168 __le16 frag_tx_cnt; /* Fragment TX Counts */
169 __le16 rts_brq_sent; /* RTS Brq Sent */
170
171 __le16 tx_packets; /* TX Packets */
172 __le16 cts_back_timeout; /* CTS Back Timeout */
173
174 __le32 phy_stats_high; /* PHY Stats High */
175 __le32 phy_stats_low; /* PHY Stats Low */
176
177 struct agnx_sta_traffic traffic[8]; /* Traffic Class Structure (8) */
178
179 __le16 traffic_class0_frag_success; /* Traffic Class 0 Fragment Success */
180 __le16 traffic_class1_frag_success; /* Traffic Class 1 Fragment Success */
181 __le16 traffic_class2_frag_success; /* Traffic Class 2 Fragment Success */
182 __le16 traffic_class3_frag_success; /* Traffic Class 3 Fragment Success */
183 __le16 traffic_class4_frag_success; /* Traffic Class 4 Fragment Success */
184 __le16 traffic_class5_frag_success; /* Traffic Class 5 Fragment Success */
185 __le16 traffic_class6_frag_success; /* Traffic Class 6 Fragment Success */
186 __le16 traffic_class7_frag_success; /* Traffic Class 7 Fragment Success */
187
188 __le16 num_frag_non_prime_rates; /* number of Fragments for non-prime rates */
189 __le16 ack_timeout_non_prime_rates; /* ACK Timeout for non-prime rates */
190
191} __attribute__((__packed__));
192
193
194struct agnx_beacon_hdr {
195 struct agnx_sta_power power; /* Tx Station Power Template */
196 u8 phy_hdr[6]; /* PHY Hdr */
197 u8 frame_len_lo; /* Frame Length Lo */
198 u8 frame_len_hi; /* Frame Length Hi */
199 u8 mac_hdr[24]; /* MAC Header */
200 /* FIXME */
201 /* 802.11(abg) beacon */
202} __attribute__((__packed__));
203
204void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id);
205void hash_dump(struct agnx_priv *priv, u8 sta_id);
206void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
207void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
208
209void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx);
210void set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power,
211 unsigned int sta_idx);
212void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
213 unsigned int sta_idx, unsigned int wq_idx);
214void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
215 unsigned int sta_idx, unsigned int wq_idx);
216void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
217void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
218
219void sta_power_init(struct agnx_priv *priv, unsigned int num);
220void sta_init(struct agnx_priv *priv, unsigned int num);
221
222#endif /* AGNX_STA_H_ */
diff --git a/drivers/staging/agnx/table.c b/drivers/staging/agnx/table.c
deleted file mode 100644
index b52fef9db0e3..000000000000
--- a/drivers/staging/agnx/table.c
+++ /dev/null
@@ -1,168 +0,0 @@
1#include <linux/pci.h>
2#include <linux/delay.h>
3#include "agnx.h"
4#include "debug.h"
5#include "phy.h"
6
7static const u32
8tx_fir_table[] = { 0x19, 0x5d, 0xce, 0x151, 0x1c3, 0x1ff, 0x1ea, 0x17c, 0xcf,
9 0x19, 0x38e, 0x350, 0x362, 0x3ad, 0x5, 0x44, 0x59, 0x49,
10 0x21, 0x3f7, 0x3e0, 0x3e3, 0x3f3, 0x0 };
11
12void tx_fir_table_init(struct agnx_priv *priv)
13{
14 void __iomem *ctl = priv->ctl;
15 int i;
16
17 for (i = 0; i < ARRAY_SIZE(tx_fir_table); i++)
18 iowrite32(tx_fir_table[i], ctl + AGNX_FIR_BASE + i*4);
19} /* fir_table_setup */
20
21
22static const u32
23gain_table[] = { 0x8, 0x8, 0xf, 0x13, 0x17, 0x1b, 0x1f, 0x23, 0x27, 0x2b,
24 0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43, 0x47, 0x4b, 0x4f,
25 0x53, 0x57, 0x5b, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
26 0x5f, 0x5f, 0x5f, 0x5f };
27
28void gain_table_init(struct agnx_priv *priv)
29{
30 void __iomem *ctl = priv->ctl;
31 int i;
32
33 for (i = 0; i < ARRAY_SIZE(gain_table); i++) {
34 iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4);
35 iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4 + 0x80);
36 }
37} /* gain_table_init */
38
39void monitor_gain_table_init(struct agnx_priv *priv)
40{
41 void __iomem *ctl = priv->ctl;
42 unsigned int i;
43
44 for (i = 0; i < 0x44; i += 4) {
45 iowrite32(0x61, ctl + AGNX_MONGCR_BASE + i);
46 iowrite32(0x61, ctl + AGNX_MONGCR_BASE + 0x200 + i);
47 }
48 for (i = 0x44; i < 0x64; i += 4) {
49 iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + i);
50 iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + 0x200 + i);
51 }
52 for (i = 0x64; i < 0x94; i += 4) {
53 iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + i);
54 iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + 0x200 + i);
55 }
56 for (i = 0x94; i < 0xdc; i += 4) {
57 iowrite32(0x87, ctl + AGNX_MONGCR_BASE + i);
58 iowrite32(0x87, ctl + AGNX_MONGCR_BASE + 0x200 + i);
59 }
60 for (i = 0xdc; i < 0x148; i += 4) {
61 iowrite32(0x95, ctl + AGNX_MONGCR_BASE + i);
62 iowrite32(0x95, ctl + AGNX_MONGCR_BASE + 0x200 + i);
63 }
64 for (i = 0x148; i < 0x1e8; i += 4) {
65 iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + i);
66 iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + 0x200 + i);
67 }
68 for (i = 0x1e8; i <= 0x1fc; i += 4) {
69 iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + i);
70 iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + 0x200 + i);
71 }
72} /* monitor_gain_table_init */
73
74
75void routing_table_init(struct agnx_priv *priv)
76{
77 void __iomem *ctl = priv->ctl;
78 unsigned int type, subtype;
79 u32 reg;
80
81 disable_receiver(priv);
82
83 for (type = 0; type < 0x3; type++) {
84 for (subtype = 0; subtype < 0x10; subtype++) {
85 /* 1. Set Routing table to R/W and to Return status on Read */
86 reg = (type << ROUTAB_TYPE_SHIFT) |
87 (subtype << ROUTAB_SUBTYPE_SHIFT);
88 reg |= (1 << ROUTAB_RW_SHIFT) | (1 << ROUTAB_STATUS_SHIFT);
89 if (type == ROUTAB_TYPE_DATA) {
90 /* NULL goes to RFP */
91 if (subtype == ROUTAB_SUBTYPE_NULL)
92/* reg |= ROUTAB_ROUTE_RFP; */
93 reg |= ROUTAB_ROUTE_CPU;
94 /* QOS NULL goes to CPU */
95 else if (subtype == ROUTAB_SUBTYPE_QOSNULL)
96 reg |= ROUTAB_ROUTE_CPU;
97 /* All Data and QOS data subtypes go to Encryption */
98 else if ((subtype == ROUTAB_SUBTYPE_DATA) ||
99 (subtype == ROUTAB_SUBTYPE_DATAACK) ||
100 (subtype == ROUTAB_SUBTYPE_DATAPOLL) ||
101 (subtype == ROUTAB_SUBTYPE_DATAPOLLACK) ||
102 (subtype == ROUTAB_SUBTYPE_QOSDATA) ||
103 (subtype == ROUTAB_SUBTYPE_QOSDATAACK) ||
104 (subtype == ROUTAB_SUBTYPE_QOSDATAPOLL) ||
105 (subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL))
106 reg |= ROUTAB_ROUTE_ENCRY;
107/* reg |= ROUTAB_ROUTE_CPU; */
108 /*Drop NULL and QOS NULL ack, poll and poll ack*/
109 else if ((subtype == ROUTAB_SUBTYPE_NULLACK) ||
110 (subtype == ROUTAB_SUBTYPE_QOSNULLACK) ||
111 (subtype == ROUTAB_SUBTYPE_NULLPOLL) ||
112 (subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) ||
113 (subtype == ROUTAB_SUBTYPE_NULLPOLLACK) ||
114 (subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK))
115/* reg |= ROUTAB_ROUTE_DROP; */
116 reg |= ROUTAB_ROUTE_CPU;
117 } else {
118 reg |= (ROUTAB_ROUTE_CPU);
119 }
120 iowrite32(reg, ctl + AGNX_RXM_ROUTAB);
121 /* Check to verify that the status bit cleared */
122 routing_table_delay();
123 }
124 }
125 enable_receiver(priv);
126} /* routing_table_init */
127
128void tx_engine_lookup_tbl_init(struct agnx_priv *priv)
129{
130 void __iomem *data = priv->data;
131 unsigned int i;
132
133 for (i = 0; i <= 28; i += 4)
134 iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
135 for (i = 32; i <= 120; i += 8) {
136 iowrite32(0x1e58, data + AGNX_ENGINE_LOOKUP_TBL + i);
137 iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
138 }
139
140 for (i = 128; i <= 156; i += 4)
141 iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
142 for (i = 160; i <= 248; i += 8) {
143 iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i);
144 iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
145 }
146
147 for (i = 256; i <= 284; i += 4)
148 iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
149 for (i = 288; i <= 376; i += 8) {
150 iowrite32(0x1a58, data + AGNX_ENGINE_LOOKUP_TBL + i);
151 iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
152 }
153
154 for (i = 512; i <= 540; i += 4)
155 iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
156 for (i = 544; i <= 632; i += 8) {
157 iowrite32(0x2058, data + AGNX_ENGINE_LOOKUP_TBL + i);
158 iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
159 }
160
161 for (i = 640; i <= 668; i += 4)
162 iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i);
163 for (i = 672; i <= 764; i += 8) {
164 iowrite32(0x2258, data + AGNX_ENGINE_LOOKUP_TBL + i);
165 iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
166 }
167}
168
diff --git a/drivers/staging/agnx/table.h b/drivers/staging/agnx/table.h
deleted file mode 100644
index f0626b5ee86b..000000000000
--- a/drivers/staging/agnx/table.h
+++ /dev/null
@@ -1,10 +0,0 @@
1#ifndef AGNX_TABLE_H_
2#define AGNX_TABLE_H_
3
4void tx_fir_table_init(struct agnx_priv *priv);
5void gain_table_init(struct agnx_priv *priv);
6void monitor_gain_table_init(struct agnx_priv *priv);
7void routing_table_init(struct agnx_priv *priv);
8void tx_engine_lookup_tbl_init(struct agnx_priv *priv);
9
10#endif /* AGNX_TABLE_H_ */
diff --git a/drivers/staging/agnx/xmit.c b/drivers/staging/agnx/xmit.c
deleted file mode 100644
index 42db41070cf0..000000000000
--- a/drivers/staging/agnx/xmit.c
+++ /dev/null
@@ -1,836 +0,0 @@
1/**
2 * Airgo MIMO wireless driver
3 *
4 * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
5
6 * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
7 * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
8
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/pci.h>
15#include <linux/delay.h>
16#include "agnx.h"
17#include "debug.h"
18#include "phy.h"
19
20unsigned int rx_frame_cnt;
21/* unsigned int local_tx_sent_cnt = 0; */
22
23static inline void disable_rx_engine(struct agnx_priv *priv)
24{
25 void __iomem *ctl = priv->ctl;
26 iowrite32(0x100, ctl + AGNX_CIR_RXCTL);
27 /* Wait for RX Control to have the Disable Rx Interrupt (0x100) set */
28 ioread32(ctl + AGNX_CIR_RXCTL);
29}
30
31static inline void enable_rx_engine(struct agnx_priv *priv)
32{
33 void __iomem *ctl = priv->ctl;
34 iowrite32(0x80, ctl + AGNX_CIR_RXCTL);
35 ioread32(ctl + AGNX_CIR_RXCTL);
36}
37
38inline void disable_rx_interrupt(struct agnx_priv *priv)
39{
40 void __iomem *ctl = priv->ctl;
41 u32 reg;
42
43 disable_rx_engine(priv);
44 reg = ioread32(ctl + AGNX_CIR_RXCFG);
45 reg &= ~0x20;
46 iowrite32(reg, ctl + AGNX_CIR_RXCFG);
47 ioread32(ctl + AGNX_CIR_RXCFG);
48}
49
50inline void enable_rx_interrupt(struct agnx_priv *priv)
51{
52 void __iomem *ctl = priv->ctl;
53 u32 reg;
54
55 reg = ioread32(ctl + AGNX_CIR_RXCFG);
56 reg |= 0x20;
57 iowrite32(reg, ctl + AGNX_CIR_RXCFG);
58 ioread32(ctl + AGNX_CIR_RXCFG);
59 enable_rx_engine(priv);
60}
61
62static inline void rx_desc_init(struct agnx_priv *priv, unsigned int idx)
63{
64 struct agnx_desc *desc = priv->rx.desc + idx;
65 struct agnx_info *info = priv->rx.info + idx;
66
67 memset(info, 0, sizeof(*info));
68
69 info->dma_len = IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct agnx_hdr);
70 info->skb = dev_alloc_skb(info->dma_len);
71 if (info->skb == NULL)
72 agnx_bug("refill err");
73
74 info->mapping = pci_map_single(priv->pdev, skb_tail_pointer(info->skb),
75 info->dma_len, PCI_DMA_FROMDEVICE);
76 memset(desc, 0, sizeof(*desc));
77 desc->dma_addr = cpu_to_be32(info->mapping);
78 /* Set the owner to the card */
79 desc->frag = cpu_to_be32(be32_to_cpu(desc->frag) | OWNER);
80}
81
82static inline void rx_desc_reinit(struct agnx_priv *priv, unsigned int idx)
83{
84 struct agnx_info *info = priv->rx.info + idx;
85
86 /* Cause ieee80211 will free the skb buffer, so we needn't to free it again?! */
87 pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_FROMDEVICE);
88 rx_desc_init(priv, idx);
89}
90
91static inline void rx_desc_reusing(struct agnx_priv *priv, unsigned int idx)
92{
93 struct agnx_desc *desc = priv->rx.desc + idx;
94 struct agnx_info *info = priv->rx.info + idx;
95
96 memset(desc, 0, sizeof(*desc));
97 desc->dma_addr = cpu_to_be32(info->mapping);
98 /* Set the owner to the card */
99 desc->frag = cpu_to_be32(be32_to_cpu(desc->frag) | OWNER);
100}
101
102static void rx_desc_free(struct agnx_priv *priv, unsigned int idx)
103{
104 struct agnx_desc *desc = priv->rx.desc + idx;
105 struct agnx_info *info = priv->rx.info + idx;
106
107 BUG_ON(!desc || !info);
108 if (info->mapping)
109 pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_FROMDEVICE);
110 if (info->skb)
111 dev_kfree_skb(info->skb);
112 memset(info, 0, sizeof(*info));
113 memset(desc, 0, sizeof(*desc));
114}
115
116static inline void __tx_desc_free(struct agnx_priv *priv,
117 struct agnx_desc *desc, struct agnx_info *info)
118{
119 BUG_ON(!desc || !info);
120 /* TODO make sure mapping, skb and len are consistency */
121 if (info->mapping)
122 pci_unmap_single(priv->pdev, info->mapping,
123 info->dma_len, PCI_DMA_TODEVICE);
124 if (info->type == PACKET)
125 dev_kfree_skb(info->skb);
126
127 memset(info, 0, sizeof(*info));
128 memset(desc, 0, sizeof(*desc));
129}
130
131static void txm_desc_free(struct agnx_priv *priv, unsigned int idx)
132{
133 struct agnx_desc *desc = priv->txm.desc + idx;
134 struct agnx_info *info = priv->txm.info + idx;
135
136 __tx_desc_free(priv, desc, info);
137}
138
139static void txd_desc_free(struct agnx_priv *priv, unsigned int idx)
140{
141 struct agnx_desc *desc = priv->txd.desc + idx;
142 struct agnx_info *info = priv->txd.info + idx;
143
144 __tx_desc_free(priv, desc, info);
145}
146
147int fill_rings(struct agnx_priv *priv)
148{
149 void __iomem *ctl = priv->ctl;
150 unsigned int i;
151 u32 reg;
152 AGNX_TRACE;
153
154 priv->txd.idx_sent = priv->txm.idx_sent = 0;
155 priv->rx.idx = priv->txm.idx = priv->txd.idx = 0;
156
157 for (i = 0; i < priv->rx.size; i++)
158 rx_desc_init(priv, i);
159 for (i = 0; i < priv->txm.size; i++) {
160 memset(priv->txm.desc + i, 0, sizeof(struct agnx_desc));
161 memset(priv->txm.info + i, 0, sizeof(struct agnx_info));
162 }
163 for (i = 0; i < priv->txd.size; i++) {
164 memset(priv->txd.desc + i, 0, sizeof(struct agnx_desc));
165 memset(priv->txd.info + i, 0, sizeof(struct agnx_info));
166 }
167
168 /* FIXME Set the card RX TXM and TXD address */
169 agnx_write32(ctl, AGNX_CIR_RXCMSTART, priv->rx.dma);
170 agnx_write32(ctl, AGNX_CIR_RXCMEND, priv->txm.dma);
171
172 agnx_write32(ctl, AGNX_CIR_TXMSTART, priv->txm.dma);
173 agnx_write32(ctl, AGNX_CIR_TXMEND, priv->txd.dma);
174
175 agnx_write32(ctl, AGNX_CIR_TXDSTART, priv->txd.dma);
176 agnx_write32(ctl, AGNX_CIR_TXDEND, priv->txd.dma +
177 sizeof(struct agnx_desc) * priv->txd.size);
178
179 /* FIXME Relinquish control of rings to card */
180 reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
181 reg &= ~0x800;
182 agnx_write32(ctl, AGNX_CIR_BLKCTL, reg);
183 return 0;
184} /* fill_rings */
185
186void unfill_rings(struct agnx_priv *priv)
187{
188 unsigned long flags;
189 unsigned int i;
190 AGNX_TRACE;
191
192 spin_lock_irqsave(&priv->lock, flags);
193
194 for (i = 0; i < priv->rx.size; i++)
195 rx_desc_free(priv, i);
196 for (i = 0; i < priv->txm.size; i++)
197 txm_desc_free(priv, i);
198 for (i = 0; i < priv->txd.size; i++)
199 txd_desc_free(priv, i);
200
201 spin_unlock_irqrestore(&priv->lock, flags);
202}
203
204/* Extract the bitrate out of a CCK PLCP header.
205 copy from bcm43xx driver */
206static inline u8 agnx_plcp_get_bitrate_cck(__be32 *phyhdr_11b)
207{
208 /* FIXME */
209 switch (*(u8 *)phyhdr_11b) {
210 case 0x0A:
211 return 0;
212 case 0x14:
213 return 1;
214 case 0x37:
215 return 2;
216 case 0x6E:
217 return 3;
218 }
219 agnx_bug("Wrong plcp rate");
220 return 0;
221}
222
223/* FIXME */
224static inline u8 agnx_plcp_get_bitrate_ofdm(__be32 *phyhdr_11g)
225{
226 u8 rate = *(u8 *)phyhdr_11g & 0xF;
227
228 printk(PFX "G mode rate is 0x%x\n", rate);
229 return rate;
230}
231
232/* FIXME */
233static void get_rx_stats(struct agnx_priv *priv, struct agnx_hdr *hdr,
234 struct ieee80211_rx_status *stat)
235{
236 void __iomem *ctl = priv->ctl;
237 u8 *rssi;
238 u32 noise;
239 /* FIXME just for test */
240 int snr = 40; /* signal-to-noise ratio */
241
242 memset(stat, 0, sizeof(*stat));
243 /* RSSI */
244 rssi = (u8 *)&hdr->phy_stats_lo;
245/* stat->ssi = (rssi[0] + rssi[1] + rssi[2]) / 3; */
246 /* Noise */
247 noise = ioread32(ctl + AGNX_GCR_NOISE0);
248 noise += ioread32(ctl + AGNX_GCR_NOISE1);
249 noise += ioread32(ctl + AGNX_GCR_NOISE2);
250 stat->noise = noise / 3;
251 /* Signal quality */
252/* snr = stat->ssi - stat->noise; */
253 if (snr >= 0 && snr < 40)
254 stat->signal = 5 * snr / 2;
255 else if (snr >= 40)
256 stat->signal = 100;
257 else
258 stat->signal = 0;
259
260
261 if (hdr->_11b0 && !hdr->_11g0) {
262 stat->rate_idx = agnx_plcp_get_bitrate_cck(&hdr->_11b0);
263 } else if (!hdr->_11b0 && hdr->_11g0) {
264 printk(PFX "RX: Found G mode packet\n");
265 stat->rate_idx = agnx_plcp_get_bitrate_ofdm(&hdr->_11g0);
266 } else
267 agnx_bug("Unknown packets type");
268
269
270 stat->band = IEEE80211_BAND_2GHZ;
271 stat->freq = agnx_channels[priv->channel - 1].center_freq;
272/* stat->antenna = 3;
273 stat->mactime = be32_to_cpu(hdr->time_stamp);
274 stat->channel = priv->channel; */
275}
276
277static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr,
278 struct sk_buff *skb)
279{
280 u16 fctl;
281 unsigned int hdrlen;
282
283 fctl = le16_to_cpu(ieeehdr->frame_control);
284 hdrlen = ieee80211_hdrlen(fctl);
285 /* FIXME */
286 if (hdrlen < (2+2+6)/*minimum hdr*/ ||
287 hdrlen > sizeof(struct ieee80211_mgmt)) {
288 printk(KERN_ERR PFX "hdr len is %d\n", hdrlen);
289 agnx_bug("Wrong ieee80211 hdr detected");
290 }
291 skb_push(skb, hdrlen);
292 memcpy(skb->data, ieeehdr, hdrlen);
293} /* combine_hdr_frag */
294
295static inline int agnx_packet_check(struct agnx_priv *priv, struct agnx_hdr *agnxhdr,
296 unsigned packet_len)
297{
298 if (agnx_get_bits(CRC_FAIL, CRC_FAIL_SHIFT, be32_to_cpu(agnxhdr->reg1)) == 1) {
299 printk(PFX "RX: CRC check fail\n");
300 goto drop;
301 }
302 if (packet_len > 2048) {
303 printk(PFX "RX: Too long packet detected\n");
304 goto drop;
305 }
306
307 /* FIXME Just usable for Promious Mode, for Manage mode exclude FCS */
308/* if (packet_len - sizeof(*agnxhdr) < FCS_LEN) { */
309/* printk(PFX "RX: Too short packet detected\n"); */
310/* goto drop; */
311/* } */
312 return 0;
313drop:
314 priv->stats.dot11FCSErrorCount++;
315 return -1;
316}
317
318void handle_rx_irq(struct agnx_priv *priv)
319{
320 struct ieee80211_rx_status status;
321 unsigned int len;
322/* AGNX_TRACE; */
323
324 do {
325 struct agnx_desc *desc;
326 u32 frag;
327 struct agnx_info *info;
328 struct agnx_hdr *hdr;
329 struct sk_buff *skb;
330 unsigned int i = priv->rx.idx % priv->rx.size;
331
332 desc = priv->rx.desc + i;
333 frag = be32_to_cpu(desc->frag);
334 if (frag & OWNER)
335 break;
336
337 info = priv->rx.info + i;
338 skb = info->skb;
339 hdr = (struct agnx_hdr *)(skb->data);
340
341 len = (frag & PACKET_LEN) >> PACKET_LEN_SHIFT;
342 if (agnx_packet_check(priv, hdr, len) == -1) {
343 rx_desc_reusing(priv, i);
344 continue;
345 }
346 skb_put(skb, len);
347
348 do {
349 u16 fctl;
350 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)->frame_control);
351 if ((fctl & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_BEACON)/* && !(fctl & IEEE80211_STYPE_BEACON)) */
352 dump_ieee80211_hdr((struct ieee80211_hdr *)hdr->mac_hdr, "RX");
353 } while (0);
354
355 if (hdr->_11b0 && !hdr->_11g0) {
356/* int j;
357 u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)
358 ->frame_control);
359 if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
360 agnx_print_rx_hdr(hdr);
361 agnx_print_sta(priv, BSSID_STAID);
362 for (j = 0; j < 8; j++)
363 agnx_print_sta_tx_wq(priv, BSSID_STAID, j);
364 } */
365
366 get_rx_stats(priv, hdr, &status);
367 skb_pull(skb, sizeof(*hdr));
368 combine_hdr_frag((struct ieee80211_hdr *)hdr->mac_hdr, skb);
369 } else if (!hdr->_11b0 && hdr->_11g0) {
370/* int j; */
371 agnx_print_rx_hdr(hdr);
372 agnx_print_sta(priv, BSSID_STAID);
373/* for (j = 0; j < 8; j++) */
374 agnx_print_sta_tx_wq(priv, BSSID_STAID, 0);
375
376 print_hex_dump_bytes("agnx: RX_PACKET: ", DUMP_PREFIX_NONE,
377 skb->data, skb->len + 8);
378
379/* if (agnx_plcp_get_bitrate_ofdm(&hdr->_11g0) == 0) */
380 get_rx_stats(priv, hdr, &status);
381 skb_pull(skb, sizeof(*hdr));
382 combine_hdr_frag((struct ieee80211_hdr *)
383 ((void *)&hdr->mac_hdr), skb);
384/* dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G"); */
385 } else
386 agnx_bug("Unknown packets type");
387 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
388 ieee80211_rx_irqsafe(priv->hw, skb);
389 rx_desc_reinit(priv, i);
390
391 } while (priv->rx.idx++);
392} /* handle_rx_irq */
393
394static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring)
395{
396 struct agnx_desc *desc;
397 struct agnx_info *info;
398 unsigned int idx;
399
400 for (idx = ring->idx_sent; idx < ring->idx; idx++) {
401 unsigned int i = idx % ring->size;
402 u32 frag;
403
404 desc = ring->desc + i;
405 info = ring->info + i;
406
407 frag = be32_to_cpu(desc->frag);
408 if (frag & OWNER) {
409 if (info->type == HEADER)
410 break;
411 else
412 agnx_bug("TX error");
413 }
414
415 pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_TODEVICE);
416
417 do {
418/* int j; */
419 size_t len;
420 len = info->skb->len - sizeof(struct agnx_hdr) + info->hdr_len;
421/* if (len == 614) { */
422/* agnx_print_desc(desc); */
423 if (info->type == PACKET) {
424/* agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data); */
425/* agnx_print_sta_power(priv, LOCAL_STAID); */
426/* agnx_print_sta(priv, LOCAL_STAID); */
427/* for (j = 0; j < 8; j++) */
428/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */
429/* agnx_print_sta_power(priv, BSSID_STAID); */
430/* agnx_print_sta(priv, BSSID_STAID); */
431/* for (j = 0; j < 8; j++) */
432/* agnx_print_sta_tx_wq(priv, BSSID_STAID, 0); */
433 }
434/* } */
435 } while (0);
436
437 if (info->type == PACKET) {
438/* dump_txm_registers(priv);
439 dump_rxm_registers(priv);
440 dump_bm_registers(priv);
441 dump_cir_registers(priv); */
442 }
443
444 if (info->type == PACKET) {
445/* struct ieee80211_hdr *hdr; */
446 struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(info->skb);
447
448 skb_pull(info->skb, sizeof(struct agnx_hdr));
449 memcpy(skb_push(info->skb, info->hdr_len), &info->hdr, info->hdr_len);
450
451/* dump_ieee80211_hdr((struct ieee80211_hdr *)info->skb->data, "TX_HANDLE"); */
452/* print_hex_dump_bytes("agnx: TX_HANDLE: ", DUMP_PREFIX_NONE, */
453/* info->skb->data, info->skb->len); */
454
455 if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK))
456 txi->flags |= IEEE80211_TX_STAT_ACK;
457
458 ieee80211_tx_status_irqsafe(priv->hw, info->skb);
459
460
461/* info->tx_status.queue_number = (ring->size - i) / 2; */
462/* ieee80211_tx_status_irqsafe(priv->hw, info->skb, &(info->tx_status)); */
463/* } else */
464/* dev_kfree_skb_irq(info->skb); */
465 }
466 memset(desc, 0, sizeof(*desc));
467 memset(info, 0, sizeof(*info));
468 }
469
470 ring->idx_sent = idx;
471 /* TODO fill the priv->low_level_stats */
472
473 /* ieee80211_wake_queue(priv->hw, 0); */
474}
475
476void handle_txm_irq(struct agnx_priv *priv)
477{
478 handle_tx_irq(priv, &priv->txm);
479}
480
481void handle_txd_irq(struct agnx_priv *priv)
482{
483 handle_tx_irq(priv, &priv->txd);
484}
485
486void handle_other_irq(struct agnx_priv *priv)
487{
488/* void __iomem *ctl = priv->ctl; */
489 u32 status = priv->irq_status;
490 void __iomem *ctl = priv->ctl;
491 u32 reg;
492
493 if (status & IRQ_TX_BEACON) {
494 iowrite32(IRQ_TX_BEACON, ctl + AGNX_INT_STAT);
495 printk(PFX "IRQ: TX Beacon control is 0X%.8X\n", ioread32(ctl + AGNX_TXM_BEACON_CTL));
496 printk(PFX "IRQ: TX Beacon rx frame num: %d\n", rx_frame_cnt);
497 }
498 if (status & IRQ_TX_RETRY) {
499 reg = ioread32(ctl + AGNX_TXM_RETRYSTAID);
500 printk(PFX "IRQ: TX Retry, RETRY STA ID is %x\n", reg);
501 }
502 if (status & IRQ_TX_ACTIVITY)
503 printk(PFX "IRQ: TX Activity\n");
504 if (status & IRQ_RX_ACTIVITY)
505 printk(PFX "IRQ: RX Activity\n");
506 if (status & IRQ_RX_X)
507 printk(PFX "IRQ: RX X\n");
508 if (status & IRQ_RX_Y) {
509 reg = ioread32(ctl + AGNX_INT_MASK);
510 reg &= ~IRQ_RX_Y;
511 iowrite32(reg, ctl + AGNX_INT_MASK);
512 iowrite32(IRQ_RX_Y, ctl + AGNX_INT_STAT);
513 printk(PFX "IRQ: RX Y\n");
514 }
515 if (status & IRQ_RX_HASHHIT) {
516 reg = ioread32(ctl + AGNX_INT_MASK);
517 reg &= ~IRQ_RX_HASHHIT;
518 iowrite32(reg, ctl + AGNX_INT_MASK);
519 iowrite32(IRQ_RX_HASHHIT, ctl + AGNX_INT_STAT);
520 printk(PFX "IRQ: RX Hash Hit\n");
521
522 }
523 if (status & IRQ_RX_FRAME) {
524 reg = ioread32(ctl + AGNX_INT_MASK);
525 reg &= ~IRQ_RX_FRAME;
526 iowrite32(reg, ctl + AGNX_INT_MASK);
527 iowrite32(IRQ_RX_FRAME, ctl + AGNX_INT_STAT);
528 printk(PFX "IRQ: RX Frame\n");
529 rx_frame_cnt++;
530 }
531 if (status & IRQ_ERR_INT) {
532 iowrite32(IRQ_ERR_INT, ctl + AGNX_INT_STAT);
533/* agnx_hw_reset(priv); */
534 printk(PFX "IRQ: Error Interrupt\n");
535 }
536 if (status & IRQ_TX_QUE_FULL)
537 printk(PFX "IRQ: TX Workqueue Full\n");
538 if (status & IRQ_BANDMAN_ERR)
539 printk(PFX "IRQ: Bandwidth Management Error\n");
540 if (status & IRQ_TX_DISABLE)
541 printk(PFX "IRQ: TX Disable\n");
542 if (status & IRQ_RX_IVASESKEY)
543 printk(PFX "IRQ: RX Invalid Session Key\n");
544 if (status & IRQ_REP_THHIT)
545 printk(PFX "IRQ: Replay Threshold Hit\n");
546 if (status & IRQ_TIMER1)
547 printk(PFX "IRQ: Timer1\n");
548 if (status & IRQ_TIMER_CNT)
549 printk(PFX "IRQ: Timer Count\n");
550 if (status & IRQ_PHY_FASTINT)
551 printk(PFX "IRQ: Phy Fast Interrupt\n");
552 if (status & IRQ_PHY_SLOWINT)
553 printk(PFX "IRQ: Phy Slow Interrupt\n");
554 if (status & IRQ_OTHER)
555 printk(PFX "IRQ: 0x80000000\n");
556} /* handle_other_irq */
557
558
559static inline void route_flag_set(struct agnx_hdr *txhdr)
560{
561/* u32 reg = 0; */
562
563 /* FIXME */
564/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */
565/* txhdr->reg5 = cpu_to_be32(reg); */
566 txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18);
567/* txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18)); */
568/* txhdr->reg5 = cpu_to_be32(0x7 << 0x0); */
569}
570
571/* Return 0 if no match */
572static inline unsigned int get_power_level(unsigned int rate, unsigned int antennas_num)
573{
574 unsigned int power_level;
575
576 switch (rate) {
577 case 10:
578 case 20:
579 case 55:
580 case 60:
581 case 90:
582 case 120:
583 power_level = 22;
584 break;
585
586 case 180:
587 power_level = 19;
588 break;
589
590 case 240:
591 power_level = 18;
592 break;
593
594 case 360:
595 power_level = 16;
596 break;
597
598 case 480:
599 power_level = 15;
600 break;
601
602 case 540:
603 power_level = 14;
604 break;
605 default:
606 agnx_bug("Error rate setting\n");
607 }
608
609 if (power_level && (antennas_num == 2))
610 power_level -= 3;
611
612 return power_level;
613}
614
615static inline void fill_agnx_hdr(struct agnx_priv *priv, struct agnx_info *tx_info)
616{
617 struct agnx_hdr *txhdr = (struct agnx_hdr *)tx_info->skb->data;
618 size_t len;
619 u16 fc = le16_to_cpu(*(__le16 *)&tx_info->hdr);
620 u32 reg;
621
622 memset(txhdr, 0, sizeof(*txhdr));
623
624/* reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, LOCAL_STAID); */
625 reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, BSSID_STAID);
626 reg |= agnx_set_bits(WORKQUEUE_ID, WORKQUEUE_ID_SHIFT, 0);
627 txhdr->reg4 = cpu_to_be32(reg);
628
629 /* Set the Hardware Sequence Number to 1? */
630 reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 0);
631/* reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 1); */
632 reg |= agnx_set_bits(MAC_HDR_LEN, MAC_HDR_LEN_SHIFT, tx_info->hdr_len);
633 txhdr->reg1 = cpu_to_be32(reg);
634 /* Set the agnx_hdr's MAC header */
635 memcpy(txhdr->mac_hdr, &tx_info->hdr, tx_info->hdr_len);
636
637 reg = agnx_set_bits(ACK, ACK_SHIFT, 1);
638/* reg = agnx_set_bits(ACK, ACK_SHIFT, 0); */
639 reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 0);
640/* reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 1); */
641 reg |= agnx_set_bits(RELAY, RELAY_SHIFT, 0);
642 reg |= agnx_set_bits(TM, TM_SHIFT, 0);
643 txhdr->reg0 = cpu_to_be32(reg);
644
645 /* Set the long and short retry limits */
646 txhdr->tx.short_retry_limit = tx_info->txi->control.rates[0].count;
647 txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count;
648
649 /* FIXME */
650 len = tx_info->skb->len - sizeof(*txhdr) + tx_info->hdr_len + FCS_LEN;
651 if (fc & IEEE80211_FCTL_PROTECTED)
652 len += 8;
653 len = 2398;
654 reg = agnx_set_bits(FRAG_SIZE, FRAG_SIZE_SHIFT, len);
655 len = tx_info->skb->len - sizeof(*txhdr);
656 reg |= agnx_set_bits(PAYLOAD_LEN, PAYLOAD_LEN_SHIFT, len);
657 txhdr->reg3 = cpu_to_be32(reg);
658
659 route_flag_set(txhdr);
660} /* fill_hdr */
661
662static void txm_power_set(struct agnx_priv *priv,
663 struct ieee80211_tx_info *txi)
664{
665 struct agnx_sta_power power;
666 u32 reg;
667
668 /* FIXME */
669 if (txi->control.rates[0].idx < 0) {
670 /* For B mode Short Preamble */
671 reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_SHORT);
672/* control->tx_rate = -control->tx_rate; */
673 } else
674 reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211G);
675/* reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_LONG); */
676 reg |= agnx_set_bits(SIGNAL, SIGNAL_SHIFT, 0xB);
677 reg |= agnx_set_bits(RATE, RATE_SHIFT, 0xB);
678/* reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 15); */
679 reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 20);
680 /* if rate < 11M set it to 0 */
681 reg |= agnx_set_bits(NUM_TRANSMITTERS, NUM_TRANSMITTERS_SHIFT, 1);
682/* reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1); */
683/* reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1); */
684
685 power.reg = reg;
686/* power.reg = cpu_to_le32(reg); */
687
688/* set_sta_power(priv, &power, LOCAL_STAID); */
689 set_sta_power(priv, &power, BSSID_STAID);
690}
691
692static inline int tx_packet_check(struct sk_buff *skb)
693{
694 unsigned int ieee_len = ieee80211_get_hdrlen_from_skb(skb);
695 if (skb->len > 2048) {
696 printk(KERN_ERR PFX "length is %d\n", skb->len);
697 agnx_bug("Too long TX skb");
698 return -1;
699 }
700 /* FIXME */
701 if (skb->len == ieee_len) {
702 printk(PFX "A strange TX packet\n");
703 return -1;
704 /* tx_faile_irqsafe(); */
705 }
706 return 0;
707}
708
709static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb,
710 struct agnx_ring *ring)
711{
712 struct agnx_desc *hdr_desc, *frag_desc;
713 struct agnx_info *hdr_info, *frag_info;
714 struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
715 unsigned long flags;
716 unsigned int i;
717
718 spin_lock_irqsave(&priv->lock, flags);
719
720 /* The RX interrupt need be Disable until this TX packet
721 is handled in the next tx interrupt */
722 disable_rx_interrupt(priv);
723
724 i = ring->idx;
725 ring->idx += 2;
726/* if (priv->txm_idx - priv->txm_idx_sent == AGNX_TXM_RING_SIZE - 2) */
727/* ieee80211_stop_queue(priv->hw, 0); */
728
729 /* Set agnx header's info and desc */
730 i %= ring->size;
731 hdr_desc = ring->desc + i;
732 hdr_info = ring->info + i;
733 hdr_info->hdr_len = ieee80211_get_hdrlen_from_skb(skb);
734 memcpy(&hdr_info->hdr, skb->data, hdr_info->hdr_len);
735
736 /* Add the agnx header to the front of the SKB */
737 skb_push(skb, sizeof(struct agnx_hdr) - hdr_info->hdr_len);
738
739 hdr_info->txi = txi;
740 hdr_info->dma_len = sizeof(struct agnx_hdr);
741 hdr_info->skb = skb;
742 hdr_info->type = HEADER;
743 fill_agnx_hdr(priv, hdr_info);
744 hdr_info->mapping = pci_map_single(priv->pdev, skb->data,
745 hdr_info->dma_len, PCI_DMA_TODEVICE);
746 do {
747 u32 frag = 0;
748 frag |= agnx_set_bits(FIRST_FRAG, FIRST_FRAG_SHIFT, 1);
749 frag |= agnx_set_bits(LAST_FRAG, LAST_FRAG_SHIFT, 0);
750 frag |= agnx_set_bits(PACKET_LEN, PACKET_LEN_SHIFT, skb->len);
751 frag |= agnx_set_bits(FIRST_FRAG_LEN, FIRST_FRAG_LEN_SHIFT, 1);
752 frag |= agnx_set_bits(OWNER, OWNER_SHIFT, 1);
753 hdr_desc->frag = cpu_to_be32(frag);
754 } while (0);
755 hdr_desc->dma_addr = cpu_to_be32(hdr_info->mapping);
756
757
758 /* Set Frag's info and desc */
759 i = (i + 1) % ring->size;
760 frag_desc = ring->desc + i;
761 frag_info = ring->info + i;
762 memcpy(frag_info, hdr_info, sizeof(struct agnx_info));
763 frag_info->type = PACKET;
764 frag_info->dma_len = skb->len - hdr_info->dma_len;
765 frag_info->mapping = pci_map_single(priv->pdev, skb->data + hdr_info->dma_len,
766 frag_info->dma_len, PCI_DMA_TODEVICE);
767 do {
768 u32 frag = 0;
769 frag |= agnx_set_bits(FIRST_FRAG, FIRST_FRAG_SHIFT, 0);
770 frag |= agnx_set_bits(LAST_FRAG, LAST_FRAG_SHIFT, 1);
771 frag |= agnx_set_bits(PACKET_LEN, PACKET_LEN_SHIFT, skb->len);
772 frag |= agnx_set_bits(SUB_FRAG_LEN, SUB_FRAG_LEN_SHIFT, frag_info->dma_len);
773 frag_desc->frag = cpu_to_be32(frag);
774 } while (0);
775 frag_desc->dma_addr = cpu_to_be32(frag_info->mapping);
776
777 txm_power_set(priv, txi);
778
779/* do { */
780/* int j; */
781/* size_t len; */
782/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */
783/* if (len == 614) { */
784/* agnx_print_desc(hdr_desc); */
785/* agnx_print_desc(frag_desc); */
786/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */
787/* agnx_print_sta_power(priv, LOCAL_STAID); */
788/* agnx_print_sta(priv, LOCAL_STAID); */
789/* for (j = 0; j < 8; j++) */
790/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */
791/* agnx_print_sta_power(priv, BSSID_STAID); */
792/* agnx_print_sta(priv, BSSID_STAID); */
793/* for (j = 0; j < 8; j++) */
794/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
795/* } */
796/* } while (0); */
797
798 spin_unlock_irqrestore(&priv->lock, flags);
799
800 /* FIXME ugly code */
801 /* Trigger TXM */
802 do {
803 u32 reg;
804 reg = (ioread32(priv->ctl + AGNX_CIR_TXMCTL));
805 reg |= 0x8;
806 iowrite32((reg), priv->ctl + AGNX_CIR_TXMCTL);
807 } while (0);
808
809 /* Trigger TXD */
810 do {
811 u32 reg;
812 reg = (ioread32(priv->ctl + AGNX_CIR_TXDCTL));
813 reg |= 0x8;
814 iowrite32((reg), priv->ctl + AGNX_CIR_TXDCTL);
815 } while (0);
816
817 return 0;
818}
819
820int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb)
821{
822 u16 fctl;
823
824 if (tx_packet_check(skb))
825 return 0;
826
827/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */
828/* skb->data, skb->len); */
829
830 fctl = le16_to_cpu(*((__le16 *)skb->data));
831
832 if ((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
833 return __agnx_tx(priv, skb, &priv->txd);
834 else
835 return __agnx_tx(priv, skb, &priv->txm);
836}
diff --git a/drivers/staging/agnx/xmit.h b/drivers/staging/agnx/xmit.h
deleted file mode 100644
index 93ac4157e697..000000000000
--- a/drivers/staging/agnx/xmit.h
+++ /dev/null
@@ -1,250 +0,0 @@
1#ifndef AGNX_XMIT_H_
2#define AGNX_XMIT_H_
3
4#include <net/mac80211.h>
5
6struct agnx_priv;
7
8static inline u32 agnx_set_bits(u32 mask, u8 shift, u32 value)
9{
10 return (value << shift) & mask;
11}
12
13static inline u32 agnx_get_bits(u32 mask, u8 shift, u32 value)
14{
15 return (value & mask) >> shift;
16}
17
18
19struct agnx_rx {
20 __be16 rx_packet_duration; /* RX Packet Duration */
21 __be16 replay_cnt; /* Replay Count */
22} __attribute__((__packed__));
23
24
25struct agnx_tx {
26 u8 long_retry_limit; /* Long Retry Limit */
27 u8 short_retry_limit; /* Short Retry Limit */
28 u8 long_retry_cnt; /* Long Retry Count */
29 u8 short_retry_cnt; /* Short Retry Count */
30} __attribute__((__packed__));
31
32
33/* Copy from bcm43xx */
34#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
35#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
36#define PAD_BYTES(nr_bytes) P4D_BYTES(__LINE__, nr_bytes)
37
38#define P4D_BIT3S(magic, nr_bits) __be32 __padding##magic:nr_bits
39#define P4D_BITS(line, nr_bits) P4D_BIT3S(line, nr_bits)
40#define PAD_BITS(nr_bits) P4D_BITS(__LINE__, nr_bits)
41
42
43struct agnx_hdr {
44 __be32 reg0;
45#define RTS 0x80000000 /* RTS */
46#define RTS_SHIFT 31
47#define MULTICAST 0x40000000 /* multicast */
48#define MULTICAST_SHIFT 30
49#define ACK 0x30000000 /* ACK */
50#define ACK_SHIFT 28
51#define TM 0x08000000 /* TM */
52#define TM_SHIFT 27
53#define RELAY 0x04000000 /* Relay */
54#define RELAY_SHIFT 26
55/* PAD_BITS(4); */
56#define REVISED_FCS 0x00380000 /* revised FCS */
57#define REVISED_FCS_SHIFT 19
58#define NEXT_BUFFER_ADDR 0x0007FFFF /* Next Buffer Address */
59#define NEXT_BUFFER_ADDR_SHIFT 0
60
61 __be32 reg1;
62#define MAC_HDR_LEN 0xFC000000 /* MAC Header Length */
63#define MAC_HDR_LEN_SHIFT 26
64#define DURATION_OVERIDE 0x02000000 /* Duration Override */
65#define DURATION_OVERIDE_SHIFT 25
66#define PHY_HDR_OVERIDE 0x01000000 /* PHY Header Override */
67#define PHY_HDR_OVERIDE_SHIFT 24
68#define CRC_FAIL 0x00800000 /* CRC fail */
69#define CRC_FAIL_SHIFT 23
70/* PAD_BITS(1); */
71#define SEQUENCE_NUMBER 0x00200000 /* Sequence Number */
72#define SEQUENCE_NUMBER_SHIFT 21
73/* PAD_BITS(2); */
74#define BUFF_HEAD_ADDR 0x0007FFFF /* Buffer Head Address */
75#define BUFF_HEAD_ADDR_SHIFT 0
76
77 __be32 reg2;
78#define PDU_COUNT 0xFC000000 /* PDU Count */
79#define PDU_COUNT_SHIFT 26
80/* PAD_BITS(3); */
81#define WEP_KEY 0x00600000 /* WEP Key # */
82#define WEP_KEY_SHIFT 21
83#define USES_WEP_KEY 0x00100000 /* Uses WEP Key */
84#define USES_WEP_KEY_SHIFT 20
85#define KEEP_ALIVE 0x00080000 /* Keep alive */
86#define KEEP_ALIVE_SHIFT 19
87#define BUFF_TAIL_ADDR 0x0007FFFF /* Buffer Tail Address */
88#define BUFF_TAIL_ADDR_SHIFT 0
89
90 __be32 reg3;
91#define CTS_11G 0x80000000 /* CTS in 11g */
92#define CTS_11G_SHIFT 31
93#define RTS_11G 0x40000000 /* RTS in 11g */
94#define RTS_11G_SHIFT 30
95/* PAD_BITS(2); */
96#define FRAG_SIZE 0x0FFF0000 /* fragment size */
97#define FRAG_SIZE_SHIFT 16
98#define PAYLOAD_LEN 0x0000FFF0 /* payload length */
99#define PAYLOAD_LEN_SHIFT 4
100#define FRAG_NUM 0x0000000F /* number of frags */
101#define FRAG_NUM_SHIFT 0
102
103 __be32 reg4;
104/* PAD_BITS(4); */
105#define RELAY_STAID 0x0FFF0000 /* relayStald */
106#define RELAY_STAID_SHIFT 16
107#define STATION_ID 0x0000FFF0 /* Station ID */
108#define STATION_ID_SHIFT 4
109#define WORKQUEUE_ID 0x0000000F /* Workqueue ID */
110#define WORKQUEUE_ID_SHIFT 0
111
112 /* FIXME this register maybe is LE? */
113 __be32 reg5;
114/* PAD_BITS(4); */
115#define ROUTE_HOST 0x0F000000
116#define ROUTE_HOST_SHIFT 24
117#define ROUTE_CARD_CPU 0x00F00000
118#define ROUTE_CARD_CPU_SHIFT 20
119#define ROUTE_ENCRYPTION 0x000F0000
120#define ROUTE_ENCRYPTION_SHIFT 16
121#define ROUTE_TX 0x0000F000
122#define ROUTE_TX_SHIFT 12
123#define ROUTE_RX1 0x00000F00
124#define ROUTE_RX1_SHIFT 8
125#define ROUTE_RX2 0x000000F0
126#define ROUTE_RX2_SHIFT 4
127#define ROUTE_COMPRESSION 0x0000000F
128#define ROUTE_COMPRESSION_SHIFT 0
129
130 __be32 _11g0; /* 11g */
131 __be32 _11g1; /* 11g */
132 __be32 _11b0; /* 11b */
133 __be32 _11b1; /* 11b */
134 u8 mac_hdr[32]; /* MAC header */
135
136 __be16 rts_duration; /* RTS duration */
137 __be16 last_duration; /* Last duration */
138 __be16 sec_last_duration; /* Second to Last duration */
139 __be16 other_duration; /* Other duration */
140 __be16 tx_last_duration; /* TX Last duration */
141 __be16 tx_other_duration; /* TX Other Duration */
142 __be16 last_11g_len; /* Length of last 11g */
143 __be16 other_11g_len; /* Lenght of other 11g */
144
145 __be16 last_11b_len; /* Length of last 11b */
146 __be16 other_11b_len; /* Lenght of other 11b */
147
148
149 __be16 reg6;
150#define MBF 0xF000 /* mbf */
151#define MBF_SHIFT 12
152#define RSVD4 0x0FFF /* rsvd4 */
153#define RSVD4_SHIFT 0
154
155 __be16 rx_frag_stat; /* RX fragmentation status */
156
157 __be32 time_stamp; /* TimeStamp */
158 __be32 phy_stats_hi; /* PHY stats hi */
159 __be32 phy_stats_lo; /* PHY stats lo */
160 __be32 mic_key0; /* MIC key 0 */
161 __be32 mic_key1; /* MIC key 1 */
162
163 union { /* RX/TX Union */
164 struct agnx_rx rx;
165 struct agnx_tx tx;
166 };
167
168 u8 rx_channel; /* Recieve Channel */
169 PAD_BYTES(3);
170
171 u8 reserved[4];
172} __attribute__((__packed__));
173
174
175struct agnx_desc {
176#define PACKET_LEN 0xFFF00000
177#define PACKET_LEN_SHIFT 20
178/* ------------------------------------------------ */
179#define FIRST_PACKET_MASK 0x00080000
180#define FIRST_PACKET_MASK_SHIFT 19
181#define FIRST_RESERV2 0x00040000
182#define FIRST_RESERV2_SHIFT 18
183#define FIRST_TKIP_ERROR 0x00020000
184#define FIRST_TKIP_ERROR_SHIFT 17
185#define FIRST_TKIP_PACKET 0x00010000
186#define FIRST_TKIP_PACKET_SHIFT 16
187#define FIRST_RESERV1 0x0000F000
188#define FIRST_RESERV1_SHIFT 12
189#define FIRST_FRAG_LEN 0x00000FF8
190#define FIRST_FRAG_LEN_SHIFT 3
191/* ------------------------------------------------ */
192#define SUB_RESERV2 0x000c0000
193#define SUB_RESERV2_SHIFT 18
194#define SUB_TKIP_ERROR 0x00020000
195#define SUB_TKIP_ERROR_SHIFT 17
196#define SUB_TKIP_PACKET 0x00010000
197#define SUB_TKIP_PACKET_SHIFT 16
198#define SUB_RESERV1 0x00008000
199#define SUB_RESERV1_SHIFT 15
200#define SUB_FRAG_LEN 0x00007FF8
201#define SUB_FRAG_LEN_SHIFT 3
202/* ------------------------------------------------ */
203#define FIRST_FRAG 0x00000004
204#define FIRST_FRAG_SHIFT 2
205#define LAST_FRAG 0x00000002
206#define LAST_FRAG_SHIFT 1
207#define OWNER 0x00000001
208#define OWNER_SHIFT 0
209 __be32 frag;
210 __be32 dma_addr;
211} __attribute__((__packed__));
212
213enum {HEADER, PACKET};
214
215struct agnx_info {
216 struct sk_buff *skb;
217 dma_addr_t mapping;
218 u32 dma_len; /* dma buffer len */
219 /* Below fields only usful for tx */
220 u32 hdr_len; /* ieee80211 header length */
221 unsigned int type;
222 struct ieee80211_tx_info *txi;
223 struct ieee80211_hdr hdr;
224};
225
226
227struct agnx_ring {
228 struct agnx_desc *desc;
229 dma_addr_t dma;
230 struct agnx_info *info;
231 /* Will lead to overflow when sent packet number enough? */
232 unsigned int idx;
233 unsigned int idx_sent; /* only usful for txd and txm */
234 unsigned int size;
235};
236
237#define AGNX_RX_RING_SIZE 128
238#define AGNX_TXD_RING_SIZE 256
239#define AGNX_TXM_RING_SIZE 128
240
241void disable_rx_interrupt(struct agnx_priv *priv);
242void enable_rx_interrupt(struct agnx_priv *priv);
243int fill_rings(struct agnx_priv *priv);
244void unfill_rings(struct agnx_priv *priv);
245void handle_rx_irq(struct agnx_priv *priv);
246void handle_txd_irq(struct agnx_priv *priv);
247void handle_txm_irq(struct agnx_priv *priv);
248void handle_other_irq(struct agnx_priv *priv);
249int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb);
250#endif /* AGNX_XMIT_H_ */
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index af723cb9d08f..d63c889ce557 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -1,7 +1,7 @@
1config COMEDI 1config COMEDI
2 tristate "Data acquisition support (comedi)" 2 tristate "Data acquisition support (comedi)"
3 default N 3 default N
4 depends on m 4 depends on m && (PCI || PCMCIA || PCCARD || USB)
5 ---help--- 5 ---help---
6 Enable support a wide range of data acquisition devices 6 Enable support a wide range of data acquisition devices
7 for Linux. 7 for Linux.
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index f54bb9b3ee37..aaad76e0a76a 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -2337,7 +2337,7 @@ static int resize_async_buffer(struct comedi_device *dev,
2337 } 2337 }
2338 2338
2339 DPRINTK("comedi%i subd %d buffer resized to %i bytes\n", 2339 DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
2340 dev->minor, s - dev->subdevices, async->prealloc_bufsz); 2340 dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
2341 return 0; 2341 return 0;
2342} 2342}
2343 2343
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 12d12b43a6f1..80c0df8656f3 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -744,7 +744,7 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)
744 744
745 /* Initialize the pcmcia_device structure */ 745 /* Initialize the pcmcia_device structure */
746 /* Interrupt setup */ 746 /* Interrupt setup */
747 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 747 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
748 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 748 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
749 link->irq.Handler = NULL; 749 link->irq.Handler = NULL;
750 750
diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
index 4d10bc31d461..09e6e3bdfb3e 100644
--- a/drivers/staging/comedi/drivers/cb_pcidio.c
+++ b/drivers/staging/comedi/drivers/cb_pcidio.c
@@ -53,7 +53,8 @@ Passing a zero for an option is the same as leaving it unspecified.
53 * Some drivers use arrays such as this, other do not. 53 * Some drivers use arrays such as this, other do not.
54 */ 54 */
55struct pcidio_board { 55struct pcidio_board {
56 const char *name; /* anme of the board */ 56 const char *name; /* name of the board */
57 int dev_id;
57 int n_8255; /* number of 8255 chips on board */ 58 int n_8255; /* number of 8255 chips on board */
58 59
59 /* indices of base address regions */ 60 /* indices of base address regions */
@@ -64,18 +65,21 @@ struct pcidio_board {
64static const struct pcidio_board pcidio_boards[] = { 65static const struct pcidio_board pcidio_boards[] = {
65 { 66 {
66 .name = "pci-dio24", 67 .name = "pci-dio24",
68 .dev_id = 0x0028,
67 .n_8255 = 1, 69 .n_8255 = 1,
68 .pcicontroler_badrindex = 1, 70 .pcicontroler_badrindex = 1,
69 .dioregs_badrindex = 2, 71 .dioregs_badrindex = 2,
70 }, 72 },
71 { 73 {
72 .name = "pci-dio24h", 74 .name = "pci-dio24h",
75 .dev_id = 0x0014,
73 .n_8255 = 1, 76 .n_8255 = 1,
74 .pcicontroler_badrindex = 1, 77 .pcicontroler_badrindex = 1,
75 .dioregs_badrindex = 2, 78 .dioregs_badrindex = 2,
76 }, 79 },
77 { 80 {
78 .name = "pci-dio48h", 81 .name = "pci-dio48h",
82 .dev_id = 0x000b,
79 .n_8255 = 2, 83 .n_8255 = 2,
80 .pcicontroler_badrindex = 0, 84 .pcicontroler_badrindex = 0,
81 .dioregs_badrindex = 1, 85 .dioregs_badrindex = 1,
@@ -206,7 +210,7 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
206 continue; 210 continue;
207 /* loop through cards supported by this driver */ 211 /* loop through cards supported by this driver */
208 for (index = 0; index < ARRAY_SIZE(pcidio_boards); index++) { 212 for (index = 0; index < ARRAY_SIZE(pcidio_boards); index++) {
209 if (pcidio_pci_table[index].device != pcidev->device) 213 if (pcidio_boards[index].dev_id != pcidev->device)
210 continue; 214 continue;
211 215
212 /* was a particular bus/slot requested? */ 216 /* was a particular bus/slot requested? */
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 14bf29bf5781..0d2c2eb23b23 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -515,6 +515,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
515{ 515{
516 struct poll_delay_t result = poll_delay_min_max(1000, 2000); 516 struct poll_delay_t result = poll_delay_min_max(1000, 2000);
517 struct jr3_pci_subdev_private *p = s->private; 517 struct jr3_pci_subdev_private *p = s->private;
518 int i;
518 519
519 if (p) { 520 if (p) {
520 volatile struct jr3_channel *channel = p->channel; 521 volatile struct jr3_channel *channel = p->channel;
@@ -570,18 +571,11 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
570 p->serial_no); 571 p->serial_no);
571 572
572 /* Transformation all zeros */ 573 /* Transformation all zeros */
573 transf.link[0].link_type = 574 for (i = 0; i < ARRAY_SIZE(transf.link); i++) {
574 (enum link_types)0; 575 transf.link[i].link_type =
575 transf.link[0].link_amount = 0; 576 (enum link_types)0;
576 transf.link[1].link_type = 577 transf.link[i].link_amount = 0;
577 (enum link_types)0; 578 }
578 transf.link[1].link_amount = 0;
579 transf.link[2].link_type =
580 (enum link_types)0;
581 transf.link[2].link_amount = 0;
582 transf.link[3].link_type =
583 (enum link_types)0;
584 transf.link[3].link_amount = 0;
585 579
586 set_transforms(channel, transf, 0); 580 set_transforms(channel, transf, 0);
587 use_transform(channel, 0); 581 use_transform(channel, 0);
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 6b118c15b49e..bbf75eb6d7f2 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -418,15 +418,15 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
418 return -EINVAL; 418 return -EINVAL;
419 base_bitfield_channel = CR_CHAN(insn->chanspec); 419 base_bitfield_channel = CR_CHAN(insn->chanspec);
420 for (j = 0; j < max_ports_per_bitfield; ++j) { 420 for (j = 0; j < max_ports_per_bitfield; ++j) {
421 const unsigned port_offset = ni_65xx_port_by_channel(base_bitfield_channel) + j;
421 const unsigned port = 422 const unsigned port =
422 sprivate(s)->base_port + 423 sprivate(s)->base_port + port_offset;
423 ni_65xx_port_by_channel(base_bitfield_channel) + j;
424 unsigned base_port_channel; 424 unsigned base_port_channel;
425 unsigned port_mask, port_data, port_read_bits; 425 unsigned port_mask, port_data, port_read_bits;
426 int bitshift; 426 int bitshift;
427 if (port >= ni_65xx_total_num_ports(board(dev))) 427 if (port >= ni_65xx_total_num_ports(board(dev)))
428 break; 428 break;
429 base_port_channel = port * ni_65xx_channels_per_port; 429 base_port_channel = port_offset * ni_65xx_channels_per_port;
430 port_mask = data[0]; 430 port_mask = data[0];
431 port_data = data[1]; 431 port_data = data[1];
432 bitshift = base_port_channel - base_bitfield_channel; 432 bitshift = base_port_channel - base_bitfield_channel;
@@ -457,6 +457,12 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
457 port_read_bits = 457 port_read_bits =
458 readb(private(dev)->mite->daq_io_addr + Port_Data(port)); 458 readb(private(dev)->mite->daq_io_addr + Port_Data(port));
459/* printk("read 0x%x from port %i\n", port_read_bits, port); */ 459/* printk("read 0x%x from port %i\n", port_read_bits, port); */
460 if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) {
461 /* Outputs inverted, so invert value read back from
462 * DO subdevice. (Does not apply to boards with DIO
463 * subdevice.) */
464 port_read_bits ^= 0xFF;
465 }
460 if (bitshift > 0) { 466 if (bitshift > 0) {
461 port_read_bits <<= bitshift; 467 port_read_bits <<= bitshift;
462 } else { 468 } else {
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 6a7797604c97..ec31a3970664 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -520,7 +520,7 @@ static int dio700_cs_attach(struct pcmcia_device *link)
520 link->priv = local; 520 link->priv = local;
521 521
522 /* Interrupt setup */ 522 /* Interrupt setup */
523 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 523 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
524 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 524 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
525 link->irq.Handler = NULL; 525 link->irq.Handler = NULL;
526 526
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index b06e81c526e8..0700a8bddd1e 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -271,7 +271,7 @@ static int dio24_cs_attach(struct pcmcia_device *link)
271 link->priv = local; 271 link->priv = local;
272 272
273 /* Interrupt setup */ 273 /* Interrupt setup */
274 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 274 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
275 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 275 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
276 link->irq.Handler = NULL; 276 link->irq.Handler = NULL;
277 277
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 57aecfa883c7..a3053b8da1c6 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -246,7 +246,7 @@ static int labpc_cs_attach(struct pcmcia_device *link)
246 link->priv = local; 246 link->priv = local;
247 247
248 /* Interrupt setup */ 248 /* Interrupt setup */
249 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_FORCED_PULSE; 249 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FORCED_PULSE;
250 link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_PULSE_ID; 250 link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_PULSE_ID;
251 link->irq.Handler = NULL; 251 link->irq.Handler = NULL;
252 252
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index b7322963cf78..9aef87fc81dc 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -273,7 +273,7 @@ static int cs_attach(struct pcmcia_device *link)
273{ 273{
274 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; 274 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
275 link->io.NumPorts1 = 16; 275 link->io.NumPorts1 = 16;
276 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 276 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
277 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 277 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
278 link->conf.Attributes = CONF_ENABLE_IRQ; 278 link->conf.Attributes = CONF_ENABLE_IRQ;
279 link->conf.IntType = INT_MEMORY_AND_IO; 279 link->conf.IntType = INT_MEMORY_AND_IO;
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 19d87553d906..24c8b8ed5b4c 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -29,7 +29,7 @@ Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio),
29 PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, PCI-6040E, 29 PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, PCI-6040E,
30 PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E, 30 PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E,
31 PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E, 31 PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E,
32 PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, PCI-6225, 32 PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, PCI-6225, PXI-6225,
33 PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PCI-6254, PCI-6259, PCIe-6259, 33 PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PCI-6254, PCI-6259, PCIe-6259,
34 PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, 34 PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289,
35 PCI-6711, PXI-6711, PCI-6713, PXI-6713, 35 PCI-6711, PXI-6711, PCI-6713, PXI-6713,
@@ -179,6 +179,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni_pci_table) = {
179 PCI_VENDOR_ID_NATINST, 0x70f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 179 PCI_VENDOR_ID_NATINST, 0x70f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
180 PCI_VENDOR_ID_NATINST, 0x710d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 180 PCI_VENDOR_ID_NATINST, 0x710d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
181 PCI_VENDOR_ID_NATINST, 0x716c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 181 PCI_VENDOR_ID_NATINST, 0x716c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
182 PCI_VENDOR_ID_NATINST, 0x716d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
182 PCI_VENDOR_ID_NATINST, 0x717f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 183 PCI_VENDOR_ID_NATINST, 0x717f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
183 PCI_VENDOR_ID_NATINST, 0x71bc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 184 PCI_VENDOR_ID_NATINST, 0x71bc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
184 PCI_VENDOR_ID_NATINST, 0x717d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 185 PCI_VENDOR_ID_NATINST, 0x717d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@@ -953,6 +954,25 @@ static const struct ni_board_struct ni_boards[] = {
953 .has_8255 = 0, 954 .has_8255 = 0,
954 }, 955 },
955 { 956 {
957 .device_id = 0x716d,
958 .name = "pxi-6225",
959 .n_adchan = 80,
960 .adbits = 16,
961 .ai_fifo_depth = 4095,
962 .gainlkup = ai_gain_622x,
963 .ai_speed = 4000,
964 .n_aochan = 2,
965 .aobits = 16,
966 .ao_fifo_depth = 8191,
967 .ao_range_table = &range_ni_M_622x_ao,
968 .reg_type = ni_reg_622x,
969 .ao_unipolar = 0,
970 .ao_speed = 1200,
971 .num_p0_dio_channels = 32,
972 .caldac = {caldac_none},
973 .has_8255 = 0,
974 },
975 {
956 .device_id = 0x70aa, 976 .device_id = 0x70aa,
957 .name = "pci-6229", 977 .name = "pci-6229",
958 .n_adchan = 32, 978 .n_adchan = 32,
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index f63bdc35cffd..344b82353e08 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -1079,7 +1079,7 @@ static int daqp_cs_attach(struct pcmcia_device *link)
1079 link->priv = local; 1079 link->priv = local;
1080 1080
1081 /* Interrupt setup */ 1081 /* Interrupt setup */
1082 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; 1082 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
1083 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 1083 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
1084 link->irq.Handler = daqp_interrupt; 1084 link->irq.Handler = daqp_interrupt;
1085 link->irq.Instance = local; 1085 link->irq.Instance = local;
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index b89e1ec267c5..07c21e686f27 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -43,6 +43,7 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3
43 43
44#include "../comedidev.h" 44#include "../comedidev.h"
45#include <linux/ioport.h> 45#include <linux/ioport.h>
46#include <asm/byteorder.h>
46 47
47#define S526_SIZE 64 48#define S526_SIZE 64
48 49
@@ -113,6 +114,7 @@ static const int s526_ports[] = {
113}; 114};
114 115
115struct counter_mode_register_t { 116struct counter_mode_register_t {
117#if defined (__LITTLE_ENDIAN_BITFIELD)
116 unsigned short coutSource:1; 118 unsigned short coutSource:1;
117 unsigned short coutPolarity:1; 119 unsigned short coutPolarity:1;
118 unsigned short autoLoadResetRcap:3; 120 unsigned short autoLoadResetRcap:3;
@@ -124,12 +126,27 @@ struct counter_mode_register_t {
124 unsigned short outputRegLatchCtrl:1; 126 unsigned short outputRegLatchCtrl:1;
125 unsigned short preloadRegSel:1; 127 unsigned short preloadRegSel:1;
126 unsigned short reserved:1; 128 unsigned short reserved:1;
129 #elif defined(__BIG_ENDIAN_BITFIELD)
130 unsigned short reserved:1;
131 unsigned short preloadRegSel:1;
132 unsigned short outputRegLatchCtrl:1;
133 unsigned short countDirCtrl:1;
134 unsigned short countDir:1;
135 unsigned short clockSource:2;
136 unsigned short ctEnableCtrl:2;
137 unsigned short hwCtEnableSource:2;
138 unsigned short autoLoadResetRcap:3;
139 unsigned short coutPolarity:1;
140 unsigned short coutSource:1;
141#else
142#error Unknown bit field order
143#endif
127}; 144};
128 145
129union { 146union cmReg {
130 struct counter_mode_register_t reg; 147 struct counter_mode_register_t reg;
131 unsigned short value; 148 unsigned short value;
132} cmReg; 149};
133 150
134#define MAX_GPCT_CONFIG_DATA 6 151#define MAX_GPCT_CONFIG_DATA 6
135 152
@@ -285,6 +302,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
285 int i, n; 302 int i, n;
286/* short value; */ 303/* short value; */
287/* int subdev_channel = 0; */ 304/* int subdev_channel = 0; */
305 union cmReg cmReg;
288 306
289 printk("comedi%d: s526: ", dev->minor); 307 printk("comedi%d: s526: ", dev->minor);
290 308
@@ -375,7 +393,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
375 if (thisboard->have_dio) { 393 if (thisboard->have_dio) {
376 s->type = COMEDI_SUBD_DIO; 394 s->type = COMEDI_SUBD_DIO;
377 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 395 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
378 s->n_chan = 2; 396 s->n_chan = 8;
379 s->maxdata = 1; 397 s->maxdata = 1;
380 s->range_table = &range_digital; 398 s->range_table = &range_digital;
381 s->insn_bits = s526_dio_insn_bits; 399 s->insn_bits = s526_dio_insn_bits;
@@ -435,11 +453,11 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
435 udelay(1000); 453 udelay(1000);
436 printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n))); 454 printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n)));
437 455
438 /* Load the pre-laod register high word */ 456 /* Load the pre-load register high word */
439/* value = (short) (0x55); */ 457/* value = (short) (0x55); */
440/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */ 458/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */
441 459
442 /* Load the pre-laod register low word */ 460 /* Load the pre-load register low word */
443/* value = (short)(0xaa55); */ 461/* value = (short)(0xaa55); */
444/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */ 462/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */
445 463
@@ -516,6 +534,7 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
516 int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */ 534 int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */
517 int i; 535 int i;
518 short value; 536 short value;
537 union cmReg cmReg;
519 538
520/* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel); */ 539/* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel); */
521 540
@@ -568,19 +587,8 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
568 587
569#if 1 588#if 1
570 /* Set Counter Mode Register */ 589 /* Set Counter Mode Register */
571 cmReg.reg.coutSource = 0; /* out RCAP */ 590 cmReg.value = insn->data[1] & 0xFFFF;
572 cmReg.reg.coutPolarity = 0; /* Polarity inverted */
573 cmReg.reg.autoLoadResetRcap = 0; /* Auto load disabled */
574 cmReg.reg.hwCtEnableSource = 2; /* NOT RCAP */
575 cmReg.reg.ctEnableCtrl = 1; /* 1: Software, >1 : Hardware */
576 cmReg.reg.clockSource = 3; /* x4 */
577 cmReg.reg.countDir = 0; /* up */
578 cmReg.reg.countDirCtrl = 0; /* quadrature */
579 cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */
580 cmReg.reg.preloadRegSel = 0; /* PR0 */
581 cmReg.reg.reserved = 0;
582 591
583 /* Set Counter Mode Register */
584/* printk("s526: Counter Mode register=%x\n", cmReg.value); */ 592/* printk("s526: Counter Mode register=%x\n", cmReg.value); */
585 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); 593 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
586 594
@@ -615,11 +623,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
615 cmReg.value = (short)(insn->data[1] & 0xFFFF); 623 cmReg.value = (short)(insn->data[1] & 0xFFFF);
616 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); 624 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
617 625
618 /* Load the pre-laod register high word */ 626 /* Load the pre-load register high word */
619 value = (short)((insn->data[2] >> 16) & 0xFFFF); 627 value = (short)((insn->data[2] >> 16) & 0xFFFF);
620 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); 628 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
621 629
622 /* Load the pre-laod register low word */ 630 /* Load the pre-load register low word */
623 value = (short)(insn->data[2] & 0xFFFF); 631 value = (short)(insn->data[2] & 0xFFFF);
624 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); 632 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
625 633
@@ -653,11 +661,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
653 cmReg.reg.preloadRegSel = 0; /* PR0 */ 661 cmReg.reg.preloadRegSel = 0; /* PR0 */
654 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); 662 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
655 663
656 /* Load the pre-laod register 0 high word */ 664 /* Load the pre-load register 0 high word */
657 value = (short)((insn->data[2] >> 16) & 0xFFFF); 665 value = (short)((insn->data[2] >> 16) & 0xFFFF);
658 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); 666 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
659 667
660 /* Load the pre-laod register 0 low word */ 668 /* Load the pre-load register 0 low word */
661 value = (short)(insn->data[2] & 0xFFFF); 669 value = (short)(insn->data[2] & 0xFFFF);
662 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); 670 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
663 671
@@ -666,17 +674,17 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
666 cmReg.reg.preloadRegSel = 1; /* PR1 */ 674 cmReg.reg.preloadRegSel = 1; /* PR1 */
667 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); 675 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
668 676
669 /* Load the pre-laod register 1 high word */ 677 /* Load the pre-load register 1 high word */
670 value = (short)((insn->data[3] >> 16) & 0xFFFF); 678 value = (short)((insn->data[3] >> 16) & 0xFFFF);
671 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); 679 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
672 680
673 /* Load the pre-laod register 1 low word */ 681 /* Load the pre-load register 1 low word */
674 value = (short)(insn->data[3] & 0xFFFF); 682 value = (short)(insn->data[3] & 0xFFFF);
675 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); 683 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
676 684
677 /* Write the Counter Control Register */ 685 /* Write the Counter Control Register */
678 if (insn->data[3] != 0) { 686 if (insn->data[4] != 0) {
679 value = (short)(insn->data[3] & 0xFFFF); 687 value = (short)(insn->data[4] & 0xFFFF);
680 outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); 688 outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
681 } 689 }
682 break; 690 break;
@@ -698,11 +706,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
698 cmReg.reg.preloadRegSel = 0; /* PR0 */ 706 cmReg.reg.preloadRegSel = 0; /* PR0 */
699 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); 707 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
700 708
701 /* Load the pre-laod register 0 high word */ 709 /* Load the pre-load register 0 high word */
702 value = (short)((insn->data[2] >> 16) & 0xFFFF); 710 value = (short)((insn->data[2] >> 16) & 0xFFFF);
703 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); 711 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
704 712
705 /* Load the pre-laod register 0 low word */ 713 /* Load the pre-load register 0 low word */
706 value = (short)(insn->data[2] & 0xFFFF); 714 value = (short)(insn->data[2] & 0xFFFF);
707 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); 715 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
708 716
@@ -711,17 +719,17 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
711 cmReg.reg.preloadRegSel = 1; /* PR1 */ 719 cmReg.reg.preloadRegSel = 1; /* PR1 */
712 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); 720 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
713 721
714 /* Load the pre-laod register 1 high word */ 722 /* Load the pre-load register 1 high word */
715 value = (short)((insn->data[3] >> 16) & 0xFFFF); 723 value = (short)((insn->data[3] >> 16) & 0xFFFF);
716 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); 724 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
717 725
718 /* Load the pre-laod register 1 low word */ 726 /* Load the pre-load register 1 low word */
719 value = (short)(insn->data[3] & 0xFFFF); 727 value = (short)(insn->data[3] & 0xFFFF);
720 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); 728 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
721 729
722 /* Write the Counter Control Register */ 730 /* Write the Counter Control Register */
723 if (insn->data[3] != 0) { 731 if (insn->data[4] != 0) {
724 value = (short)(insn->data[3] & 0xFFFF); 732 value = (short)(insn->data[4] & 0xFFFF);
725 outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); 733 outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
726 } 734 }
727 break; 735 break;
@@ -741,6 +749,7 @@ static int s526_gpct_winsn(struct comedi_device *dev,
741{ 749{
742 int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */ 750 int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */
743 short value; 751 short value;
752 union cmReg cmReg;
744 753
745 printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel); 754 printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel);
746 cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel)); 755 cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
@@ -775,9 +784,8 @@ static int s526_gpct_winsn(struct comedi_device *dev,
775 (devpriv->s526_gpct_config[subdev_channel]).data[1] = 784 (devpriv->s526_gpct_config[subdev_channel]).data[1] =
776 insn->data[1]; 785 insn->data[1];
777 } else { 786 } else {
778 printk("%d \t %d\n", insn->data[1], insn->data[2]); 787 printk("s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n",
779 printk 788 insn->data[0], insn->data[1]);
780 ("s526: INSN_WRITE: PTG: Problem with Pulse params\n");
781 return -EINVAL; 789 return -EINVAL;
782 } 790 }
783 791
@@ -949,7 +957,7 @@ static int s526_dio_insn_bits(struct comedi_device *dev,
949 data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; /* low 8 bits are the data */ 957 data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; /* low 8 bits are the data */
950 /* or we could just return the software copy of the output values if 958 /* or we could just return the software copy of the output values if
951 * it was a purely digital output subdevice */ 959 * it was a purely digital output subdevice */
952 /* data[1]=s->state; */ 960 /* data[1]=s->state & 0xFF; */
953 961
954 return 2; 962 return 2;
955} 963}
@@ -959,28 +967,33 @@ static int s526_dio_insn_config(struct comedi_device *dev,
959 struct comedi_insn *insn, unsigned int *data) 967 struct comedi_insn *insn, unsigned int *data)
960{ 968{
961 int chan = CR_CHAN(insn->chanspec); 969 int chan = CR_CHAN(insn->chanspec);
962 short value; 970 int group, mask;
963 971
964 printk("S526 DIO insn_config\n"); 972 printk("S526 DIO insn_config\n");
965 973
966 if (insn->n != 1)
967 return -EINVAL;
968
969 value = inw(ADDR_REG(REG_DIO));
970
971 /* The input or output configuration of each digital line is 974 /* The input or output configuration of each digital line is
972 * configured by a special insn_config instruction. chanspec 975 * configured by a special insn_config instruction. chanspec
973 * contains the channel to be changed, and data[0] contains the 976 * contains the channel to be changed, and data[0] contains the
974 * value COMEDI_INPUT or COMEDI_OUTPUT. */ 977 * value COMEDI_INPUT or COMEDI_OUTPUT. */
975 978
976 if (data[0] == COMEDI_OUTPUT) { 979 group = chan >> 2;
977 value |= 1 << (chan + 10); /* bit 10/11 set the group 1/2's mode */ 980 mask = 0xF << (group << 2);
978 s->io_bits |= (0xF << chan); 981 switch (data[0]) {
979 } else { 982 case INSN_CONFIG_DIO_OUTPUT:
980 value &= ~(1 << (chan + 10)); /* 1 is output, 0 is input. */ 983 s->state |= 1 << (group + 10); // bit 10/11 set the group 1/2's mode
981 s->io_bits &= ~(0xF << chan); 984 s->io_bits |= mask;
985 break;
986 case INSN_CONFIG_DIO_INPUT:
987 s->state &= ~(1 << (group + 10));// 1 is output, 0 is input.
988 s->io_bits &= ~mask;
989 break;
990 case INSN_CONFIG_DIO_QUERY:
991 data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
992 return insn->n;
993 default:
994 return -EINVAL;
982 } 995 }
983 outw(value, ADDR_REG(REG_DIO)); 996 outw(s->state, ADDR_REG(REG_DIO));
984 997
985 return 1; 998 return 1;
986} 999}
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index a21967983942..82aa86e718b2 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -35,6 +35,7 @@ Status: in development
35 35
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/ioport.h> 37#include <linux/ioport.h>
38#include <linux/sched.h>
38 39
39#include <asm/termios.h> 40#include <asm/termios.h>
40#include <asm/ioctls.h> 41#include <asm/ioctls.h>
diff --git a/drivers/staging/cowloop/Kconfig b/drivers/staging/cowloop/Kconfig
deleted file mode 100644
index 58d2a23bd2c1..000000000000
--- a/drivers/staging/cowloop/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
1config COWLOOP
2 tristate "copy-on-write pseudo Block Driver"
3 depends on BLOCK
4 default n
5 ---help---
6 Cowloop is a "copy-on-write" pseudo block driver. It can be
7 stacked on top of a "real" block driver, and catches all write
8 operations on their way from the file systems layer above to
9 the real driver below, effectively shielding the lower driver
10 from those write accesses. The requests are then diverted to
11 an ordinary file, located somewhere else (configurable). Later
12 read requests are checked to see whether they can be serviced
13 by the "real" block driver below, or must be pulled in from
14 the diverted location. More information and userspace tools to
15 use the driver are on the project's website
16 http://www.ATComputing.nl/cowloop/
diff --git a/drivers/staging/cowloop/Makefile b/drivers/staging/cowloop/Makefile
deleted file mode 100644
index 2b6b81a63d21..000000000000
--- a/drivers/staging/cowloop/Makefile
+++ /dev/null
@@ -1 +0,0 @@
1obj-$(CONFIG_COWLOOP) += cowloop.o
diff --git a/drivers/staging/cowloop/TODO b/drivers/staging/cowloop/TODO
deleted file mode 100644
index 9399d1c16e15..000000000000
--- a/drivers/staging/cowloop/TODO
+++ /dev/null
@@ -1,11 +0,0 @@
1TODO:
2 - checkpatch.pl cleanups
3 - run sparse to ensure clean
4 - fix up 32/64bit ioctl issues
5 - move proc file usage to debugfs
6 - audit ioctls
7 - add documentation
8 - get linux-fsdevel to review it
9
10Please send patches to "H.J. Thomassen" <hjt@ATComputing.nl> and
11Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/cowloop/cowloop.c b/drivers/staging/cowloop/cowloop.c
deleted file mode 100644
index a71c743a1196..000000000000
--- a/drivers/staging/cowloop/cowloop.c
+++ /dev/null
@@ -1,2842 +0,0 @@
1/*
2** COWLOOP block device driver (2.6 kernel compliant)
3** =======================================================================
4** Read-write loop-driver with copy-on-write functionality.
5**
6** Synopsis:
7**
8** modprobe cowloop [maxcows=..] [rdofile=..... cowfile=.... [option=r]]
9**
10** Definition of number of configured cowdevices:
11** maxcows= number of configured cowdevices (default: 16)
12** (do not confuse this with MAXCOWS: absolute maximum as compiled)
13**
14** One pair of filenames can be supplied during insmod/modprobe to open
15** the first cowdevice:
16** rdofile= read-only file (or filesystem)
17** cowfile= storage-space for modified blocks of read-only file(system)
18** option=r repair cowfile automatically if it appears to be dirty
19**
20** Other cowdevices can be activated via the command "cowdev"
21** whenever the cowloop-driver is loaded.
22**
23** The read-only file may be of type 'regular' or 'block-device'.
24**
25** The cowfile must be of type 'regular'.
26** If an existing regular file is used as cowfile, its contents will be
27** used again for the current read-only file. When the cowfile has not been
28** closed properly during a previous session (i.e. rmmod cowloop), the
29** cowloop-driver refuses to open it unless the parameter "option=r" is
30** specified.
31**
32** Layout of cowfile:
33**
34** +-----------------------------+
35** | cow head block | MAPUNIT bytes
36** |-----------------------------|
37** | | MAPUNIT bytes
38** |--- ---|
39** | | MAPUNIT bytes
40** |--- ---|
41** | used-block bitmap | MAPUNIT bytes
42** |-----------------------------|
43** | gap to align start-offset |
44** | to 4K multiple |
45** |-----------------------------| <---- start-offset cow blocks
46** | |
47** | written cow blocks | MAPUNIT bytes
48** | ..... |
49**
50** cowhead block:
51** - contains general info about the rdofile which is related
52** to this cowfile
53**
54** used-block bitmap:
55** - contains one bit per block with a size of MAPUNIT bytes
56** - bit-value '1' = block has been written on cow
57** '0' = block unused on cow
58** - total bitmap rounded to multiples of MAPUNIT
59**
60** ============================================================================
61** Author: Gerlof Langeveld - AT Computing (March 2003)
62** Current maintainer: Hendrik-Jan Thomassen - AT Computing (Summer 2006)
63** Email: hjt@ATComputing.nl
64** ----------------------------------------------------------------------------
65** Copyright (C) 2003-2009 AT Consultancy
66**
67** This program is free software; you can redistribute it and/or modify it
68** under the terms of the GNU General Public License as published by the
69** Free Software Foundation; either version 2, or (at your option) any
70** later version.
71**
72** This program is distributed in the hope that it will be useful, but
73** WITHOUT ANY WARRANTY; without even the implied warranty of
74** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
75** See the GNU General Public License for more details.
76**
77** You should have received a copy of the GNU General Public License
78** along with this program; if not, write to the Free Software
79** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
80** ----------------------------------------------------------------------------
81**
82** Major modifications:
83**
84** 200405 Ported to kernel-version 2.6 Hendrik-Jan Thomassen
85** 200405 Added cowhead to cowfile to garantee
86** consistency with read-only file Gerlof Langeveld
87** 200405 Postponed flushing of bitmaps to improve
88** performance. Gerlof Langeveld
89** 200405 Inline recovery for dirty cowfiles. Gerlof Langeveld
90** 200502 Redesign to support more cowdevices. Gerlof Langeveld
91** 200502 Support devices/file > 2 Gbytes. Gerlof Langeveld
92** 200507 Check for free space to expand cowfile. Gerlof Langeveld
93** 200902 Upgrade for kernel 2.6.28 Hendrik-Jan Thomassen
94**
95** Inspired by
96** loop.c by Theodore Ts'o and
97** cloop.c by Paul `Rusty' Russell & Klaus Knopper.
98**
99** Design-considerations:
100**
101** For the first experiments with the cowloop-driver, the request-queue
102** made use of the do_generic_file_read() which worked fine except
103** in combination with the cloop-driver; that combination
104** resulted in a non-interruptible hangup of the system during
105** heavy load. Other experiments using the `make_request' interface also
106** resulted in unpredictable system hangups (with proper use of spinlocks).
107**
108** To overcome these problems, the cowloop-driver starts a kernel-thread
109** for every active cowdevice.
110** All read- and write-request on the read-only file and copy-on-write file
111** are handled in the context of that thread.
112** A scheme has been designed to wakeup the kernel-thread as
113** soon as I/O-requests are available in the request-queue; this thread
114** handles the requests one-by-one by calling the proper read- or
115** write-function related to the open read-only file or copy-on-write file.
116** When all pending requests have been handled, the kernel-thread goes
117** back to sleep-state.
118** This approach requires some additional context-switches; however the
119** performance loss during heavy I/O is less than 3%.
120**
121** -------------------------------------------------------------------------*/
122/* The following is the cowloop package version number. It must be
123 identical to the content of the include-file "version.h" that is
124 used in all supporting utilities: */
125char revision[] = "$Revision: 3.1 $"; /* cowlo_init_module() has
126 assumptions about this string's format */
127
128/* Note that the following numbers are *not* the cowloop package version
129 numbers, but separate revision history numbers to track the
130 modifications of this particular source file: */
131/* $Log: cowloop.c,v $
132**
133** Revision 1.30 2009/02/08 hjt
134** Integrated earlier fixes
135** Upgraded to kernel 2.6.28 (thanks Jerome Poulin)
136**
137** Revision 1.29 2006/12/03 22:12:00 hjt
138** changed 'cowdevlock' from spinlock to semaphore, to avoid
139** "scheduling while atomic". Contributed by Juergen Christ.
140** Added version.h again
141**
142** Revision 1.28 2006/08/16 16:00:00 hjt
143** malloc each individual cowloopdevice struct separately
144**
145** Revision 1.27 2006/03/14 14:57:03 root
146** Removed include version.h
147**
148** Revision 1.26 2005/08/08 11:22:48 root
149** Implement possibility to close a cow file or reopen a cowfile read-only.
150**
151** Revision 1.25 2005/08/03 14:00:39 root
152** Added modinfo info to driver.
153**
154** Revision 1.24 2005/07/21 06:14:53 root
155** Cosmetic changes source code.
156**
157** Revision 1.23 2005/07/20 13:07:32 root
158** Supply ioctl to write watchdog program to react on lack of cowfile space.
159**
160** Revision 1.22 2005/07/20 07:53:34 root
161** Regular verification of free space in filesystem holding the cowfile
162** (give warnings whenever space is almost exhausted).
163** Terminology change: checksum renamed to fingerprint.
164**
165** Revision 1.21 2005/07/19 09:21:52 root
166** Removing maximum limit of 16 Gb per cowdevice.
167**
168** Revision 1.20 2005/07/19 07:50:33 root
169** Minor bugfixes and cosmetic changes.
170**
171** Revision 1.19 2005/06/10 12:29:55 root
172** Removed lock/unlock operation from cowlo_open().
173**
174** Revision 1.18 2005/05/09 12:56:26 root
175** Allow a cowdevice to be open more than once
176** (needed for support of ReiserFS and XFS).
177**
178** Revision 1.17 2005/03/17 14:36:16 root
179** Fixed some license issues.
180**
181** Revision 1.16 2005/03/07 14:42:05 root
182** Only allow one parallel open per cowdevice.
183**
184** Revision 1.15 2005/02/18 11:52:04 gerlof
185** Redesign to support more than one cowdevice > 2 Gb space.
186**
187** Revision 1.14 2004/08/17 14:19:16 gerlof
188** Modified output of /proc/cowloop.
189**
190** Revision 1.13 2004/08/16 07:21:10 gerlof
191** Separate statistical counter for read on rdofile and cowfile.
192**
193** Revision 1.12 2004/08/11 06:52:11 gerlof
194** Modified messages.
195**
196** Revision 1.11 2004/08/11 06:44:11 gerlof
197** Modified log messages.
198**
199** Revision 1.10 2004/08/10 12:27:27 gerlof
200** Cosmetic changes.
201**
202** Revision 1.9 2004/08/09 11:43:37 gerlof
203** Removed double definition of major number (COWMAJOR).
204**
205** Revision 1.8 2004/08/09 08:03:39 gerlof
206** Cleanup of messages.
207**
208** Revision 1.7 2004/05/27 06:37:33 gerlof
209** Modified /proc message.
210**
211** Revision 1.6 2004/05/26 21:23:28 gerlof
212** Modified /proc output.
213**
214** Revision 1.5 2004/05/26 13:23:34 gerlof
215** Support cowsync to force flushing the bitmaps and cowhead.
216**
217** Revision 1.4 2004/05/26 11:11:10 gerlof
218** Updated the comment to the actual situation.
219**
220** Revision 1.3 2004/05/26 10:50:00 gerlof
221** Implemented recovery-option.
222**
223** Revision 1.2 2004/05/25 15:14:41 gerlof
224** Modified bitmap flushing strategy.
225**
226*/
227
228#define COWMAJOR 241
229
230// #define COWDEBUG
231
232#ifdef COWDEBUG
233#define DEBUGP printk
234#define DCOW KERN_ALERT
235#else
236#define DEBUGP(format, x...)
237#endif
238
239#include <linux/types.h>
240#include <linux/autoconf.h>
241#ifndef AUTOCONF_INCLUDED
242#include <linux/config.h>
243#endif
244#include <linux/module.h>
245#include <linux/version.h>
246#include <linux/moduleparam.h>
247#include <linux/init.h>
248#include <linux/errno.h>
249#include <linux/kernel.h>
250#include <linux/major.h>
251#include <linux/sched.h>
252#include <linux/fs.h>
253#include <linux/file.h>
254#include <linux/stat.h>
255#include <linux/vmalloc.h>
256#include <linux/slab.h>
257#include <linux/semaphore.h>
258#include <asm/uaccess.h>
259#include <linux/proc_fs.h>
260#include <linux/blkdev.h>
261#include <linux/buffer_head.h>
262#include <linux/hdreg.h>
263#include <linux/genhd.h>
264#include <linux/statfs.h>
265
266#include "cowloop.h"
267
268MODULE_LICENSE("GPL");
269/* MODULE_AUTHOR("Gerlof Langeveld <gerlof@ATComputing.nl>"); obsolete address */
270MODULE_AUTHOR("Hendrik-Jan Thomassen <hjt@ATComputing.nl>"); /* current maintainer */
271MODULE_DESCRIPTION("Copy-on-write loop driver");
272MODULE_PARM_DESC(maxcows, " Number of configured cowdevices (default 16)");
273MODULE_PARM_DESC(rdofile, " Read-only file for /dev/cow/0");
274MODULE_PARM_DESC(cowfile, " Cowfile for /dev/cow/0");
275MODULE_PARM_DESC(option, " Repair cowfile if inconsistent: option=r");
276
277#define DEVICE_NAME "cow"
278
279#define DFLCOWS 16 /* default cowloop devices */
280
281static int maxcows = DFLCOWS;
282module_param(maxcows, int, 0);
283static char *rdofile = "";
284module_param(rdofile, charp, 0);
285static char *cowfile = "";
286module_param(cowfile, charp, 0);
287static char *option = "";
288module_param(option, charp, 0);
289
290/*
291** per cowdevice several bitmap chunks are allowed of MAPCHUNKSZ each
292**
293** each bitmap chunk can describe MAPCHUNKSZ * 8 * MAPUNIT bytes of data
294** suppose:
295** MAPCHUNKSZ 4096 and MAPUNIT 1024 --> 4096 * 8 * 1024 = 32 Mb per chunk
296*/
297#define MAPCHUNKSZ 4096 /* #bytes per bitmap chunk (do not change) */
298
299#define SPCMINBLK 100 /* space threshold to give warning messages */
300#define SPCDFLINTVL 16 /* once every SPCDFLINTVL writes to cowfile, */
301 /* available space in filesystem is checked */
302
303#define CALCMAP(x) ((x)/(MAPCHUNKSZ*8))
304#define CALCBYTE(x) (((x)%(MAPCHUNKSZ*8))>>3)
305#define CALCBIT(x) ((x)&7)
306
307#define ALLCOW 1
308#define ALLRDO 2
309#define MIXEDUP 3
310
311static char allzeroes[MAPUNIT];
312
313/*
314** administration per cowdevice (pair of cowfile/rdofile)
315*/
316
317/* bit-values for state */
318#define COWDEVOPEN 0x01 /* cowdevice opened */
319#define COWRWCOWOPEN 0x02 /* cowfile opened read-write */
320#define COWRDCOWOPEN 0x04 /* cowfile opened read-only */
321#define COWWATCHDOG 0x08 /* ioctl for watchdog cowfile space active */
322
323#define COWCOWOPEN (COWRWCOWOPEN|COWRDCOWOPEN)
324
325struct cowloop_device
326{
327 /*
328 ** current status
329 */
330 int state; /* bit-values (see above) */
331 int opencnt; /* # opens for cowdevice */
332
333 /*
334 ** open file pointers
335 */
336 struct file *rdofp, *cowfp; /* open file pointers */
337 char *rdoname, *cowname; /* file names */
338
339 /*
340 ** request queue administration
341 */
342 struct request_queue *rqueue;
343 spinlock_t rqlock;
344 struct gendisk *gd;
345
346 /*
347 ** administration about read-only file
348 */
349 unsigned int numblocks; /* # blocks input file in MAPUNIT */
350 unsigned int blocksz; /* minimum unit to access this dev */
351 unsigned long fingerprint; /* fingerprint of current rdofile */
352 struct block_device *belowdev; /* block device below us */
353 struct gendisk *belowgd; /* gendisk for blk dev below us */
354 struct request_queue *belowq; /* req. queue of blk dev below us */
355
356 /*
357 ** bitmap administration to register which blocks are modified
358 */
359 long int mapsize; /* total size of bitmap (bytes) */
360 long int mapremain; /* remaining bytes in last bitmap */
361 int mapcount; /* number of bitmaps in use */
362 char **mapcache; /* area with pointers to bitmaps */
363
364 char *iobuf; /* databuffer of MAPUNIT bytes */
365 struct cowhead *cowhead; /* buffer containing cowhead */
366
367 /*
368 ** administration for interface with the kernel-thread
369 */
370 int pid; /* pid==0: no thread available */
371 struct request *req; /* request to be handled now */
372 wait_queue_head_t waitq; /* wait-Q: thread waits for work */
373 char closedown; /* boolean: thread exit required */
374 char qfilled; /* boolean: I/O request pending */
375 char iobusy; /* boolean: req under treatment */
376
377 /*
378 ** administration to keep track of free space in cowfile filesystem
379 */
380 unsigned long blksize; /* block size of fs (bytes) */
381 unsigned long blktotal; /* recent total space in fs (blocks) */
382 unsigned long blkavail; /* recent free space in fs (blocks) */
383
384 wait_queue_head_t watchq; /* wait-Q: watcher awaits threshold */
385 unsigned long watchthresh; /* threshold of watcher (blocks) */
386
387 /*
388 ** statistical counters
389 */
390 unsigned long rdoreads; /* number of read-actions rdo */
391 unsigned long cowreads; /* number of read-actions cow */
392 unsigned long cowwrites; /* number of write-actions */
393 unsigned long nrcowblocks; /* number of blocks in use on cow */
394};
395
396static struct cowloop_device **cowdevall; /* ptr to ptrs to all cowdevices */
397static struct semaphore cowdevlock; /* generic lock for cowdevs */
398
399static struct gendisk *cowctlgd; /* gendisk control channel */
400static spinlock_t cowctlrqlock; /* for req.q. of ctrl. channel */
401
402/*
403** private directory /proc/cow
404*/
405struct proc_dir_entry *cowlo_procdir;
406
407/*
408** function prototypes
409*/
410static long int cowlo_do_request (struct request *req);
411static void cowlo_sync (void);
412static int cowlo_checkio (struct cowloop_device *, int, loff_t);
413static int cowlo_readmix (struct cowloop_device *, void *, int, loff_t);
414static int cowlo_writemix (struct cowloop_device *, void *, int, loff_t);
415static long int cowlo_readrdo (struct cowloop_device *, void *, int, loff_t);
416static long int cowlo_readcow (struct cowloop_device *, void *, int, loff_t);
417static long int cowlo_readcowraw (struct cowloop_device *, void *, int, loff_t);
418static long int cowlo_writecow (struct cowloop_device *, void *, int, loff_t);
419static long int cowlo_writecowraw(struct cowloop_device *, void *, int, loff_t);
420static int cowlo_ioctl (struct block_device *, fmode_t,
421 unsigned int, unsigned long);
422static int cowlo_makepair (struct cowpair __user *);
423static int cowlo_removepair (unsigned long __user *);
424static int cowlo_watch (struct cowpair __user *);
425static int cowlo_cowctl (unsigned long __user *, int);
426static int cowlo_openpair (char *, char *, int, int);
427static int cowlo_closepair (struct cowloop_device *);
428static int cowlo_openrdo (struct cowloop_device *, char *);
429static int cowlo_opencow (struct cowloop_device *, char *, int);
430static void cowlo_undo_openrdo(struct cowloop_device *);
431static void cowlo_undo_opencow(struct cowloop_device *);
432
433/*****************************************************************************/
434/* System call handling */
435/*****************************************************************************/
436
437/*
438** handle system call open()/mount()
439**
440** returns:
441** 0 - okay
442** < 0 - error value
443*/
444static int cowlo_open(struct block_device *bdev, fmode_t mode)
445{
446 struct inode *inode = bdev->bd_inode;
447
448 if (!inode)
449 return -EINVAL;
450
451 if (imajor(inode) != COWMAJOR) {
452 printk(KERN_WARNING
453 "cowloop - unexpected major %d\n", imajor(inode));
454 return -ENODEV;
455 }
456
457 switch (iminor(inode)) {
458 case COWCTL:
459 DEBUGP(DCOW"cowloop - open %d control\n", COWCTL);
460 break;
461
462 default:
463 DEBUGP(DCOW"cowloop - open minor %d\n", iminor(inode));
464
465 if ( iminor(inode) >= maxcows )
466 return -ENODEV;
467
468 if ( !((cowdevall[iminor(inode)])->state & COWDEVOPEN) )
469 return -ENODEV;
470
471 (cowdevall[iminor(inode)])->opencnt++;
472 }
473
474 return 0;
475}
476
477/*
478** handle system call close()/umount()
479**
480** returns:
481** 0 - okay
482*/
483static int cowlo_release(struct gendisk *gd, fmode_t mode)
484{
485 struct block_device *bdev;
486 struct inode *inode;
487
488 bdev = bdget_disk(gd, 0);
489 inode = bdev->bd_inode;
490 if (!inode)
491 return 0;
492
493 DEBUGP(DCOW"cowloop - release (close) minor %d\n", iminor(inode));
494
495 if ( iminor(inode) != COWCTL)
496 (cowdevall[iminor(inode)])->opencnt--;
497
498 return 0;
499}
500
501/*
502** handle system call ioctl()
503**
504** returns:
505** 0 - okay
506** < 0 - error value
507*/
508static int cowlo_ioctl(struct block_device *bdev, fmode_t mode,
509 unsigned int cmd, unsigned long arg)
510{
511 struct hd_geometry geo;
512 struct inode *inode = bdev->bd_inode;
513
514 DEBUGP(DCOW "cowloop - ioctl cmd %x\n", cmd);
515
516 switch ( iminor(inode) ) {
517
518 /*
519 ** allowed via control device only
520 */
521 case COWCTL:
522 switch (cmd) {
523 /*
524 ** write all bitmap chunks and cowheaders to cowfiles
525 */
526 case COWSYNC:
527 down(&cowdevlock);
528 cowlo_sync();
529 up(&cowdevlock);
530 return 0;
531
532 /*
533 ** open a new cowdevice (pair of rdofile/cowfile)
534 */
535 case COWMKPAIR:
536 return cowlo_makepair((void __user *)arg);
537
538 /*
539 ** close a cowdevice (pair of rdofile/cowfile)
540 */
541 case COWRMPAIR:
542 return cowlo_removepair((void __user *)arg);
543
544 /*
545 ** watch free space of filesystem containing cowfile
546 */
547 case COWWATCH:
548 return cowlo_watch((void __user *)arg);
549
550 /*
551 ** close cowfile for active device
552 */
553 case COWCLOSE:
554 return cowlo_cowctl((void __user *)arg, COWCLOSE);
555
556 /*
557 ** reopen cowfile read-only for active device
558 */
559 case COWRDOPEN:
560 return cowlo_cowctl((void __user *)arg, COWRDOPEN);
561
562 default:
563 return -EINVAL;
564 } /* end of switch on command */
565
566 /*
567 ** allowed for any other cowdevice
568 */
569 default:
570 switch (cmd) {
571 /*
572 ** HDIO_GETGEO must be supported for fdisk, etc
573 */
574 case HDIO_GETGEO:
575 geo.cylinders = 0;
576 geo.heads = 0;
577 geo.sectors = 0;
578
579 if (copy_to_user((void __user *)arg, &geo, sizeof geo))
580 return -EFAULT;
581 return 0;
582
583 default:
584 return -EINVAL;
585 } /* end of switch on ioctl-cmd code parameter */
586 } /* end of switch on minor number */
587}
588
589static struct block_device_operations cowlo_fops =
590{
591 .owner = THIS_MODULE,
592 .open = cowlo_open, /* called upon open */
593 .release = cowlo_release, /* called upon close */
594 .ioctl = cowlo_ioctl, /* called upon ioctl */
595};
596
597/*
598** handle ioctl-command COWMKPAIR:
599** open a new cowdevice (pair of rdofile/cowfile) on-the-fly
600**
601** returns:
602** 0 - okay
603** < 0 - error value
604*/
605static int
606cowlo_makepair(struct cowpair __user *arg)
607{
608 int i, rv=0;
609 struct cowpair cowpair;
610 unsigned char *cowpath;
611 unsigned char *rdopath;
612
613 /*
614 ** retrieve info about pathnames
615 */
616 if ( copy_from_user(&cowpair, arg, sizeof cowpair) )
617 return -EFAULT;
618
619 if ( (MAJOR(cowpair.device) != COWMAJOR) && (cowpair.device != ANYDEV) )
620 return -EINVAL;
621
622 if ( (MINOR(cowpair.device) >= maxcows) && (cowpair.device != ANYDEV) )
623 return -EINVAL;
624
625 /*
626 ** retrieve pathname strings
627 */
628 if ( (cowpair.cowflen > PATH_MAX) || (cowpair.rdoflen > PATH_MAX) )
629 return -ENAMETOOLONG;
630
631 if ( !(cowpath = kmalloc(cowpair.cowflen+1, GFP_KERNEL)) )
632 return -ENOMEM;
633
634 if ( copy_from_user(cowpath, (void __user *)cowpair.cowfile,
635 cowpair.cowflen) ) {
636 kfree(cowpath);
637 return -EFAULT;
638 }
639 *(cowpath+cowpair.cowflen) = 0;
640
641 if ( !(rdopath = kmalloc(cowpair.rdoflen+1, GFP_KERNEL)) ) {
642 kfree(cowpath);
643 return -ENOMEM;
644 }
645
646 if ( copy_from_user(rdopath, (void __user *)cowpair.rdofile,
647 cowpair.rdoflen) ) {
648 kfree(rdopath);
649 kfree(cowpath);
650 return -EFAULT;
651 }
652 *(rdopath+cowpair.rdoflen) = 0;
653
654 /*
655 ** open new cowdevice
656 */
657 if ( cowpair.device == ANYDEV) {
658 /*
659 ** search first unused minor
660 */
661 for (i=0, rv=-EBUSY; i < maxcows; i++) {
662 if ( !((cowdevall[i])->state & COWDEVOPEN) ) {
663 rv = cowlo_openpair(rdopath, cowpath, 0, i);
664 break;
665 }
666 }
667
668 if (rv) { /* open failed? */
669 kfree(rdopath);
670 kfree(cowpath);
671 return rv;
672 }
673
674 /*
675 ** return newly allocated cowdevice to user space
676 */
677 cowpair.device = MKDEV(COWMAJOR, i);
678
679 if ( copy_to_user(arg, &cowpair, sizeof cowpair)) {
680 kfree(rdopath);
681 kfree(cowpath);
682 return -EFAULT;
683 }
684 } else { /* specific minor requested */
685 if ( (rv = cowlo_openpair(rdopath, cowpath, 0,
686 MINOR(cowpair.device)))) {
687 kfree(rdopath);
688 kfree(cowpath);
689 return rv;
690 }
691 }
692
693 return 0;
694}
695
696/*
697** handle ioctl-command COWRMPAIR:
698** deactivate an existing cowdevice (pair of rdofile/cowfile) on-the-fly
699**
700** returns:
701** 0 - okay
702** < 0 - error value
703*/
704static int
705cowlo_removepair(unsigned long __user *arg)
706{
707 unsigned long cowdevice;
708 struct cowloop_device *cowdev;
709
710 /*
711 ** retrieve info about device to be removed
712 */
713 if ( copy_from_user(&cowdevice, arg, sizeof cowdevice))
714 return -EFAULT;
715
716 /*
717 ** verify major-minor number
718 */
719 if ( MAJOR(cowdevice) != COWMAJOR)
720 return -EINVAL;
721
722 if ( MINOR(cowdevice) >= maxcows)
723 return -EINVAL;
724
725 cowdev = cowdevall[MINOR(cowdevice)];
726
727 if ( !(cowdev->state & COWDEVOPEN) )
728 return -ENODEV;
729
730 /*
731 ** synchronize bitmaps and close cowdevice
732 */
733 if (cowdev->state & COWRWCOWOPEN) {
734 down(&cowdevlock);
735 cowlo_sync();
736 up(&cowdevlock);
737 }
738
739 return cowlo_closepair(cowdev);
740}
741
742/*
743** handle ioctl-command COWWATCH:
744** watch the free space of the filesystem containing a cowfile
745** of an open cowdevice
746**
747** returns:
748** 0 - okay
749** < 0 - error value
750*/
751static int
752cowlo_watch(struct cowpair __user *arg)
753{
754 struct cowloop_device *cowdev;
755 struct cowwatch cowwatch;
756
757 /*
758 ** retrieve structure holding info
759 */
760 if ( copy_from_user(&cowwatch, arg, sizeof cowwatch))
761 return -EFAULT;
762
763 /*
764 ** verify if cowdevice exists and is currently open
765 */
766 if ( MINOR(cowwatch.device) >= maxcows)
767 return -EINVAL;
768
769 cowdev = cowdevall[MINOR(cowwatch.device)];
770
771 if ( !(cowdev->state & COWDEVOPEN) )
772 return -ENODEV;
773
774 /*
775 ** if the WATCHWAIT-option is set, wait until the indicated
776 ** threshold is reached (only one waiter allowed)
777 */
778 if (cowwatch.flags & WATCHWAIT) {
779 /*
780 ** check if already another waiter active
781 ** for this cowdevice
782 */
783 if (cowdev->state & COWWATCHDOG)
784 return -EAGAIN;
785
786 cowdev->state |= COWWATCHDOG;
787
788 cowdev->watchthresh = (unsigned long long)
789 cowwatch.threshold /
790 (cowdev->blksize / 1024);
791
792 if (wait_event_interruptible(cowdev->watchq,
793 cowdev->watchthresh >= cowdev->blkavail)) {
794 cowdev->state &= ~COWWATCHDOG;
795 return EINTR;
796 }
797
798 cowdev->state &= ~COWWATCHDOG;
799 }
800
801 cowwatch.totalkb = (unsigned long long)cowdev->blktotal *
802 cowdev->blksize / 1024;
803 cowwatch.availkb = (unsigned long long)cowdev->blkavail *
804 cowdev->blksize / 1024;
805
806 if ( copy_to_user(arg, &cowwatch, sizeof cowwatch))
807 return -EFAULT;
808
809 return 0;
810}
811
812/*
813** handle ioctl-commands COWCLOSE and COWRDOPEN:
814** COWCLOSE - close the cowfile while the cowdevice remains open;
815** this allows an unmount of the filesystem on which
816** the cowfile resides
817** COWRDOPEN - close the cowfile and reopen it for read-only;
818** this allows a remount read-ony of the filesystem
819** on which the cowfile resides
820**
821** returns:
822** 0 - okay
823** < 0 - error value
824*/
825static int
826cowlo_cowctl(unsigned long __user *arg, int cmd)
827{
828 struct cowloop_device *cowdev;
829 unsigned long cowdevice;
830
831 /*
832 ** retrieve info about device to be removed
833 */
834 if ( copy_from_user(&cowdevice, arg, sizeof cowdevice))
835 return -EFAULT;
836
837 /*
838 ** verify major-minor number
839 */
840 if ( MAJOR(cowdevice) != COWMAJOR)
841 return -EINVAL;
842
843 if ( MINOR(cowdevice) >= maxcows)
844 return -EINVAL;
845
846 cowdev = cowdevall[MINOR(cowdevice)];
847
848 if ( !(cowdev->state & COWDEVOPEN) )
849 return -ENODEV;
850
851 /*
852 ** synchronize bitmaps and close cowfile
853 */
854 if (cowdev->state & COWRWCOWOPEN) {
855 down(&cowdevlock);
856 cowlo_sync();
857 up(&cowdevlock);
858 }
859
860 /*
861 ** handle specific ioctl-command
862 */
863 switch (cmd) {
864 case COWRDOPEN:
865 /*
866 ** if the cowfile is still opened read-write
867 */
868 if (cowdev->state & COWRWCOWOPEN) {
869 /*
870 ** close the cowfile
871 */
872 if (cowdev->cowfp)
873 filp_close(cowdev->cowfp, 0);
874
875 cowdev->state &= ~COWRWCOWOPEN;
876
877 /*
878 ** open again for read-only
879 */
880 cowdev->cowfp = filp_open(cowdev->cowname,
881 O_RDONLY|O_LARGEFILE, 0600);
882
883 if ( (cowdev->cowfp == NULL) || IS_ERR(cowdev->cowfp) ) {
884 printk(KERN_ERR
885 "cowloop - failed to reopen cowfile %s\n",
886 cowdev->cowname);
887 return -EINVAL;
888 }
889
890 /*
891 ** mark cowfile open for read-only
892 */
893 cowdev->state |= COWRDCOWOPEN;
894 } else {
895 return -EINVAL;
896 }
897 break;
898
899 case COWCLOSE:
900 /*
901 ** if the cowfile is still open
902 */
903 if (cowdev->state & COWCOWOPEN) {
904 /*
905 ** close the cowfile
906 */
907 if (cowdev->cowfp)
908 filp_close(cowdev->cowfp, 0);
909
910 cowdev->state &= ~COWCOWOPEN;
911 }
912 }
913
914 return 0;
915}
916
917
918/*****************************************************************************/
919/* Handling of I/O-requests for a cowdevice */
920/*****************************************************************************/
921
922/*
923** function to be called by core-kernel to handle the I/O-requests
924** in the queue
925*/
926static void cowlo_request(struct request_queue *q)
927{
928 struct request *req;
929 struct cowloop_device *cowdev;
930
931 DEBUGP(DCOW "cowloop - request function called....\n");
932
933 while((req = blk_peek_request(q)) != NULL) {
934 DEBUGP(DCOW "cowloop - got next request\n");
935
936 if (! blk_fs_request(req)) {
937 /* this is not a normal file system request */
938 __blk_end_request_cur(req, -EIO);
939 continue;
940 }
941 cowdev = req->rq_disk->private_data;
942
943 if (cowdev->iobusy)
944 return;
945 else
946 cowdev->iobusy = 1;
947
948 /*
949 ** when no kernel-thread is available, the request will
950 ** produce an I/O-error
951 */
952 if (!cowdev->pid) {
953 printk(KERN_ERR"cowloop - no thread available\n");
954 __blk_end_request_cur(req, -EIO); /* request failed */
955 cowdev->iobusy = 0;
956 continue;
957 }
958
959 /*
960 ** handle I/O-request in the context of the kernel-thread
961 */
962 cowdev->req = req;
963 cowdev->qfilled = 1;
964
965 wake_up_interruptible_sync(&cowdev->waitq);
966
967 /*
968 ** get out of this function now while the I/O-request is
969 ** under treatment of the kernel-thread; this function
970 ** will be called again after the current I/O-request has
971 ** been finished by the thread
972 */
973 return;
974 }
975}
976
977/*
978** daemon-process (kernel-thread) executes this function
979*/
980static int
981cowlo_daemon(struct cowloop_device *cowdev)
982{
983 int rv;
984 int minor;
985 char myname[16];
986
987 for (minor = 0; minor < maxcows; minor++) {
988 if (cowdev == cowdevall[minor]) break;
989 }
990 sprintf(myname, "cowloopd%d", minor);
991
992 daemonize(myname);
993
994 while (!cowdev->closedown) {
995 /*
996 ** sleep while waiting for an I/O request;
997 ** note that no non-interruptible wait has been used
998 ** because the non-interruptible version of
999 ** a *synchronous* wake_up does not exist (any more)
1000 */
1001 if (wait_event_interruptible(cowdev->waitq, cowdev->qfilled)){
1002 flush_signals(current); /* ignore signal-based wakeup */
1003 continue;
1004 }
1005
1006 if (cowdev->closedown) /* module will be unloaded ? */{
1007 cowdev->pid = 0;
1008 return 0;
1009 }
1010
1011 /*
1012 ** woken up by the I/O-request handler: treat requested I/O
1013 */
1014 cowdev->qfilled = 0;
1015
1016 rv = cowlo_do_request(cowdev->req);
1017
1018 /*
1019 ** reacquire the queue-spinlock for manipulating
1020 ** the request-queue and dequeue the request
1021 */
1022 spin_lock_irq(&cowdev->rqlock);
1023
1024 __blk_end_request_cur(cowdev->req, rv);
1025 cowdev->iobusy = 0;
1026
1027 /*
1028 ** initiate the next request from the queue
1029 */
1030 cowlo_request(cowdev->rqueue);
1031
1032 spin_unlock_irq(&cowdev->rqlock);
1033 }
1034 return 0;
1035}
1036
1037/*
1038** function to be called in the context of the kernel thread
1039** to handle the queued I/O-requests
1040**
1041** returns:
1042** 0 - fail
1043** 1 - success
1044*/
1045static long int
1046cowlo_do_request(struct request *req)
1047{
1048 unsigned long len;
1049 long int rv;
1050 loff_t offset;
1051 struct cowloop_device *cowdev = req->rq_disk->private_data;
1052
1053 /*
1054 ** calculate some variables which are needed later on
1055 */
1056 len = blk_rq_cur_sectors(req) << 9;
1057 offset = (loff_t) blk_rq_pos(req) << 9;
1058
1059 DEBUGP(DCOW"cowloop - req cmd=%d offset=%lld len=%lu addr=%p\n",
1060 *(req->cmd), offset, len, req->buffer);
1061
1062 /*
1063 ** handle READ- or WRITE-request
1064 */
1065 switch (rq_data_dir(req)) {
1066 /**********************************************************/
1067 case READ:
1068 switch ( cowlo_checkio(cowdev, len, offset) ) {
1069 case ALLCOW:
1070 rv = cowlo_readcow(cowdev, req->buffer, len, offset);
1071 break;
1072
1073 case ALLRDO:
1074 rv = cowlo_readrdo(cowdev, req->buffer, len, offset);
1075 break;
1076
1077 case MIXEDUP:
1078 rv = cowlo_readmix(cowdev, req->buffer, len, offset);
1079 break;
1080
1081 default:
1082 rv = 0; /* never happens */
1083 }
1084 break;
1085
1086 /**********************************************************/
1087 case WRITE:
1088 switch ( cowlo_checkio(cowdev, len, offset) ) {
1089 case ALLCOW:
1090 /*
1091 ** straight-forward write will do...
1092 */
1093 DEBUGP(DCOW"cowloop - write straight ");
1094
1095 rv = cowlo_writecow(cowdev, req->buffer, len, offset);
1096 break; /* from switch */
1097
1098 case ALLRDO:
1099 if ( (len & MUMASK) == 0) {
1100 DEBUGP(DCOW"cowloop - write straight ");
1101
1102 rv = cowlo_writecow(cowdev, req->buffer,
1103 len, offset);
1104 break;
1105 }
1106
1107 case MIXEDUP:
1108 rv = cowlo_writemix(cowdev, req->buffer, len, offset);
1109 break;
1110
1111 default:
1112 rv = 0; /* never happens */
1113 }
1114 break;
1115
1116 default:
1117 printk(KERN_ERR
1118 "cowloop - unrecognized command %d\n", *(req->cmd));
1119 rv = 0;
1120 }
1121
1122 return (rv <= 0 ? 0 : 1);
1123}
1124
1125/*
1126** check for a given I/O-request if all underlying blocks
1127** (with size MAPUNIT) are either in the read-only file or in
1128** the cowfile (or a combination of the two)
1129**
1130** returns:
1131** ALLRDO - all underlying blocks in rdofile
1132** ALLCOW - all underlying blocks in cowfile
1133** MIXEDUP - underlying blocks partly in rdofile and partly in cowfile
1134*/
1135static int
1136cowlo_checkio(struct cowloop_device *cowdev, int len, loff_t offset)
1137{
1138 unsigned long mapnum, bytenum, bitnum, blocknr, partlen;
1139 long int totcnt, cowcnt;
1140 char *mc;
1141
1142 /*
1143 ** notice that the requested block might cross
1144 ** a blocksize boundary while one of the concerned
1145 ** blocks resides in the read-only file and another
1146 ** one in the copy-on-write file; in that case the
1147 ** request will be broken up into pieces
1148 */
1149 if ( (len <= MAPUNIT) &&
1150 (MAPUNIT - (offset & MUMASK) <= len) ) {
1151 /*
1152 ** easy situation:
1153 ** requested data-block entirely fits within
1154 ** the mapunit used for the bitmap
1155 ** check if that block is located in rdofile or
1156 ** cowfile
1157 */
1158 blocknr = offset >> MUSHIFT;
1159
1160 mapnum = CALCMAP (blocknr);
1161 bytenum = CALCBYTE(blocknr);
1162 bitnum = CALCBIT (blocknr);
1163
1164 if (*(*(cowdev->mapcache+mapnum)+bytenum)&(1<<bitnum))
1165 return ALLCOW;
1166 else
1167 return ALLRDO;
1168 }
1169
1170 /*
1171 ** less easy situation:
1172 ** the requested data-block does not fit within the mapunit
1173 ** used for the bitmap
1174 ** check if *all* underlying blocks involved reside on the rdofile
1175 ** or the cowfile (so still no breakup required)
1176 */
1177 for (cowcnt=totcnt=0; len > 0; len-=partlen, offset+=partlen, totcnt++){
1178 /*
1179 ** calculate blocknr of involved block
1180 */
1181 blocknr = offset >> MUSHIFT;
1182
1183 /*
1184 ** calculate partial length for this transfer
1185 */
1186 partlen = MAPUNIT - (offset & MUMASK);
1187 if (partlen > len)
1188 partlen = len;
1189
1190 /*
1191 ** is this block located in the cowfile
1192 */
1193 mapnum = CALCMAP (blocknr);
1194 bytenum = CALCBYTE(blocknr);
1195 bitnum = CALCBIT (blocknr);
1196
1197 mc = *(cowdev->mapcache+mapnum);
1198
1199 if (*(mc+bytenum)&(1<<bitnum))
1200 cowcnt++;;
1201
1202 DEBUGP(DCOW
1203 "cowloop - check %lu - map %lu, byte %lu, bit %lu, "
1204 "cowcnt %ld, totcnt %ld %02x %p\n",
1205 blocknr, mapnum, bytenum, bitnum, cowcnt, totcnt,
1206 *(mc+bytenum), mc);
1207 }
1208
1209 if (cowcnt == 0) /* all involved blocks on rdofile? */
1210 return ALLRDO;
1211
1212 if (cowcnt == totcnt) /* all involved blocks on cowfile? */
1213 return ALLCOW;
1214
1215 /*
1216 ** situation somewhat more complicated:
1217 ** involved underlying blocks spread over both files
1218 */
1219 return MIXEDUP;
1220}
1221
1222/*
1223** read requested chunk partly from rdofile and partly from cowfile
1224**
1225** returns:
1226** 0 - fail
1227** 1 - success
1228*/
1229static int
1230cowlo_readmix(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
1231{
1232 unsigned long mapnum, bytenum, bitnum, blocknr, partlen;
1233 long int rv;
1234 char *mc;
1235
1236 /*
1237 ** complicated approach: breakup required of read-request
1238 */
1239 for (rv=1; len > 0; len-=partlen, buf+=partlen, offset+=partlen) {
1240 /*
1241 ** calculate blocknr of entire block
1242 */
1243 blocknr = offset >> MUSHIFT;
1244
1245 /*
1246 ** calculate partial length for this transfer
1247 */
1248 partlen = MAPUNIT - (offset & MUMASK);
1249 if (partlen > len)
1250 partlen = len;
1251
1252 /*
1253 ** is this block located in the cowfile
1254 */
1255 mapnum = CALCMAP (blocknr);
1256 bytenum = CALCBYTE(blocknr);
1257 bitnum = CALCBIT (blocknr);
1258 mc = *(cowdev->mapcache+mapnum);
1259
1260 if (*(mc+bytenum)&(1<<bitnum)) {
1261 /*
1262 ** read (partial) block from cowfile
1263 */
1264 DEBUGP(DCOW"cowloop - split read "
1265 "cow partlen=%ld off=%lld\n", partlen, offset);
1266
1267 if (cowlo_readcow(cowdev, buf, partlen, offset) <= 0)
1268 rv = 0;
1269 } else {
1270 /*
1271 ** read (partial) block from rdofile
1272 */
1273 DEBUGP(DCOW"cowloop - split read "
1274 "rdo partlen=%ld off=%lld\n", partlen, offset);
1275
1276 if (cowlo_readrdo(cowdev, buf, partlen, offset) <= 0)
1277 rv = 0;
1278 }
1279 }
1280
1281 return rv;
1282}
1283
1284/*
1285** chunk to be written to the cowfile needs pieces to be
1286** read from the rdofile
1287**
1288** returns:
1289** 0 - fail
1290** 1 - success
1291*/
1292static int
1293cowlo_writemix(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
1294{
1295 unsigned long mapnum, bytenum, bitnum, blocknr, partlen;
1296 long int rv;
1297 char *mc;
1298
1299 /*
1300 ** somewhat more complicated stuff is required:
1301 ** if the request is larger than one underlying
1302 ** block or is spread over two underlying blocks,
1303 ** split the request into pieces; if a block does not
1304 ** start at a block boundary, take care that
1305 ** surrounding data is read first (if needed),
1306 ** fit the new data in and write it as a full block
1307 */
1308 for (rv=1; len > 0; len-=partlen, buf+=partlen, offset+=partlen) {
1309 /*
1310 ** calculate partial length for this transfer
1311 */
1312 partlen = MAPUNIT - (offset & MUMASK);
1313 if (partlen > len)
1314 partlen = len;
1315
1316 /*
1317 ** calculate blocknr of entire block
1318 */
1319 blocknr = offset >> MUSHIFT;
1320
1321 /*
1322 ** has this block been written before?
1323 */
1324 mapnum = CALCMAP (blocknr);
1325 bytenum = CALCBYTE(blocknr);
1326 bitnum = CALCBIT (blocknr);
1327 mc = *(cowdev->mapcache+mapnum);
1328
1329 if (*(mc+bytenum)&(1<<bitnum)) {
1330 /*
1331 ** block has been written before;
1332 ** write transparantly to cowfile
1333 */
1334 DEBUGP(DCOW
1335 "cowloop - splitwr transp\n");
1336
1337 if (cowlo_writecow(cowdev, buf, partlen, offset) <= 0)
1338 rv = 0;
1339 } else {
1340 /*
1341 ** block has never been written before,
1342 ** so read entire block from
1343 ** read-only file first, unless
1344 ** a full block is requested to
1345 ** be written
1346 */
1347 if (partlen < MAPUNIT) {
1348 if (cowlo_readrdo(cowdev, cowdev->iobuf,
1349 MAPUNIT, (loff_t)blocknr << MUSHIFT) <= 0)
1350 rv = 0;
1351 }
1352
1353 /*
1354 ** transfer modified part into
1355 ** the block just read
1356 */
1357 memcpy(cowdev->iobuf + (offset & MUMASK), buf, partlen);
1358
1359 /*
1360 ** write entire block to cowfile
1361 */
1362 DEBUGP(DCOW"cowloop - split "
1363 "partlen=%ld off=%lld\n",
1364 partlen, (loff_t)blocknr << MUSHIFT);
1365
1366 if (cowlo_writecow(cowdev, cowdev->iobuf, MAPUNIT,
1367 (loff_t)blocknr << MUSHIFT) <= 0)
1368 rv = 0;
1369 }
1370 }
1371
1372 return rv;
1373}
1374
1375/*****************************************************************************/
1376/* I/O-support for read-only file and copy-on-write file */
1377/*****************************************************************************/
1378
1379/*
1380** read data from the read-only file
1381**
1382** return-value: similar to user-mode read
1383*/
1384static long int
1385cowlo_readrdo(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
1386{
1387 long int rv;
1388 mm_segment_t old_fs;
1389 loff_t saveoffset = offset;
1390
1391 DEBUGP(DCOW"cowloop - readrdo called\n");
1392
1393 old_fs = get_fs();
1394 set_fs( get_ds() );
1395 rv = cowdev->rdofp->f_op->read(cowdev->rdofp, buf, len, &offset);
1396 set_fs(old_fs);
1397
1398 if (rv < len) {
1399 printk(KERN_WARNING "cowloop - read-failure %ld on rdofile"
1400 "- offset=%lld len=%d\n",
1401 rv, saveoffset, len);
1402 }
1403
1404 cowdev->rdoreads++;
1405 return rv;
1406}
1407
1408/*
1409** read cowfile from a modified offset, i.e. skipping the bitmap and cowhead
1410**
1411** return-value: similar to user-mode read
1412*/
1413static long int
1414cowlo_readcow(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
1415{
1416 DEBUGP(DCOW"cowloop - readcow called\n");
1417
1418 offset += cowdev->cowhead->doffset;
1419
1420 return cowlo_readcowraw(cowdev, buf, len, offset);
1421}
1422
1423/*
1424** read cowfile from an absolute offset
1425**
1426** return-value: similar to user-mode read
1427*/
1428static long int
1429cowlo_readcowraw(struct cowloop_device *cowdev,
1430 void *buf, int len, loff_t offset)
1431{
1432 long int rv;
1433 mm_segment_t old_fs;
1434 loff_t saveoffset = offset;
1435
1436 DEBUGP(DCOW"cowloop - readcowraw called\n");
1437
1438 /*
1439 ** be sure that cowfile is opened for read-write
1440 */
1441 if ( !(cowdev->state & COWCOWOPEN) ) {
1442 printk(KERN_WARNING
1443 "cowloop - read request from cowfile refused\n");
1444
1445 return -EBADF;
1446 }
1447
1448 /*
1449 ** issue low level read
1450 */
1451 old_fs = get_fs();
1452 set_fs( get_ds() );
1453 rv = cowdev->cowfp->f_op->read(cowdev->cowfp, buf, len, &offset);
1454 set_fs(old_fs);
1455
1456 if (rv < len) {
1457 printk(KERN_WARNING
1458 "cowloop - read-failure %ld on cowfile"
1459 "- offset=%lld len=%d\n", rv, saveoffset, len);
1460 }
1461
1462 cowdev->cowreads++;
1463 return rv;
1464}
1465
1466/*
1467** write cowfile from a modified offset, i.e. skipping the bitmap and cowhead
1468**
1469** if a block is written for the first time while its contents consists
1470** of binary zeroes only, the concerning bitmap is flushed to the cowfile
1471**
1472** return-value: similar to user-mode write
1473*/
1474static long int
1475cowlo_writecow(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
1476{
1477 long int rv;
1478 unsigned long mapnum=0, mapbyte=0, mapbit=0, cowblock=0, partlen;
1479 char *tmpptr, *mapptr = NULL;
1480 loff_t tmpoffset, mapoffset = 0;
1481
1482 DEBUGP(DCOW"cowloop - writecow called\n");
1483
1484 /*
1485 ** be sure that cowfile is opened for read-write
1486 */
1487 if ( !(cowdev->state & COWRWCOWOPEN) ) {
1488 printk(KERN_WARNING
1489 "cowloop - Write request to cowfile refused\n");
1490
1491 return -EBADF;
1492 }
1493
1494 /*
1495 ** write the entire block to the cowfile
1496 */
1497 tmpoffset = offset + cowdev->cowhead->doffset;
1498
1499 rv = cowlo_writecowraw(cowdev, buf, len, tmpoffset);
1500
1501 /*
1502 ** verify if enough space available on filesystem holding
1503 ** the cowfile
1504 ** - when the last write failed (might be caused by lack of space)
1505 ** - when a watcher is active (to react adequatly)
1506 ** - when the previous check indicated fs was almost full
1507 ** - with regular intervals
1508 */
1509 if ( (rv <= 0) ||
1510 (cowdev->state & COWWATCHDOG) ||
1511 (cowdev->blkavail / 2 < SPCDFLINTVL) ||
1512 (cowdev->cowwrites % SPCDFLINTVL == 0) ) {
1513 struct kstatfs ks;
1514
1515 if (vfs_statfs(cowdev->cowfp->f_dentry, &ks)==0){
1516 if (ks.f_bavail <= SPCMINBLK) {
1517 switch (ks.f_bavail) {
1518 case 0:
1519 case 1:
1520 case 2:
1521 case 3:
1522 printk(KERN_ALERT
1523 "cowloop - "
1524 "ALERT: cowfile full!\n");
1525 break;
1526
1527 default:
1528 printk(KERN_WARNING
1529 "cowloop - cowfile almost "
1530 "full (only %llu Kb free)\n",
1531 (unsigned long long)
1532 ks.f_bsize * ks.f_bavail /1024);
1533 }
1534 }
1535
1536 cowdev->blktotal = ks.f_blocks;
1537 cowdev->blkavail = ks.f_bavail;
1538
1539 /*
1540 ** wakeup watcher if threshold has been reached
1541 */
1542 if ( (cowdev->state & COWWATCHDOG) &&
1543 (cowdev->watchthresh >= cowdev->blkavail) ) {
1544 wake_up_interruptible(&cowdev->watchq);
1545 }
1546 }
1547 }
1548
1549 if (rv <= 0)
1550 return rv;
1551
1552 DEBUGP(DCOW"cowloop - block written\n");
1553
1554 /*
1555 ** check if block(s) is/are written to the cowfile
1556 ** for the first time; if so, adapt the bitmap
1557 */
1558 for (; len > 0; len-=partlen, offset+=partlen, buf+=partlen) {
1559 /*
1560 ** calculate partial length for this transfer
1561 */
1562 partlen = MAPUNIT - (offset & MUMASK);
1563 if (partlen > len)
1564 partlen = len;
1565
1566 /*
1567 ** calculate bitnr of written chunk of cowblock
1568 */
1569 cowblock = offset >> MUSHIFT;
1570
1571 mapnum = CALCMAP (cowblock);
1572 mapbyte = CALCBYTE(cowblock);
1573 mapbit = CALCBIT (cowblock);
1574
1575 if (*(*(cowdev->mapcache+mapnum)+mapbyte) & (1<<mapbit))
1576 continue; /* already written before */
1577
1578 /*
1579 ** if the block is written for the first time,
1580 ** the corresponding bit should be set in the bitmap
1581 */
1582 *(*(cowdev->mapcache+mapnum)+mapbyte) |= (1<<mapbit);
1583
1584 cowdev->nrcowblocks++;
1585
1586 DEBUGP(DCOW"cowloop - bitupdate blk=%ld map=%ld "
1587 "byte=%ld bit=%ld\n",
1588 cowblock, mapnum, mapbyte, mapbit);
1589
1590 /*
1591 ** check if the cowhead in the cowfile is currently
1592 ** marked clean; if so, mark it dirty and flush it
1593 */
1594 if ( !(cowdev->cowhead->flags &= COWDIRTY)) {
1595 cowdev->cowhead->flags |= COWDIRTY;
1596
1597 cowlo_writecowraw(cowdev, cowdev->cowhead,
1598 MAPUNIT, (loff_t)0);
1599 }
1600
1601 /*
1602 ** if the written datablock contained binary zeroes,
1603 ** the bitmap block should be marked to be flushed to disk
1604 ** (blocks containing all zeroes cannot be recovered by
1605 ** the cowrepair-program later on if cowloop is not properly
1606 ** removed via rmmod)
1607 */
1608 if ( memcmp(buf, allzeroes, partlen) ) /* not all zeroes? */
1609 continue; /* no flush needed */
1610
1611 /*
1612 ** calculate positions of bitmap block to be flushed
1613 ** - pointer of bitmap block in memory
1614 ** - offset of bitmap block in cowfile
1615 */
1616 tmpptr = *(cowdev->mapcache+mapnum) + (mapbyte & (~MUMASK));
1617 tmpoffset = (loff_t) MAPUNIT + mapnum * MAPCHUNKSZ +
1618 (mapbyte & (~MUMASK));
1619
1620 /*
1621 ** flush a bitmap block at the moment that all bits have
1622 ** been set in that block, i.e. at the moment that we
1623 ** switch to another bitmap block
1624 */
1625 if ( (mapoffset != 0) && (mapoffset != tmpoffset) ) {
1626 if (cowlo_writecowraw(cowdev, mapptr, MAPUNIT,
1627 mapoffset) < 0) {
1628 printk(KERN_WARNING
1629 "cowloop - write-failure on bitmap - "
1630 "blk=%ld map=%ld byte=%ld bit=%ld\n",
1631 cowblock, mapnum, mapbyte, mapbit);
1632 }
1633
1634 DEBUGP(DCOW"cowloop - bitmap blk written %lld\n",
1635 mapoffset);
1636 }
1637
1638 /*
1639 ** remember offset in cowfile and offset in memory
1640 ** for bitmap to be flushed; flushing will be done
1641 ** as soon as all updates in this bitmap block have
1642 ** been done
1643 */
1644 mapoffset = tmpoffset;
1645 mapptr = tmpptr;
1646 }
1647
1648 /*
1649 ** any new block written containing binary zeroes?
1650 */
1651 if (mapoffset) {
1652 if (cowlo_writecowraw(cowdev, mapptr, MAPUNIT, mapoffset) < 0) {
1653 printk(KERN_WARNING
1654 "cowloop - write-failure on bitmap - "
1655 "blk=%ld map=%ld byte=%ld bit=%ld\n",
1656 cowblock, mapnum, mapbyte, mapbit);
1657 }
1658
1659 DEBUGP(DCOW"cowloop - bitmap block written %lld\n", mapoffset);
1660 }
1661
1662 return rv;
1663}
1664
1665/*
1666** write cowfile from an absolute offset
1667**
1668** return-value: similar to user-mode write
1669*/
1670static long int
1671cowlo_writecowraw(struct cowloop_device *cowdev,
1672 void *buf, int len, loff_t offset)
1673{
1674 long int rv;
1675 mm_segment_t old_fs;
1676 loff_t saveoffset = offset;
1677
1678 DEBUGP(DCOW"cowloop - writecowraw called\n");
1679
1680 /*
1681 ** be sure that cowfile is opened for read-write
1682 */
1683 if ( !(cowdev->state & COWRWCOWOPEN) ) {
1684 printk(KERN_WARNING
1685 "cowloop - write request to cowfile refused\n");
1686
1687 return -EBADF;
1688 }
1689
1690 /*
1691 ** issue low level write
1692 */
1693 old_fs = get_fs();
1694 set_fs( get_ds() );
1695 rv = cowdev->cowfp->f_op->write(cowdev->cowfp, buf, len, &offset);
1696 set_fs(old_fs);
1697
1698 if (rv < len) {
1699 printk(KERN_WARNING
1700 "cowloop - write-failure %ld on cowfile"
1701 "- offset=%lld len=%d\n", rv, saveoffset, len);
1702 }
1703
1704 cowdev->cowwrites++;
1705 return rv;
1706}
1707
1708
1709/*
1710** readproc-function: called when the corresponding /proc-file is read
1711*/
1712static int
1713cowlo_readproc(char *buf, char **start, off_t pos, int cnt, int *eof, void *p)
1714{
1715 struct cowloop_device *cowdev = p;
1716
1717 revision[sizeof revision - 3] = '\0';
1718
1719 return sprintf(buf,
1720 " cowloop version: %9s\n\n"
1721 " device state: %s%s%s%s\n"
1722 " number of opens: %9d\n"
1723 " pid of thread: %9d\n\n"
1724 " read-only file: %9s\n"
1725 " rdoreads: %9lu\n\n"
1726 "copy-on-write file: %9s\n"
1727 " state cowfile: %9s\n"
1728 " bitmap-blocks: %9lu (of %d bytes)\n"
1729 " cowblocks in use: %9lu (of %d bytes)\n"
1730 " cowreads: %9lu\n"
1731 " cowwrites: %9lu\n",
1732 &revision[11],
1733
1734 cowdev->state & COWDEVOPEN ? "devopen " : "",
1735 cowdev->state & COWRWCOWOPEN ? "cowopenrw " : "",
1736 cowdev->state & COWRDCOWOPEN ? "cowopenro " : "",
1737 cowdev->state & COWWATCHDOG ? "watchdog " : "",
1738
1739 cowdev->opencnt,
1740 cowdev->pid,
1741 cowdev->rdoname,
1742 cowdev->rdoreads,
1743 cowdev->cowname,
1744 cowdev->cowhead->flags & COWDIRTY ? "dirty":"clean",
1745 cowdev->mapsize >> MUSHIFT, MAPUNIT,
1746 cowdev->nrcowblocks, MAPUNIT,
1747 cowdev->cowreads,
1748 cowdev->cowwrites);
1749}
1750
1751/*****************************************************************************/
1752/* Setup and destroy cowdevices */
1753/*****************************************************************************/
1754
1755/*
1756** open and prepare a cowdevice (rdofile and cowfile) and allocate bitmaps
1757**
1758** returns:
1759** 0 - okay
1760** < 0 - error value
1761*/
1762static int
1763cowlo_openpair(char *rdof, char *cowf, int autorecover, int minor)
1764{
1765 long int rv;
1766 struct cowloop_device *cowdev = cowdevall[minor];
1767 struct kstatfs ks;
1768
1769 down(&cowdevlock);
1770
1771 /*
1772 ** requested device exists?
1773 */
1774 if (minor >= maxcows) {
1775 up(&cowdevlock);
1776 return -ENODEV;
1777 }
1778
1779 /*
1780 ** requested device already assigned to cowdevice?
1781 */
1782 if (cowdev->state & COWDEVOPEN) {
1783 up(&cowdevlock);
1784 return -EBUSY;
1785 }
1786
1787 /*
1788 ** initialize administration
1789 */
1790 memset(cowdev, 0, sizeof *cowdev);
1791
1792 spin_lock_init (&cowdev->rqlock);
1793 init_waitqueue_head(&cowdev->waitq);
1794 init_waitqueue_head(&cowdev->watchq);
1795
1796 /*
1797 ** open the read-only file
1798 */
1799 DEBUGP(DCOW"cowloop - call openrdo....\n");
1800
1801 if ( (rv = cowlo_openrdo(cowdev, rdof)) ) {
1802 cowlo_undo_openrdo(cowdev);
1803 up(&cowdevlock);
1804 return rv;
1805 }
1806
1807 /*
1808 ** open the cowfile
1809 */
1810 DEBUGP(DCOW"cowloop - call opencow....\n");
1811
1812 if ( (rv = cowlo_opencow(cowdev, cowf, autorecover)) ) {
1813 cowlo_undo_openrdo(cowdev);
1814 cowlo_undo_opencow(cowdev);
1815 up(&cowdevlock);
1816 return rv;
1817 }
1818
1819 /*
1820 ** administer total and available size of filesystem holding cowfile
1821 */
1822 if (vfs_statfs(cowdev->cowfp->f_dentry, &ks)==0) {
1823 cowdev->blksize = ks.f_bsize;
1824 cowdev->blktotal = ks.f_blocks;
1825 cowdev->blkavail = ks.f_bavail;
1826 } else {
1827 cowdev->blksize = 1024; /* avoid division by zero */
1828 }
1829
1830 /*
1831 ** flush the (recovered) bitmaps and cowhead to the cowfile
1832 */
1833 DEBUGP(DCOW"cowloop - call cowsync....\n");
1834
1835 cowlo_sync();
1836
1837 /*
1838 ** allocate gendisk for the cow device
1839 */
1840 DEBUGP(DCOW"cowloop - alloc disk....\n");
1841
1842 if ((cowdev->gd = alloc_disk(1)) == NULL) {
1843 printk(KERN_WARNING
1844 "cowloop - unable to alloc_disk for cowloop\n");
1845
1846 cowlo_undo_openrdo(cowdev);
1847 cowlo_undo_opencow(cowdev);
1848 up(&cowdevlock);
1849 return -ENOMEM;
1850 }
1851
1852 cowdev->gd->major = COWMAJOR;
1853 cowdev->gd->first_minor = minor;
1854 cowdev->gd->minors = 1;
1855 cowdev->gd->fops = &cowlo_fops;
1856 cowdev->gd->private_data = cowdev;
1857 sprintf(cowdev->gd->disk_name, "%s%d", DEVICE_NAME, minor);
1858
1859 /* in .5 Kb units */
1860 set_capacity(cowdev->gd, (cowdev->numblocks*(MAPUNIT/512)));
1861
1862 DEBUGP(DCOW"cowloop - init request queue....\n");
1863
1864 if ((cowdev->rqueue = blk_init_queue(cowlo_request, &cowdev->rqlock))
1865 == NULL) {
1866 printk(KERN_WARNING
1867 "cowloop - unable to get request queue for cowloop\n");
1868
1869 del_gendisk(cowdev->gd);
1870 cowlo_undo_openrdo(cowdev);
1871 cowlo_undo_opencow(cowdev);
1872 up(&cowdevlock);
1873 return -EINVAL;
1874 }
1875
1876 blk_queue_logical_block_size(cowdev->rqueue, cowdev->blocksz);
1877 cowdev->gd->queue = cowdev->rqueue;
1878
1879 /*
1880 ** start kernel thread to handle requests
1881 */
1882 DEBUGP(DCOW"cowloop - kickoff daemon....\n");
1883
1884 cowdev->pid = kernel_thread((int (*)(void *))cowlo_daemon, cowdev, 0);
1885
1886 /*
1887 ** create a file below directory /proc/cow for this new cowdevice
1888 */
1889 if (cowlo_procdir) {
1890 char tmpname[64];
1891
1892 sprintf(tmpname, "%d", minor);
1893
1894 create_proc_read_entry(tmpname, 0 , cowlo_procdir,
1895 cowlo_readproc, cowdev);
1896 }
1897
1898 cowdev->state |= COWDEVOPEN;
1899
1900 cowdev->rdoname = rdof;
1901 cowdev->cowname = cowf;
1902
1903 /*
1904 ** enable the new disk; this triggers the first request!
1905 */
1906 DEBUGP(DCOW"cowloop - call add_disk....\n");
1907
1908 add_disk(cowdev->gd);
1909
1910 up(&cowdevlock);
1911 return 0;
1912}
1913
1914/*
1915** close a cowdevice (pair of rdofile/cowfile) and release memory
1916**
1917** returns:
1918** 0 - okay
1919** < 0 - error value
1920*/
1921static int
1922cowlo_closepair(struct cowloop_device *cowdev)
1923{
1924 int minor;
1925
1926 down(&cowdevlock);
1927
1928 /*
1929 ** if cowdevice is not activated at all, refuse
1930 */
1931 if ( !(cowdev->state & COWDEVOPEN) ) {
1932 up(&cowdevlock);
1933 return -ENODEV;
1934 }
1935
1936 /*
1937 ** if this cowdevice is still open, refuse
1938 */
1939 if (cowdev->opencnt > 0) {
1940 up(&cowdevlock);
1941 return -EBUSY;
1942 }
1943
1944 up(&cowdevlock);
1945
1946 /*
1947 ** wakeup watcher (if any)
1948 */
1949 if (cowdev->state & COWWATCHDOG) {
1950 cowdev->watchthresh = cowdev->blkavail;
1951 wake_up_interruptible(&cowdev->watchq);
1952 }
1953
1954 /*
1955 ** wakeup kernel-thread to be able to exit
1956 ** and wait until it has exited
1957 */
1958 cowdev->closedown = 1;
1959 cowdev->qfilled = 1;
1960 wake_up_interruptible(&cowdev->waitq);
1961
1962 while (cowdev->pid)
1963 schedule();
1964
1965 del_gendisk(cowdev->gd); /* revert the alloc_disk() */
1966 put_disk(cowdev->gd); /* revert the add_disk() */
1967
1968 if (cowlo_procdir) {
1969 char tmpname[64];
1970
1971 for (minor = 0; minor < maxcows; minor++) {
1972 if (cowdev == cowdevall[minor]) break;
1973 }
1974 sprintf(tmpname, "%d", minor);
1975
1976 remove_proc_entry(tmpname, cowlo_procdir);
1977 }
1978
1979 blk_cleanup_queue(cowdev->rqueue);
1980
1981 /*
1982 ** release memory for filenames if these names have
1983 ** been allocated dynamically
1984 */
1985 if ( (cowdev->cowname) && (cowdev->cowname != cowfile))
1986 kfree(cowdev->cowname);
1987
1988 if ( (cowdev->rdoname) && (cowdev->rdoname != rdofile))
1989 kfree(cowdev->rdoname);
1990
1991 cowlo_undo_openrdo(cowdev);
1992 cowlo_undo_opencow(cowdev);
1993
1994 cowdev->state &= ~COWDEVOPEN;
1995
1996 return 0;
1997}
1998
1999/*
2000** open the read-only file
2001**
2002** returns:
2003** 0 - okay
2004** < 0 - error value
2005*/
2006static int
2007cowlo_openrdo(struct cowloop_device *cowdev, char *rdof)
2008{
2009 struct file *f;
2010 struct inode *inode;
2011 long int i, nrval;
2012
2013 DEBUGP(DCOW"cowloop - openrdo called\n");
2014
2015 /*
2016 ** open the read-only file
2017 */
2018 if(*rdof == '\0') {
2019 printk(KERN_ERR
2020 "cowloop - specify name for read-only file\n\n");
2021 return -EINVAL;
2022 }
2023
2024 f = filp_open(rdof, O_RDONLY|O_LARGEFILE, 0);
2025
2026 if ( (f == NULL) || IS_ERR(f) ) {
2027 printk(KERN_ERR
2028 "cowloop - open of rdofile %s failed\n", rdof);
2029 return -EINVAL;
2030 }
2031
2032 cowdev->rdofp = f;
2033
2034 inode = f->f_dentry->d_inode;
2035
2036 if ( !S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode) ) {
2037 printk(KERN_ERR
2038 "cowloop - %s not regular file or blockdev\n", rdof);
2039 return -EINVAL;
2040 }
2041
2042 DEBUGP(DCOW"cowloop - determine size rdo....\n");
2043
2044 /*
2045 ** determine block-size and total size of read-only file
2046 */
2047 if (S_ISREG(inode->i_mode)) {
2048 /*
2049 ** read-only file is a regular file
2050 */
2051 cowdev->blocksz = 512; /* other value fails */
2052 cowdev->numblocks = inode->i_size >> MUSHIFT;
2053
2054 if (inode->i_size & MUMASK) {
2055 printk(KERN_WARNING
2056 "cowloop - rdofile %s truncated to multiple "
2057 "of %d bytes\n", rdof, MAPUNIT);
2058 }
2059
2060 DEBUGP(DCOW"cowloop - RO=regular: numblocks=%d, blocksz=%d\n",
2061 cowdev->numblocks, cowdev->blocksz);
2062 } else {
2063 /*
2064 ** read-only file is a block device
2065 */
2066 cowdev->belowdev = inode->i_bdev;
2067 cowdev->belowgd = cowdev->belowdev->bd_disk; /* gendisk */
2068
2069 if (cowdev->belowdev->bd_part) {
2070 cowdev->numblocks = cowdev->belowdev->bd_part->nr_sects
2071 / (MAPUNIT/512);
2072 }
2073
2074 if (cowdev->belowgd) {
2075 cowdev->belowq = cowdev->belowgd->queue;
2076
2077 if (cowdev->numblocks == 0) {
2078 cowdev->numblocks = get_capacity(cowdev->belowgd)
2079 / (MAPUNIT/512);
2080 }
2081 }
2082
2083
2084 if (cowdev->belowq)
2085 cowdev->blocksz = queue_logical_block_size(cowdev->belowq);
2086
2087 if (cowdev->blocksz == 0)
2088 cowdev->blocksz = BLOCK_SIZE; /* default 2^10 */
2089
2090 DEBUGP(DCOW"cowloop - numblocks=%d, "
2091 "blocksz=%d, belowgd=%p, belowq=%p\n",
2092 cowdev->numblocks, cowdev->blocksz,
2093 cowdev->belowgd, cowdev->belowq);
2094
2095 DEBUGP(DCOW"cowloop - belowdev.bd_block_size=%d\n",
2096 cowdev->belowdev->bd_block_size);
2097 }
2098
2099 if (cowdev->numblocks == 0) {
2100 printk(KERN_ERR "cowloop - %s has no contents\n", rdof);
2101 return -EINVAL;
2102 }
2103
2104 /*
2105 ** reserve space in memory as generic I/O buffer
2106 */
2107 cowdev->iobuf = kmalloc(MAPUNIT, GFP_KERNEL);
2108
2109 if (!cowdev->iobuf) {
2110 printk(KERN_ERR
2111 "cowloop - cannot get space for buffer %d\n", MAPUNIT);
2112 return -ENOMEM;
2113 }
2114
2115 DEBUGP(DCOW"cowloop - determine fingerprint rdo....\n");
2116
2117 /*
2118 ** determine fingerprint for read-only file
2119 ** calculate fingerprint from first four datablocks
2120 ** which do not contain binary zeroes
2121 */
2122 for (i=0, cowdev->fingerprint=0, nrval=0;
2123 (nrval < 4)&&(i < cowdev->numblocks); i++) {
2124 int j;
2125 unsigned char cs;
2126
2127 /*
2128 ** read next block
2129 */
2130 if (cowlo_readrdo(cowdev, cowdev->iobuf, MAPUNIT,
2131 (loff_t)i << MUSHIFT) < 1)
2132 break;
2133
2134 /*
2135 ** calculate fingerprint by adding all byte-values
2136 */
2137 for (j=0, cs=0; j < MAPUNIT; j++)
2138 cs += *(cowdev->iobuf+j);
2139
2140 if (cs == 0) /* block probably contained zeroes */
2141 continue;
2142
2143 /*
2144 ** shift byte-value to proper place in final fingerprint
2145 */
2146 cowdev->fingerprint |= cs << (nrval*8);
2147 nrval++;
2148 }
2149
2150 return 0;
2151}
2152
2153/*
2154** undo memory allocs and file opens issued so far
2155** related to the read-only file
2156*/
2157static void
2158cowlo_undo_openrdo(struct cowloop_device *cowdev)
2159{
2160 if(cowdev->iobuf);
2161 kfree(cowdev->iobuf);
2162
2163 if (cowdev->rdofp)
2164 filp_close(cowdev->rdofp, 0);
2165}
2166
2167/*
2168** open the cowfile
2169**
2170** returns:
2171** 0 - okay
2172** < 0 - error value
2173*/
2174static int
2175cowlo_opencow(struct cowloop_device *cowdev, char *cowf, int autorecover)
2176{
2177 long int i, rv;
2178 int minor;
2179 unsigned long nb;
2180 struct file *f;
2181 struct inode *inode;
2182 loff_t offset;
2183 struct cowloop_device *cowtmp;
2184
2185 DEBUGP(DCOW"cowloop - opencow called\n");
2186
2187 /*
2188 ** open copy-on-write file (read-write)
2189 */
2190 if (cowf[0] == '\0') {
2191 printk(KERN_ERR
2192 "cowloop - specify name of copy-on-write file\n\n");
2193 return -EINVAL;
2194 }
2195
2196 f = filp_open(cowf, O_RDWR|O_LARGEFILE, 0600);
2197
2198 if ( (f == NULL) || IS_ERR(f) ) {
2199 /*
2200 ** non-existing cowfile: try to create
2201 */
2202 f = filp_open(cowf, O_RDWR|O_CREAT|O_LARGEFILE, 0600);
2203
2204 if ( (f == NULL) || IS_ERR(f) ) {
2205 printk(KERN_ERR
2206 "cowloop - failed to open file %s for read-write\n\n",
2207 cowf);
2208 return -EINVAL;
2209 }
2210 }
2211
2212 cowdev->cowfp = f;
2213
2214 inode = f->f_dentry->d_inode;
2215
2216 if (!S_ISREG(inode->i_mode)) {
2217 printk(KERN_ERR "cowloop - %s is not regular file\n", cowf);
2218 return -EINVAL;
2219 }
2220
2221 /*
2222 ** check if this cowfile is already in use for another cowdevice
2223 */
2224 for (minor = 0; minor < maxcows; minor++) {
2225
2226 cowtmp = cowdevall[minor];
2227
2228 if ( !(cowtmp->state & COWDEVOPEN) )
2229 continue;
2230
2231 if (cowtmp == cowdev)
2232 continue;
2233
2234 if (cowtmp->cowfp->f_dentry->d_inode == f->f_dentry->d_inode) {
2235 printk(KERN_ERR
2236 "cowloop - %s: already in use as cow\n", cowf);
2237 return -EBUSY;
2238 }
2239 }
2240
2241 /*
2242 ** mark cowfile open for read-write
2243 */
2244 cowdev->state |= COWRWCOWOPEN;
2245
2246 /*
2247 ** calculate size (in bytes) for total bitmap in cowfile;
2248 ** when the size of the cowhead block is added, the start-offset
2249 ** for the modified data blocks can be found
2250 */
2251 nb = cowdev->numblocks;
2252
2253 if (nb%8) /* transform #bits to #bytes */
2254 nb+=8; /* rounded if necessary */
2255 nb /= 8;
2256
2257 if (nb & MUMASK) /* round up #bytes to MAPUNIT chunks */
2258 cowdev->mapsize = ( (nb>>MUSHIFT) +1) << MUSHIFT;
2259 else
2260 cowdev->mapsize = nb;
2261
2262 /*
2263 ** reserve space in memory for the cowhead
2264 */
2265 cowdev->cowhead = kmalloc(MAPUNIT, GFP_KERNEL);
2266
2267 if (!cowdev->cowhead) {
2268 printk(KERN_ERR "cowloop - cannot get space for cowhead %d\n",
2269 MAPUNIT);
2270 return -ENOMEM;
2271 }
2272
2273 memset(cowdev->cowhead, 0, MAPUNIT);
2274
2275 DEBUGP(DCOW"cowloop - prepare cowhead....\n");
2276
2277 /*
2278 ** check if the cowfile exists or should be created
2279 */
2280 if (inode->i_size != 0) {
2281 /*
2282 ** existing cowfile: read the cow head
2283 */
2284 if (inode->i_size < MAPUNIT) {
2285 printk(KERN_ERR
2286 "cowloop - existing cowfile %s too small\n",
2287 cowf);
2288 return -EINVAL;
2289 }
2290
2291 cowlo_readcowraw(cowdev, cowdev->cowhead, MAPUNIT, (loff_t) 0);
2292
2293 /*
2294 ** verify if the existing file is really a cowfile
2295 */
2296 if (cowdev->cowhead->magic != COWMAGIC) {
2297 printk(KERN_ERR
2298 "cowloop - cowfile %s has incorrect format\n",
2299 cowf);
2300 return -EINVAL;
2301 }
2302
2303 /*
2304 ** verify the cowhead version of the cowfile
2305 */
2306 if (cowdev->cowhead->version > COWVERSION) {
2307 printk(KERN_ERR
2308 "cowloop - cowfile %s newer than this driver\n",
2309 cowf);
2310 return -EINVAL;
2311 }
2312
2313 /*
2314 ** make sure that this is not a packed cowfile
2315 */
2316 if (cowdev->cowhead->flags & COWPACKED) {
2317 printk(KERN_ERR
2318 "cowloop - packed cowfile %s not accepted\n", cowf);
2319 return -EINVAL;
2320 }
2321
2322 /*
2323 ** verify if the cowfile has been properly closed
2324 */
2325 if (cowdev->cowhead->flags & COWDIRTY) {
2326 /*
2327 ** cowfile was not properly closed;
2328 ** check if automatic recovery is required
2329 ** (actual recovery will be done later on)
2330 */
2331 if (!autorecover) {
2332 printk(KERN_ERR
2333 "cowloop - cowfile %s is dirty "
2334 "(not properly closed by rmmod?)\n",
2335 cowf);
2336 printk(KERN_ERR
2337 "cowloop - run cowrepair or specify "
2338 "'option=r' to recover\n");
2339 return -EINVAL;
2340 }
2341 }
2342
2343 /*
2344 ** verify if the cowfile is really related to this rdofile
2345 */
2346 if (cowdev->cowhead->rdoblocks != cowdev->numblocks) {
2347 printk(KERN_ERR
2348 "cowloop - cowfile %s (size %lld) not related "
2349 "to rdofile (size %lld)\n",
2350 cowf,
2351 (long long)cowdev->cowhead->rdoblocks <<MUSHIFT,
2352 (long long)cowdev->numblocks <<MUSHIFT);
2353 return -EINVAL;
2354 }
2355
2356 if (cowdev->cowhead->rdofingerprint != cowdev->fingerprint) {
2357 printk(KERN_ERR
2358 "cowloop - cowfile %s not related to rdofile "
2359 " (fingerprint err - rdofile modified?)\n", cowf);
2360 return -EINVAL;
2361 }
2362 } else {
2363 /*
2364 ** new cowfile: determine the minimal size (cowhead+bitmap)
2365 */
2366 offset = (loff_t) MAPUNIT + cowdev->mapsize - 1;
2367
2368 if ( cowlo_writecowraw(cowdev, "", 1, offset) < 1) {
2369 printk(KERN_ERR
2370 "cowloop - cannot set cowfile to size %lld\n",
2371 offset+1);
2372 return -EINVAL;
2373 }
2374
2375 /*
2376 ** prepare new cowhead
2377 */
2378 cowdev->cowhead->magic = COWMAGIC;
2379 cowdev->cowhead->version = COWVERSION;
2380 cowdev->cowhead->mapunit = MAPUNIT;
2381 cowdev->cowhead->mapsize = cowdev->mapsize;
2382 cowdev->cowhead->rdoblocks = cowdev->numblocks;
2383 cowdev->cowhead->rdofingerprint = cowdev->fingerprint;
2384 cowdev->cowhead->cowused = 0;
2385
2386 /*
2387 ** calculate start offset of data in cowfile,
2388 ** rounded up to multiple of 4K to avoid
2389 ** unnecessary disk-usage for written datablocks in
2390 ** the sparsed cowfile on e.g. 4K filesystems
2391 */
2392 cowdev->cowhead->doffset =
2393 ((MAPUNIT+cowdev->mapsize+4095)>>12)<<12;
2394 }
2395
2396 cowdev->cowhead->flags = 0;
2397
2398 DEBUGP(DCOW"cowloop - reserve space bitmap....\n");
2399
2400 /*
2401 ** reserve space in memory for the entire bitmap and
2402 ** fill it with the bitmap-data from disk; the entire
2403 ** bitmap is allocated in several chunks because kmalloc
2404 ** has restrictions regarding the allowed size per kmalloc
2405 */
2406 cowdev->mapcount = (cowdev->mapsize+MAPCHUNKSZ-1)/MAPCHUNKSZ;
2407
2408 /*
2409 ** the size of every bitmap chunk will be MAPCHUNKSZ bytes, except for
2410 ** the last bitmap chunk: calculate remaining size for this chunk
2411 */
2412 if (cowdev->mapsize % MAPCHUNKSZ == 0)
2413 cowdev->mapremain = MAPCHUNKSZ;
2414 else
2415 cowdev->mapremain = cowdev->mapsize % MAPCHUNKSZ;
2416
2417 /*
2418 ** allocate space to store all pointers for the bitmap-chunks
2419 ** (initialize area with zeroes to allow proper undo)
2420 */
2421 cowdev->mapcache = kmalloc(cowdev->mapcount * sizeof(char *),
2422 GFP_KERNEL);
2423 if (!cowdev->mapcache) {
2424 printk(KERN_ERR
2425 "cowloop - can not allocate space for bitmap ptrs\n");
2426 return -ENOMEM;
2427 }
2428
2429 memset(cowdev->mapcache, 0, cowdev->mapcount * sizeof(char *));
2430
2431 /*
2432 ** allocate space to store the bitmap-chunks themselves
2433 */
2434 for (i=0; i < cowdev->mapcount; i++) {
2435 if (i < (cowdev->mapcount-1))
2436 *(cowdev->mapcache+i) = kmalloc(MAPCHUNKSZ, GFP_KERNEL);
2437 else
2438 *(cowdev->mapcache+i) = kmalloc(cowdev->mapremain,
2439 GFP_KERNEL);
2440
2441 if (*(cowdev->mapcache+i) == NULL) {
2442 printk(KERN_ERR "cowloop - no space for bitmapchunk %ld"
2443 " totmapsz=%ld, mapcnt=%d mapunit=%d\n",
2444 i, cowdev->mapsize, cowdev->mapcount,
2445 MAPUNIT);
2446 return -ENOMEM;
2447 }
2448 }
2449
2450 DEBUGP(DCOW"cowloop - read bitmap from cow....\n");
2451
2452 /*
2453 ** read the entire bitmap from the cowfile into the in-memory cache;
2454 ** count the number of blocks that are in use already
2455 ** (statistical purposes)
2456 */
2457 for (i=0, offset=MAPUNIT; i < cowdev->mapcount;
2458 i++, offset+=MAPCHUNKSZ) {
2459 unsigned long numbytes;
2460
2461 if (i < (cowdev->mapcount-1))
2462 /*
2463 ** full bitmap chunk
2464 */
2465 numbytes = MAPCHUNKSZ;
2466 else
2467 /*
2468 ** last bitmap chunk: might be partly filled
2469 */
2470 numbytes = cowdev->mapremain;
2471
2472 cowlo_readcowraw(cowdev, *(cowdev->mapcache+i),
2473 numbytes, offset);
2474 }
2475
2476 /*
2477 ** if the cowfile was dirty and automatic recovery is required,
2478 ** reconstruct a proper bitmap in memory now
2479 */
2480 if (cowdev->cowhead->flags & COWDIRTY) {
2481 unsigned long long blocknum;
2482 char databuf[MAPUNIT];
2483 unsigned long mapnum, mapbyte, mapbit;
2484
2485 printk(KERN_NOTICE "cowloop - recover dirty cowfile %s....\n",
2486 cowf);
2487
2488 /*
2489 ** read all data blocks
2490 */
2491 for (blocknum=0, rv=1, offset=0;
2492 cowlo_readcow(cowdev, databuf, MAPUNIT, offset) > 0;
2493 blocknum++, offset += MAPUNIT) {
2494
2495 /*
2496 ** if this datablock contains real data (not binary
2497 ** zeroes), set the corresponding bit in the bitmap
2498 */
2499 if ( memcmp(databuf, allzeroes, MAPUNIT) == 0)
2500 continue;
2501
2502 mapnum = CALCMAP (blocknum);
2503 mapbyte = CALCBYTE(blocknum);
2504 mapbit = CALCBIT (blocknum);
2505
2506 *(*(cowdev->mapcache+mapnum)+mapbyte) |= (1<<mapbit);
2507 }
2508
2509 printk(KERN_NOTICE "cowloop - cowfile recovery completed\n");
2510 }
2511
2512 /*
2513 ** count all bits set in the bitmaps for statistical purposes
2514 */
2515 for (i=0, cowdev->nrcowblocks = 0; i < cowdev->mapcount; i++) {
2516 long numbytes;
2517 char *p;
2518
2519 if (i < (cowdev->mapcount-1))
2520 numbytes = MAPCHUNKSZ;
2521 else
2522 numbytes = cowdev->mapremain;
2523
2524 p = *(cowdev->mapcache+i);
2525
2526 for (numbytes--; numbytes >= 0; numbytes--, p++) {
2527 /*
2528 ** for only eight checks the following construction
2529 ** is faster than a loop-construction
2530 */
2531 if ((*p) & 0x01) cowdev->nrcowblocks++;
2532 if ((*p) & 0x02) cowdev->nrcowblocks++;
2533 if ((*p) & 0x04) cowdev->nrcowblocks++;
2534 if ((*p) & 0x08) cowdev->nrcowblocks++;
2535 if ((*p) & 0x10) cowdev->nrcowblocks++;
2536 if ((*p) & 0x20) cowdev->nrcowblocks++;
2537 if ((*p) & 0x40) cowdev->nrcowblocks++;
2538 if ((*p) & 0x80) cowdev->nrcowblocks++;
2539 }
2540 }
2541
2542 /*
2543 ** consistency-check for number of bits set in bitmap
2544 */
2545 if ( !(cowdev->cowhead->flags & COWDIRTY) &&
2546 (cowdev->cowhead->cowused != cowdev->nrcowblocks) ) {
2547 printk(KERN_ERR "cowloop - inconsistent cowfile admi\n");
2548 return -EINVAL;
2549 }
2550
2551 return 0;
2552}
2553
2554/*
2555** undo memory allocs and file opens issued so far
2556** related to the cowfile
2557*/
2558static void
2559cowlo_undo_opencow(struct cowloop_device *cowdev)
2560{
2561 int i;
2562
2563 if (cowdev->mapcache) {
2564 for (i=0; i < cowdev->mapcount; i++) {
2565 if (*(cowdev->mapcache+i) != NULL)
2566 kfree( *(cowdev->mapcache+i) );
2567 }
2568
2569 kfree(cowdev->mapcache);
2570 }
2571
2572 if (cowdev->cowhead)
2573 kfree(cowdev->cowhead);
2574
2575 if ( (cowdev->state & COWCOWOPEN) && (cowdev->cowfp) )
2576 filp_close(cowdev->cowfp, 0);
2577
2578 /*
2579 ** mark cowfile closed
2580 */
2581 cowdev->state &= ~COWCOWOPEN;
2582}
2583
2584/*
2585** flush the entire bitmap and the cowhead (clean) to the cowfile
2586**
2587** must be called with the cowdevices-lock set
2588*/
2589static void
2590cowlo_sync(void)
2591{
2592 int i, minor;
2593 loff_t offset;
2594 struct cowloop_device *cowdev;
2595
2596 for (minor=0; minor < maxcows; minor++) {
2597 cowdev = cowdevall[minor];
2598 if ( ! (cowdev->state & COWRWCOWOPEN) )
2599 continue;
2600
2601 for (i=0, offset=MAPUNIT; i < cowdev->mapcount;
2602 i++, offset += MAPCHUNKSZ) {
2603 unsigned long numbytes;
2604
2605 if (i < (cowdev->mapcount-1))
2606 /*
2607 ** full bitmap chunk
2608 */
2609 numbytes = MAPCHUNKSZ;
2610 else
2611 /*
2612 ** last bitmap chunk: might be partly filled
2613 */
2614 numbytes = cowdev->mapremain;
2615
2616 DEBUGP(DCOW
2617 "cowloop - flushing bitmap %2d (%3ld Kb)\n",
2618 i, numbytes/1024);
2619
2620 if (cowlo_writecowraw(cowdev, *(cowdev->mapcache+i),
2621 numbytes, offset) < numbytes) {
2622 break;
2623 }
2624 }
2625
2626 /*
2627 ** flush clean up-to-date cowhead to cowfile
2628 */
2629 cowdev->cowhead->cowused = cowdev->nrcowblocks;
2630 cowdev->cowhead->flags &= ~COWDIRTY;
2631
2632 DEBUGP(DCOW "cowloop - flushing cowhead (%3d Kb)\n",
2633 MAPUNIT/1024);
2634
2635 cowlo_writecowraw(cowdev, cowdev->cowhead, MAPUNIT, (loff_t) 0);
2636 }
2637}
2638
2639/*****************************************************************************/
2640/* Module loading/unloading */
2641/*****************************************************************************/
2642
2643/*
2644** called during insmod/modprobe
2645*/
2646static int __init
2647cowlo_init_module(void)
2648{
2649 int rv;
2650 int minor, uptocows;
2651
2652 revision[sizeof revision - 3] = '\0';
2653
2654 printk(KERN_NOTICE "cowloop - (C) 2009 ATComputing.nl - version: %s\n", &revision[11]);
2655 printk(KERN_NOTICE "cowloop - info: www.ATComputing.nl/cowloop\n");
2656
2657 memset(allzeroes, 0, MAPUNIT);
2658
2659 /*
2660 ** Setup administration for all possible cowdevices.
2661 ** Note that their minor numbers go from 0 to MAXCOWS-1 inclusive
2662 ** and minor == MAXCOWS-1 is reserved for the control device.
2663 */
2664 if ((maxcows < 1) || (maxcows > MAXCOWS)) {
2665 printk(KERN_WARNING
2666 "cowloop - maxcows exceeds maximum of %d\n", MAXCOWS);
2667
2668 maxcows = DFLCOWS;
2669 }
2670
2671 /* allocate room for a table with a pointer to each cowloop_device: */
2672 if ( (cowdevall = kmalloc(maxcows * sizeof(struct cowloop_device *),
2673 GFP_KERNEL)) == NULL) {
2674 printk(KERN_WARNING
2675 "cowloop - can not alloc table for %d devs\n", maxcows);
2676 uptocows = 0;
2677 rv = -ENOMEM;
2678 goto error_out;
2679 }
2680 memset(cowdevall, 0, maxcows * sizeof(struct cowloop_device *));
2681 /* then hook an actual cowloop_device struct to each pointer: */
2682 for (minor=0; minor < maxcows; minor++) {
2683 if ((cowdevall[minor] = kmalloc(sizeof(struct cowloop_device),
2684 GFP_KERNEL)) == NULL) {
2685 printk(KERN_WARNING
2686 "cowloop - can not alloc admin-struct for dev no %d\n", minor);
2687
2688 uptocows = minor; /* this is how far we got.... */
2689 rv = -ENOMEM;
2690 goto error_out;
2691 }
2692 memset(cowdevall[minor], 0, sizeof(struct cowloop_device));
2693 }
2694 uptocows = maxcows; /* we got all devices */
2695
2696 sema_init(&cowdevlock, 1);
2697
2698 /*
2699 ** register cowloop module
2700 */
2701 if ( register_blkdev(COWMAJOR, DEVICE_NAME) < 0) {
2702 printk(KERN_WARNING
2703 "cowloop - unable to get major %d for cowloop\n", COWMAJOR);
2704 rv = -EIO;
2705 goto error_out;
2706 }
2707
2708 /*
2709 ** create a directory below /proc to allocate a file
2710 ** for each cowdevice that is allocated later on
2711 */
2712 cowlo_procdir = proc_mkdir("cow", NULL);
2713
2714 /*
2715 ** check if a cowdevice has to be opened during insmod/modprobe;
2716 ** two parameters should be specified then: rdofile= and cowfile=
2717 */
2718 if( (rdofile[0] != '\0') && (cowfile[0] != '\0') ) {
2719 char *po = option;
2720 int wantrecover = 0;
2721
2722 /*
2723 ** check if automatic recovery is wanted
2724 */
2725 while (*po) {
2726 if (*po == 'r') {
2727 wantrecover = 1;
2728 break;
2729 }
2730 po++;
2731 }
2732
2733 /*
2734 ** open new cowdevice with minor number 0
2735 */
2736 if ( (rv = cowlo_openpair(rdofile, cowfile, wantrecover, 0))) {
2737 remove_proc_entry("cow", NULL);
2738 unregister_blkdev(COWMAJOR, DEVICE_NAME);
2739 goto error_out;
2740 }
2741 } else {
2742 /*
2743 ** check if only one parameter has been specified
2744 */
2745 if( (rdofile[0] != '\0') || (cowfile[0] != '\0') ) {
2746 printk(KERN_ERR
2747 "cowloop - only one filename specified\n");
2748 remove_proc_entry("cow", NULL);
2749 unregister_blkdev(COWMAJOR, DEVICE_NAME);
2750 rv = -EINVAL;
2751 goto error_out;
2752 }
2753 }
2754
2755 /*
2756 ** allocate fake disk as control channel to handle the requests
2757 ** to activate and deactivate cowdevices dynamically
2758 */
2759 if (!(cowctlgd = alloc_disk(1))) {
2760 printk(KERN_WARNING
2761 "cowloop - unable to alloc_disk for cowctl\n");
2762
2763 remove_proc_entry("cow", NULL);
2764 (void) cowlo_closepair(cowdevall[0]);
2765 unregister_blkdev(COWMAJOR, DEVICE_NAME);
2766 rv = -ENOMEM;
2767 goto error_out;
2768 }
2769
2770 spin_lock_init(&cowctlrqlock);
2771 cowctlgd->major = COWMAJOR;
2772 cowctlgd->first_minor = COWCTL;
2773 cowctlgd->minors = 1;
2774 cowctlgd->fops = &cowlo_fops;
2775 cowctlgd->private_data = NULL;
2776 /* the device has capacity 0, so there will be no q-requests */
2777 cowctlgd->queue = blk_init_queue(NULL, &cowctlrqlock);
2778 sprintf(cowctlgd->disk_name, "cowctl");
2779 set_capacity(cowctlgd, 0);
2780
2781 add_disk(cowctlgd);
2782
2783 printk(KERN_NOTICE "cowloop - number of configured cowdevices: %d\n",
2784 maxcows);
2785 if (rdofile[0] != '\0') {
2786 printk(KERN_NOTICE "cowloop - initialized on rdofile=%s\n",
2787 rdofile);
2788 } else {
2789 printk(KERN_NOTICE "cowloop - initialized without rdofile yet\n");
2790 }
2791 return 0;
2792
2793error_out:
2794 for (minor=0; minor < uptocows ; minor++) {
2795 kfree(cowdevall[minor]);
2796 }
2797 kfree(cowdevall);
2798 return rv;
2799}
2800
2801/*
2802** called during rmmod
2803*/
2804static void __exit
2805cowlo_cleanup_module(void)
2806{
2807 int minor;
2808
2809 /*
2810 ** flush bitmaps and cowheads to the cowfiles
2811 */
2812 down(&cowdevlock);
2813 cowlo_sync();
2814 up(&cowdevlock);
2815
2816 /*
2817 ** close all cowdevices
2818 */
2819 for (minor=0; minor < maxcows; minor++)
2820 (void) cowlo_closepair(cowdevall[minor]);
2821
2822 unregister_blkdev(COWMAJOR, DEVICE_NAME);
2823
2824 /*
2825 ** get rid of /proc/cow and unregister the driver
2826 */
2827 remove_proc_entry("cow", NULL);
2828
2829 for (minor = 0; minor < maxcows; minor++) {
2830 kfree(cowdevall[minor]);
2831 }
2832 kfree(cowdevall);
2833
2834 del_gendisk(cowctlgd); /* revert the alloc_disk() */
2835 put_disk (cowctlgd); /* revert the add_disk() */
2836 blk_cleanup_queue(cowctlgd->queue); /* cleanup the empty queue */
2837
2838 printk(KERN_NOTICE "cowloop - unloaded\n");
2839}
2840
2841module_init(cowlo_init_module);
2842module_exit(cowlo_cleanup_module);
diff --git a/drivers/staging/cowloop/cowloop.h b/drivers/staging/cowloop/cowloop.h
deleted file mode 100644
index bbd4a35ac667..000000000000
--- a/drivers/staging/cowloop/cowloop.h
+++ /dev/null
@@ -1,66 +0,0 @@
1/*
2** DO NOT MODIFY THESE VALUES (would make old cowfiles unusable)
3*/
4#define MAPUNIT 1024 /* blocksize for bit in bitmap */
5#define MUSHIFT 10 /* bitshift for bit in bitmap */
6#define MUMASK 0x3ff /* bitmask for bit in bitmap */
7
8#define COWMAGIC 0x574f437f /* byte-swapped '7f C O W' */
9#define COWDIRTY 0x01
10#define COWPACKED 0x02
11#define COWVERSION 1
12
13struct cowhead
14{
15 int magic; /* identifies a cowfile */
16 short version; /* version of cowhead */
17 short flags; /* flags indicating status */
18 unsigned long mapunit; /* blocksize per bit in bitmap */
19 unsigned long mapsize; /* total size of bitmap (bytes) */
20 unsigned long doffset; /* start-offset datablocks in cow */
21 unsigned long rdoblocks; /* size of related read-only file */
22 unsigned long rdofingerprint; /* fingerprint of read-only file */
23 unsigned long cowused; /* number of datablocks used in cow */
24};
25
26#define COWDEVDIR "/dev/cow/"
27#define COWDEVICE COWDEVDIR "%ld"
28#define COWCONTROL COWDEVDIR "ctl"
29
30#define MAXCOWS 1024
31#define COWCTL (MAXCOWS-1) /* minor number of /dev/cow/ctl */
32
33#define COWPROCDIR "/proc/cow/"
34#define COWPROCFILE COWPROCDIR "%d"
35
36/*
37** ioctl related stuff
38*/
39#define ANYDEV ((unsigned long)-1)
40
41struct cowpair
42{
43 unsigned char *rdofile; /* pathname of the rdofile */
44 unsigned char *cowfile; /* pathname of the cowfile */
45 unsigned short rdoflen; /* length of rdofile pathname */
46 unsigned short cowflen; /* length of cowfile pathname */
47 unsigned long device; /* requested/returned device number */
48};
49
50struct cowwatch
51{
52 int flags; /* request flags */
53 unsigned long device; /* requested device number */
54 unsigned long threshold; /* continue if free Kb < threshold */
55 unsigned long totalkb; /* ret: total filesystem size (Kb) */
56 unsigned long availkb; /* ret: free filesystem size (Kb) */
57};
58
59#define WATCHWAIT 0x01 /* block until threshold reached */
60
61#define COWSYNC _IO ('C', 1)
62#define COWMKPAIR _IOW ('C', 2, struct cowpair)
63#define COWRMPAIR _IOW ('C', 3, unsigned long)
64#define COWWATCH _IOW ('C', 4, struct cowwatch)
65#define COWCLOSE _IOW ('C', 5, unsigned long)
66#define COWRDOPEN _IOW ('C', 6, unsigned long)
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index beb99a547f09..4586650d65c3 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -4,6 +4,7 @@
4 4
5menuconfig IIO 5menuconfig IIO
6 tristate "Industrial I/O support" 6 tristate "Industrial I/O support"
7 depends on !S390
7 ---help--- 8 ---help---
8 The industrial I/O subsystem provides a unified framework for 9 The industrial I/O subsystem provides a unified framework for
9 drivers for many different types of embedded sensors using a 10 drivers for many different types of embedded sensors using a
diff --git a/drivers/staging/p9auth/p9auth.c b/drivers/staging/p9auth/p9auth.c
index 9111dcba37a1..8ccfff723eec 100644
--- a/drivers/staging/p9auth/p9auth.c
+++ b/drivers/staging/p9auth/p9auth.c
@@ -183,7 +183,7 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
183 user_buf_running = NULL; 183 user_buf_running = NULL;
184 hash_str = NULL; 184 hash_str = NULL;
185 node_ptr = kmalloc(sizeof(struct cap_node), GFP_KERNEL); 185 node_ptr = kmalloc(sizeof(struct cap_node), GFP_KERNEL);
186 user_buf = kzalloc(count, GFP_KERNEL); 186 user_buf = kzalloc(count+1, GFP_KERNEL);
187 if (!node_ptr || !user_buf) 187 if (!node_ptr || !user_buf)
188 goto out; 188 goto out;
189 189
@@ -207,6 +207,7 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
207 list_add(&(node_ptr->list), &(dev->head->list)); 207 list_add(&(node_ptr->list), &(dev->head->list));
208 node_ptr = NULL; 208 node_ptr = NULL;
209 } else { 209 } else {
210 char *tmpu;
210 if (!cap_devices[0].head || 211 if (!cap_devices[0].head ||
211 list_empty(&(cap_devices[0].head->list))) { 212 list_empty(&(cap_devices[0].head->list))) {
212 retval = -EINVAL; 213 retval = -EINVAL;
@@ -218,10 +219,10 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
218 * need to split it and hash 'user1@user2' using 'randomstring' 219 * need to split it and hash 'user1@user2' using 'randomstring'
219 * as the key. 220 * as the key.
220 */ 221 */
221 user_buf_running = kstrdup(user_buf, GFP_KERNEL); 222 tmpu = user_buf_running = kstrdup(user_buf, GFP_KERNEL);
222 source_user = strsep(&user_buf_running, "@"); 223 source_user = strsep(&tmpu, "@");
223 target_user = strsep(&user_buf_running, "@"); 224 target_user = strsep(&tmpu, "@");
224 rand_str = strsep(&user_buf_running, "@"); 225 rand_str = tmpu;
225 if (!source_user || !target_user || !rand_str) { 226 if (!source_user || !target_user || !rand_str) {
226 retval = -EINVAL; 227 retval = -EINVAL;
227 goto out; 228 goto out;
@@ -229,7 +230,8 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
229 230
230 /* hash the string user1@user2 with rand_str as the key */ 231 /* hash the string user1@user2 with rand_str as the key */
231 len = strlen(source_user) + strlen(target_user) + 1; 232 len = strlen(source_user) + strlen(target_user) + 1;
232 hash_str = kzalloc(len, GFP_KERNEL); 233 /* src, @, len, \0 */
234 hash_str = kzalloc(len+1, GFP_KERNEL);
233 strcat(hash_str, source_user); 235 strcat(hash_str, source_user);
234 strcat(hash_str, "@"); 236 strcat(hash_str, "@");
235 strcat(hash_str, target_user); 237 strcat(hash_str, target_user);
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c
index d4fa65489655..b0802a7aeb5f 100644
--- a/drivers/staging/rtl8192e/r8192E_core.c
+++ b/drivers/staging/rtl8192e/r8192E_core.c
@@ -46,6 +46,7 @@
46#undef DEBUG_TX_DESC 46#undef DEBUG_TX_DESC
47 47
48//#define CONFIG_RTL8192_IO_MAP 48//#define CONFIG_RTL8192_IO_MAP
49#include <linux/vmalloc.h>
49#include <asm/uaccess.h> 50#include <asm/uaccess.h>
50#include "r8192E_hw.h" 51#include "r8192E_hw.h"
51#include "r8192E.h" 52#include "r8192E.h"
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 8950724f168e..067082a7d759 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -51,10 +51,26 @@ static struct ieee80211_supported_band wbsoft_band_2GHz = {
51 .n_bitrates = ARRAY_SIZE(wbsoft_rates), 51 .n_bitrates = ARRAY_SIZE(wbsoft_rates),
52}; 52};
53 53
54static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
55{
56 u32 tmp;
57
58 if (pHwData->SurpriseRemove)
59 return;
60
61 pHwData->BeaconPeriod = beacon_period;
62 tmp = pHwData->BeaconPeriod << 16;
63 tmp |= pHwData->ProbeDelay;
64 Wb35Reg_Write(pHwData, 0x0848, tmp);
65}
66
54static int wbsoft_add_interface(struct ieee80211_hw *dev, 67static int wbsoft_add_interface(struct ieee80211_hw *dev,
55 struct ieee80211_if_init_conf *conf) 68 struct ieee80211_if_init_conf *conf)
56{ 69{
57 printk("wbsoft_add interface called\n"); 70 struct wbsoft_priv *priv = dev->priv;
71
72 hal_set_beacon_period(&priv->sHwData, conf->vif->bss_conf.beacon_int);
73
58 return 0; 74 return 0;
59} 75}
60 76
@@ -83,10 +99,16 @@ static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
83 return 0; 99 return 0;
84} 100}
85 101
102static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
103 struct dev_addr_list *mc_list)
104{
105 return mc_count;
106}
107
86static void wbsoft_configure_filter(struct ieee80211_hw *dev, 108static void wbsoft_configure_filter(struct ieee80211_hw *dev,
87 unsigned int changed_flags, 109 unsigned int changed_flags,
88 unsigned int *total_flags, 110 unsigned int *total_flags,
89 int mc_count, struct dev_mc_list *mclist) 111 u64 multicast)
90{ 112{
91 unsigned int new_flags; 113 unsigned int new_flags;
92 114
@@ -94,7 +116,7 @@ static void wbsoft_configure_filter(struct ieee80211_hw *dev,
94 116
95 if (*total_flags & FIF_PROMISC_IN_BSS) 117 if (*total_flags & FIF_PROMISC_IN_BSS)
96 new_flags |= FIF_PROMISC_IN_BSS; 118 new_flags |= FIF_PROMISC_IN_BSS;
97 else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) 119 else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
98 new_flags |= FIF_ALLMULTI; 120 new_flags |= FIF_ALLMULTI;
99 121
100 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; 122 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
@@ -138,19 +160,6 @@ static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
138 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl); 160 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
139} 161}
140 162
141static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
142{
143 u32 tmp;
144
145 if (pHwData->SurpriseRemove)
146 return;
147
148 pHwData->BeaconPeriod = beacon_period;
149 tmp = pHwData->BeaconPeriod << 16;
150 tmp |= pHwData->ProbeDelay;
151 Wb35Reg_Write(pHwData, 0x0848, tmp);
152}
153
154static void 163static void
155hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel) 164hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel)
156{ 165{
@@ -244,7 +253,6 @@ static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
244static int wbsoft_config(struct ieee80211_hw *dev, u32 changed) 253static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
245{ 254{
246 struct wbsoft_priv *priv = dev->priv; 255 struct wbsoft_priv *priv = dev->priv;
247 struct ieee80211_conf *conf = &dev->conf;
248 ChanInfo ch; 256 ChanInfo ch;
249 257
250 printk("wbsoft_config called\n"); 258 printk("wbsoft_config called\n");
@@ -254,7 +262,6 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
254 ch.ChanNo = 1; 262 ch.ChanNo = 1;
255 263
256 hal_set_current_channel(&priv->sHwData, ch); 264 hal_set_current_channel(&priv->sHwData, ch);
257 hal_set_beacon_period(&priv->sHwData, conf->beacon_int);
258 hal_set_accept_broadcast(&priv->sHwData, 1); 265 hal_set_accept_broadcast(&priv->sHwData, 1);
259 hal_set_accept_promiscuous(&priv->sHwData, 1); 266 hal_set_accept_promiscuous(&priv->sHwData, 1);
260 hal_set_accept_multicast(&priv->sHwData, 1); 267 hal_set_accept_multicast(&priv->sHwData, 1);
@@ -277,6 +284,7 @@ static const struct ieee80211_ops wbsoft_ops = {
277 .add_interface = wbsoft_add_interface, 284 .add_interface = wbsoft_add_interface,
278 .remove_interface = wbsoft_remove_interface, 285 .remove_interface = wbsoft_remove_interface,
279 .config = wbsoft_config, 286 .config = wbsoft_config,
287 .prepare_multicast = wbsoft_prepare_multicast,
280 .configure_filter = wbsoft_configure_filter, 288 .configure_filter = wbsoft_configure_filter,
281 .get_stats = wbsoft_get_stats, 289 .get_stats = wbsoft_get_stats,
282 .get_tx_stats = wbsoft_get_tx_stats, 290 .get_tx_stats = wbsoft_get_tx_stats,