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
41static zyd_res zyd_hw_configure(struct zyd_softc *sc);
42static zyd_res	zyd_al2230_rf_init(struct zyd_softc *);
43static zyd_res	zyd_al2230_rf_init_b(struct zyd_softc *);
44static zyd_res	zyd_al2230_switch_radio(struct zyd_softc *, boolean_t);
45static zyd_res	zyd_al2230_set_channel(struct zyd_softc *, uint8_t);
46static zyd_res	zyd_rfmd_rf_init(struct zyd_softc *);
47static zyd_res	zyd_rfmd_switch_radio(struct zyd_softc *, boolean_t);
48static zyd_res	zyd_rfmd_set_channel(struct zyd_softc *, uint8_t);
49
50/* io write sequences to initialize RF-independent PHY registers */
51static const struct zyd_iowrite16 zyd_def_phy[] = ZYD_DEF_PHY;
52static const struct zyd_iowrite16 zyd_def_phyB[] = ZYD_DEF_PHYB;
53static 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 */
71zyd_res
72zyd_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 */
107zyd_res
108zyd_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 */
130zyd_res
131zyd_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 */
167zyd_res
168zyd_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 */
188zyd_res
189zyd_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 */
206static void
207zyd_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 */
219static void
220zyd_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 */
232static zyd_res
233zyd_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 */
257static zyd_res
258zyd_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 */
294static void
295zyd_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 */
309static void
310zyd_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 */
324static void
325zyd_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
373zyd_res
374zyd_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
464fail3:
465	zyd_usb_cmd_in_stop_polling(uc);
466fail2:
467	zyd_usb_close_pipes(uc);
468fail1:
469	return (ZYD_FAILURE);
470}
471
472void
473zyd_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 */
484static zyd_res
485zyd_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 */
562void
563zyd_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 */
607zyd_res
608zyd_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
669fail2:
670	zyd_usb_data_in_disable(uc);
671fail1:
672	return (ZYD_FAILURE);
673}
674
675/*
676 * Deactivate the device.
677 */
678void
679zyd_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 */
714static zyd_res
715zyd_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 */
751static zyd_res
752zyd_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 */
784static zyd_res
785zyd_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 */
804static zyd_res
805zyd_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 */
823static zyd_res
824zyd_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
852static zyd_res
853zyd_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
862static zyd_res
863zyd_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