3 * Driver core for the "Hermes" wireless MAC controller, as used in
4 * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
5 * work on the hfa3841 and hfa3842 MAC controller chips used in the
6 * Prism I & II chipsets.
8 * This is not a complete driver, just low-level access routines for
9 * the MAC controller itself.
11 * Based on the prism2 driver from Absolute Value Systems' linux-wlan
12 * project, the Linux wvlan_cs driver, Lucent's HCF-Light
13 * (wvlan_hcf.c) library, and the NetBSD wireless driver.
15 * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
17 * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
19 * This file distributed under the GPL, version 2.
27 * As a module of low level hardware access routines, there is no
28 * locking. Users of this module should ensure that they serialize
29 * access to the hermes_t structure, and to the hardware
32 #include <linux/delay.h>
33 #include <linux/if_ether.h>
36 * Limits and constants
38 #define HERMES_ALLOC_LEN_MIN ((uint16_t)4)
39 #define HERMES_ALLOC_LEN_MAX ((uint16_t)2400)
40 #define HERMES_LTV_LEN_MAX (34)
41 #define HERMES_BAP_DATALEN_MAX ((uint16_t)4096)
42 #define HERMES_BAP_OFFSET_MAX ((uint16_t)4096)
43 #define HERMES_PORTID_MAX ((uint16_t)7)
44 #define HERMES_NUMPORTS_MAX ((uint16_t)(HERMES_PORTID_MAX+1))
45 #define HERMES_PDR_LEN_MAX ((uint16_t)260) /* in bytes, from EK */
46 #define HERMES_PDA_RECS_MAX ((uint16_t)200) /* a guess */
47 #define HERMES_PDA_LEN_MAX ((uint16_t)1024) /* in bytes, from EK */
48 #define HERMES_SCANRESULT_MAX ((uint16_t)35)
49 #define HERMES_CHINFORESULT_MAX ((uint16_t)8)
50 #define HERMES_FRAME_LEN_MAX (2304)
51 #define HERMES_MAX_MULTICAST (16)
52 #define HERMES_MAGIC (0x7d1f)
55 * Hermes register offsets
57 #define HERMES_CMD (0x00)
58 #define HERMES_PARAM0 (0x02)
59 #define HERMES_PARAM1 (0x04)
60 #define HERMES_PARAM2 (0x06)
61 #define HERMES_STATUS (0x08)
62 #define HERMES_RESP0 (0x0A)
63 #define HERMES_RESP1 (0x0C)
64 #define HERMES_RESP2 (0x0E)
65 #define HERMES_INFOFID (0x10)
66 #define HERMES_RXFID (0x20)
67 #define HERMES_ALLOCFID (0x22)
68 #define HERMES_TXCOMPLFID (0x24)
69 #define HERMES_SELECT0 (0x18)
70 #define HERMES_OFFSET0 (0x1C)
71 #define HERMES_DATA0 (0x36)
72 #define HERMES_SELECT1 (0x1A)
73 #define HERMES_OFFSET1 (0x1E)
74 #define HERMES_DATA1 (0x38)
75 #define HERMES_EVSTAT (0x30)
76 #define HERMES_INTEN (0x32)
77 #define HERMES_EVACK (0x34)
78 #define HERMES_CONTROL (0x14)
79 #define HERMES_SWSUPPORT0 (0x28)
80 #define HERMES_SWSUPPORT1 (0x2A)
81 #define HERMES_SWSUPPORT2 (0x2C)
82 #define HERMES_AUXPAGE (0x3A)
83 #define HERMES_AUXOFFSET (0x3C)
84 #define HERMES_AUXDATA (0x3E)
87 * CMD register bitmasks
89 #define HERMES_CMD_BUSY ((uint16_t)0x8000)
90 #define HERMES_CMD_AINFO ((uint16_t)0x7f00)
91 #define HERMES_CMD_MACPORT ((uint16_t)0x0700)
92 #define HERMES_CMD_RECL ((uint16_t)0x0100)
93 #define HERMES_CMD_WRITE ((uint16_t)0x0100)
94 #define HERMES_CMD_PROGMODE ((uint16_t)0x0300)
95 #define HERMES_CMD_CMDCODE ((uint16_t)0x003f)
98 * STATUS register bitmasks
100 #define HERMES_STATUS_RESULT ((uint16_t)0x7f00)
101 #define HERMES_STATUS_CMDCODE ((uint16_t)0x003f)
104 * OFFSET refister bitmasks
106 #define HERMES_OFFSET_BUSY ((uint16_t)0x8000)
107 #define HERMES_OFFSET_ERR ((uint16_t)0x4000)
108 #define HERMES_OFFSET_DATAOFF ((uint16_t)0x0ffe)
111 * Event register bitmasks (INTEN, EVSTAT, EVACK)
113 #define HERMES_EV_TICK ((uint16_t)0x8000)
114 #define HERMES_EV_WTERR ((uint16_t)0x4000)
115 #define HERMES_EV_INFDROP ((uint16_t)0x2000)
116 #define HERMES_EV_INFO ((uint16_t)0x0080)
117 #define HERMES_EV_DTIM ((uint16_t)0x0020)
118 #define HERMES_EV_CMD ((uint16_t)0x0010)
119 #define HERMES_EV_ALLOC ((uint16_t)0x0008)
120 #define HERMES_EV_TXEXC ((uint16_t)0x0004)
121 #define HERMES_EV_TX ((uint16_t)0x0002)
122 #define HERMES_EV_RX ((uint16_t)0x0001)
127 /*--- Controller Commands --------------------------*/
128 #define HERMES_CMD_INIT ((uint16_t)0x00)
129 #define HERMES_CMD_ENABLE ((uint16_t)0x01)
130 #define HERMES_CMD_DISABLE ((uint16_t)0x02)
131 #define HERMES_CMD_DIAG ((uint16_t)0x03)
133 /*--- Buffer Mgmt Commands --------------------------*/
134 #define HERMES_CMD_ALLOC ((uint16_t)0x0A)
135 #define HERMES_CMD_TX ((uint16_t)0x0B)
136 #define HERMES_CMD_CLRPRST ((uint16_t)0x12)
138 /*--- Regulate Commands --------------------------*/
139 #define HERMES_CMD_NOTIFY ((uint16_t)0x10)
140 #define HERMES_CMD_INQ ((uint16_t)0x11)
142 /*--- Configure Commands --------------------------*/
143 #define HERMES_CMD_ACCESS ((uint16_t)0x21)
144 #define HERMES_CMD_DOWNLD ((uint16_t)0x22)
146 /*--- Debugging Commands -----------------------------*/
147 #define HERMES_CMD_MONITOR ((uint16_t)(0x38))
148 #define HERMES_MONITOR_ENABLE ((uint16_t)(0x0b))
149 #define HERMES_MONITOR_DISABLE ((uint16_t)(0x0f))
155 #define HERMES_RID_CNF_PORTTYPE ((uint16_t)0xfc00)
156 #define HERMES_RID_CNF_MACADDR ((uint16_t)0xfc01)
157 #define HERMES_RID_CNF_DESIRED_SSID ((uint16_t)0xfc02)
158 #define HERMES_RID_CNF_CHANNEL ((uint16_t)0xfc03)
159 #define HERMES_RID_CNF_OWN_SSID ((uint16_t)0xfc04)
160 #define HERMES_RID_CNF_SYSTEM_SCALE ((uint16_t)0xfc06)
161 #define HERMES_RID_CNF_MAX_DATA_LEN ((uint16_t)0xfc07)
162 #define HERMES_RID_CNF_PM_ENABLE ((uint16_t)0xfc09)
163 #define HERMES_RID_CNF_PM_MCAST_RX ((uint16_t)0xfc0b)
164 #define HERMES_RID_CNF_PM_PERIOD ((uint16_t)0xfc0c)
165 #define HERMES_RID_CNF_PM_HOLDOVER ((uint16_t)0xfc0d)
166 #define HERMES_RID_CNF_NICKNAME ((uint16_t)0xfc0e)
167 #define HERMES_RID_CNF_WEP_ON ((uint16_t)0xfc20)
168 #define HERMES_RID_CNF_MWO_ROBUST ((uint16_t)0xfc25)
169 #define HERMES_RID_CNF_PRISM2_WEP_ON ((uint16_t)0xfc28)
170 #define HERMES_RID_CNF_MULTICAST_LIST ((uint16_t)0xfc80)
171 #define HERMES_RID_CNF_CREATEIBSS ((uint16_t)0xfc81)
172 #define HERMES_RID_CNF_FRAG_THRESH ((uint16_t)0xfc82)
173 #define HERMES_RID_CNF_RTS_THRESH ((uint16_t)0xfc83)
174 #define HERMES_RID_CNF_TX_RATE_CTRL ((uint16_t)0xfc84)
175 #define HERMES_RID_CNF_PROMISCUOUS ((uint16_t)0xfc85)
176 #define HERMES_RID_CNF_KEYS ((uint16_t)0xfcb0)
177 #define HERMES_RID_CNF_TX_KEY ((uint16_t)0xfcb1)
178 #define HERMES_RID_CNF_TICKTIME ((uint16_t)0xfce0)
180 #define HERMES_RID_CNF_PRISM2_TX_KEY ((uint16_t)0xfc23)
181 #define HERMES_RID_CNF_PRISM2_KEY0 ((uint16_t)0xfc24)
182 #define HERMES_RID_CNF_PRISM2_KEY1 ((uint16_t)0xfc25)
183 #define HERMES_RID_CNF_PRISM2_KEY2 ((uint16_t)0xfc26)
184 #define HERMES_RID_CNF_PRISM2_KEY3 ((uint16_t)0xfc27)
185 #define HERMES_RID_CNF_SYMBOL_AUTH_TYPE ((uint16_t)0xfc2A)
186 /* This one is read only */
187 #define HERMES_RID_CNF_SYMBOL_KEY_LENGTH ((uint16_t)0xfc2B)
188 #define HERMES_RID_CNF_SYMBOL_BASIC_RATES ((uint16_t)0xfc8A)
193 #define HERMES_RID_CHANNEL_LIST ((uint16_t)0xfd10)
194 #define HERMES_RID_STAIDENTITY ((uint16_t)0xfd20)
195 #define HERMES_RID_CURRENT_SSID ((uint16_t)0xfd41)
196 #define HERMES_RID_CURRENT_BSSID ((uint16_t)0xfd42)
197 #define HERMES_RID_COMMSQUALITY ((uint16_t)0xfd43)
198 #define HERMES_RID_CURRENT_TX_RATE ((uint16_t)0xfd44)
199 #define HERMES_RID_WEP_AVAIL ((uint16_t)0xfd4f)
200 #define HERMES_RID_CURRENT_CHANNEL ((uint16_t)0xfdc1)
201 #define HERMES_RID_DATARATES ((uint16_t)0xfdc6)
204 * Frame structures and constants
207 typedef struct hermes_frame_desc {
208 /* Hermes - i.e. little-endian byte-order */
209 uint16_t status; /* 0x0 */
210 uint16_t res1, res2; /* 0x2, 0x4 */
211 uint16_t q_info; /* 0x6 */
212 uint16_t res3, res4; /* 0x8, 0xA */
213 uint16_t tx_ctl; /* 0xC */
214 } __attribute__ ((packed)) hermes_frame_desc_t;
216 #define HERMES_RXSTAT_ERR ((uint16_t)0x0003)
217 #define HERMES_RXSTAT_MACPORT ((uint16_t)0x0700)
218 #define HERMES_RXSTAT_MSGTYPE ((uint16_t)0xE000)
220 #define HERMES_RXSTAT_BADCRC ((uint16_t)0x0001)
221 #define HERMES_RXSTAT_UNDECRYPTABLE ((uint16_t)0x0002)
223 /* RFC-1042 encoded frame */
224 #define HERMES_RXSTAT_1042 ((uint16_t)0x2000)
225 /* Bridge-tunnel encoded frame */
226 #define HERMES_RXSTAT_TUNNEL ((uint16_t)0x4000)
227 /* Wavelan-II Management Protocol frame */
228 #define HERMES_RXSTAT_WMP ((uint16_t)0x6000)
232 /* Basic control structure */
233 typedef struct hermes {
236 uint16_t inten; /* Which interrupts should be enabled? */
239 typedef struct hermes_response {
240 uint16_t status, resp0, resp1, resp2;
243 /* Firmware information structure */
244 typedef struct hermes_identity {
245 uint16_t id, vendor, major, minor;
246 } __attribute__ ((packed)) hermes_identity_t;
248 /* "ID" structure - used for ESSID and station nickname */
249 typedef struct hermes_id {
252 } __attribute__ ((packed)) hermes_id_t;
254 typedef struct hermes_commsqual {
255 uint16_t qual, signal, noise;
256 } __attribute__ ((packed)) hermes_commsqual_t;
258 typedef struct hermes_multicast {
259 uint8_t addr[HERMES_MAX_MULTICAST][ETH_ALEN];
260 } __attribute__ ((packed)) hermes_multicast_t;
262 /* Register access convenience macros */
263 #define hermes_read_reg(hw, off) (inw((hw)->iobase + (off)))
264 #define hermes_write_reg(hw, off, val) (outw_p((val), (hw)->iobase + (off)))
266 #define hermes_read_regn(hw, name) (hermes_read_reg((hw), HERMES_##name))
267 #define hermes_write_regn(hw, name, val) (hermes_write_reg((hw), HERMES_##name, (val)))
269 /* Note that for the next two, the count is in 16-bit words, not bytes */
270 #define hermes_read_data(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
271 #define hermes_write_data(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
273 /* Function prototypes */
274 void hermes_struct_init(hermes_t *hw, ushort io);
275 int hermes_reset(hermes_t *hw);
276 int hermes_docmd_wait(hermes_t *hw, uint16_t cmd, uint16_t parm0, hermes_response_t *resp);
277 int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid);
280 int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
281 uint16_t id, uint16_t offset);
282 int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
283 uint16_t id, uint16_t offset);
284 int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
285 uint16_t *length, void *buf);
286 int hermes_write_ltv(hermes_t *hw, int bap, uint16_t rid,
287 uint16_t length, const void *value);
289 /* Inline functions */
291 static inline int hermes_present(hermes_t *hw)
293 return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
296 static inline void hermes_enable_interrupt(hermes_t *hw, uint16_t events)
299 hermes_write_regn(hw, INTEN, hw->inten);
302 static inline void hermes_set_irqmask(hermes_t *hw, uint16_t events)
305 hermes_write_regn(hw, INTEN, events);
308 static inline int hermes_enable_port(hermes_t *hw, int port)
310 hermes_response_t resp;
312 return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
316 static inline int hermes_disable_port(hermes_t *hw, int port)
318 hermes_response_t resp;
320 return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
324 #define HERMES_BYTES_TO_RECLEN(n) ( ((n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+1 )
325 #define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
327 #define HERMES_READ_RECORD(hw, bap, rid, buf) \
328 (hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf)))
329 #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
330 (hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(sizeof(*buf)),(buf)))
331 #define HERMES_WRITE_RECORD_LEN(hw, bap, rid, buf, len) \
332 (hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(len),(buf)))
334 static inline int hermes_read_wordrec(hermes_t *hw, int bap, uint16_t rid, uint16_t *word)
339 err = HERMES_READ_RECORD(hw, bap, rid, &rec);
340 *word = le16_to_cpu(rec);
344 static inline int hermes_write_wordrec(hermes_t *hw, int bap, uint16_t rid, uint16_t word)
346 uint16_t rec = cpu_to_le16(word);
347 return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
350 static inline int hermes_read_staidentity(hermes_t *hw, int bap, hermes_identity_t *buf)
354 err = HERMES_READ_RECORD(hw, bap, HERMES_RID_STAIDENTITY, buf);
358 le16_to_cpus(&buf->id);
359 le16_to_cpus(&buf->vendor);
360 le16_to_cpus(&buf->major);
361 le16_to_cpus(&buf->minor);
366 static inline int hermes_read_commsqual(hermes_t *hw, int bap, hermes_commsqual_t *buf)
370 err = HERMES_READ_RECORD(hw, bap, HERMES_RID_COMMSQUALITY, buf);
374 le16_to_cpus(&buf->qual);
375 le16_to_cpus(&buf->signal);
376 le16_to_cpus(&buf->noise);
381 #else /* ! __KERNEL__ */
383 /* These are provided for the benefit of userspace drivers and testing programs
384 which use ioperm() or iopl() */
386 #define hermes_read_reg(base, off) (inw((base) + (off)))
387 #define hermes_write_reg(base, off, val) (outw((val), (base) + (off)))
389 #define hermes_read_regn(base, name) (hermes_read_reg((base), HERMES_##name))
390 #define hermes_write_regn(base, name, val) (hermes_write_reg((base), HERMES_##name, (val)))
392 /* Note that for the next two, the count is in 16-bit words, not bytes */
393 #define hermes_read_data(base, off, buf, count) (insw((base) + (off), (buf), (count)))
394 #define hermes_write_data(base, off, buf, count) (outsw((base) + (off), (buf), (count)))
396 #endif /* ! __KERNEL__ */
398 #endif /* _HERMES_H */