xref: /illumos-gate/usr/src/uts/common/io/zyd/zyd_hw.c (revision 598f4ceed9327d2d6c2325dd67cae3aa06f7fea6)
1 /*
2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 2008 by  Ben Taylor <bentaylor.solx86@gmail.com>
8  * Copyright (c) 2007 by  Lukas Turek <turek@ksvi.mff.cuni.cz>
9  * Copyright (c) 2007 by  Jiri Svoboda <jirik.svoboda@seznam.cz>
10  * Copyright (c) 2007 by  Martin Krulis <martin.krulis@matfyz.cz>
11  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
12  * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
13  *
14  * Permission to use, copy, modify, and distribute this software for any
15  * purpose with or without fee is hereby granted, provided that the above
16  * copyright notice and this permission notice appear in all copies.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  *
26  */
27 
28 /*
29  * ZD1211 wLAN driver
30  * Device hardware control
31  *
32  * Control the ZD1211 chip and the RF chip.
33  */
34 
35 #include <sys/byteorder.h>
36 #include <sys/strsun.h>
37 
38 #include "zyd.h"
39 #include "zyd_reg.h"
40 
41 static zyd_res zyd_hw_configure(struct zyd_softc *sc);
42 static zyd_res	zyd_al2230_rf_init(struct zyd_softc *);
43 static zyd_res	zyd_al2230_rf_init_b(struct zyd_softc *);
44 static zyd_res	zyd_al2230_switch_radio(struct zyd_softc *, boolean_t);
45 static zyd_res	zyd_al2230_set_channel(struct zyd_softc *, uint8_t);
46 static zyd_res	zyd_rfmd_rf_init(struct zyd_softc *);
47 static zyd_res	zyd_rfmd_switch_radio(struct zyd_softc *, boolean_t);
48 static zyd_res	zyd_rfmd_set_channel(struct zyd_softc *, uint8_t);
49 
50 /* io write sequences to initialize RF-independent PHY registers */
51 static const struct zyd_iowrite16 zyd_def_phy[] = ZYD_DEF_PHY;
52 static const struct zyd_iowrite16 zyd_def_phyB[] = ZYD_DEF_PHYB;
53 static const char *zyd_rf_name(uint8_t type)
54 {
55 	static const char *const zyd_rfs[] = {
56 		"unknown", "unknown", "UW2451", "UCHIP", "AL2230",
57 		"AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT",
58 		"PV2000", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2",
59 		"PHILIPS"
60 	};
61 	return (zyd_rfs[(type > 15) ? 0 : type]);
62 }
63 
64 /*
65  * Read a 32-bit I/O register.
66  *
67  *	sc	soft state
68  *	reg	register number
69  *	*val	place to store the value
70  */
71 zyd_res
72 zyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val)
73 {
74 	zyd_res result;
75 	uint16_t tmp[4];
76 	uint16_t regs[2];
77 
78 	regs[0] = LE_16(ZYD_REG32_HI(reg));
79 	regs[1] = LE_16(ZYD_REG32_LO(reg));
80 
81 	result = zyd_usb_ioread_req(&sc->usb, regs, sizeof (regs),
82 	    tmp, sizeof (tmp));
83 
84 	if (result != USB_SUCCESS)
85 		return (ZYD_FAILURE);
86 
87 	if (tmp[0] != regs[0] || tmp[2] != regs[1]) {
88 		ZYD_WARN("ioread response doesn't match request\n");
89 		ZYD_WARN("requested regs %04x, %04x; got %04x, %04x\n",
90 		    LE_16(regs[0]), LE_16(regs[1]),
91 		    LE_16(tmp[0]), LE_16(tmp[2]));
92 		return (ZYD_FAILURE);
93 	}
94 
95 	*val = ((uint32_t)LE_16(tmp[1]) << 16) | (uint32_t)LE_16(tmp[3]);
96 
97 	return (ZYD_SUCCESS);
98 }
99 
100 /*
101  * Write a 32-bit I/O register.
102  *
103  *	sc	soft state
104  *	reg	register number
105  *	val	value to write
106  */
107 zyd_res
108 zyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val)
109 {
110 	zyd_res result;
111 	uint16_t tmp[4];
112 
113 	tmp[0] = LE_16(ZYD_REG32_HI(reg));
114 	tmp[1] = LE_16(val >> 16);
115 	tmp[2] = LE_16(ZYD_REG32_LO(reg));
116 	tmp[3] = LE_16(val & 0xffff);
117 
118 	result = zyd_usb_cmd_send(&sc->usb, ZYD_CMD_IOWR, tmp, sizeof (tmp));
119 
120 	return (result);
121 }
122 
123 /*
124  * Read a 16-bit I/O register.
125  *
126  *	sc	soft state
127  *	reg	register number
128  *	*val	place to store the value
129  */
130 zyd_res
131 zyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val)
132 {
133 	zyd_res result;
134 	uint16_t tmp[2];
135 	uint16_t regbuf;
136 
137 	regbuf = LE_16(reg);
138 
139 	result = zyd_usb_ioread_req(&sc->usb, &regbuf, sizeof (regbuf),
140 	    tmp, sizeof (tmp));
141 
142 	if (result != USB_SUCCESS)
143 		return (ZYD_FAILURE);
144 
145 	if (tmp[0] != regbuf) {
146 		ZYD_WARN("ioread response doesn't match request\n");
147 		ZYD_WARN("requested reg %04x; got %04x\n",
148 		    LE_16(regbuf), LE_16(tmp[0]));
149 		return (ZYD_FAILURE);
150 	}
151 
152 	if (result != USB_SUCCESS)
153 		return (ZYD_FAILURE);
154 
155 	*val = LE_16(tmp[1]);
156 
157 	return (ZYD_SUCCESS);
158 }
159 
160 /*
161  * Write a 16-bit I/O register.
162  *
163  *	sc	soft state
164  *	reg	register number
165  *	val	value to write
166  */
167 zyd_res
168 zyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val)
169 {
170 	zyd_res result;
171 	uint16_t tmp[2];
172 
173 	tmp[0] = LE_16(ZYD_REG32_LO(reg));
174 	tmp[1] = LE_16(val & 0xffff);
175 
176 	result = zyd_usb_cmd_send(&sc->usb, ZYD_CMD_IOWR, tmp, sizeof (tmp));
177 
178 	return (result);
179 }
180 
181 /*
182  * Write an array of 16-bit registers.
183  *
184  *	sc	soft state
185  *	*reqa	array of register-value pairs
186  *	n	number of registers
187  */
188 zyd_res
189 zyd_write16a(struct zyd_softc *sc, const struct zyd_iowrite16 *reqa, int n)
190 {
191 	zyd_res res;
192 	int i;
193 
194 	for (i = 0; i < n; i++) {
195 		res = zyd_write16(sc, reqa[i].reg, reqa[i].value);
196 		if (res != ZYD_SUCCESS)
197 			return (ZYD_FAILURE);
198 	}
199 
200 	return (ZYD_SUCCESS);
201 }
202 
203 /*
204  * Lock PHY registers.
205  */
206 static void
207 zyd_lock_phy(struct zyd_softc *sc)
208 {
209 	uint32_t tmp;
210 
211 	(void) zyd_read32(sc, ZYD_MAC_MISC, &tmp);
212 	tmp &= ~ZYD_UNLOCK_PHY_REGS;
213 	(void) zyd_write32(sc, ZYD_MAC_MISC, tmp);
214 }
215 
216 /*
217  * Unlock PHY registers.
218  */
219 static void
220 zyd_unlock_phy(struct zyd_softc *sc)
221 {
222 	uint32_t tmp;
223 
224 	(void) zyd_read32(sc, ZYD_MAC_MISC, &tmp);
225 	tmp |= ZYD_UNLOCK_PHY_REGS;
226 	(void) zyd_write32(sc, ZYD_MAC_MISC, tmp);
227 }
228 
229 /*
230  * Read MAC address from EEPROM.
231  */
232 static zyd_res
233 zyd_read_mac(struct zyd_softc *sc)
234 {
235 	uint32_t tmp;
236 
237 	if (zyd_read32(sc, ZYD_EEPROM_MAC_ADDR_P1, &tmp) != ZYD_SUCCESS)
238 		return (ZYD_FAILURE);
239 
240 	sc->macaddr[0] = tmp & 0xff;
241 	sc->macaddr[1] = tmp >> 8;
242 	sc->macaddr[2] = tmp >> 16;
243 	sc->macaddr[3] = tmp >> 24;
244 
245 	if (zyd_read32(sc, ZYD_EEPROM_MAC_ADDR_P2, &tmp) != ZYD_SUCCESS)
246 		return (ZYD_FAILURE);
247 
248 	sc->macaddr[4] = tmp & 0xff;
249 	sc->macaddr[5] = tmp >> 8;
250 
251 	return (ZYD_SUCCESS);
252 }
253 
254 /*
255  * Write bits to RF configuration register.
256  */
257 static zyd_res
258 zyd_rfwrite(struct zyd_softc *sc, uint32_t val, int bits)
259 {
260 	uint16_t cr203;
261 	struct zyd_rfwrite req;
262 	uint16_t tmp;
263 	int bit;
264 	zyd_res res;
265 	int i;
266 
267 	if (zyd_read16(sc, ZYD_CR203, &cr203) != ZYD_SUCCESS)
268 		return (ZYD_FAILURE);
269 
270 	cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA);
271 
272 	req.code = LE_16(ZYD_RFCFG_VALUE);
273 	req.width = LE_16((uint16_t)bits);
274 
275 	for (i = 0; i < bits; i++) {
276 		bit = (val & (1 << (bits - i - 1))) != 0;
277 		tmp = LE_16(cr203) | (bit ? LE_16(ZYD_RF_DATA) : 0);
278 		req.bit[i] = tmp;
279 	}
280 	res = zyd_usb_cmd_send(&sc->usb, ZYD_CMD_RFCFG, &req,
281 	    sizeof (uint16_t) * (2 + bits));
282 
283 	if (res != ZYD_SUCCESS) {
284 		ZYD_WARN("failed configuring rf register\n");
285 		return (ZYD_FAILURE);
286 	}
287 
288 	return (ZYD_SUCCESS);
289 }
290 
291 /*
292  * Control the LEDs.
293  */
294 static void
295 zyd_set_led(struct zyd_softc *sc, int which, boolean_t on)
296 {
297 	uint32_t tmp;
298 
299 	(void) zyd_read32(sc, ZYD_MAC_TX_PE_CONTROL, &tmp);
300 	tmp &= ~which;
301 	if (on == B_TRUE)
302 		tmp |= which;
303 	(void) zyd_write32(sc, ZYD_MAC_TX_PE_CONTROL, tmp);
304 }
305 
306 /*
307  * Set MAC address.
308  */
309 static void
310 zyd_set_macaddr(struct zyd_softc *sc, const uint8_t *addr)
311 {
312 	uint32_t tmp;
313 
314 	tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0];
315 	(void) zyd_write32(sc, ZYD_MAC_MACADRL, tmp);
316 
317 	tmp = addr[5] << 8 | addr[4];
318 	(void) zyd_write32(sc, ZYD_MAC_MACADRH, tmp);
319 }
320 
321 /*
322  * Read data from EEPROM.
323  */
324 static void
325 zyd_read_eeprom(struct zyd_softc *sc)
326 {
327 	uint32_t tmp;
328 	uint16_t val;
329 	int i;
330 
331 	/* read RF chip type */
332 	(void) zyd_read32(sc, ZYD_EEPROM_POD, &tmp);
333 	sc->rf_rev = tmp & 0x0f;
334 	sc->pa_rev = (tmp >> 16) & 0x0f;
335 	sc->fix_cr47 = (tmp >> 8) & 0x01;
336 	sc->fix_cr157 = (tmp >> 13) & 0x01;
337 
338 	ZYD_DEBUG((ZYD_DBG_HW, "fix cr47: 0x%x\n", sc->fix_cr47));
339 	ZYD_DEBUG((ZYD_DBG_HW, "fix cr157: 0x%x\n", sc->fix_cr157));
340 	ZYD_DEBUG((ZYD_DBG_HW, "found RF chip %s, rev 0x%x\n",
341 	    zyd_rf_name(sc->rf_rev), sc->rf_rev));
342 
343 	/* read regulatory domain (currently unused) */
344 	(void) zyd_read32(sc, ZYD_EEPROM_SUBID, &tmp);
345 	sc->regdomain = tmp >> 16;
346 
347 	ZYD_DEBUG((ZYD_DBG_HW, "regulatory domain: %x\n", sc->regdomain));
348 
349 	/* read Tx power calibration tables */
350 	for (i = 0; i < 7; i++) {
351 		(void) zyd_read16(sc, ZYD_EEPROM_PWR_CAL + i, &val);
352 		sc->pwr_cal[i * 2] = val >> 8;
353 		sc->pwr_cal[i * 2 + 1] = val & 0xff;
354 
355 		(void) zyd_read16(sc, ZYD_EEPROM_PWR_INT + i, &val);
356 		sc->pwr_int[i * 2] = val >> 8;
357 		sc->pwr_int[i * 2 + 1] = val & 0xff;
358 
359 		(void) zyd_read16(sc, ZYD_EEPROM_36M_CAL + i, &val);
360 		sc->ofdm36_cal[i * 2] = val >> 8;
361 		sc->ofdm36_cal[i * 2 + 1] = val & 0xff;
362 
363 		(void) zyd_read16(sc, ZYD_EEPROM_48M_CAL + i, &val);
364 		sc->ofdm48_cal[i * 2] = val >> 8;
365 		sc->ofdm48_cal[i * 2 + 1] = val & 0xff;
366 
367 		(void) zyd_read16(sc, ZYD_EEPROM_54M_CAL + i, &val);
368 		sc->ofdm54_cal[i * 2] = val >> 8;
369 		sc->ofdm54_cal[i * 2 + 1] = val & 0xff;
370 	}
371 }
372 
373 zyd_res
374 zyd_hw_init(struct zyd_softc *sc)
375 {
376 	struct zyd_usb *uc = &sc->usb;
377 	int ures;
378 	zyd_res res;
379 
380 	sc->mac_rev = zyd_usb_mac_rev(uc->cdata->dev_descr->idVendor,
381 	    uc->cdata->dev_descr->idProduct);
382 	if (sc->mac_rev == ZYD_ZD1211) {
383 		res = zyd_usb_loadfirmware(uc, zd1211_firmware,
384 		    zd1211_firmware_size);
385 	} else {
386 		res = zyd_usb_loadfirmware(uc, zd1211b_firmware,
387 		    zd1211b_firmware_size);
388 	}
389 	if (res != ZYD_SUCCESS) {
390 		ZYD_WARN("failed to load firmware\n");
391 		goto fail1;
392 	}
393 
394 	/* set configuration 1 - required for later communication */
395 	ures = usb_set_cfg(uc->dip, 0, USB_FLAGS_SLEEP, NULL, NULL);
396 	if (ures != USB_SUCCESS) {
397 		ZYD_WARN("failed to set configuration 1 (%d)\n", ures);
398 		goto fail1;
399 	}
400 
401 	if (zyd_usb_open_pipes(uc) != ZYD_SUCCESS) {
402 		ZYD_WARN("failed to open pipes\n");
403 		goto fail1;
404 	}
405 
406 	if (zyd_usb_cmd_in_start_polling(uc) != ZYD_SUCCESS) {
407 		ZYD_WARN("failed to start command IN polling\n");
408 		goto fail2;
409 	}
410 
411 	if (zyd_read_mac(sc) != ZYD_SUCCESS) {
412 		ZYD_WARN("failed to read MAC address\n");
413 		goto fail3;
414 	}
415 
416 	zyd_read_eeprom(sc);
417 	switch (sc->rf_rev) {
418 	case ZYD_RF_AL2230:
419 	case ZYD_RF_RFMD:
420 		break;
421 	default:
422 		ZYD_WARN("unsupported RF %s, chip type 0x%x\n",
423 		    zyd_rf_name(sc->rf_rev), sc->rf_rev);
424 		goto fail3;
425 	}
426 
427 	if (zyd_hw_configure(sc) != ZYD_SUCCESS) {
428 		ZYD_WARN("failed to configure hardware\n");
429 		goto fail3;
430 	}
431 
432 	/* RF chip init */
433 	zyd_lock_phy(sc);
434 	switch (sc->rf_rev) {
435 	case ZYD_RF_AL2230:
436 		if (sc->mac_rev == ZYD_ZD1211) {
437 			res = zyd_al2230_rf_init(sc);
438 		} else {
439 			res = zyd_al2230_rf_init_b(sc);
440 		}
441 		break;
442 	case ZYD_RF_RFMD:
443 		res = zyd_rfmd_rf_init(sc);
444 		break;
445 	default:
446 		ZYD_WARN("unsupported Radio %s, code = 0x%x\n",
447 		    zyd_rf_name(sc->rf_rev), sc->rf_rev);
448 		res = ZYD_FAILURE;
449 		break;
450 	}
451 	zyd_unlock_phy(sc);
452 
453 	if (res != ZYD_SUCCESS) {
454 		ZYD_WARN("failed to configure RF chip\n");
455 		goto fail3;
456 	}
457 
458 	ZYD_DEBUG((ZYD_DBG_HW, "MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
459 	    sc->macaddr[0], sc->macaddr[1], sc->macaddr[2],
460 	    sc->macaddr[3], sc->macaddr[4], sc->macaddr[5]));
461 
462 	return (ZYD_SUCCESS);
463 
464 fail3:
465 	zyd_usb_cmd_in_stop_polling(uc);
466 fail2:
467 	zyd_usb_close_pipes(uc);
468 fail1:
469 	return (ZYD_FAILURE);
470 }
471 
472 void
473 zyd_hw_deinit(struct zyd_softc *sc)
474 {
475 	struct zyd_usb *uc = &sc->usb;
476 
477 	zyd_usb_cmd_in_stop_polling(uc);
478 	zyd_usb_close_pipes(uc);
479 }
480 
481 /*
482  * Finish ZD chip initialization.
483  */
484 static zyd_res
485 zyd_hw_configure(struct zyd_softc *sc)
486 {
487 	zyd_res res;
488 	uint32_t tmp;
489 
490 	/* specify that the plug and play is finished */
491 	(void) zyd_write32(sc, ZYD_MAC_AFTER_PNP, 1);
492 	(void) zyd_read16(sc, ZYD_FIRMWARE_BASE_ADDR, &sc->fwbase);
493 	ZYD_DEBUG((ZYD_DBG_FW, "firmware base address: 0x%04x\n", sc->fwbase));
494 
495 	/* retrieve firmware revision number */
496 	(void) zyd_read16(sc, sc->fwbase + ZYD_FW_FIRMWARE_REV, &sc->fw_rev);
497 	ZYD_DEBUG((ZYD_DBG_FW, "firmware revision: x0x%4x\n", sc->fw_rev));
498 
499 	(void) zyd_write32(sc, ZYD_CR_GPI_EN, 0);
500 	(void) zyd_write32(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f);
501 
502 	/* disable interrupts */
503 	(void) zyd_write32(sc, ZYD_CR_INTERRUPT, 0);
504 
505 	/* Init RF chip-independent PHY registers */
506 	zyd_lock_phy(sc);
507 	if (sc->mac_rev == ZYD_ZD1211) {
508 		res = zyd_write16a(sc, zyd_def_phy,
509 		    ZYD_ARRAY_LENGTH(zyd_def_phy));
510 	} else {
511 		res = zyd_write16a(sc, zyd_def_phyB,
512 		    ZYD_ARRAY_LENGTH(zyd_def_phyB));
513 	}
514 	if (sc->fix_cr157) {
515 		if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0)
516 			(void) zyd_write32(sc, ZYD_CR157, tmp >> 8);
517 	}
518 	zyd_unlock_phy(sc);
519 
520 	if (res != ZYD_SUCCESS)
521 		return (ZYD_FAILURE);
522 
523 	/* HMAC initialization magic */
524 	if (sc->mac_rev == ZYD_ZD1211) {
525 		(void) zyd_write32(sc, ZYD_MAC_RETRY, 0x00000002);
526 	} else {
527 		(void) zyd_write32(sc, ZYD_MACB_MAX_RETRY, 0x02020202);
528 		(void) zyd_write32(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f);
529 		(void) zyd_write32(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f);
530 		(void) zyd_write32(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f);
531 		(void) zyd_write32(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f);
532 		(void) zyd_write32(sc, ZYD_MACB_AIFS_CTL1, 0x00280028);
533 		(void) zyd_write32(sc, ZYD_MACB_AIFS_CTL2, 0x008C003c);
534 		(void) zyd_write32(sc, ZYD_MACB_TXOP, 0x01800824);
535 	}
536 	(void) zyd_write32(sc, ZYD_MAC_ACK_EXT, 0x00000020);
537 	(void) zyd_write32(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808);
538 	(void) zyd_write32(sc, ZYD_MAC_SNIFFER, 0x00000000);
539 	(void) zyd_write32(sc, ZYD_MAC_RXFILTER, 0x00000000);
540 	(void) zyd_write32(sc, ZYD_MAC_GHTBL, 0x00000000);
541 	(void) zyd_write32(sc, ZYD_MAC_GHTBH, 0x80000000);
542 	(void) zyd_write32(sc, ZYD_MAC_MISC, 0x000000a4);
543 	(void) zyd_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x0000007f);
544 	(void) zyd_write32(sc, ZYD_MAC_BCNCFG, 0x00f00401);
545 	(void) zyd_write32(sc, ZYD_MAC_PHY_DELAY2, 0x00000000);
546 	(void) zyd_write32(sc, ZYD_MAC_ACK_EXT, 0x00000080);
547 	(void) zyd_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000);
548 	(void) zyd_write32(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100);
549 	(void) zyd_write32(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0547c032);
550 	(void) zyd_write32(sc, ZYD_CR_RX_PE_DELAY, 0x00000070);
551 	(void) zyd_write32(sc, ZYD_CR_PS_CTRL, 0x10000000);
552 	(void) zyd_write32(sc, ZYD_MAC_RTSCTSRATE, 0x02030203);
553 	(void) zyd_write32(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640);
554 	(void) zyd_write32(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114);
555 
556 	return (ZYD_SUCCESS);
557 }
558 
559 /*
560  * Set active channel number.
561  */
562 void
563 zyd_hw_set_channel(struct zyd_softc *sc, uint8_t chan)
564 {
565 	uint32_t tmp;
566 
567 	zyd_lock_phy(sc);
568 
569 	ZYD_DEBUG((ZYD_DBG_HW, "setting channel %d\n", chan));
570 
571 	switch (sc->rf_rev) {
572 	case ZYD_RF_AL2230:
573 		(void) zyd_al2230_set_channel(sc, chan);
574 		break;
575 	case ZYD_RF_RFMD:
576 		(void) zyd_rfmd_set_channel(sc, chan);
577 		break;
578 	}
579 
580 	/* update Tx power */
581 	ZYD_DEBUG((ZYD_DBG_HW, "updating tx power table\n"));
582 
583 	(void) zyd_write16(sc, ZYD_CR31, sc->pwr_int[chan - 1]);
584 	if (sc->mac_rev == ZYD_ZD1211B) {
585 		(void) zyd_write16(sc, ZYD_CR67, sc->ofdm36_cal[chan - 1]);
586 		(void) zyd_write16(sc, ZYD_CR66, sc->ofdm48_cal[chan - 1]);
587 		(void) zyd_write16(sc, ZYD_CR65, sc->ofdm54_cal[chan - 1]);
588 		(void) zyd_write16(sc, ZYD_CR68, sc->pwr_cal[chan - 1]);
589 		(void) zyd_write16(sc, ZYD_CR69, 0x28);
590 		(void) zyd_write16(sc, ZYD_CR69, 0x2a);
591 	}
592 
593 	if (sc->fix_cr47) {
594 		/* set CCK baseband gain from EEPROM */
595 		if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0)
596 			(void) zyd_write16(sc, ZYD_CR47, tmp & 0xff);
597 	}
598 
599 	(void) zyd_write32(sc, ZYD_CR_CONFIG_PHILIPS, 0);
600 
601 	zyd_unlock_phy(sc);
602 }
603 
604 /*
605  * Activate the device.
606  */
607 zyd_res
608 zyd_hw_start(struct zyd_softc *sc)
609 {
610 	struct zyd_usb *uc = &sc->usb;
611 	struct ieee80211com *ic = &sc->ic;
612 	zyd_res res;
613 
614 	if (zyd_usb_data_in_enable(&sc->usb) != ZYD_SUCCESS) {
615 		ZYD_WARN("error starting rx transfer\n");
616 		goto fail1;
617 	}
618 
619 	ZYD_DEBUG((ZYD_DBG_HW, "setting MAC address\n"));
620 	zyd_set_macaddr(sc, sc->macaddr);
621 
622 	/* we'll do software WEP decryption for now */
623 	ZYD_DEBUG((ZYD_DBG_HW, "setting encryption mode\n"));
624 	res = zyd_write32(sc, ZYD_MAC_ENCRYPTION_TYPE, ZYD_ENC_SNIFFER);
625 	if (res != ZYD_SUCCESS)
626 		goto fail2;
627 
628 	/* promiscuous mode */
629 	(void) zyd_write32(sc, ZYD_MAC_SNIFFER, 0);
630 
631 	/* try to catch all packets */
632 	(void) zyd_write32(sc, ZYD_MAC_RXFILTER, ZYD_FILTER_BSS);
633 
634 	/* switch radio transmitter ON */
635 	switch (sc->rf_rev) {
636 	case ZYD_RF_AL2230:
637 		(void) zyd_al2230_switch_radio(sc, B_TRUE);
638 		break;
639 	case ZYD_RF_RFMD:
640 		(void) zyd_rfmd_switch_radio(sc, B_TRUE);
641 		break;
642 	}
643 
644 	/* set basic rates */
645 	ZYD_DEBUG((ZYD_DBG_HW, "setting basic rates\n"));
646 	if (ic->ic_curmode == IEEE80211_MODE_11B)
647 		(void) zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x0003);
648 	else if (ic->ic_curmode == IEEE80211_MODE_11A)
649 		(void) zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x1500);
650 	else			/* assumes 802.11b/g */
651 		(void) zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x000f);
652 
653 	/* set mandatory rates */
654 	ZYD_DEBUG((ZYD_DBG_HW, "setting mandatory rates\n"));
655 	if (ic->ic_curmode == IEEE80211_MODE_11B)
656 		(void) zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x000f);
657 	else if (ic->ic_curmode == IEEE80211_MODE_11A)
658 		(void) zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x1500);
659 	else			/* assumes 802.11b/g */
660 		(void) zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x150f);
661 
662 	/* enable interrupts */
663 	(void) zyd_write32(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
664 
665 	zyd_set_led(sc, ZYD_LED2, B_TRUE);
666 
667 	return (ZYD_SUCCESS);
668 
669 fail2:
670 	zyd_usb_data_in_disable(uc);
671 fail1:
672 	return (ZYD_FAILURE);
673 }
674 
675 /*
676  * Deactivate the device.
677  */
678 void
679 zyd_hw_stop(struct zyd_softc *sc)
680 {
681 	struct zyd_usb *uc = &sc->usb;
682 
683 	if (uc->connected) {
684 		/* switch radio transmitter OFF */
685 		switch (sc->rf_rev) {
686 		case ZYD_RF_AL2230:
687 			(void) zyd_al2230_switch_radio(sc, B_FALSE);
688 			break;
689 		case ZYD_RF_RFMD:
690 			(void) zyd_rfmd_switch_radio(sc, B_FALSE);
691 			break;
692 		}
693 
694 		/* disable reception */
695 		(void) zyd_write32(sc, ZYD_MAC_RXFILTER, 0);
696 
697 		/* disable interrupts */
698 		(void) zyd_write32(sc, ZYD_CR_INTERRUPT, 0);
699 
700 		zyd_set_led(sc, ZYD_LED2, B_FALSE);
701 	} else {
702 		ZYD_DEBUG((ZYD_DBG_HW, "stop: device absent\n"));
703 
704 	}
705 
706 	zyd_usb_data_in_disable(uc);
707 	sc->tx_queued = 0;
708 }
709 
710 /*
711  * ZD1211 AL2230 Radio control
712  * Init the AL2230 RF chip.
713  */
714 static zyd_res
715 zyd_al2230_rf_init(struct zyd_softc *sc)
716 {
717 	const struct zyd_iowrite16 phyini[] = ZYD_AL2230_PHY;
718 	const uint32_t rfini[] = ZYD_AL2230_RF;
719 
720 	zyd_res res;
721 	int i;
722 
723 	zyd_lock_phy(sc);
724 
725 	/* init RF-dependent PHY registers */
726 	res = zyd_write16a(sc, phyini, ZYD_ARRAY_LENGTH(phyini));
727 	if (res != ZYD_SUCCESS) {
728 		zyd_unlock_phy(sc);
729 		return (ZYD_FAILURE);
730 	}
731 
732 	/* init AL2230 radio */
733 	for (i = 0; i < ZYD_ARRAY_LENGTH(rfini); i++) {
734 		res = zyd_rfwrite(sc, rfini[i], ZYD_AL2230_RF_BITS);
735 		if (res != ZYD_SUCCESS) {
736 			zyd_unlock_phy(sc);
737 			return (ZYD_FAILURE);
738 		}
739 	}
740 
741 	zyd_unlock_phy(sc);
742 
743 	ZYD_DEBUG((ZYD_DBG_HW, "RF chip AL2230 initialized\n"));
744 
745 	return (ZYD_SUCCESS);
746 }
747 
748 /*
749  * Init the AL2230B RF chip (11b).
750  */
751 static zyd_res
752 zyd_al2230_rf_init_b(struct zyd_softc *sc)
753 {
754 	const struct zyd_iowrite16 phyini[] = ZYD_AL2230_PHY_B;
755 	const uint32_t rfini[] = ZYD_AL2230_RF_B;
756 	zyd_res res;
757 	int i;
758 
759 	zyd_lock_phy(sc);
760 	/* init RF-dependent PHY registers */
761 	res = zyd_write16a(sc, phyini, ZYD_ARRAY_LENGTH(phyini));
762 	if (res != ZYD_SUCCESS) {
763 		zyd_unlock_phy(sc);
764 		return (ZYD_FAILURE);
765 	}
766 
767 	/* init AL2230 radio */
768 	for (i = 0; i < ZYD_ARRAY_LENGTH(rfini); i++) {
769 		res = zyd_rfwrite(sc, rfini[i], ZYD_AL2230_RF_BITS);
770 		if (res != ZYD_SUCCESS) {
771 			zyd_unlock_phy(sc);
772 			return (ZYD_FAILURE);
773 		}
774 	}
775 	zyd_unlock_phy(sc);
776 	ZYD_DEBUG((ZYD_DBG_HW, "RF chip AL2230 (11b) initialized\n"));
777 
778 	return (ZYD_SUCCESS);
779 }
780 
781 /*
782  * Tune RF chip to a specified channel.
783  */
784 static zyd_res
785 zyd_al2230_set_channel(struct zyd_softc *sc, uint8_t chan)
786 {
787 	static const struct {
788 		uint32_t r1, r2, r3;
789 	} rfprog[] = ZYD_AL2230_CHANTABLE;
790 
791 	(void) zyd_rfwrite(sc, rfprog[chan - 1].r1, ZYD_AL2230_RF_BITS);
792 	(void) zyd_rfwrite(sc, rfprog[chan - 1].r2, ZYD_AL2230_RF_BITS);
793 	(void) zyd_rfwrite(sc, rfprog[chan - 1].r3, ZYD_AL2230_RF_BITS);
794 
795 	(void) zyd_write16(sc, ZYD_CR138, 0x28);
796 	(void) zyd_write16(sc, ZYD_CR203, 0x06);
797 
798 	return (ZYD_SUCCESS);
799 }
800 
801 /*
802  * Turn the radio transciever on/off.
803  */
804 static zyd_res
805 zyd_al2230_switch_radio(struct zyd_softc *sc, boolean_t on)
806 {
807 	int on251 = (sc->mac_rev == ZYD_ZD1211) ? 0x3f : 0x7f;
808 
809 	zyd_lock_phy(sc);
810 
811 	(void) zyd_write16(sc, ZYD_CR11, (on == B_TRUE) ? 0x00 : 0x04);
812 	(void) zyd_write16(sc, ZYD_CR251, (on == B_TRUE) ? on251 : 0x2f);
813 
814 	zyd_unlock_phy(sc);
815 
816 	return (ZYD_SUCCESS);
817 }
818 
819 
820 /*
821  * RFMD RF methods.
822  */
823 static zyd_res
824 zyd_rfmd_rf_init(struct zyd_softc *sc)
825 {
826 	static const struct zyd_iowrite16 phyini[] = ZYD_RFMD_PHY;
827 	static const uint32_t rfini[] = ZYD_RFMD_RF;
828 	zyd_res res;
829 	int i;
830 
831 	/* init RF-dependent PHY registers */
832 	zyd_lock_phy(sc);
833 	res = zyd_write16a(sc, phyini, ZYD_ARRAY_LENGTH(phyini));
834 	if (res != ZYD_SUCCESS) {
835 		zyd_unlock_phy(sc);
836 		return (ZYD_FAILURE);
837 	}
838 	/* init RFMD radio */
839 	for (i = 0; i < ZYD_ARRAY_LENGTH(rfini); i++) {
840 		res = zyd_rfwrite(sc, rfini[i], ZYD_RFMD_RF_BITS);
841 		if (res != ZYD_SUCCESS) {
842 			zyd_unlock_phy(sc);
843 			return (ZYD_FAILURE);
844 		}
845 	}
846 	zyd_unlock_phy(sc);
847 	ZYD_DEBUG((ZYD_DBG_HW, "RF chip RFMD initialized\n"));
848 
849 	return (ZYD_SUCCESS);
850 }
851 
852 static zyd_res
853 zyd_rfmd_switch_radio(struct zyd_softc *sc, boolean_t on)
854 {
855 
856 	(void) zyd_write16(sc, ZYD_CR10, on ? 0x89 : 0x15);
857 	(void) zyd_write16(sc, ZYD_CR11, on ? 0x00 : 0x81);
858 
859 	return (ZYD_SUCCESS);
860 }
861 
862 static zyd_res
863 zyd_rfmd_set_channel(struct zyd_softc *sc, uint8_t chan)
864 {
865 	static const struct {
866 		uint32_t r1, r2;
867 	} rfprog[] = ZYD_RFMD_CHANTABLE;
868 
869 	(void) zyd_rfwrite(sc, rfprog[chan - 1].r1, ZYD_RFMD_RF_BITS);
870 	(void) zyd_rfwrite(sc, rfprog[chan - 1].r2, ZYD_RFMD_RF_BITS);
871 
872 	return (ZYD_SUCCESS);
873 }
874