Bug Summary

File:dev/usb/if_zyd.c
Warning:line 888, column 8
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_zyd.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/if_zyd.c
1/* $OpenBSD: if_zyd.c,v 1.127 2022/01/09 05:43:00 jsg Exp $ */
2
3/*-
4 * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
5 * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/*
21 * ZyDAS ZD1211/ZD1211B USB WLAN driver.
22 */
23
24#include "bpfilter.h"
25
26#include <sys/param.h>
27#include <sys/sockio.h>
28#include <sys/mbuf.h>
29#include <sys/kernel.h>
30#include <sys/socket.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/timeout.h>
34#include <sys/conf.h>
35#include <sys/device.h>
36#include <sys/endian.h>
37
38#if NBPFILTER1 > 0
39#include <net/bpf.h>
40#endif
41#include <net/if.h>
42#include <net/if_dl.h>
43#include <net/if_media.h>
44
45#include <netinet/in.h>
46#include <netinet/if_ether.h>
47
48#include <net80211/ieee80211_var.h>
49#include <net80211/ieee80211_amrr.h>
50#include <net80211/ieee80211_radiotap.h>
51
52#include <dev/usb/usb.h>
53#include <dev/usb/usbdi.h>
54#include <dev/usb/usbdi_util.h>
55#include <dev/usb/usbdevs.h>
56
57#include <dev/usb/if_zydreg.h>
58
59#ifdef ZYD_DEBUG
60#define DPRINTF(x) do { if (zyddebug > 0) printf x; } while (0)
61#define DPRINTFN(n, x) do { if (zyddebug > (n)) printf x; } while (0)
62int zyddebug = 0;
63#else
64#define DPRINTF(x)
65#define DPRINTFN(n, x)
66#endif
67
68static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY{ { 0x9000, 0x0a }, { 0x9004, 0x06 }, { 0x9008, 0x26 }, { 0x900c
, 0x38 }, { 0x9020, 0x80 }, { 0x9024, 0xa0 }, { 0x9028, 0x81 }
, { 0x902c, 0x00 }, { 0x9030, 0x7f }, { 0x9034, 0x8c }, { 0x9038
, 0x80 }, { 0x903c, 0x3d }, { 0x9040, 0x20 }, { 0x9044, 0x1e }
, { 0x9048, 0x0a }, { 0x904c, 0x48 }, { 0x9050, 0x0c }, { 0x9054
, 0x0c }, { 0x9058, 0x23 }, { 0x905c, 0x90 }, { 0x9060, 0x14 }
, { 0x9064, 0x40 }, { 0x9068, 0x10 }, { 0x906c, 0x19 }, { 0x9070
, 0x7f }, { 0x9074, 0x80 }, { 0x9078, 0x4b }, { 0x907c, 0x60 }
, { 0x9080, 0x43 }, { 0x9084, 0x08 }, { 0x9088, 0x06 }, { 0x908c
, 0x0a }, { 0x9090, 0x00 }, { 0x9094, 0x00 }, { 0x9098, 0x38 }
, { 0x909c, 0x0c }, { 0x90a0, 0x84 }, { 0x90a4, 0x2a }, { 0x90a8
, 0x80 }, { 0x90ac, 0x10 }, { 0x90b0, 0x12 }, { 0x90b8, 0xff }
, { 0x90bc, 0x08 }, { 0x90c0, 0x26 }, { 0x90c4, 0x5b }, { 0x9100
, 0xd0 }, { 0x9104, 0x04 }, { 0x9108, 0x58 }, { 0x910c, 0xc9 }
, { 0x9110, 0x88 }, { 0x9114, 0x41 }, { 0x9118, 0x23 }, { 0x911c
, 0x10 }, { 0x9120, 0xff }, { 0x9124, 0x32 }, { 0x9128, 0x30 }
, { 0x912c, 0x65 }, { 0x9130, 0x41 }, { 0x9134, 0x1b }, { 0x9138
, 0x30 }, { 0x913c, 0x68 }, { 0x9140, 0x64 }, { 0x9144, 0x64 }
, { 0x9148, 0x00 }, { 0x914c, 0x00 }, { 0x9150, 0x00 }, { 0x9154
, 0x02 }, { 0x9158, 0x00 }, { 0x915c, 0x00 }, { 0x9160, 0xff }
, { 0x9164, 0xfc }, { 0x9168, 0x00 }, { 0x916c, 0x00 }, { 0x9170
, 0x00 }, { 0x9174, 0x08 }, { 0x9178, 0x00 }, { 0x917c, 0x00 }
, { 0x9180, 0xff }, { 0x9184, 0xe7 }, { 0x9188, 0x00 }, { 0x918c
, 0x00 }, { 0x9190, 0x00 }, { 0x9194, 0xae }, { 0x9198, 0x02 }
, { 0x919c, 0x00 }, { 0x91a0, 0x03 }, { 0x91a4, 0x65 }, { 0x91a8
, 0x04 }, { 0x91ac, 0x00 }, { 0x91b0, 0x0a }, { 0x91b4, 0xaa }
, { 0x91b8, 0xaa }, { 0x91bc, 0x25 }, { 0x91c0, 0x25 }, { 0x91c4
, 0x00 }, { 0x91dc, 0x1e }, { 0x91f4, 0x90 }, { 0x91f8, 0x00 }
, { 0x91fc, 0x00 }, { 0x9010, 0x00 }, { 0x9014, 0x00 }, { 0x9018
, 0x00 }, { 0x901c, 0x00 }, { 0x9024, 0x20 }, { 0x9030, 0xf0 }
, { 0x9050, 0x0e }, { 0x9054, 0x0e }, { 0x906c, 0x10 }, { 0x90b0
, 0x33 }, { 0x90bc, 0x30 }, { 0x914c, 0x24 }, { 0x9150, 0x04 }
, { 0x9154, 0x00 }, { 0x9158, 0x0C }, { 0x915c, 0x12 }, { 0x9160
, 0x0C }, { 0x9164, 0x00 }, { 0x9168, 0x10 }, { 0x916c, 0x08 }
, { 0x9174, 0x00 }, { 0x9178, 0x01 }, { 0x917c, 0x00 }, { 0x9180
, 0x50 }, { 0x9184, 0x37 }, { 0x9188, 0x35 }, { 0x9194, 0x13 }
, { 0x9198, 0x27 }, { 0x919c, 0x27 }, { 0x91a0, 0x18 }, { 0x91a4
, 0x12 }, { 0x91b4, 0x27 }, { 0x91b8, 0x27 }, { 0x91bc, 0x27 }
, { 0x91c0, 0x27 }, { 0x91c4, 0x27 }, { 0x91c8, 0x27 }, { 0x91cc
, 0x26 }, { 0x91d0, 0x24 }, { 0x91d4, 0xfc }, { 0x91d8, 0xfa }
, { 0x91e0, 0x4f }, { 0x91ec, 0x27 }, { 0x91f4, 0xaa }, { 0x91fc
, 0x03 }, { 0x9200, 0x14 }, { 0x9204, 0x12 }, { 0x9208, 0x10 }
, { 0x920c, 0x0C }, { 0x9220, 0xdf }, { 0x9224, 0x40 }, { 0x9228
, 0xa0 }, { 0x922c, 0xb0 }, { 0x9230, 0x99 }, { 0x9234, 0x82 }
, { 0x9238, 0x54 }, { 0x923c, 0x1c }, { 0x9240, 0x6c }, { 0x924c
, 0x07 }, { 0x9250, 0x4c }, { 0x9254, 0x50 }, { 0x9258, 0x0e }
, { 0x925c, 0x18 }, { 0x9280, 0xfe }, { 0x9284, 0xee }, { 0x9288
, 0xaa }, { 0x928c, 0xfa }, { 0x9290, 0xfa }, { 0x9294, 0xea }
, { 0x9298, 0xbe }, { 0x929c, 0xbe }, { 0x92a0, 0x6a }, { 0x92a4
, 0xba }, { 0x92a8, 0xba }, { 0x92ac, 0xba }, { 0x9330, 0x7d }
, { 0x932c, 0x30 }, { 0, 0 } }
;
69static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB{ { 0x9000, 0x14 }, { 0x9004, 0x06 }, { 0x9008, 0x26 }, { 0x900c
, 0x38 }, { 0x9020, 0x80 }, { 0x9024, 0xe0 }, { 0x9028, 0x81 }
, { 0x902c, 0x00 }, { 0x9030, 0xf0 }, { 0x9034, 0x8c }, { 0x9038
, 0x80 }, { 0x903c, 0x3d }, { 0x9040, 0x20 }, { 0x9044, 0x1e }
, { 0x9048, 0x0a }, { 0x904c, 0x48 }, { 0x9050, 0x10 }, { 0x9054
, 0x0e }, { 0x9058, 0x23 }, { 0x905c, 0x90 }, { 0x9060, 0x14 }
, { 0x9064, 0x40 }, { 0x9068, 0x10 }, { 0x906c, 0x10 }, { 0x9070
, 0x7f }, { 0x9074, 0x80 }, { 0x9078, 0x4b }, { 0x907c, 0x60 }
, { 0x9080, 0x43 }, { 0x9084, 0x08 }, { 0x9088, 0x06 }, { 0x908c
, 0x0a }, { 0x9090, 0x00 }, { 0x9094, 0x00 }, { 0x9098, 0x38 }
, { 0x909c, 0x0c }, { 0x90a0, 0x84 }, { 0x90a4, 0x2a }, { 0x90a8
, 0x80 }, { 0x90ac, 0x10 }, { 0x90b0, 0x33 }, { 0x90b8, 0xff }
, { 0x90bc, 0x1E }, { 0x90c0, 0x26 }, { 0x90c4, 0x5b }, { 0x9100
, 0xd0 }, { 0x9104, 0x04 }, { 0x9108, 0x58 }, { 0x910c, 0xc9 }
, { 0x9110, 0x88 }, { 0x9114, 0x41 }, { 0x9118, 0x23 }, { 0x911c
, 0x10 }, { 0x9120, 0xff }, { 0x9124, 0x32 }, { 0x9128, 0x30 }
, { 0x912c, 0x65 }, { 0x9130, 0x41 }, { 0x9134, 0x1b }, { 0x9138
, 0x30 }, { 0x913c, 0xf0 }, { 0x9140, 0x64 }, { 0x9144, 0x64 }
, { 0x9148, 0x00 }, { 0x914c, 0x24 }, { 0x9150, 0x04 }, { 0x9154
, 0x00 }, { 0x9158, 0x0c }, { 0x915c, 0x12 }, { 0x9160, 0x0c }
, { 0x9164, 0x00 }, { 0x9168, 0x58 }, { 0x916c, 0x04 }, { 0x9170
, 0x00 }, { 0x9174, 0x00 }, { 0x9178, 0x01 }, { 0x917c, 0x20 }
, { 0x9180, 0x50 }, { 0x9184, 0x37 }, { 0x9188, 0x35 }, { 0x918c
, 0x00 }, { 0x9190, 0x01 }, { 0x9194, 0x13 }, { 0x9198, 0x27 }
, { 0x919c, 0x27 }, { 0x91a0, 0x18 }, { 0x91a4, 0x12 }, { 0x91a8
, 0x04 }, { 0x91ac, 0x00 }, { 0x91b0, 0x0a }, { 0x91b4, 0x27 }
, { 0x91b8, 0x27 }, { 0x91bc, 0x27 }, { 0x91c0, 0x27 }, { 0x91c4
, 0x27 }, { 0x91c8, 0x27 }, { 0x91cc, 0x26 }, { 0x91d0, 0x24 }
, { 0x91d4, 0xfc }, { 0x91d8, 0xfa }, { 0x91dc, 0x1e }, { 0x91f4
, 0x90 }, { 0x91f8, 0x00 }, { 0x91fc, 0x00 }, { 0x9200, 0x14 }
, { 0x9204, 0x12 }, { 0x9208, 0x10 }, { 0x920c, 0x0c }, { 0x9220
, 0xdf }, { 0x9224, 0xa0 }, { 0x9228, 0xa8 }, { 0x922c, 0xb4 }
, { 0x9230, 0x98 }, { 0x9234, 0x82 }, { 0x9238, 0x53 }, { 0x923c
, 0x1c }, { 0x9240, 0x6c }, { 0x924c, 0x07 }, { 0x9250, 0x40 }
, { 0x9254, 0x40 }, { 0x9258, 0x14 }, { 0x925c, 0x18 }, { 0x927c
, 0x70 }, { 0x9280, 0xfe }, { 0x9284, 0xee }, { 0x9288, 0xaa }
, { 0x928c, 0xfa }, { 0x9290, 0xfa }, { 0x9294, 0xea }, { 0x9298
, 0xbe }, { 0x929c, 0xbe }, { 0x92a0, 0x6a }, { 0x92a4, 0xba }
, { 0x92a8, 0xba }, { 0x92ac, 0xba }, { 0x9330, 0x7d }, { 0x932c
, 0x30 }, { 0, 0 } }
;
70
71/* various supported device vendors/products */
72#define ZYD_ZD1211_DEV(v, p){ { USB_VENDOR_v, USB_PRODUCT_v_p }, 0 } \
73 { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD12110 }
74#define ZYD_ZD1211B_DEV(v, p){ { USB_VENDOR_v, USB_PRODUCT_v_p }, 1 } \
75 { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211B1 }
76static const struct zyd_type {
77 struct usb_devno dev;
78 uint8_t rev;
79#define ZYD_ZD12110 0
80#define ZYD_ZD1211B1 1
81} zyd_devs[] = {
82 ZYD_ZD1211_DEV(3COM2, 3CRUSB10075){ { 0x6891, 0xa727 }, 0 },
83 ZYD_ZD1211_DEV(ABOCOM, WL54){ { 0x07b8, 0x6001 }, 0 },
84 ZYD_ZD1211_DEV(ASUS, WL159G){ { 0x0b05, 0x170c }, 0 },
85 ZYD_ZD1211_DEV(CYBERTAN, TG54USB){ { 0x129b, 0x1666 }, 0 },
86 ZYD_ZD1211_DEV(DRAYTEK, VIGOR550){ { 0x0675, 0x0550 }, 0 },
87 ZYD_ZD1211_DEV(PLANEX2, GWUS54GD){ { 0x2019, 0xed01 }, 0 },
88 ZYD_ZD1211_DEV(PLANEX2, GWUS54GZL){ { 0x2019, 0xc007 }, 0 },
89 ZYD_ZD1211_DEV(PLANEX3, GWUS54GZ){ { 0x14ea, 0xab10 }, 0 },
90 ZYD_ZD1211_DEV(PLANEX3, GWUS54MINI){ { 0x14ea, 0xab13 }, 0 },
91 ZYD_ZD1211_DEV(SAGEM, XG760A){ { 0x079b, 0x004a }, 0 },
92 ZYD_ZD1211_DEV(SENAO, NUB8301){ { 0x1740, 0x2000 }, 0 },
93 ZYD_ZD1211_DEV(SITECOMEU, WL113){ { 0x0df6, 0x9071 }, 0 },
94 ZYD_ZD1211_DEV(SWEEX, ZD1211){ { 0x5173, 0x1809 }, 0 },
95 ZYD_ZD1211_DEV(TEKRAM, QUICKWLAN){ { 0x0b3b, 0x1630 }, 0 },
96 ZYD_ZD1211_DEV(TEKRAM, ZD1211_1){ { 0x0b3b, 0x5630 }, 0 },
97 ZYD_ZD1211_DEV(TEKRAM, ZD1211_2){ { 0x0b3b, 0x6630 }, 0 },
98 ZYD_ZD1211_DEV(TWINMOS, G240){ { 0x126f, 0xa006 }, 0 },
99 ZYD_ZD1211_DEV(UMEDIA, ALL0298V2){ { 0x157e, 0x3204 }, 0 },
100 ZYD_ZD1211_DEV(UMEDIA, TEW429UB_A){ { 0x157e, 0x300a }, 0 },
101 ZYD_ZD1211_DEV(UMEDIA, TEW429UB){ { 0x157e, 0x300b }, 0 },
102 ZYD_ZD1211_DEV(UNKNOWN2, NW3100){ { 0x0105, 0x145f }, 0 },
103 ZYD_ZD1211_DEV(WISTRONNEWEB, UR055G){ { 0x1435, 0x0711 }, 0 },
104 ZYD_ZD1211_DEV(ZCOM, ZD1211){ { 0x0cde, 0x0011 }, 0 },
105 ZYD_ZD1211_DEV(ZYDAS, ALL0298){ { 0x0ace, 0xa211 }, 0 },
106 ZYD_ZD1211_DEV(ZYDAS, ZD1211){ { 0x0ace, 0x1211 }, 0 },
107 ZYD_ZD1211_DEV(ZYXEL, AG225H){ { 0x0586, 0x3409 }, 0 },
108 ZYD_ZD1211_DEV(ZYXEL, G200V2){ { 0x0586, 0x3407 }, 0 },
109 ZYD_ZD1211_DEV(ZYXEL, G202){ { 0x0586, 0x3410 }, 0 },
110 ZYD_ZD1211_DEV(ZYXEL, G220){ { 0x0586, 0x3401 }, 0 },
111 ZYD_ZD1211_DEV(ZYXEL, G220F){ { 0x0586, 0x3402 }, 0 },
112
113 ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG){ { 0x083a, 0x4505 }, 1 },
114 ZYD_ZD1211B_DEV(ACCTON, WN4501H_LF_IR){ { 0x083a, 0xe503 }, 1 },
115 ZYD_ZD1211B_DEV(ACCTON, WUS201){ { 0x083a, 0xe506 }, 1 },
116 ZYD_ZD1211B_DEV(ACCTON, ZD1211B){ { 0x083a, 0xe501 }, 1 },
117 ZYD_ZD1211B_DEV(ASUS, A9T_WIFI){ { 0x0b05, 0x171b }, 1 },
118 ZYD_ZD1211B_DEV(BELKIN, F5D7050C){ { 0x050d, 0x705c }, 1 },
119 ZYD_ZD1211B_DEV(BELKIN, ZD1211B){ { 0x050d, 0x4050 }, 1 },
120 ZYD_ZD1211B_DEV(BEWAN, BWIFI_USB54AR){ { 0x07fa, 0x1196 }, 1 },
121 ZYD_ZD1211B_DEV(CISCOLINKSYS, WUSBF54G){ { 0x13b1, 0x0024 }, 1 },
122 ZYD_ZD1211B_DEV(CYBERTAN, ZD1211B){ { 0x129b, 0x1667 }, 1 },
123 ZYD_ZD1211B_DEV(FIBERLINE, WL430U){ { 0x1582, 0x6003 }, 1 },
124 ZYD_ZD1211B_DEV(MELCO, KG54L){ { 0x0411, 0x00da }, 1 },
125 ZYD_ZD1211B_DEV(PHILIPS, SNU5600){ { 0x0471, 0x1236 }, 1 },
126 ZYD_ZD1211B_DEV(PHILIPS, SNU5630NS05){ { 0x0471, 0x1237 }, 1 },
127 ZYD_ZD1211B_DEV(PLANEX2, GW_US54GXS){ { 0x2019, 0x5303 }, 1 },
128 ZYD_ZD1211B_DEV(PLANEX4, GWUS54ZGL){ { 0x0053, 0x5301 }, 1 },
129 ZYD_ZD1211B_DEV(PLANEX4, ZD1211B){ { 0x0053, 0x5302 }, 1 },
130 ZYD_ZD1211B_DEV(SAGEM, XG76NA){ { 0x079b, 0x0062 }, 1 },
131 ZYD_ZD1211B_DEV(SITECOMEU, WL603){ { 0x0df6, 0x0036 }, 1 },
132 ZYD_ZD1211B_DEV(SITECOMEU, ZD1211B){ { 0x0df6, 0x9075 }, 1 },
133 ZYD_ZD1211B_DEV(UMEDIA, TEW429UBC1){ { 0x157e, 0x300d }, 1 },
134 ZYD_ZD1211B_DEV(UNKNOWN2, ZD1211B){ { 0x0105, 0x0105 }, 1 },
135 ZYD_ZD1211B_DEV(UNKNOWN3, ZD1211B){ { 0x1233, 0x1233 }, 1 },
136 ZYD_ZD1211B_DEV(SONY, IFU_WLM2){ { 0x054c, 0x0257 }, 1 },
137 ZYD_ZD1211B_DEV(USR, USR5423){ { 0x0baf, 0x0121 }, 1 },
138 ZYD_ZD1211B_DEV(VTECH, ZD1211B){ { 0x0f88, 0x3014 }, 1 },
139 ZYD_ZD1211B_DEV(ZCOM, ZD1211B){ { 0x0cde, 0x001a }, 1 },
140 ZYD_ZD1211B_DEV(ZYDAS, ZD1211B){ { 0x0ace, 0x1215 }, 1 },
141 ZYD_ZD1211B_DEV(ZYDAS, ZD1211B_2){ { 0x0ace, 0xb215 }, 1 },
142 ZYD_ZD1211B_DEV(ZYXEL, AG220){ { 0x0586, 0x3412 }, 1 },
143 ZYD_ZD1211B_DEV(ZYXEL, AG225HV2){ { 0x0586, 0x3413 }, 1 },
144 ZYD_ZD1211B_DEV(ZYXEL, G220V2){ { 0x0586, 0x340f }, 1 },
145 ZYD_ZD1211B_DEV(ZYXEL, M202){ { 0x0586, 0x340a }, 1 }
146};
147#define zyd_lookup(v, p)((const struct zyd_type *)usbd_match_device((const struct usb_devno
*)(zyd_devs), sizeof (zyd_devs) / sizeof ((zyd_devs)[0]), sizeof
((zyd_devs)[0]), (v), (p)))
\
148 ((const struct zyd_type *)usb_lookup(zyd_devs, v, p)usbd_match_device((const struct usb_devno *)(zyd_devs), sizeof
(zyd_devs) / sizeof ((zyd_devs)[0]), sizeof ((zyd_devs)[0]),
(v), (p))
)
149
150int zyd_match(struct device *, void *, void *);
151void zyd_attach(struct device *, struct device *, void *);
152int zyd_detach(struct device *, int);
153
154struct cfdriver zyd_cd = {
155 NULL((void *)0), "zyd", DV_IFNET
156};
157
158const struct cfattach zyd_ca = {
159 sizeof(struct zyd_softc), zyd_match, zyd_attach, zyd_detach
160};
161
162void zyd_attachhook(struct device *);
163int zyd_complete_attach(struct zyd_softc *);
164int zyd_open_pipes(struct zyd_softc *);
165void zyd_close_pipes(struct zyd_softc *);
166int zyd_alloc_tx_list(struct zyd_softc *);
167void zyd_free_tx_list(struct zyd_softc *);
168int zyd_alloc_rx_list(struct zyd_softc *);
169void zyd_free_rx_list(struct zyd_softc *);
170struct ieee80211_node *zyd_node_alloc(struct ieee80211com *);
171int zyd_media_change(struct ifnet *);
172void zyd_next_scan(void *);
173void zyd_task(void *);
174int zyd_newstate(struct ieee80211com *, enum ieee80211_state, int);
175int zyd_cmd_read(struct zyd_softc *, const void *, size_t, int);
176int zyd_read16(struct zyd_softc *, uint16_t, uint16_t *);
177int zyd_read32(struct zyd_softc *, uint16_t, uint32_t *);
178int zyd_cmd_write(struct zyd_softc *, u_int16_t, const void *, int);
179int zyd_write16(struct zyd_softc *, uint16_t, uint16_t);
180int zyd_write32(struct zyd_softc *, uint16_t, uint32_t);
181int zyd_rfwrite(struct zyd_softc *, uint32_t);
182void zyd_lock_phy(struct zyd_softc *);
183void zyd_unlock_phy(struct zyd_softc *);
184int zyd_rfmd_init(struct zyd_rf *);
185int zyd_rfmd_switch_radio(struct zyd_rf *, int);
186int zyd_rfmd_set_channel(struct zyd_rf *, uint8_t);
187int zyd_al2230_init(struct zyd_rf *);
188int zyd_al2230_switch_radio(struct zyd_rf *, int);
189int zyd_al2230_set_channel(struct zyd_rf *, uint8_t);
190int zyd_al2230_init_b(struct zyd_rf *);
191int zyd_al7230B_init(struct zyd_rf *);
192int zyd_al7230B_switch_radio(struct zyd_rf *, int);
193int zyd_al7230B_set_channel(struct zyd_rf *, uint8_t);
194int zyd_al2210_init(struct zyd_rf *);
195int zyd_al2210_switch_radio(struct zyd_rf *, int);
196int zyd_al2210_set_channel(struct zyd_rf *, uint8_t);
197int zyd_gct_init(struct zyd_rf *);
198int zyd_gct_switch_radio(struct zyd_rf *, int);
199int zyd_gct_set_channel(struct zyd_rf *, uint8_t);
200int zyd_maxim_init(struct zyd_rf *);
201int zyd_maxim_switch_radio(struct zyd_rf *, int);
202int zyd_maxim_set_channel(struct zyd_rf *, uint8_t);
203int zyd_maxim2_init(struct zyd_rf *);
204int zyd_maxim2_switch_radio(struct zyd_rf *, int);
205int zyd_maxim2_set_channel(struct zyd_rf *, uint8_t);
206int zyd_rf_attach(struct zyd_softc *, uint8_t);
207const char *zyd_rf_name(uint8_t);
208int zyd_hw_init(struct zyd_softc *);
209int zyd_read_eeprom(struct zyd_softc *);
210void zyd_set_multi(struct zyd_softc *);
211void zyd_set_macaddr(struct zyd_softc *, const uint8_t *);
212void zyd_set_bssid(struct zyd_softc *, const uint8_t *);
213int zyd_switch_radio(struct zyd_softc *, int);
214void zyd_set_led(struct zyd_softc *, int, int);
215int zyd_set_rxfilter(struct zyd_softc *);
216void zyd_set_chan(struct zyd_softc *, struct ieee80211_channel *);
217int zyd_set_beacon_interval(struct zyd_softc *, int);
218uint8_t zyd_plcp_signal(int);
219void zyd_intr(struct usbd_xfer *, void *, usbd_status);
220void zyd_rx_data(struct zyd_softc *, const uint8_t *, uint16_t,
221 struct mbuf_list *);
222void zyd_rxeof(struct usbd_xfer *, void *, usbd_status);
223void zyd_txeof(struct usbd_xfer *, void *, usbd_status);
224int zyd_tx(struct zyd_softc *, struct mbuf *,
225 struct ieee80211_node *);
226void zyd_start(struct ifnet *);
227void zyd_watchdog(struct ifnet *);
228int zyd_ioctl(struct ifnet *, u_long, caddr_t);
229int zyd_init(struct ifnet *);
230void zyd_stop(struct ifnet *, int);
231int zyd_loadfirmware(struct zyd_softc *, u_char *, size_t);
232void zyd_iter_func(void *, struct ieee80211_node *);
233void zyd_amrr_timeout(void *);
234void zyd_newassoc(struct ieee80211com *, struct ieee80211_node *,
235 int);
236
237int
238zyd_match(struct device *parent, void *match, void *aux)
239{
240 struct usb_attach_arg *uaa = aux;
241
242 if (uaa->iface == NULL((void *)0) || uaa->configno != ZYD_CONFIG_NO1)
243 return UMATCH_NONE0;
244
245 return (zyd_lookup(uaa->vendor, uaa->product)((const struct zyd_type *)usbd_match_device((const struct usb_devno
*)(zyd_devs), sizeof (zyd_devs) / sizeof ((zyd_devs)[0]), sizeof
((zyd_devs)[0]), (uaa->vendor), (uaa->product)))
!= NULL((void *)0)) ?
246 UMATCH_VENDOR_PRODUCT13 : UMATCH_NONE0;
247}
248
249void
250zyd_attachhook(struct device *self)
251{
252 struct zyd_softc *sc = (struct zyd_softc *)self;
253 const char *fwname;
254 u_char *fw;
255 size_t fwsize;
256 int error;
257
258 fwname = (sc->mac_rev == ZYD_ZD12110) ? "zd1211" : "zd1211b";
259 if ((error = loadfirmware(fwname, &fw, &fwsize)) != 0) {
260 printf("%s: error %d, could not read firmware file %s\n",
261 sc->sc_dev.dv_xname, error, fwname);
262 return;
263 }
264
265 error = zyd_loadfirmware(sc, fw, fwsize);
266 free(fw, M_DEVBUF2, fwsize);
267 if (error != 0) {
268 printf("%s: could not load firmware (error=%d)\n",
269 sc->sc_dev.dv_xname, error);
270 return;
271 }
272
273 /* complete the attach process */
274 if (zyd_complete_attach(sc) == 0)
275 sc->attached = 1;
276}
277
278void
279zyd_attach(struct device *parent, struct device *self, void *aux)
280{
281 struct zyd_softc *sc = (struct zyd_softc *)self;
282 struct usb_attach_arg *uaa = aux;
283 usb_device_descriptor_t* ddesc;
284
285 sc->sc_udev = uaa->device;
286 sc->sc_iface = uaa->iface;
287
288 sc->mac_rev = zyd_lookup(uaa->vendor, uaa->product)((const struct zyd_type *)usbd_match_device((const struct usb_devno
*)(zyd_devs), sizeof (zyd_devs) / sizeof ((zyd_devs)[0]), sizeof
((zyd_devs)[0]), (uaa->vendor), (uaa->product)))
->rev;
289
290 ddesc = usbd_get_device_descriptor(sc->sc_udev);
291 if (UGETW(ddesc->bcdDevice)(*(u_int16_t *)(ddesc->bcdDevice)) < 0x4330) {
292 printf("%s: device version mismatch: 0x%x "
293 "(only >= 43.30 supported)\n", sc->sc_dev.dv_xname,
294 UGETW(ddesc->bcdDevice)(*(u_int16_t *)(ddesc->bcdDevice)));
295 return;
296 }
297
298 config_mountroot(self, zyd_attachhook);
299}
300
301int
302zyd_complete_attach(struct zyd_softc *sc)
303{
304 struct ieee80211com *ic = &sc->sc_ic;
305 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
306 usbd_status error;
307 int i;
308
309 usb_init_task(&sc->sc_task, zyd_task, sc, USB_TASK_TYPE_GENERIC)((&sc->sc_task)->fun = (zyd_task), (&sc->sc_task
)->arg = (sc), (&sc->sc_task)->type = (0), (&
sc->sc_task)->state = 0x0)
;
310 timeout_set(&sc->scan_to, zyd_next_scan, sc);
311
312 sc->amrr.amrr_min_success_threshold = 1;
313 sc->amrr.amrr_max_success_threshold = 10;
314 timeout_set(&sc->amrr_to, zyd_amrr_timeout, sc);
315
316 error = usbd_set_config_no(sc->sc_udev, ZYD_CONFIG_NO1, 1);
317 if (error != 0) {
318 printf("%s: setting config no failed\n",
319 sc->sc_dev.dv_xname);
320 goto fail;
321 }
322
323 error = usbd_device2interface_handle(sc->sc_udev, ZYD_IFACE_INDEX0,
324 &sc->sc_iface);
325 if (error != 0) {
326 printf("%s: getting interface handle failed\n",
327 sc->sc_dev.dv_xname);
328 goto fail;
329 }
330
331 if ((error = zyd_open_pipes(sc)) != 0) {
332 printf("%s: could not open pipes\n", sc->sc_dev.dv_xname);
333 goto fail;
334 }
335
336 if ((error = zyd_read_eeprom(sc)) != 0) {
337 printf("%s: could not read EEPROM\n", sc->sc_dev.dv_xname);
338 goto fail;
339 }
340
341 if ((error = zyd_rf_attach(sc, sc->rf_rev)) != 0) {
342 printf("%s: could not attach RF\n", sc->sc_dev.dv_xname);
343 goto fail;
344 }
345
346 if ((error = zyd_hw_init(sc)) != 0) {
347 printf("%s: hardware initialization failed\n",
348 sc->sc_dev.dv_xname);
349 goto fail;
350 }
351
352 printf("%s: HMAC ZD1211%s, FW %02x.%02x, RF %s, PA %x, address %s\n",
353 sc->sc_dev.dv_xname, (sc->mac_rev == ZYD_ZD12110) ? "": "B",
354 sc->fw_rev >> 8, sc->fw_rev & 0xff, zyd_rf_name(sc->rf_rev),
355 sc->pa_rev, ether_sprintf(ic->ic_myaddr));
356
357 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
358 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
359 ic->ic_state = IEEE80211_S_INIT;
360
361 /* set device capabilities */
362 ic->ic_caps =
363 IEEE80211_C_MONITOR0x00000200 | /* monitor mode supported */
364 IEEE80211_C_TXPMGT0x00000040 | /* tx power management */
365 IEEE80211_C_SHPREAMBLE0x00000100 | /* short preamble supported */
366 IEEE80211_C_WEP0x00000001 | /* s/w WEP */
367 IEEE80211_C_RSN0x00001000; /* WPA/RSN */
368
369 /* set supported .11b and .11g rates */
370 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
371 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
372
373 /* set supported .11b and .11g channels (1 through 14) */
374 for (i = 1; i <= 14; i++) {
375 ic->ic_channels[i].ic_freq =
376 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ0x0080);
377 ic->ic_channels[i].ic_flags =
378 IEEE80211_CHAN_CCK0x0020 | IEEE80211_CHAN_OFDM0x0040 |
379 IEEE80211_CHAN_DYN0x0400 | IEEE80211_CHAN_2GHZ0x0080;
380 }
381
382 ifp->if_softc = sc;
383 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
384 ifp->if_ioctl = zyd_ioctl;
385 ifp->if_start = zyd_start;
386 ifp->if_watchdog = zyd_watchdog;
387 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ)__builtin_memcpy((ifp->if_xname), (sc->sc_dev.dv_xname)
, (16))
;
388
389 if_attach(ifp);
390 ieee80211_ifattach(ifp);
391 ic->ic_node_alloc = zyd_node_alloc;
392 ic->ic_newassoc = zyd_newassoc;
393
394 /* override state transition machine */
395 sc->sc_newstate = ic->ic_newstate;
396 ic->ic_newstate = zyd_newstate;
397 ieee80211_media_init(ifp, zyd_media_change, ieee80211_media_status);
398
399#if NBPFILTER1 > 0
400 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO127,
401 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN64);
402
403 sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
404 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_len = htole16(sc->sc_rxtap_len)((__uint16_t)(sc->sc_rxtap_len));
405 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_FLAGS) | (1 <<
IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL
) | (1 << IEEE80211_RADIOTAP_RSSI))))
;
406
407 sc->sc_txtap_len = sizeof sc->sc_txtapu;
408 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_len = htole16(sc->sc_txtap_len)((__uint16_t)(sc->sc_txtap_len));
409 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_FLAGS) | (1 <<
IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL
))))
;
410#endif
411
412fail: return error;
413}
414
415int
416zyd_detach(struct device *self, int flags)
417{
418 struct zyd_softc *sc = (struct zyd_softc *)self;
419 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
420 int s;
421
422 s = splusb()splraise(0x5);
423
424 usb_rem_task(sc->sc_udev, &sc->sc_task);
425 if (timeout_initialized(&sc->scan_to)((&sc->scan_to)->to_flags & 0x04))
426 timeout_del(&sc->scan_to);
427 if (timeout_initialized(&sc->amrr_to)((&sc->amrr_to)->to_flags & 0x04))
428 timeout_del(&sc->amrr_to);
429
430 zyd_close_pipes(sc);
431
432 if (!sc->attached) {
433 splx(s)spllower(s);
434 return 0;
435 }
436
437 zyd_free_rx_list(sc);
438 zyd_free_tx_list(sc);
439
440 if (ifp->if_softc != NULL((void *)0)) {
441 ieee80211_ifdetach(ifp);
442 if_detach(ifp);
443 }
444
445 sc->attached = 0;
446
447 splx(s)spllower(s);
448
449 return 0;
450}
451
452int
453zyd_open_pipes(struct zyd_softc *sc)
454{
455 usb_endpoint_descriptor_t *edesc;
456 int isize;
457 usbd_status error;
458
459 /* interrupt in */
460 edesc = usbd_get_endpoint_descriptor(sc->sc_iface, 0x83);
461 if (edesc == NULL((void *)0))
462 return EINVAL22;
463
464 isize = UGETW(edesc->wMaxPacketSize)(*(u_int16_t *)(edesc->wMaxPacketSize));
465 if (isize == 0) /* should not happen */
466 return EINVAL22;
467
468 sc->ibuf = malloc(isize, M_USBDEV102, M_NOWAIT0x0002);
469 if (sc->ibuf == NULL((void *)0))
470 return ENOMEM12;
471 sc->ibuflen = isize;
472 error = usbd_open_pipe_intr(sc->sc_iface, 0x83, USBD_SHORT_XFER_OK0x04,
473 &sc->zyd_ep[ZYD_ENDPT_IIN2], sc, sc->ibuf, isize, zyd_intr,
474 USBD_DEFAULT_INTERVAL(-1));
475 if (error != 0) {
476 printf("%s: open rx intr pipe failed: %s\n",
477 sc->sc_dev.dv_xname, usbd_errstr(error));
478 goto fail;
479 }
480
481 /* interrupt out (not necessarily an interrupt pipe) */
482 error = usbd_open_pipe(sc->sc_iface, 0x04, USBD_EXCLUSIVE_USE0x01,
483 &sc->zyd_ep[ZYD_ENDPT_IOUT3]);
484 if (error != 0) {
485 printf("%s: open tx intr pipe failed: %s\n",
486 sc->sc_dev.dv_xname, usbd_errstr(error));
487 goto fail;
488 }
489
490 /* bulk in */
491 error = usbd_open_pipe(sc->sc_iface, 0x82, USBD_EXCLUSIVE_USE0x01,
492 &sc->zyd_ep[ZYD_ENDPT_BIN1]);
493 if (error != 0) {
494 printf("%s: open rx pipe failed: %s\n",
495 sc->sc_dev.dv_xname, usbd_errstr(error));
496 goto fail;
497 }
498
499 /* bulk out */
500 error = usbd_open_pipe(sc->sc_iface, 0x01, USBD_EXCLUSIVE_USE0x01,
501 &sc->zyd_ep[ZYD_ENDPT_BOUT0]);
502 if (error != 0) {
503 printf("%s: open tx pipe failed: %s\n",
504 sc->sc_dev.dv_xname, usbd_errstr(error));
505 goto fail;
506 }
507
508 return 0;
509
510fail: zyd_close_pipes(sc);
511 return error;
512}
513
514void
515zyd_close_pipes(struct zyd_softc *sc)
516{
517 int i;
518
519 for (i = 0; i < ZYD_ENDPT_CNT4; i++) {
520 if (sc->zyd_ep[i] != NULL((void *)0)) {
521 usbd_close_pipe(sc->zyd_ep[i]);
522 sc->zyd_ep[i] = NULL((void *)0);
523 }
524 }
525 if (sc->ibuf != NULL((void *)0)) {
526 free(sc->ibuf, M_USBDEV102, sc->ibuflen);
527 sc->ibuf = NULL((void *)0);
528 }
529}
530
531int
532zyd_alloc_tx_list(struct zyd_softc *sc)
533{
534 int i, error;
535
536 sc->tx_queued = 0;
537
538 for (i = 0; i < ZYD_TX_LIST_CNT1; i++) {
539 struct zyd_tx_data *data = &sc->tx_data[i];
540
541 data->sc = sc; /* backpointer for callbacks */
542
543 data->xfer = usbd_alloc_xfer(sc->sc_udev);
544 if (data->xfer == NULL((void *)0)) {
545 printf("%s: could not allocate tx xfer\n",
546 sc->sc_dev.dv_xname);
547 error = ENOMEM12;
548 goto fail;
549 }
550 data->buf = usbd_alloc_buffer(data->xfer, ZYD_MAX_TXBUFSZ(sizeof (struct zyd_tx_desc) + (2300 + 4 + (3 + 1 + 4))));
551 if (data->buf == NULL((void *)0)) {
552 printf("%s: could not allocate tx buffer\n",
553 sc->sc_dev.dv_xname);
554 error = ENOMEM12;
555 goto fail;
556 }
557
558 /* clear Tx descriptor */
559 bzero(data->buf, sizeof (struct zyd_tx_desc))__builtin_bzero((data->buf), (sizeof (struct zyd_tx_desc))
)
;
560 }
561 return 0;
562
563fail: zyd_free_tx_list(sc);
564 return error;
565}
566
567void
568zyd_free_tx_list(struct zyd_softc *sc)
569{
570 struct ieee80211com *ic = &sc->sc_ic;
571 int i;
572
573 for (i = 0; i < ZYD_TX_LIST_CNT1; i++) {
574 struct zyd_tx_data *data = &sc->tx_data[i];
575
576 if (data->xfer != NULL((void *)0)) {
577 usbd_free_xfer(data->xfer);
578 data->xfer = NULL((void *)0);
579 }
580 if (data->ni != NULL((void *)0)) {
581 ieee80211_release_node(ic, data->ni);
582 data->ni = NULL((void *)0);
583 }
584 }
585}
586
587int
588zyd_alloc_rx_list(struct zyd_softc *sc)
589{
590 int i, error;
591
592 for (i = 0; i < ZYD_RX_LIST_CNT1; i++) {
593 struct zyd_rx_data *data = &sc->rx_data[i];
594
595 data->sc = sc; /* backpointer for callbacks */
596
597 data->xfer = usbd_alloc_xfer(sc->sc_udev);
598 if (data->xfer == NULL((void *)0)) {
599 printf("%s: could not allocate rx xfer\n",
600 sc->sc_dev.dv_xname);
601 error = ENOMEM12;
602 goto fail;
603 }
604 data->buf = usbd_alloc_buffer(data->xfer, ZYX_MAX_RXBUFSZ((sizeof (struct zyd_plcphdr) + (2300 + 4 + (3 + 1 + 4)) + sizeof
(struct zyd_rx_stat)) * 3 + sizeof (struct zyd_rx_desc))
);
605 if (data->buf == NULL((void *)0)) {
606 printf("%s: could not allocate rx buffer\n",
607 sc->sc_dev.dv_xname);
608 error = ENOMEM12;
609 goto fail;
610 }
611 }
612 return 0;
613
614fail: zyd_free_rx_list(sc);
615 return error;
616}
617
618void
619zyd_free_rx_list(struct zyd_softc *sc)
620{
621 int i;
622
623 for (i = 0; i < ZYD_RX_LIST_CNT1; i++) {
624 struct zyd_rx_data *data = &sc->rx_data[i];
625
626 if (data->xfer != NULL((void *)0)) {
627 usbd_free_xfer(data->xfer);
628 data->xfer = NULL((void *)0);
629 }
630 }
631}
632
633struct ieee80211_node *
634zyd_node_alloc(struct ieee80211com *ic)
635{
636 return malloc(sizeof (struct zyd_node), M_USBDEV102, M_NOWAIT0x0002 | M_ZERO0x0008);
637}
638
639int
640zyd_media_change(struct ifnet *ifp)
641{
642 int error;
643
644 error = ieee80211_media_change(ifp);
645 if (error != ENETRESET52)
646 return error;
647
648 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) == (IFF_UP0x1 | IFF_RUNNING0x40))
649 error = zyd_init(ifp);
650
651 return error;
652}
653
654/*
655 * This function is called periodically (every 200ms) during scanning to
656 * switch from one channel to another.
657 */
658void
659zyd_next_scan(void *arg)
660{
661 struct zyd_softc *sc = arg;
662 struct ieee80211com *ic = &sc->sc_ic;
663 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
664
665 if (ic->ic_state == IEEE80211_S_SCAN)
666 ieee80211_next_scan(ifp);
667}
668
669void
670zyd_task(void *arg)
671{
672 struct zyd_softc *sc = arg;
673 struct ieee80211com *ic = &sc->sc_ic;
674 enum ieee80211_state ostate;
675
676 ostate = ic->ic_state;
677
678 switch (sc->sc_state) {
679 case IEEE80211_S_INIT:
680 if (ostate == IEEE80211_S_RUN) {
681 /* turn link LED off */
682 zyd_set_led(sc, ZYD_LED1(1 << 8), 0);
683
684 /* stop data LED from blinking */
685 zyd_write32(sc, sc->fwbase + ZYD_FW_LINK_STATUS0x0003, 0);
686 }
687 break;
688
689 case IEEE80211_S_SCAN:
690 zyd_set_chan(sc, ic->ic_bss->ni_chan);
691 timeout_add_msec(&sc->scan_to, 200);
692 break;
693
694 case IEEE80211_S_AUTH:
695 case IEEE80211_S_ASSOC:
696 zyd_set_chan(sc, ic->ic_bss->ni_chan);
697 break;
698
699 case IEEE80211_S_RUN:
700 {
701 struct ieee80211_node *ni = ic->ic_bss;
702
703 zyd_set_chan(sc, ni->ni_chan);
704
705 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
706 /* turn link LED on */
707 zyd_set_led(sc, ZYD_LED1(1 << 8), 1);
708
709 /* make data LED blink upon Tx */
710 zyd_write32(sc, sc->fwbase + ZYD_FW_LINK_STATUS0x0003, 1);
711
712 zyd_set_bssid(sc, ni->ni_bssid);
713 }
714
715 if (ic->ic_opmode == IEEE80211_M_STA) {
716 /* fake a join to init the tx rate */
717 zyd_newassoc(ic, ni, 1);
718 }
719
720 /* start automatic rate control timer */
721 if (ic->ic_fixed_rate == -1)
722 timeout_add_sec(&sc->amrr_to, 1);
723
724 break;
725 }
726 }
727
728 sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
729}
730
731int
732zyd_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
733{
734 struct zyd_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
735
736 usb_rem_task(sc->sc_udev, &sc->sc_task);
737 timeout_del(&sc->scan_to);
738 timeout_del(&sc->amrr_to);
739
740 /* do it in a process context */
741 sc->sc_state = nstate;
742 sc->sc_arg = arg;
743 usb_add_task(sc->sc_udev, &sc->sc_task);
744
745 return 0;
746}
747
748/*
749 * Issue a read command for the specified register (of size regsize)
750 * and await a reply of olen bytes in sc->odata.
751 */
752int
753zyd_cmd_read(struct zyd_softc *sc, const void *reg, size_t regsize, int olen)
754{
755 struct usbd_xfer *xfer;
756 struct zyd_cmd cmd;
757 usbd_status error;
758 int s;
759
760 if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0))
761 return ENOMEM12;
762
763 bzero(&cmd, sizeof(cmd))__builtin_bzero((&cmd), (sizeof(cmd)));
764 cmd.code = htole16(ZYD_CMD_IORD)((__uint16_t)(0x0022));
765 bcopy(reg, cmd.data, regsize);
766
767 bzero(sc->odata, sizeof(sc->odata))__builtin_bzero((sc->odata), (sizeof(sc->odata)));
768 sc->olen = olen;
769
770 usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_IOUT3], 0,
771 &cmd, sizeof(cmd.code) + regsize,
772 USBD_FORCE_SHORT_XFER0x08 | USBD_SYNCHRONOUS0x02,
773 ZYD_INTR_TIMEOUT1000, NULL((void *)0));
774 s = splusb()splraise(0x5);
775 sc->odone = 0;
776 error = usbd_transfer(xfer);
777 splx(s)spllower(s);
778 if (error) {
779 printf("%s: could not send command: %s\n",
780 sc->sc_dev.dv_xname, usbd_errstr(error));
781 usbd_free_xfer(xfer);
782 return EIO5;
783 }
784
785 if (!sc->odone) {
786 /* wait for ZYD_NOTIF_IORD interrupt */
787 if (tsleep_nsec(sc, PWAIT32, "zydcmd",
788 MSEC_TO_NSEC(ZYD_INTR_TIMEOUT1000)) != 0)
789 printf("%s: read command failed\n",
790 sc->sc_dev.dv_xname);
791 }
792 usbd_free_xfer(xfer);
793
794 return error;
795}
796
797int
798zyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val)
799{
800 struct zyd_io *odata;
801 int error;
802
803 reg = htole16(reg)((__uint16_t)(reg));
804 error = zyd_cmd_read(sc, &reg, sizeof(reg), sizeof(*odata));
805 if (error
3.1
'error' is not equal to 0
== 0) {
4
Taking false branch
806 odata = (struct zyd_io *)sc->odata;
807 *val = letoh16(odata[0].val)((__uint16_t)(odata[0].val));
808 }
809 return error;
5
Returning without writing to '*val'
810}
811
812int
813zyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val)
814{
815 struct zyd_io *odata;
816 uint16_t regs[2];
817 int error;
818
819 regs[0] = htole16(ZYD_REG32_HI(reg))((__uint16_t)(((reg) + ((((reg) & 0xf000) == 0x9000) ? 2 :
1))))
;
820 regs[1] = htole16(ZYD_REG32_LO(reg))((__uint16_t)((reg)));
821 error = zyd_cmd_read(sc, regs, sizeof(regs), sizeof(*odata) * 2);
822 if (error == 0) {
823 odata = (struct zyd_io *)sc->odata;
824 *val = letoh16(odata[0].val)((__uint16_t)(odata[0].val)) << 16 | letoh16(odata[1].val)((__uint16_t)(odata[1].val));
825 }
826 return error;
827}
828
829int
830zyd_cmd_write(struct zyd_softc *sc, u_int16_t code, const void *data, int len)
831{
832 struct usbd_xfer *xfer;
833 struct zyd_cmd cmd;
834 usbd_status error;
835
836 if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0))
837 return ENOMEM12;
838
839 bzero(&cmd, sizeof(cmd))__builtin_bzero((&cmd), (sizeof(cmd)));
840 cmd.code = htole16(code)((__uint16_t)(code));
841 bcopy(data, cmd.data, len);
842
843 usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_IOUT3], 0,
844 &cmd, sizeof(cmd.code) + len,
845 USBD_FORCE_SHORT_XFER0x08 | USBD_SYNCHRONOUS0x02,
846 ZYD_INTR_TIMEOUT1000, NULL((void *)0));
847 error = usbd_transfer(xfer);
848 if (error)
849 printf("%s: could not send command: %s\n",
850 sc->sc_dev.dv_xname, usbd_errstr(error));
851
852 usbd_free_xfer(xfer);
853 return error;
854}
855
856int
857zyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val)
858{
859 struct zyd_io io;
860
861 io.reg = htole16(reg)((__uint16_t)(reg));
862 io.val = htole16(val)((__uint16_t)(val));
863 return zyd_cmd_write(sc, ZYD_CMD_IOWR0x0021, &io, sizeof(io));
864}
865
866int
867zyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val)
868{
869 struct zyd_io io[2];
870
871 io[0].reg = htole16(ZYD_REG32_HI(reg))((__uint16_t)(((reg) + ((((reg) & 0xf000) == 0x9000) ? 2 :
1))))
;
872 io[0].val = htole16(val >> 16)((__uint16_t)(val >> 16));
873 io[1].reg = htole16(ZYD_REG32_LO(reg))((__uint16_t)((reg)));
874 io[1].val = htole16(val & 0xffff)((__uint16_t)(val & 0xffff));
875
876 return zyd_cmd_write(sc, ZYD_CMD_IOWR0x0021, io, sizeof(io));
877}
878
879int
880zyd_rfwrite(struct zyd_softc *sc, uint32_t val)
881{
882 struct zyd_rf *rf = &sc->sc_rf;
883 struct zyd_rfwrite req;
884 uint16_t cr203;
2
'cr203' declared without an initial value
885 int i;
886
887 (void)zyd_read16(sc, ZYD_CR2030x932c, &cr203);
3
Calling 'zyd_read16'
6
Returning from 'zyd_read16'
888 cr203 &= ~(ZYD_RF_IF_LE(1 << 1) | ZYD_RF_CLK(1 << 2) | ZYD_RF_DATA(1 << 3));
7
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage
889
890 req.code = htole16(2)((__uint16_t)(2));
891 req.width = htole16(rf->width)((__uint16_t)(rf->width));
892 for (i = 0; i < rf->width; i++) {
893 req.bit[i] = htole16(cr203)((__uint16_t)(cr203));
894 if (val & (1 << (rf->width - 1 - i)))
895 req.bit[i] |= htole16(ZYD_RF_DATA)((__uint16_t)((1 << 3)));
896 }
897 return zyd_cmd_write(sc, ZYD_CMD_RFCFG0x0023, &req, 4 + 2 * rf->width);
898}
899
900void
901zyd_lock_phy(struct zyd_softc *sc)
902{
903 uint32_t tmp;
904
905 (void)zyd_read32(sc, ZYD_MAC_MISC0x9680, &tmp);
906 tmp &= ~ZYD_UNLOCK_PHY_REGS0x80;
907 (void)zyd_write32(sc, ZYD_MAC_MISC0x9680, tmp);
908}
909
910void
911zyd_unlock_phy(struct zyd_softc *sc)
912{
913 uint32_t tmp;
914
915 (void)zyd_read32(sc, ZYD_MAC_MISC0x9680, &tmp);
916 tmp |= ZYD_UNLOCK_PHY_REGS0x80;
917 (void)zyd_write32(sc, ZYD_MAC_MISC0x9680, tmp);
918}
919
920/*
921 * RFMD RF methods.
922 */
923int
924zyd_rfmd_init(struct zyd_rf *rf)
925{
926 struct zyd_softc *sc = rf->rf_sc;
927 static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY{ { 0x9008, 0x1e }, { 0x9024, 0x20 }, { 0x9028, 0x89 }, { 0x902c
, 0x00 }, { 0x903c, 0xd0 }, { 0x9044, 0x68 }, { 0x904c, 0x4a }
, { 0x9050, 0x0c }, { 0x9054, 0x0e }, { 0x905c, 0x48 }, { 0x9060
, 0x14 }, { 0x9068, 0x90 }, { 0x906c, 0x30 }, { 0x9074, 0x20 }
, { 0x907c, 0xb2 }, { 0x9080, 0x43 }, { 0x9084, 0x28 }, { 0x9098
, 0x30 }, { 0x9088, 0x0f }, { 0x908c, 0xf0 }, { 0x90a4, 0x2a }
, { 0x90b8, 0x7f }, { 0x90bc, 0x1e }, { 0x90cc, 0xc5 }, { 0x90d0
, 0xc5 }, { 0x90d4, 0xc5 }, { 0x913c, 0x58 }, { 0x9140, 0x30 }
, { 0x9144, 0x30 }, { 0x9148, 0x00 }, { 0x914c, 0x24 }, { 0x9150
, 0x04 }, { 0x9154, 0x00 }, { 0x9158, 0x10 }, { 0x915c, 0x2a }
, { 0x9160, 0x10 }, { 0x9164, 0x24 }, { 0x9168, 0x18 }, { 0x916c
, 0x00 }, { 0x9170, 0x0a }, { 0x9174, 0x00 }, { 0x9178, 0x01 }
, { 0x917c, 0x00 }, { 0x9180, 0x40 }, { 0x9184, 0x37 }, { 0x9188
, 0x05 }, { 0x918c, 0x28 }, { 0x9190, 0x00 }, { 0x9194, 0x13 }
, { 0x9198, 0x27 }, { 0x919c, 0x27 }, { 0x91a0, 0x18 }, { 0x91a4
, 0x12 }, { 0x91a8, 0x1a }, { 0x91ac, 0x24 }, { 0x91b0, 0x0a }
, { 0x91b4, 0x13 }, { 0x91b8, 0x2f }, { 0x91bc, 0x27 }, { 0x91c0
, 0x27 }, { 0x91c4, 0x27 }, { 0x91c8, 0x27 }, { 0x91cc, 0x40 }
, { 0x91d0, 0x40 }, { 0x91d4, 0xf0 }, { 0x91d8, 0xf0 }, { 0x91dc
, 0x16 }, { 0x91e8, 0x00 }, { 0x91fc, 0x03 }, { 0x920c, 0x08 }
, { 0x9228, 0x28 }, { 0x9250, 0x44 }, { 0x9258, 0x10 }, { 0x92a4
, 0xbb }, { 0x92a8, 0xbb } }
;
928 static const uint32_t rfini[] = ZYD_RFMD_RF{ 0x000007, 0x07dd43, 0x080959, 0x0e6666, 0x116a57, 0x17dd43,
0x1819f9, 0x1e6666, 0x214554, 0x25e7fa, 0x27fffa, 0x294128, 0x2c0000
, 0x300000, 0x340000, 0x381e0f, 0x6c180f }
;
929 int i, error;
930
931 /* init RF-dependent PHY registers */
932 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
933 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
934 if (error != 0)
935 return error;
936 }
937
938 /* init RFMD radio */
939 for (i = 0; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
940 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
941 return error;
942 }
943 return 0;
944}
945
946int
947zyd_rfmd_switch_radio(struct zyd_rf *rf, int on)
948{
949 struct zyd_softc *sc = rf->rf_sc;
950
951 (void)zyd_write16(sc, ZYD_CR100x9028, on ? 0x89 : 0x15);
952 (void)zyd_write16(sc, ZYD_CR110x902c, on ? 0x00 : 0x81);
953
954 return 0;
955}
956
957int
958zyd_rfmd_set_channel(struct zyd_rf *rf, uint8_t chan)
959{
960 struct zyd_softc *sc = rf->rf_sc;
961 static const struct {
962 uint32_t r1, r2;
963 } rfprog[] = ZYD_RFMD_CHANTABLE{ { 0x181979, 0x1e6666 }, { 0x181989, 0x1e6666 }, { 0x181999,
0x1e6666 }, { 0x1819a9, 0x1e6666 }, { 0x1819b9, 0x1e6666 }, {
0x1819c9, 0x1e6666 }, { 0x1819d9, 0x1e6666 }, { 0x1819e9, 0x1e6666
}, { 0x1819f9, 0x1e6666 }, { 0x181a09, 0x1e6666 }, { 0x181a19
, 0x1e6666 }, { 0x181a29, 0x1e6666 }, { 0x181a39, 0x1e6666 },
{ 0x181a60, 0x1c0000 } }
;
964
965 (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
966 (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
967
968 return 0;
969}
970
971/*
972 * AL2230 RF methods.
973 */
974int
975zyd_al2230_init(struct zyd_rf *rf)
976{
977 struct zyd_softc *sc = rf->rf_sc;
978 static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY{ { 0x903c, 0x20 }, { 0x905c, 0x40 }, { 0x9060, 0x20 }, { 0x9068
, 0x11 }, { 0x9070, 0x3e }, { 0x9074, 0x00 }, { 0x90b0, 0x33 }
, { 0x91a8, 0x2a }, { 0x91ac, 0x1a }, { 0x91b4, 0x09 }, { 0x91b8
, 0x27 }, { 0x91bc, 0x2b }, { 0x91c0, 0x2b }, { 0x91dc, 0x0a }
, { 0x9028, 0x89 }, { 0x9044, 0x28 }, { 0x9068, 0x93 }, { 0x9088
, 0x30 }, { 0x908c, 0x3e }, { 0x90a4, 0x24 }, { 0x90b0, 0x32 }
, { 0x90b8, 0x96 }, { 0x90bc, 0x1e }, { 0x913c, 0x58 }, { 0x9140
, 0x30 }, { 0x9144, 0x30 }, { 0x915c, 0x0a }, { 0x9164, 0x04 }
, { 0x9170, 0x0a }, { 0x918c, 0x28 }, { 0x9190, 0x00 }, { 0x9194
, 0x13 }, { 0x9198, 0x27 }, { 0x91a8, 0x24 }, { 0x91ac, 0x2a }
, { 0x91b4, 0x09 }, { 0x91b8, 0x13 }, { 0x91bc, 0x1f }, { 0x91c0
, 0x1f }, { 0x91c4, 0x27 }, { 0x91c8, 0x27 }, { 0x91cc, 0x24 }
, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }, { 0x91d8, 0xfc }, { 0x91dc
, 0x10 }, { 0x91e0, 0x4f }, { 0x91e4, 0x77 }, { 0x91e8, 0xe0 }
, { 0x9224, 0x88 }, { 0x93f0, 0xff }, { 0x93f4, 0xff }, { 0x93ec
, 0x2f }, { 0x93ec, 0x3f }, { 0x9228, 0x28 }, { 0x932c, 0x06 }
}
;
979 static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT{ { 0x90bc, 0x1e }, { 0x91a8, 0x22 }, { 0x91ac, 0x2a }, { 0x91b4
, 0x13 }, { 0x91d8, 0xf8 }, { 0x91dc, 0x12 }, { 0x91e8, 0xe0 }
, { 0x9200, 0x10 }, { 0x9204, 0x0e }, { 0x9208, 0x10 } }
;
980 static const uint32_t rfini[] = ZYD_AL2230_RF{ 0x03f790, 0x033331, 0x00000d, 0x0b3331, 0x03b812, 0x00fff3,
0x000da4, 0x0f4dc5, 0x0805b6, 0x011687, 0x000688, 0x0403b9, 0x00dbba
, 0x00099b, 0x0bdffc, 0x00000d, 0x00500f, 0x00d00f, 0x004c0f,
0x00540f, 0x00700f, 0x00500f }
;
981 int i, error;
982
983 /* init RF-dependent PHY registers */
984 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
985 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
986 if (error != 0)
987 return error;
988 }
989 if (sc->rf_rev == ZYD_RF_AL2230S0xa) {
990 for (i = 0; i < nitems(phy2230s)(sizeof((phy2230s)) / sizeof((phy2230s)[0])); i++) {
991 error = zyd_write16(sc, phy2230s[i].reg,
992 phy2230s[i].val);
993 if (error != 0)
994 return error;
995 }
996 }
997 /* init AL2230 radio */
998 for (i = 0; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
999 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1000 return error;
1001 }
1002 return 0;
1003}
1004
1005int
1006zyd_al2230_init_b(struct zyd_rf *rf)
1007{
1008 struct zyd_softc *sc = rf->rf_sc;
1009 static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B{ { 0x9028, 0x89 }, { 0x903c, 0x20 }, { 0x9044, 0x2b }, { 0x905c
, 0x40 }, { 0x9060, 0x20 }, { 0x9068, 0x93 }, { 0x9070, 0x3e }
, { 0x9074, 0x00 }, { 0x9084, 0x28 }, { 0x9088, 0x30 }, { 0x908c
, 0x3e }, { 0x90a4, 0x24 }, { 0x90b0, 0x32 }, { 0x90b8, 0x99 }
, { 0x90bc, 0x1e }, { 0x90c0, 0x00 }, { 0x90c4, 0x00 }, { 0x90cc
, 0x01 }, { 0x90d0, 0x80 }, { 0x90d4, 0x7e }, { 0x9104, 0x00 }
, { 0x9108, 0x00 }, { 0x910c, 0x00 }, { 0x9110, 0x00 }, { 0x9114
, 0x28 }, { 0x913c, 0x58 }, { 0x9140, 0x30 }, { 0x9144, 0x30 }
, { 0x915c, 0x0a }, { 0x9164, 0x04 }, { 0x916c, 0x00 }, { 0x9170
, 0x0a }, { 0x9188, 0x8d }, { 0x918c, 0x00 }, { 0x9194, 0x13 }
, { 0x91a8, 0x24 }, { 0x91ac, 0x2a }, { 0x91b4, 0x13 }, { 0x91b8
, 0x1f }, { 0x91bc, 0x1f }, { 0x91c8, 0x27 }, { 0x91cc, 0x26 }
, { 0x91d0, 0x24 }, { 0x91d4, 0xfa }, { 0x91d8, 0xfa }, { 0x91dc
, 0x10 }, { 0x91e0, 0x4f }, { 0x91e4, 0x6c }, { 0x91e8, 0xfc }
, { 0x91ec, 0x57 }, { 0x91f4, 0xad }, { 0x91f8, 0x6c }, { 0x91fc
, 0x03 }, { 0x9224, 0x50 }, { 0x9228, 0xa8 }, { 0x9240, 0xac }
, { 0x9258, 0x0d }, { 0x93f0, 0x00 }, { 0x93f4, 0x00 } }
;
1010 static const uint32_t rfini[] = ZYD_AL2230_RF_B{ 0x03f790, 0x033331, 0x00000d, 0x0b3331, 0x03b812, 0x00fff3,
0x0005a4, 0x0f4dc5, 0x0805b6, 0x0146c7, 0x000688, 0x0403b9, 0x00dbba
, 0x00099b, 0x0bdffc, 0x00000d, 0x00580f }
;
1011 int i, error;
1012
1013 /* init RF-dependent PHY registers */
1014 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
1015 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1016 if (error != 0)
1017 return error;
1018 }
1019
1020 /* init AL2230 radio */
1021 for (i = 0; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
1022 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1023 return error;
1024 }
1025 return 0;
1026}
1027
1028int
1029zyd_al2230_switch_radio(struct zyd_rf *rf, int on)
1030{
1031 struct zyd_softc *sc = rf->rf_sc;
1032 int on251 = (sc->mac_rev == ZYD_ZD12110) ? 0x3f : 0x7f;
1033
1034 (void)zyd_write16(sc, ZYD_CR110x902c, on ? 0x00 : 0x04);
1035 (void)zyd_write16(sc, ZYD_CR2510x93ec, on ? on251 : 0x2f);
1036
1037 return 0;
1038}
1039
1040int
1041zyd_al2230_set_channel(struct zyd_rf *rf, uint8_t chan)
1042{
1043 struct zyd_softc *sc = rf->rf_sc;
1044 static const struct {
1045 uint32_t r1, r2, r3;
1046 } rfprog[] = ZYD_AL2230_CHANTABLE{ { 0x03f790, 0x033331, 0x00000d }, { 0x03f790, 0x0b3331, 0x00000d
}, { 0x03e790, 0x033331, 0x00000d }, { 0x03e790, 0x0b3331, 0x00000d
}, { 0x03f7a0, 0x033331, 0x00000d }, { 0x03f7a0, 0x0b3331, 0x00000d
}, { 0x03e7a0, 0x033331, 0x00000d }, { 0x03e7a0, 0x0b3331, 0x00000d
}, { 0x03f7b0, 0x033331, 0x00000d }, { 0x03f7b0, 0x0b3331, 0x00000d
}, { 0x03e7b0, 0x033331, 0x00000d }, { 0x03e7b0, 0x0b3331, 0x00000d
}, { 0x03f7c0, 0x033331, 0x00000d }, { 0x03e7c0, 0x066661, 0x00000d
} }
;
1047
1048 (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
1049 (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
1050 (void)zyd_rfwrite(sc, rfprog[chan - 1].r3);
1051
1052 (void)zyd_write16(sc, ZYD_CR1380x9228, 0x28);
1053 (void)zyd_write16(sc, ZYD_CR2030x932c, 0x06);
1054
1055 return 0;
1056}
1057
1058/*
1059 * AL7230B RF methods.
1060 */
1061int
1062zyd_al7230B_init(struct zyd_rf *rf)
1063{
1064 struct zyd_softc *sc = rf->rf_sc;
1065 static const struct zyd_phy_pair phyini_1[] = ZYD_AL7230B_PHY_1{ { 0x93c0, 0x57 }, { 0x903c, 0x20 }, { 0x905c, 0x40 }, { 0x9060
, 0x20 }, { 0x9068, 0x11 }, { 0x9070, 0x3e }, { 0x9074, 0x00 }
, { 0x90b0, 0x33 }, { 0x91a8, 0x22 }, { 0x91ac, 0x1a }, { 0x91b4
, 0x09 }, { 0x91b8, 0x27 }, { 0x91bc, 0x2b }, { 0x91c0, 0x2b }
, { 0x91dc, 0x0a }, { 0x91e8, 0xfc }, { 0x9028, 0x89 }, { 0x9044
, 0x28 }, { 0x9068, 0x93 }, { 0x9088, 0x30 }, { 0x908c, 0x3e }
, { 0x90a4, 0x24 }, { 0x90b0, 0x32 }, { 0x90b8, 0x96 }, { 0x90bc
, 0x1e }, { 0x913c, 0x58 }, { 0x9140, 0x30 }, { 0x9144, 0x30 }
, { 0x915c, 0x0a }, { 0x9164, 0x04 }, { 0x9170, 0x0a }, { 0x918c
, 0x28 }, { 0x9190, 0x02 }, { 0x9194, 0x13 }, { 0x9198, 0x27 }
, { 0x91a8, 0x22 }, { 0x91ac, 0x3f }, { 0x91b4, 0x09 }, { 0x91b8
, 0x1f }, { 0x91bc, 0x1f }, { 0x91c0, 0x1f }, { 0x91c4, 0x27 }
, { 0x91c8, 0x27 }, { 0x91cc, 0x24 }, { 0x91d0, 0x3f }, { 0x91d4
, 0xfa }, { 0x91d8, 0xfc }, { 0x91dc, 0x10 }, { 0x91e0, 0x4f }
, { 0x91e4, 0x77 }, { 0x9224, 0x88 }, { 0x9228, 0xa8 }, { 0x93f0
, 0x34 }, { 0x93f4, 0x34 }, { 0x93ec, 0x2f } }
;
1066 static const struct zyd_phy_pair phyini_2[] = ZYD_AL7230B_PHY_2{ { 0x93ec, 0x3f }, { 0x9200, 0x14 }, { 0x9204, 0x12 }, { 0x9208
, 0x10 }, { 0x9098, 0x38 }, { 0x9220, 0xdf } }
;
1067 static const struct zyd_phy_pair phyini_3[] = ZYD_AL7230B_PHY_3{ { 0x932c, 0x06 }, { 0x93c0, 0x80 } };
1068 static const uint32_t rfini_1[] = ZYD_AL7230B_RF_1{ 0x09ec04, 0x8cccc8, 0x4ff821, 0xc5fbfc, 0x21ebfe, 0xafd401,
0x6cf56a, 0xe04073, 0x193d76, 0x9dd844, 0x500007, 0xd8c010, 0x3c9000
, 0xbfffff, 0x700000, 0xf15d58 }
;
1069 static const uint32_t rfini_2[] = ZYD_AL7230B_RF_2{ 0xf15d59, 0xf15d5c, 0xf15d58 };
1070 int i, error;
1071
1072 /* for AL7230B, PHY and RF need to be initialized in "phases" */
1073
1074 /* init RF-dependent PHY registers, part one */
1075 for (i = 0; i < nitems(phyini_1)(sizeof((phyini_1)) / sizeof((phyini_1)[0])); i++) {
1076 error = zyd_write16(sc, phyini_1[i].reg, phyini_1[i].val);
1077 if (error != 0)
1078 return error;
1079 }
1080 /* init AL7230B radio, part one */
1081 for (i = 0; i < nitems(rfini_1)(sizeof((rfini_1)) / sizeof((rfini_1)[0])); i++) {
1082 if ((error = zyd_rfwrite(sc, rfini_1[i])) != 0)
1083 return error;
1084 }
1085 /* init RF-dependent PHY registers, part two */
1086 for (i = 0; i < nitems(phyini_2)(sizeof((phyini_2)) / sizeof((phyini_2)[0])); i++) {
1087 error = zyd_write16(sc, phyini_2[i].reg, phyini_2[i].val);
1088 if (error != 0)
1089 return error;
1090 }
1091 /* init AL7230B radio, part two */
1092 for (i = 0; i < nitems(rfini_2)(sizeof((rfini_2)) / sizeof((rfini_2)[0])); i++) {
1093 if ((error = zyd_rfwrite(sc, rfini_2[i])) != 0)
1094 return error;
1095 }
1096 /* init RF-dependent PHY registers, part three */
1097 for (i = 0; i < nitems(phyini_3)(sizeof((phyini_3)) / sizeof((phyini_3)[0])); i++) {
1098 error = zyd_write16(sc, phyini_3[i].reg, phyini_3[i].val);
1099 if (error != 0)
1100 return error;
1101 }
1102
1103 return 0;
1104}
1105
1106int
1107zyd_al7230B_switch_radio(struct zyd_rf *rf, int on)
1108{
1109 struct zyd_softc *sc = rf->rf_sc;
1110
1111 (void)zyd_write16(sc, ZYD_CR110x902c, on ? 0x00 : 0x04);
1112 (void)zyd_write16(sc, ZYD_CR2510x93ec, on ? 0x3f : 0x2f);
1113
1114 return 0;
1115}
1116
1117int
1118zyd_al7230B_set_channel(struct zyd_rf *rf, uint8_t chan)
1119{
1120 struct zyd_softc *sc = rf->rf_sc;
1121 static const struct {
1122 uint32_t r1, r2;
1123 } rfprog[] = ZYD_AL7230B_CHANTABLE{ { 0x09ec00, 0x8cccc8 }, { 0x09ec00, 0x8cccd8 }, { 0x09ec00,
0x8cccc0 }, { 0x09ec00, 0x8cccd0 }, { 0x05ec00, 0x8cccc8 }, {
0x05ec00, 0x8cccd8 }, { 0x05ec00, 0x8cccc0 }, { 0x05ec00, 0x8cccd0
}, { 0x0dec00, 0x8cccc8 }, { 0x0dec00, 0x8cccd8 }, { 0x0dec00
, 0x8cccc0 }, { 0x0dec00, 0x8cccd0 }, { 0x03ec00, 0x8cccc8 },
{ 0x03ec00, 0x866660 } }
;
1124 static const uint32_t rfsc[] = ZYD_AL7230B_RF_SETCHANNEL{ 0x4ff821, 0xc5fbfc, 0x21ebfe, 0xafd401, 0x6cf56a, 0xe04073,
0x193d76, 0x9dd844, 0x500007, 0xd8c010, 0x3c9000, 0xf15d58 }
;
1125 int i, error;
1126
1127 (void)zyd_write16(sc, ZYD_CR2400x93c0, 0x57);
1128 (void)zyd_write16(sc, ZYD_CR2510x93ec, 0x2f);
1129
1130 for (i = 0; i < nitems(rfsc)(sizeof((rfsc)) / sizeof((rfsc)[0])); i++) {
1131 if ((error = zyd_rfwrite(sc, rfsc[i])) != 0)
1132 return error;
1133 }
1134
1135 (void)zyd_write16(sc, ZYD_CR1280x9200, 0x14);
1136 (void)zyd_write16(sc, ZYD_CR1290x9204, 0x12);
1137 (void)zyd_write16(sc, ZYD_CR1300x9208, 0x10);
1138 (void)zyd_write16(sc, ZYD_CR380x9098, 0x38);
1139 (void)zyd_write16(sc, ZYD_CR1360x9220, 0xdf);
1140
1141 (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
1142 (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
1143 (void)zyd_rfwrite(sc, 0x3c9000);
1144
1145 (void)zyd_write16(sc, ZYD_CR2510x93ec, 0x3f);
1146 (void)zyd_write16(sc, ZYD_CR2030x932c, 0x06);
1147 (void)zyd_write16(sc, ZYD_CR2400x93c0, 0x08);
1148
1149 return 0;
1150}
1151
1152/*
1153 * AL2210 RF methods.
1154 */
1155int
1156zyd_al2210_init(struct zyd_rf *rf)
1157{
1158 struct zyd_softc *sc = rf->rf_sc;
1159 static const struct zyd_phy_pair phyini[] = ZYD_AL2210_PHY{ { 0x9024, 0xe0 }, { 0x9028, 0x91 }, { 0x9030, 0x90 }, { 0x903c
, 0xd0 }, { 0x9040, 0x40 }, { 0x9044, 0x58 }, { 0x9048, 0x04 }
, { 0x905c, 0x66 }, { 0x9060, 0x14 }, { 0x9068, 0x90 }, { 0x907c
, 0x80 }, { 0x9088, 0x06 }, { 0x908c, 0x3e }, { 0x9098, 0x38 }
, { 0x90b8, 0x90 }, { 0x90bc, 0x1e }, { 0x9100, 0x64 }, { 0x913c
, 0xb5 }, { 0x9140, 0x38 }, { 0x9144, 0x30 }, { 0x91c4, 0xc0 }
, { 0x91fc, 0x03 } }
;
1160 static const uint32_t rfini[] = ZYD_AL2210_RF{ 0x2396c0, 0x00fcb1, 0x358132, 0x0108b3, 0xc77804, 0x456415,
0xff2226, 0x806667, 0x7860f8, 0xbb01c9, 0x00000a, 0x00000b }
;
1161 uint32_t tmp;
1162 int i, error;
1163
1164 (void)zyd_write32(sc, ZYD_CR180x9048, 2);
1165
1166 /* init RF-dependent PHY registers */
1167 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
1168 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1169 if (error != 0)
1170 return error;
1171 }
1172 /* init AL2210 radio */
1173 for (i = 0; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
1174 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1175 return error;
1176 }
1177 (void)zyd_write16(sc, ZYD_CR470x90bc, 0x1e);
1178 (void)zyd_read32(sc, ZYD_CR_RADIO_PD0x942c, &tmp);
1179 (void)zyd_write32(sc, ZYD_CR_RADIO_PD0x942c, tmp & ~1);
1180 (void)zyd_write32(sc, ZYD_CR_RADIO_PD0x942c, tmp | 1);
1181 (void)zyd_write32(sc, ZYD_CR_RFCFG0x9464, 0x05);
1182 (void)zyd_write32(sc, ZYD_CR_RFCFG0x9464, 0x00);
1183 (void)zyd_write16(sc, ZYD_CR470x90bc, 0x1e);
1184 (void)zyd_write32(sc, ZYD_CR180x9048, 3);
1185
1186 return 0;
1187}
1188
1189int
1190zyd_al2210_switch_radio(struct zyd_rf *rf, int on)
1191{
1192 /* vendor driver does nothing for this RF chip */
1193
1194 return 0;
1195}
1196
1197int
1198zyd_al2210_set_channel(struct zyd_rf *rf, uint8_t chan)
1199{
1200 struct zyd_softc *sc = rf->rf_sc;
1201 static const uint32_t rfprog[] = ZYD_AL2210_CHANTABLE{ 0x0196c0, 0x019710, 0x019760, 0x0197b0, 0x019800, 0x019850,
0x0198a0, 0x0198f0, 0x019940, 0x019990, 0x0199e0, 0x019a30, 0x019a80
, 0x019b40 }
;
1202 uint32_t tmp;
1203
1204 (void)zyd_write32(sc, ZYD_CR180x9048, 2);
1205 (void)zyd_write16(sc, ZYD_CR470x90bc, 0x1e);
1206 (void)zyd_read32(sc, ZYD_CR_RADIO_PD0x942c, &tmp);
1207 (void)zyd_write32(sc, ZYD_CR_RADIO_PD0x942c, tmp & ~1);
1208 (void)zyd_write32(sc, ZYD_CR_RADIO_PD0x942c, tmp | 1);
1209 (void)zyd_write32(sc, ZYD_CR_RFCFG0x9464, 0x05);
1210
1211 (void)zyd_write32(sc, ZYD_CR_RFCFG0x9464, 0x00);
1212 (void)zyd_write16(sc, ZYD_CR470x90bc, 0x1e);
1213
1214 /* actually set the channel */
1215 (void)zyd_rfwrite(sc, rfprog[chan - 1]);
1216
1217 (void)zyd_write32(sc, ZYD_CR180x9048, 3);
1218
1219 return 0;
1220}
1221
1222/*
1223 * GCT RF methods.
1224 */
1225int
1226zyd_gct_init(struct zyd_rf *rf)
1227{
1228 struct zyd_softc *sc = rf->rf_sc;
1229 static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY{ { 0x90bc, 0x1e }, { 0x903c, 0xdc }, { 0x91c4, 0xc0 }, { 0x9050
, 0x0c }, { 0x9044, 0x65 }, { 0x9088, 0x04 }, { 0x908c, 0x35 }
, { 0x9060, 0x20 }, { 0x9024, 0xe0 }, { 0x91fc, 0x02 }, { 0x9028
, 0x91 }, { 0x905c, 0x7f }, { 0x906c, 0x10 }, { 0x9070, 0x7a }
, { 0x913c, 0xb5 }, { 0x9100, 0x80 }, { 0x9084, 0x28 }, { 0x9098
, 0x30 } }
;
1230 static const uint32_t rfini[] = ZYD_GCT_RF{ 0x1f0000, 0x1f0000, 0x1f0200, 0x1f0600, 0x1f8600, 0x1f8600,
0x002050, 0x1f8000, 0x1f8200, 0x1f8600, 0x1c0000, 0x10c458, 0x088e92
, 0x187b82, 0x0401b4, 0x140816, 0x0c7000, 0x1c0000, 0x02ccae,
0x128023, 0x0a0000, 0x1a0000, 0x06e380, 0x16cb94, 0x0e1740, 0x014980
, 0x116240, 0x090000, 0x192304, 0x05112f, 0x0d54a8, 0x0f8000,
0x1c0008, 0x1c0000, 0x1a0000, 0x1c0008, 0x150000, 0x0c7000, 0x150800
, 0x150000 }
;
1231 int i, error;
1232
1233 /* init RF-dependent PHY registers */
1234 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
1235 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1236 if (error != 0)
1237 return error;
1238 }
1239 /* init cgt radio */
1240 for (i = 0; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
1241 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1242 return error;
1243 }
1244 return 0;
1245}
1246
1247int
1248zyd_gct_switch_radio(struct zyd_rf *rf, int on)
1249{
1250 /* vendor driver does nothing for this RF chip */
1251
1252 return 0;
1253}
1254
1255int
1256zyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan)
1257{
1258 struct zyd_softc *sc = rf->rf_sc;
1259 static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE{ 0x1a0000, 0x1a8000, 0x1a4000, 0x1ac000, 0x1a2000, 0x1aa000,
0x1a6000, 0x1ae000, 0x1a1000, 0x1a9000, 0x1a5000, 0x1ad000, 0x1a3000
, 0x1ab000 }
;
1260
1261 (void)zyd_rfwrite(sc, 0x1c0000);
1
Calling 'zyd_rfwrite'
1262 (void)zyd_rfwrite(sc, rfprog[chan - 1]);
1263 (void)zyd_rfwrite(sc, 0x1c0008);
1264
1265 return 0;
1266}
1267
1268/*
1269 * Maxim RF methods.
1270 */
1271int
1272zyd_maxim_init(struct zyd_rf *rf)
1273{
1274 struct zyd_softc *sc = rf->rf_sc;
1275 static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY{ { 0x905c, 0x40 }, { 0x903c, 0x20 }, { 0x9070, 0x3e }, { 0x9074
, 0x00 }, { 0x9068, 0x11 }, { 0x90b0, 0x33 }, { 0x91a8, 0x2a }
, { 0x91ac, 0x1a }, { 0x91b4, 0x2b }, { 0x91b8, 0x2b }, { 0x91bc
, 0x2b }, { 0x91c0, 0x2b }, { 0x9028, 0x89 }, { 0x9044, 0x20 }
, { 0x9068, 0x93 }, { 0x9088, 0x30 }, { 0x908c, 0x40 }, { 0x90a4
, 0x24 }, { 0x90b0, 0x32 }, { 0x90b8, 0x90 }, { 0x9164, 0x18 }
, { 0x9170, 0x0a }, { 0x9194, 0x13 }, { 0x9198, 0x27 }, { 0x91a8
, 0x20 }, { 0x91ac, 0x24 }, { 0x91b4, 0x09 }, { 0x91b8, 0x13 }
, { 0x91bc, 0x13 }, { 0x91c0, 0x13 }, { 0x91c4, 0x27 }, { 0x91c8
, 0x27 }, { 0x91cc, 0x24 }, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }
, { 0x91d8, 0xfa }, { 0x91e0, 0x4f }, { 0x91e4, 0x77 }, { 0x91e8
, 0xfe }, { 0x9028, 0x89 }, { 0x9044, 0x20 }, { 0x9068, 0x93 }
, { 0x9088, 0x30 }, { 0x908c, 0x40 }, { 0x90a4, 0x24 }, { 0x90b0
, 0x32 }, { 0x90b8, 0x90 }, { 0x9164, 0x18 }, { 0x9170, 0x0a }
, { 0x9194, 0x13 }, { 0x9198, 0x27 }, { 0x91a8, 0x20 }, { 0x91ac
, 0x24 }, { 0x91b4, 0x13 }, { 0x91b8, 0x27 }, { 0x91bc, 0x27 }
, { 0x91c0, 0x13 }, { 0x91c4, 0x27 }, { 0x91c8, 0x27 }, { 0x91cc
, 0x24 }, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }, { 0x91d8, 0x00 }
, { 0x91e0, 0x4f }, { 0x91e4, 0x06 }, { 0x91e8, 0xfe }, { 0x9258
, 0x0d } }
;
1276 static const uint32_t rfini[] = ZYD_MAXIM_RF{ 0x00ccd4, 0x030a03, 0x000400, 0x000ca1, 0x010072, 0x018645,
0x004006, 0x0000a7, 0x008258, 0x003fc9, 0x00040a, 0x00000b, 0x00026c
}
;
1277 uint16_t tmp;
1278 int i, error;
1279
1280 /* init RF-dependent PHY registers */
1281 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
1282 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1283 if (error != 0)
1284 return error;
1285 }
1286 (void)zyd_read16(sc, ZYD_CR2030x932c, &tmp);
1287 (void)zyd_write16(sc, ZYD_CR2030x932c, tmp & ~(1 << 4));
1288
1289 /* init maxim radio */
1290 for (i = 0; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
1291 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1292 return error;
1293 }
1294 (void)zyd_read16(sc, ZYD_CR2030x932c, &tmp);
1295 (void)zyd_write16(sc, ZYD_CR2030x932c, tmp | (1 << 4));
1296
1297 return 0;
1298}
1299
1300int
1301zyd_maxim_switch_radio(struct zyd_rf *rf, int on)
1302{
1303 /* vendor driver does nothing for this RF chip */
1304
1305 return 0;
1306}
1307
1308int
1309zyd_maxim_set_channel(struct zyd_rf *rf, uint8_t chan)
1310{
1311 struct zyd_softc *sc = rf->rf_sc;
1312 static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY{ { 0x905c, 0x40 }, { 0x903c, 0x20 }, { 0x9070, 0x3e }, { 0x9074
, 0x00 }, { 0x9068, 0x11 }, { 0x90b0, 0x33 }, { 0x91a8, 0x2a }
, { 0x91ac, 0x1a }, { 0x91b4, 0x2b }, { 0x91b8, 0x2b }, { 0x91bc
, 0x2b }, { 0x91c0, 0x2b }, { 0x9028, 0x89 }, { 0x9044, 0x20 }
, { 0x9068, 0x93 }, { 0x9088, 0x30 }, { 0x908c, 0x40 }, { 0x90a4
, 0x24 }, { 0x90b0, 0x32 }, { 0x90b8, 0x90 }, { 0x9164, 0x18 }
, { 0x9170, 0x0a }, { 0x9194, 0x13 }, { 0x9198, 0x27 }, { 0x91a8
, 0x20 }, { 0x91ac, 0x24 }, { 0x91b4, 0x09 }, { 0x91b8, 0x13 }
, { 0x91bc, 0x13 }, { 0x91c0, 0x13 }, { 0x91c4, 0x27 }, { 0x91c8
, 0x27 }, { 0x91cc, 0x24 }, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }
, { 0x91d8, 0xfa }, { 0x91e0, 0x4f }, { 0x91e4, 0x77 }, { 0x91e8
, 0xfe }, { 0x9028, 0x89 }, { 0x9044, 0x20 }, { 0x9068, 0x93 }
, { 0x9088, 0x30 }, { 0x908c, 0x40 }, { 0x90a4, 0x24 }, { 0x90b0
, 0x32 }, { 0x90b8, 0x90 }, { 0x9164, 0x18 }, { 0x9170, 0x0a }
, { 0x9194, 0x13 }, { 0x9198, 0x27 }, { 0x91a8, 0x20 }, { 0x91ac
, 0x24 }, { 0x91b4, 0x13 }, { 0x91b8, 0x27 }, { 0x91bc, 0x27 }
, { 0x91c0, 0x13 }, { 0x91c4, 0x27 }, { 0x91c8, 0x27 }, { 0x91cc
, 0x24 }, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }, { 0x91d8, 0x00 }
, { 0x91e0, 0x4f }, { 0x91e4, 0x06 }, { 0x91e8, 0xfe }, { 0x9258
, 0x0d } }
;
1313 static const uint32_t rfini[] = ZYD_MAXIM_RF{ 0x00ccd4, 0x030a03, 0x000400, 0x000ca1, 0x010072, 0x018645,
0x004006, 0x0000a7, 0x008258, 0x003fc9, 0x00040a, 0x00000b, 0x00026c
}
;
1314 static const struct {
1315 uint32_t r1, r2;
1316 } rfprog[] = ZYD_MAXIM_CHANTABLE{ { 0x0ccd4, 0x30a03 }, { 0x22224, 0x00a13 }, { 0x37774, 0x10a13
}, { 0x0ccd4, 0x30a13 }, { 0x22224, 0x00a23 }, { 0x37774, 0x10a23
}, { 0x0ccd4, 0x30a23 }, { 0x22224, 0x00a33 }, { 0x37774, 0x10a33
}, { 0x0ccd4, 0x30a33 }, { 0x22224, 0x00a43 }, { 0x37774, 0x10a43
}, { 0x0ccd4, 0x30a43 }, { 0x199a4, 0x20a53 } }
;
1317 uint16_t tmp;
1318 int i, error;
1319
1320 /*
1321 * Do the same as we do when initializing it, except for the channel
1322 * values coming from the two channel tables.
1323 */
1324
1325 /* init RF-dependent PHY registers */
1326 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
1327 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1328 if (error != 0)
1329 return error;
1330 }
1331 (void)zyd_read16(sc, ZYD_CR2030x932c, &tmp);
1332 (void)zyd_write16(sc, ZYD_CR2030x932c, tmp & ~(1 << 4));
1333
1334 /* first two values taken from the chantables */
1335 (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
1336 (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
1337
1338 /* init maxim radio - skipping the two first values */
1339 for (i = 2; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
1340 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1341 return error;
1342 }
1343 (void)zyd_read16(sc, ZYD_CR2030x932c, &tmp);
1344 (void)zyd_write16(sc, ZYD_CR2030x932c, tmp | (1 << 4));
1345
1346 return 0;
1347}
1348
1349/*
1350 * Maxim2 RF methods.
1351 */
1352int
1353zyd_maxim2_init(struct zyd_rf *rf)
1354{
1355 struct zyd_softc *sc = rf->rf_sc;
1356 static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY{ { 0x905c, 0x40 }, { 0x903c, 0x20 }, { 0x9070, 0x3e }, { 0x9074
, 0x00 }, { 0x9068, 0x11 }, { 0x90b0, 0x33 }, { 0x91a8, 0x2a }
, { 0x91ac, 0x1a }, { 0x91b4, 0x2b }, { 0x91b8, 0x2b }, { 0x91bc
, 0x2b }, { 0x91c0, 0x2b }, { 0x9028, 0x89 }, { 0x9044, 0x20 }
, { 0x9068, 0x93 }, { 0x9088, 0x30 }, { 0x908c, 0x40 }, { 0x90a4
, 0x24 }, { 0x90b0, 0x32 }, { 0x90b8, 0x90 }, { 0x9164, 0x18 }
, { 0x9170, 0x0a }, { 0x9194, 0x13 }, { 0x9198, 0x27 }, { 0x91a8
, 0x20 }, { 0x91ac, 0x24 }, { 0x91b4, 0x09 }, { 0x91b8, 0x13 }
, { 0x91bc, 0x13 }, { 0x91c0, 0x13 }, { 0x91c4, 0x27 }, { 0x91c8
, 0x27 }, { 0x91cc, 0x24 }, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }
, { 0x91d8, 0xfa }, { 0x91e0, 0x4f }, { 0x91e4, 0x77 }, { 0x91e8
, 0xfe }, { 0x9028, 0x89 }, { 0x9044, 0x20 }, { 0x9068, 0x93 }
, { 0x9088, 0x30 }, { 0x908c, 0x40 }, { 0x90a4, 0x24 }, { 0x90b0
, 0x32 }, { 0x90b8, 0x90 }, { 0x913c, 0x58 }, { 0x9140, 0x30 }
, { 0x9144, 0x30 }, { 0x9164, 0x18 }, { 0x9170, 0x0a }, { 0x9194
, 0x13 }, { 0x9198, 0x27 }, { 0x91a8, 0x20 }, { 0x91ac, 0x24 }
, { 0x91b4, 0x09 }, { 0x91b8, 0x13 }, { 0x91bc, 0x13 }, { 0x91c0
, 0x13 }, { 0x91c4, 0x27 }, { 0x91c8, 0x27 }, { 0x91cc, 0x24 }
, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }, { 0x91d8, 0x00 }, { 0x91e0
, 0x4f }, { 0x91e4, 0x06 }, { 0x91e8, 0xfe } }
;
1357 static const uint32_t rfini[] = ZYD_MAXIM2_RF{ 0x33334, 0x10a03, 0x00400, 0x00ca1, 0x10072, 0x18645, 0x04006
, 0x000a7, 0x08258, 0x03fc9, 0x0040a, 0x0000b, 0x0026c }
;
1358 uint16_t tmp;
1359 int i, error;
1360
1361 /* init RF-dependent PHY registers */
1362 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
1363 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1364 if (error != 0)
1365 return error;
1366 }
1367 (void)zyd_read16(sc, ZYD_CR2030x932c, &tmp);
1368 (void)zyd_write16(sc, ZYD_CR2030x932c, tmp & ~(1 << 4));
1369
1370 /* init maxim2 radio */
1371 for (i = 0; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
1372 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1373 return error;
1374 }
1375 (void)zyd_read16(sc, ZYD_CR2030x932c, &tmp);
1376 (void)zyd_write16(sc, ZYD_CR2030x932c, tmp | (1 << 4));
1377
1378 return 0;
1379}
1380
1381int
1382zyd_maxim2_switch_radio(struct zyd_rf *rf, int on)
1383{
1384 /* vendor driver does nothing for this RF chip */
1385
1386 return 0;
1387}
1388
1389int
1390zyd_maxim2_set_channel(struct zyd_rf *rf, uint8_t chan)
1391{
1392 struct zyd_softc *sc = rf->rf_sc;
1393 static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY{ { 0x905c, 0x40 }, { 0x903c, 0x20 }, { 0x9070, 0x3e }, { 0x9074
, 0x00 }, { 0x9068, 0x11 }, { 0x90b0, 0x33 }, { 0x91a8, 0x2a }
, { 0x91ac, 0x1a }, { 0x91b4, 0x2b }, { 0x91b8, 0x2b }, { 0x91bc
, 0x2b }, { 0x91c0, 0x2b }, { 0x9028, 0x89 }, { 0x9044, 0x20 }
, { 0x9068, 0x93 }, { 0x9088, 0x30 }, { 0x908c, 0x40 }, { 0x90a4
, 0x24 }, { 0x90b0, 0x32 }, { 0x90b8, 0x90 }, { 0x9164, 0x18 }
, { 0x9170, 0x0a }, { 0x9194, 0x13 }, { 0x9198, 0x27 }, { 0x91a8
, 0x20 }, { 0x91ac, 0x24 }, { 0x91b4, 0x09 }, { 0x91b8, 0x13 }
, { 0x91bc, 0x13 }, { 0x91c0, 0x13 }, { 0x91c4, 0x27 }, { 0x91c8
, 0x27 }, { 0x91cc, 0x24 }, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }
, { 0x91d8, 0xfa }, { 0x91e0, 0x4f }, { 0x91e4, 0x77 }, { 0x91e8
, 0xfe }, { 0x9028, 0x89 }, { 0x9044, 0x20 }, { 0x9068, 0x93 }
, { 0x9088, 0x30 }, { 0x908c, 0x40 }, { 0x90a4, 0x24 }, { 0x90b0
, 0x32 }, { 0x90b8, 0x90 }, { 0x913c, 0x58 }, { 0x9140, 0x30 }
, { 0x9144, 0x30 }, { 0x9164, 0x18 }, { 0x9170, 0x0a }, { 0x9194
, 0x13 }, { 0x9198, 0x27 }, { 0x91a8, 0x20 }, { 0x91ac, 0x24 }
, { 0x91b4, 0x09 }, { 0x91b8, 0x13 }, { 0x91bc, 0x13 }, { 0x91c0
, 0x13 }, { 0x91c4, 0x27 }, { 0x91c8, 0x27 }, { 0x91cc, 0x24 }
, { 0x91d0, 0x24 }, { 0x91d4, 0xf4 }, { 0x91d8, 0x00 }, { 0x91e0
, 0x4f }, { 0x91e4, 0x06 }, { 0x91e8, 0xfe } }
;
1394 static const uint32_t rfini[] = ZYD_MAXIM2_RF{ 0x33334, 0x10a03, 0x00400, 0x00ca1, 0x10072, 0x18645, 0x04006
, 0x000a7, 0x08258, 0x03fc9, 0x0040a, 0x0000b, 0x0026c }
;
1395 static const struct {
1396 uint32_t r1, r2;
1397 } rfprog[] = ZYD_MAXIM2_CHANTABLE{ { 0x33334, 0x10a03 }, { 0x08884, 0x20a13 }, { 0x1ddd4, 0x30a13
}, { 0x33334, 0x10a13 }, { 0x08884, 0x20a23 }, { 0x1ddd4, 0x30a23
}, { 0x33334, 0x10a23 }, { 0x08884, 0x20a33 }, { 0x1ddd4, 0x30a33
}, { 0x33334, 0x10a33 }, { 0x08884, 0x20a43 }, { 0x1ddd4, 0x30a43
}, { 0x33334, 0x10a43 }, { 0x26664, 0x20a53 } }
;
1398 uint16_t tmp;
1399 int i, error;
1400
1401 /*
1402 * Do the same as we do when initializing it, except for the channel
1403 * values coming from the two channel tables.
1404 */
1405
1406 /* init RF-dependent PHY registers */
1407 for (i = 0; i < nitems(phyini)(sizeof((phyini)) / sizeof((phyini)[0])); i++) {
1408 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1409 if (error != 0)
1410 return error;
1411 }
1412 (void)zyd_read16(sc, ZYD_CR2030x932c, &tmp);
1413 (void)zyd_write16(sc, ZYD_CR2030x932c, tmp & ~(1 << 4));
1414
1415 /* first two values taken from the chantables */
1416 (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
1417 (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
1418
1419 /* init maxim2 radio - skipping the two first values */
1420 for (i = 2; i < nitems(rfini)(sizeof((rfini)) / sizeof((rfini)[0])); i++) {
1421 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1422 return error;
1423 }
1424 (void)zyd_read16(sc, ZYD_CR2030x932c, &tmp);
1425 (void)zyd_write16(sc, ZYD_CR2030x932c, tmp | (1 << 4));
1426
1427 return 0;
1428}
1429
1430int
1431zyd_rf_attach(struct zyd_softc *sc, uint8_t type)
1432{
1433 struct zyd_rf *rf = &sc->sc_rf;
1434
1435 rf->rf_sc = sc;
1436
1437 switch (type) {
1438 case ZYD_RF_RFMD0xd:
1439 rf->init = zyd_rfmd_init;
1440 rf->switch_radio = zyd_rfmd_switch_radio;
1441 rf->set_channel = zyd_rfmd_set_channel;
1442 rf->width = 24; /* 24-bit RF values */
1443 break;
1444 case ZYD_RF_AL22300x4:
1445 case ZYD_RF_AL2230S0xa:
1446 if (sc->mac_rev == ZYD_ZD1211B1)
1447 rf->init = zyd_al2230_init_b;
1448 else
1449 rf->init = zyd_al2230_init;
1450 rf->switch_radio = zyd_al2230_switch_radio;
1451 rf->set_channel = zyd_al2230_set_channel;
1452 rf->width = 24; /* 24-bit RF values */
1453 break;
1454 case ZYD_RF_AL7230B0x5:
1455 rf->init = zyd_al7230B_init;
1456 rf->switch_radio = zyd_al7230B_switch_radio;
1457 rf->set_channel = zyd_al7230B_set_channel;
1458 rf->width = 24; /* 24-bit RF values */
1459 break;
1460 case ZYD_RF_AL22100x7:
1461 rf->init = zyd_al2210_init;
1462 rf->switch_radio = zyd_al2210_switch_radio;
1463 rf->set_channel = zyd_al2210_set_channel;
1464 rf->width = 24; /* 24-bit RF values */
1465 break;
1466 case ZYD_RF_GCT0x9:
1467 rf->init = zyd_gct_init;
1468 rf->switch_radio = zyd_gct_switch_radio;
1469 rf->set_channel = zyd_gct_set_channel;
1470 rf->width = 21; /* 21-bit RF values */
1471 break;
1472 case ZYD_RF_MAXIM_NEW0x8:
1473 rf->init = zyd_maxim_init;
1474 rf->switch_radio = zyd_maxim_switch_radio;
1475 rf->set_channel = zyd_maxim_set_channel;
1476 rf->width = 18; /* 18-bit RF values */
1477 break;
1478 case ZYD_RF_MAXIM_NEW20xe:
1479 rf->init = zyd_maxim2_init;
1480 rf->switch_radio = zyd_maxim2_switch_radio;
1481 rf->set_channel = zyd_maxim2_set_channel;
1482 rf->width = 18; /* 18-bit RF values */
1483 break;
1484 default:
1485 printf("%s: sorry, radio \"%s\" is not supported yet\n",
1486 sc->sc_dev.dv_xname, zyd_rf_name(type));
1487 return EINVAL22;
1488 }
1489 return 0;
1490}
1491
1492const char *
1493zyd_rf_name(uint8_t type)
1494{
1495 static const char * const zyd_rfs[] = {
1496 "unknown", "unknown", "UW2451", "UCHIP", "AL2230",
1497 "AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT",
1498 "AL2230S", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2",
1499 "PHILIPS"
1500 };
1501 return zyd_rfs[(type > 15) ? 0 : type];
1502}
1503
1504int
1505zyd_hw_init(struct zyd_softc *sc)
1506{
1507 struct zyd_rf *rf = &sc->sc_rf;
1508 const struct zyd_phy_pair *phyp;
1509 uint32_t tmp;
1510 int error;
1511
1512 /* specify that the plug and play is finished */
1513 (void)zyd_write32(sc, ZYD_MAC_AFTER_PNP0x9648, 1);
1514
1515 (void)zyd_read16(sc, ZYD_FIRMWARE_BASE_ADDR0xee1d, &sc->fwbase);
1516 DPRINTF(("firmware base address=0x%04x\n", sc->fwbase));
1517
1518 /* retrieve firmware revision number */
1519 (void)zyd_read16(sc, sc->fwbase + ZYD_FW_FIRMWARE_REV0x0000, &sc->fw_rev);
1520
1521 (void)zyd_write32(sc, ZYD_CR_GPI_EN0x9418, 0);
1522 (void)zyd_write32(sc, ZYD_MAC_CONT_WIN_LIMIT0x96f0, 0x7f043f);
1523
1524 /* disable interrupts */
1525 (void)zyd_write32(sc, ZYD_CR_INTERRUPT0x9510, 0);
1526
1527 /* PHY init */
1528 zyd_lock_phy(sc);
1529 phyp = (sc->mac_rev == ZYD_ZD1211B1) ? zyd_def_phyB : zyd_def_phy;
1530 for (; phyp->reg != 0; phyp++) {
1531 if ((error = zyd_write16(sc, phyp->reg, phyp->val)) != 0)
1532 goto fail;
1533 }
1534 if (sc->fix_cr157) {
1535 if (zyd_read32(sc, ZYD_EEPROM_PHY_REG0xf831, &tmp) == 0)
1536 (void)zyd_write32(sc, ZYD_CR1570x9274, tmp >> 8);
1537 }
1538 zyd_unlock_phy(sc);
1539
1540 /* HMAC init */
1541 zyd_write32(sc, ZYD_MAC_ACK_EXT0x9690, 0x00000020);
1542 zyd_write32(sc, ZYD_CR_ADDA_MBIAS_WT0x9508, 0x30000808);
1543
1544 if (sc->mac_rev == ZYD_ZD12110) {
1545 zyd_write32(sc, ZYD_MAC_RETRY0x967c, 0x00000002);
1546 } else {
1547 zyd_write32(sc, ZYD_MACB_MAX_RETRY0x9b28, 0x02020202);
1548 zyd_write32(sc, ZYD_MACB_TXPWR_CTL40x9b0c, 0x007f003f);
1549 zyd_write32(sc, ZYD_MACB_TXPWR_CTL30x9b08, 0x007f003f);
1550 zyd_write32(sc, ZYD_MACB_TXPWR_CTL20x9b04, 0x003f001f);
1551 zyd_write32(sc, ZYD_MACB_TXPWR_CTL10x9b00, 0x001f000f);
1552 zyd_write32(sc, ZYD_MACB_AIFS_CTL10x9b10, 0x00280028);
1553 zyd_write32(sc, ZYD_MACB_AIFS_CTL20x9b14, 0x008C003c);
1554 zyd_write32(sc, ZYD_MACB_TXOP0x9b20, 0x01800824);
1555 }
1556
1557 zyd_write32(sc, ZYD_MAC_SNIFFER0x9674, 0x00000000);
1558 zyd_write32(sc, ZYD_MAC_RXFILTER0x968c, 0x00000000);
1559 zyd_write32(sc, ZYD_MAC_GHTBL0x9624, 0x00000000);
1560 zyd_write32(sc, ZYD_MAC_GHTBH0x9628, 0x80000000);
1561 zyd_write32(sc, ZYD_MAC_MISC0x9680, 0x000000a4);
1562 zyd_write32(sc, ZYD_CR_ADDA_PWR_DWN0x9504, 0x0000007f);
1563 zyd_write32(sc, ZYD_MAC_BCNCFG0x9620, 0x00f00401);
1564 zyd_write32(sc, ZYD_MAC_PHY_DELAY20x966c, 0x00000000);
1565 zyd_write32(sc, ZYD_MAC_ACK_EXT0x9690, 0x00000080);
1566 zyd_write32(sc, ZYD_CR_ADDA_PWR_DWN0x9504, 0x00000000);
1567 zyd_write32(sc, ZYD_MAC_SIFS_ACK_TIME0x9658, 0x00000100);
1568 zyd_write32(sc, ZYD_MAC_DIFS_EIFS_SIFS0x9698, 0x0547c032);
1569 zyd_write32(sc, ZYD_CR_RX_PE_DELAY0x947c, 0x00000070);
1570 zyd_write32(sc, ZYD_CR_PS_CTRL0x9500, 0x10000000);
1571 zyd_write32(sc, ZYD_MAC_RTSCTSRATE0x9638, 0x02030203);
1572 zyd_write32(sc, ZYD_MAC_RX_THRESHOLD0x9640, 0x000c0640);
1573 zyd_write32(sc, ZYD_MAC_BACKOFF_PROTECT0x963c, 0x00000114);
1574
1575 /* RF chip init */
1576 zyd_lock_phy(sc);
1577 error = (*rf->init)(rf);
1578 zyd_unlock_phy(sc);
1579 if (error != 0) {
1580 printf("%s: radio initialization failed\n",
1581 sc->sc_dev.dv_xname);
1582 goto fail;
1583 }
1584
1585 /* init beacon interval to 100ms */
1586 if ((error = zyd_set_beacon_interval(sc, 100)) != 0)
1587 goto fail;
1588
1589fail: return error;
1590}
1591
1592int
1593zyd_read_eeprom(struct zyd_softc *sc)
1594{
1595 struct ieee80211com *ic = &sc->sc_ic;
1596 uint32_t tmp;
1597 uint16_t val;
1598 int i;
1599
1600 /* read MAC address */
1601 (void)zyd_read32(sc, ZYD_EEPROM_MAC_ADDR_P10xf81b, &tmp);
1602 ic->ic_myaddr[0] = tmp & 0xff;
1603 ic->ic_myaddr[1] = tmp >> 8;
1604 ic->ic_myaddr[2] = tmp >> 16;
1605 ic->ic_myaddr[3] = tmp >> 24;
1606 (void)zyd_read32(sc, ZYD_EEPROM_MAC_ADDR_P20xf81d, &tmp);
1607 ic->ic_myaddr[4] = tmp & 0xff;
1608 ic->ic_myaddr[5] = tmp >> 8;
1609
1610 (void)zyd_read32(sc, ZYD_EEPROM_POD0xf819, &tmp);
1611 sc->rf_rev = tmp & 0x0f;
1612 sc->fix_cr47 = (tmp >> 8 ) & 0x01;
1613 sc->fix_cr157 = (tmp >> 13) & 0x01;
1614 sc->pa_rev = (tmp >> 16) & 0x0f;
1615
1616 /* read regulatory domain (currently unused) */
1617 (void)zyd_read32(sc, ZYD_EEPROM_SUBID0xf817, &tmp);
1618 sc->regdomain = tmp >> 16;
1619 DPRINTF(("regulatory domain %x\n", sc->regdomain));
1620
1621 /* read Tx power calibration tables */
1622 for (i = 0; i < 7; i++) {
1623 (void)zyd_read16(sc, ZYD_EEPROM_PWR_CAL0xf81f + i, &val);
1624 sc->pwr_cal[i * 2] = val >> 8;
1625 sc->pwr_cal[i * 2 + 1] = val & 0xff;
1626
1627 (void)zyd_read16(sc, ZYD_EEPROM_PWR_INT0xf827 + i, &val);
1628 sc->pwr_int[i * 2] = val >> 8;
1629 sc->pwr_int[i * 2 + 1] = val & 0xff;
1630
1631 (void)zyd_read16(sc, ZYD_EEPROM_36M_CAL0xf83f + i, &val);
1632 sc->ofdm36_cal[i * 2] = val >> 8;
1633 sc->ofdm36_cal[i * 2 + 1] = val & 0xff;
1634
1635 (void)zyd_read16(sc, ZYD_EEPROM_48M_CAL0xf84f + i, &val);
1636 sc->ofdm48_cal[i * 2] = val >> 8;
1637 sc->ofdm48_cal[i * 2 + 1] = val & 0xff;
1638
1639 (void)zyd_read16(sc, ZYD_EEPROM_54M_CAL0xf85f + i, &val);
1640 sc->ofdm54_cal[i * 2] = val >> 8;
1641 sc->ofdm54_cal[i * 2 + 1] = val & 0xff;
1642 }
1643 return 0;
1644}
1645
1646void
1647zyd_set_multi(struct zyd_softc *sc)
1648{
1649 struct arpcom *ac = &sc->sc_ic.ic_ac;
1650 struct ifnet *ifp = &ac->ac_if;
1651 struct ether_multi *enm;
1652 struct ether_multistep step;
1653 uint32_t lo, hi;
1654 uint8_t bit;
1655
1656 if (ac->ac_multirangecnt > 0)
1657 ifp->if_flags |= IFF_ALLMULTI0x200;
1658
1659 if ((ifp->if_flags & (IFF_ALLMULTI0x200 | IFF_PROMISC0x100)) != 0) {
1660 lo = hi = 0xffffffff;
1661 goto done;
1662 }
1663 lo = hi = 0;
1664 ETHER_FIRST_MULTI(step, ac, enm)do { (step).e_enm = ((&(ac)->ac_multiaddrs)->lh_first
); do { if ((((enm)) = ((step)).e_enm) != ((void *)0)) ((step
)).e_enm = ((((enm)))->enm_list.le_next); } while ( 0); } while
( 0)
;
1665 while (enm != NULL((void *)0)) {
1666 bit = enm->enm_addrlo[5] >> 2;
1667 if (bit < 32)
1668 lo |= 1 << bit;
1669 else
1670 hi |= 1 << (bit - 32);
1671 ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm =
(((enm))->enm_list.le_next); } while ( 0)
;
1672 }
1673
1674done:
1675 hi |= 1U << 31; /* make sure the broadcast bit is set */
1676 zyd_write32(sc, ZYD_MAC_GHTBL0x9624, lo);
1677 zyd_write32(sc, ZYD_MAC_GHTBH0x9628, hi);
1678}
1679
1680void
1681zyd_set_macaddr(struct zyd_softc *sc, const uint8_t *addr)
1682{
1683 uint32_t tmp;
1684
1685 tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0];
1686 (void)zyd_write32(sc, ZYD_MAC_MACADRL0x9610, tmp);
1687
1688 tmp = addr[5] << 8 | addr[4];
1689 (void)zyd_write32(sc, ZYD_MAC_MACADRH0x9614, tmp);
1690}
1691
1692void
1693zyd_set_bssid(struct zyd_softc *sc, const uint8_t *addr)
1694{
1695 uint32_t tmp;
1696
1697 tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0];
1698 (void)zyd_write32(sc, ZYD_MAC_BSSADRL0x9618, tmp);
1699
1700 tmp = addr[5] << 8 | addr[4];
1701 (void)zyd_write32(sc, ZYD_MAC_BSSADRH0x961c, tmp);
1702}
1703
1704int
1705zyd_switch_radio(struct zyd_softc *sc, int on)
1706{
1707 struct zyd_rf *rf = &sc->sc_rf;
1708 int error;
1709
1710 zyd_lock_phy(sc);
1711 error = (*rf->switch_radio)(rf, on);
1712 zyd_unlock_phy(sc);
1713
1714 return error;
1715}
1716
1717void
1718zyd_set_led(struct zyd_softc *sc, int which, int on)
1719{
1720 uint32_t tmp;
1721
1722 (void)zyd_read32(sc, ZYD_MAC_TX_PE_CONTROL0x9644, &tmp);
1723 tmp &= ~which;
1724 if (on)
1725 tmp |= which;
1726 (void)zyd_write32(sc, ZYD_MAC_TX_PE_CONTROL0x9644, tmp);
1727}
1728
1729int
1730zyd_set_rxfilter(struct zyd_softc *sc)
1731{
1732 uint32_t rxfilter;
1733
1734 switch (sc->sc_ic.ic_opmode) {
1735 case IEEE80211_M_STA:
1736 rxfilter = ZYD_FILTER_BSS0x2400ffff;
1737 break;
1738#ifndef IEEE80211_STA_ONLY
1739 case IEEE80211_M_IBSS:
1740 case IEEE80211_M_HOSTAP:
1741 rxfilter = ZYD_FILTER_HOSTAP((1U << 0) | (1U << 2) | (1U << 4) | (1U <<
10) | (1U << 11) | (1U << 12) | (1U << 26)
)
;
1742 break;
1743#endif
1744 case IEEE80211_M_MONITOR:
1745 rxfilter = ZYD_FILTER_MONITOR0x000fffff;
1746 break;
1747 default:
1748 /* should not get there */
1749 return EINVAL22;
1750 }
1751 return zyd_write32(sc, ZYD_MAC_RXFILTER0x968c, rxfilter);
1752}
1753
1754void
1755zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c)
1756{
1757 struct ieee80211com *ic = &sc->sc_ic;
1758 struct zyd_rf *rf = &sc->sc_rf;
1759 uint32_t tmp;
1760 u_int chan;
1761
1762 chan = ieee80211_chan2ieee(ic, c);
1763 if (chan == 0 || chan == IEEE80211_CHAN_ANY0xffff)
1764 return;
1765
1766 zyd_lock_phy(sc);
1767
1768 (*rf->set_channel)(rf, chan);
1769
1770 /* update Tx power */
1771 (void)zyd_write16(sc, ZYD_CR310x907c, sc->pwr_int[chan - 1]);
1772
1773 if (sc->mac_rev == ZYD_ZD1211B1) {
1774 (void)zyd_write16(sc, ZYD_CR670x910c, sc->ofdm36_cal[chan - 1]);
1775 (void)zyd_write16(sc, ZYD_CR660x9108, sc->ofdm48_cal[chan - 1]);
1776 (void)zyd_write16(sc, ZYD_CR650x9104, sc->ofdm54_cal[chan - 1]);
1777
1778 (void)zyd_write16(sc, ZYD_CR680x9110, sc->pwr_cal[chan - 1]);
1779
1780 (void)zyd_write16(sc, ZYD_CR690x9114, 0x28);
1781 (void)zyd_write16(sc, ZYD_CR690x9114, 0x2a);
1782 }
1783
1784 if (sc->fix_cr47) {
1785 /* set CCK baseband gain from EEPROM */
1786 if (zyd_read32(sc, ZYD_EEPROM_PHY_REG0xf831, &tmp) == 0)
1787 (void)zyd_write16(sc, ZYD_CR470x90bc, tmp & 0xff);
1788 }
1789
1790 (void)zyd_write32(sc, ZYD_CR_CONFIG_PHILIPS0x9440, 0);
1791
1792 zyd_unlock_phy(sc);
1793}
1794
1795int
1796zyd_set_beacon_interval(struct zyd_softc *sc, int bintval)
1797{
1798 /* XXX this is probably broken.. */
1799 (void)zyd_write32(sc, ZYD_CR_ATIM_WND_PERIOD0x951c, bintval - 2);
1800 (void)zyd_write32(sc, ZYD_CR_PRE_TBTT0x9524, bintval - 1);
1801 (void)zyd_write32(sc, ZYD_CR_BCN_INTERVAL0x9520, bintval);
1802
1803 return 0;
1804}
1805
1806uint8_t
1807zyd_plcp_signal(int rate)
1808{
1809 switch (rate) {
1810 /* CCK rates (returned values are device-dependent) */
1811 case 2: return 0x0;
1812 case 4: return 0x1;
1813 case 11: return 0x2;
1814 case 22: return 0x3;
1815
1816 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
1817 case 12: return 0xb;
1818 case 18: return 0xf;
1819 case 24: return 0xa;
1820 case 36: return 0xe;
1821 case 48: return 0x9;
1822 case 72: return 0xd;
1823 case 96: return 0x8;
1824 case 108: return 0xc;
1825
1826 /* unsupported rates (should not get there) */
1827 default: return 0xff;
1828 }
1829}
1830
1831void
1832zyd_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1833{
1834 struct zyd_softc *sc = (struct zyd_softc *)priv;
1835 const struct zyd_cmd *cmd;
1836 uint32_t len;
1837
1838 if (status != USBD_NORMAL_COMPLETION) {
1839 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1840 return;
1841
1842 if (status == USBD_STALLED) {
1843 usbd_clear_endpoint_stall_async(
1844 sc->zyd_ep[ZYD_ENDPT_IIN2]);
1845 }
1846 return;
1847 }
1848
1849 cmd = (const struct zyd_cmd *)sc->ibuf;
1850
1851 if (letoh16(cmd->code)((__uint16_t)(cmd->code)) == ZYD_NOTIF_RETRYSTATUS0xa001) {
1852 struct zyd_notif_retry *retry =
1853 (struct zyd_notif_retry *)cmd->data;
1854 struct ieee80211com *ic = &sc->sc_ic;
1855 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1856 struct ieee80211_node *ni;
1857
1858 DPRINTF(("retry intr: rate=0x%x addr=%s count=%d (0x%x)\n",
1859 letoh16(retry->rate), ether_sprintf(retry->macaddr),
1860 letoh16(retry->count) & 0xff, letoh16(retry->count)));
1861
1862 /*
1863 * Find the node to which the packet was sent and update its
1864 * retry statistics. In BSS mode, this node is the AP we're
1865 * associated to so no lookup is actually needed.
1866 */
1867 if (ic->ic_opmode != IEEE80211_M_STA) {
1868 ni = ieee80211_find_node(ic, retry->macaddr);
1869 if (ni == NULL((void *)0))
1870 return; /* just ignore */
1871 } else
1872 ni = ic->ic_bss;
1873
1874 ((struct zyd_node *)ni)->amn.amn_retrycnt++;
1875
1876 if (letoh16(retry->count)((__uint16_t)(retry->count)) & 0x100)
1877 ifp->if_oerrorsif_data.ifi_oerrors++; /* too many retries */
1878
1879 } else if (letoh16(cmd->code)((__uint16_t)(cmd->code)) == ZYD_NOTIF_IORD0x9001) {
1880 if (letoh16(*(uint16_t *)cmd->data)((__uint16_t)(*(uint16_t *)cmd->data)) == ZYD_CR_INTERRUPT0x9510)
1881 return; /* HMAC interrupt */
1882
1883 if (!sc->odone) {
1884 /* copy answer into sc->odata buffer */
1885 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
1886 bcopy(cmd->data, sc->odata, sc->olen);
1887 sc->odone = 1;
1888 wakeup(sc); /* wakeup zyd_cmd_read() */
1889 }
1890
1891 } else {
1892 printf("%s: unknown notification %x\n", sc->sc_dev.dv_xname,
1893 letoh16(cmd->code)((__uint16_t)(cmd->code)));
1894 }
1895}
1896
1897void
1898zyd_rx_data(struct zyd_softc *sc, const uint8_t *buf, uint16_t len,
1899 struct mbuf_list *ml)
1900{
1901 struct ieee80211com *ic = &sc->sc_ic;
1902 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1903 struct ieee80211_node *ni;
1904 struct ieee80211_frame *wh;
1905 struct ieee80211_rxinfo rxi;
1906 const struct zyd_plcphdr *plcp;
1907 const struct zyd_rx_stat *stat;
1908 struct mbuf *m;
1909 int s;
1910
1911 if (len < ZYD_MIN_FRAGSZ(sizeof (struct zyd_plcphdr) + (sizeof(struct ieee80211_frame_ack
) + 4) + sizeof (struct zyd_rx_stat))
) {
1912 DPRINTFN(2, ("frame too short (length=%d)\n", len));
1913 ifp->if_ierrorsif_data.ifi_ierrors++;
1914 return;
1915 }
1916
1917 plcp = (const struct zyd_plcphdr *)buf;
1918 stat = (const struct zyd_rx_stat *)(buf + len - sizeof (*stat));
1919
1920 if (stat->flags & ZYD_RX_ERROR(1 << 7)) {
1921 DPRINTF(("%s: RX status indicated error (%x)\n",
1922 sc->sc_dev.dv_xname, stat->flags));
1923 ifp->if_ierrorsif_data.ifi_ierrors++;
1924 return;
1925 }
1926
1927 /* compute actual frame length */
1928 len -= (sizeof (*plcp) + sizeof (*stat) + IEEE80211_CRC_LEN4);
1929
1930 if (len > MCLBYTES(1 << 11)) {
1931 DPRINTFN(2, ("frame too large (length=%d)\n", len));
1932 ifp->if_ierrorsif_data.ifi_ierrors++;
1933 return;
1934 }
1935
1936 /* allocate a mbuf to store the frame */
1937 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1938 if (m == NULL((void *)0)) {
1939 ifp->if_ierrorsif_data.ifi_ierrors++;
1940 return;
1941 }
1942 if (len > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1943 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1944 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
1945 ifp->if_ierrorsif_data.ifi_ierrors++;
1946 m_freem(m);
1947 return;
1948 }
1949 }
1950 bcopy(plcp + 1, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), len);
1951 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = len;
1952
1953#if NBPFILTER1 > 0
1954 if (sc->sc_drvbpf != NULL((void *)0)) {
1955 struct mbuf mb;
1956 struct zyd_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
1957 static const uint8_t rates[] = {
1958 /* reverse function of zyd_plcp_signal() */
1959 2, 4, 11, 22, 0, 0, 0, 0,
1960 96, 48, 24, 12, 108, 72, 36, 18
1961 };
1962
1963 tap->wr_flags = 0;
1964 tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1965 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1966 tap->wr_rssi = stat->rssi;
1967 tap->wr_rate = rates[plcp->signal & 0xf];
1968
1969 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1970 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
1971 mb.m_nextm_hdr.mh_next = m;
1972 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1973 mb.m_typem_hdr.mh_type = 0;
1974 mb.m_flagsm_hdr.mh_flags = 0;
1975 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
1976 }
1977#endif
1978
1979 s = splnet()splraise(0x7);
1980 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1981 ni = ieee80211_find_rxnode(ic, wh);
1982 rxi.rxi_flags = 0;
1983 rxi.rxi_rssi = stat->rssi;
1984 rxi.rxi_tstamp = 0; /* unused */
1985 ieee80211_inputm(ifp, m, ni, &rxi, ml);
1986
1987 /* node is no longer needed */
1988 ieee80211_release_node(ic, ni);
1989
1990 splx(s)spllower(s);
1991}
1992
1993void
1994zyd_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1995{
1996 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1997 struct zyd_rx_data *data = priv;
1998 struct zyd_softc *sc = data->sc;
1999 struct ieee80211com *ic = &sc->sc_ic;
2000 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2001 const struct zyd_rx_desc *desc;
2002 int len;
2003
2004 if (status != USBD_NORMAL_COMPLETION) {
2005 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
2006 return;
2007
2008 if (status == USBD_STALLED)
2009 usbd_clear_endpoint_stall(sc->zyd_ep[ZYD_ENDPT_BIN1]);
2010
2011 goto skip;
2012 }
2013 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
2014
2015 if (len < ZYD_MIN_RXBUFSZ(sizeof (struct zyd_plcphdr) + (sizeof(struct ieee80211_frame_ack
) + 4) + sizeof (struct zyd_rx_stat))
) {
2016 DPRINTFN(2, ("xfer too short (length=%d)\n", len));
2017 ifp->if_ierrorsif_data.ifi_ierrors++;
2018 goto skip;
2019 }
2020
2021 desc = (const struct zyd_rx_desc *)
2022 (data->buf + len - sizeof (struct zyd_rx_desc));
2023
2024 if (UGETW(desc->tag)(*(u_int16_t *)(desc->tag)) == ZYD_TAG_MULTIFRAME0x697e) {
2025 const uint8_t *p = data->buf, *end = p + len;
2026 int i;
2027
2028 DPRINTFN(3, ("received multi-frame transfer\n"));
2029
2030 for (i = 0; i < ZYD_MAX_RXFRAMECNT3; i++) {
2031 const uint16_t len = UGETW(desc->len[i])(*(u_int16_t *)(desc->len[i]));
2032
2033 if (len == 0 || p + len >= end)
2034 break;
2035
2036 zyd_rx_data(sc, p, len, &ml);
2037 /* next frame is aligned on a 32-bit boundary */
2038 p += (len + 3) & ~3;
2039 }
2040 } else {
2041 DPRINTFN(3, ("received single-frame transfer\n"));
2042
2043 zyd_rx_data(sc, data->buf, len, &ml);
2044 }
2045 if_input(ifp, &ml);
2046
2047skip: /* setup a new transfer */
2048 usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_BIN1], data, NULL((void *)0),
2049 ZYX_MAX_RXBUFSZ((sizeof (struct zyd_plcphdr) + (2300 + 4 + (3 + 1 + 4)) + sizeof
(struct zyd_rx_stat)) * 3 + sizeof (struct zyd_rx_desc))
, USBD_NO_COPY0x01 | USBD_SHORT_XFER_OK0x04,
2050 USBD_NO_TIMEOUT0, zyd_rxeof);
2051 (void)usbd_transfer(xfer);
2052}
2053
2054void
2055zyd_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
2056{
2057 struct zyd_tx_data *data = priv;
2058 struct zyd_softc *sc = data->sc;
2059 struct ieee80211com *ic = &sc->sc_ic;
2060 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2061 int s;
2062
2063 if (status != USBD_NORMAL_COMPLETION) {
2064 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
2065 return;
2066
2067 printf("%s: could not transmit buffer: %s\n",
2068 sc->sc_dev.dv_xname, usbd_errstr(status));
2069
2070 if (status == USBD_STALLED) {
2071 usbd_clear_endpoint_stall_async(
2072 sc->zyd_ep[ZYD_ENDPT_BOUT0]);
2073 }
2074 ifp->if_oerrorsif_data.ifi_oerrors++;
2075 return;
2076 }
2077
2078 s = splnet()splraise(0x7);
2079
2080 /* update rate control statistics */
2081 ((struct zyd_node *)data->ni)->amn.amn_txcnt++;
2082
2083 ieee80211_release_node(ic, data->ni);
2084 data->ni = NULL((void *)0);
2085
2086 sc->tx_queued--;
2087
2088 sc->tx_timer = 0;
2089 ifq_clr_oactive(&ifp->if_snd);
2090 zyd_start(ifp);
2091
2092 splx(s)spllower(s);
2093}
2094
2095int
2096zyd_tx(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
2097{
2098 struct ieee80211com *ic = &sc->sc_ic;
2099 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2100 struct zyd_tx_desc *desc;
2101 struct zyd_tx_data *data;
2102 struct ieee80211_frame *wh;
2103 struct ieee80211_key *k;
2104 int xferlen, totlen, rate;
2105 uint16_t pktlen;
2106 usbd_status error;
2107
2108 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2109
2110 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
2111 k = ieee80211_get_txkey(ic, wh, ni);
2112 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0))
2113 return ENOBUFS55;
2114 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2115 }
2116
2117 /* pickup a rate */
2118 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
2119 ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) ==
2120 IEEE80211_FC0_TYPE_MGT0x00)) {
2121 /* mgmt/multicast frames are sent at the lowest avail. rate */
2122 rate = ni->ni_rates.rs_rates[0];
2123 } else if (ic->ic_fixed_rate != -1) {
2124 rate = ic->ic_sup_rates[ic->ic_curmode].
2125 rs_rates[ic->ic_fixed_rate];
2126 } else
2127 rate = ni->ni_rates.rs_rates[ni->ni_txrate];
2128 rate &= IEEE80211_RATE_VAL0x7f;
2129 if (rate == 0) /* XXX should not happen */
2130 rate = 2;
2131
2132 data = &sc->tx_data[0];
2133 desc = (struct zyd_tx_desc *)data->buf;
2134
2135 data->ni = ni;
2136
2137 xferlen = sizeof (struct zyd_tx_desc) + m->m_pkthdrM_dat.MH.MH_pkthdr.len;
2138 totlen = m->m_pkthdrM_dat.MH.MH_pkthdr.len + IEEE80211_CRC_LEN4;
2139
2140 /* fill Tx descriptor */
2141 desc->len = htole16(totlen)((__uint16_t)(totlen));
2142
2143 desc->flags = ZYD_TX_FLAG_BACKOFF(1 << 0);
2144 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
2145 /* multicast frames are not sent at OFDM rates in 802.11b/g */
2146 if (totlen > ic->ic_rtsthreshold) {
2147 desc->flags |= ZYD_TX_FLAG_RTS(1 << 5);
2148 } else if (ZYD_RATE_IS_OFDM(rate)((rate) >= 12 && (rate) != 22) &&
2149 (ic->ic_flags & IEEE80211_F_USEPROT0x00100000)) {
2150 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
2151 desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF(1 << 7);
2152 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
2153 desc->flags |= ZYD_TX_FLAG_RTS(1 << 5);
2154 }
2155 } else
2156 desc->flags |= ZYD_TX_FLAG_MULTICAST(1 << 1);
2157
2158 if ((wh->i_fc[0] &
2159 (IEEE80211_FC0_TYPE_MASK0x0c | IEEE80211_FC0_SUBTYPE_MASK0xf0)) ==
2160 (IEEE80211_FC0_TYPE_CTL0x04 | IEEE80211_FC0_SUBTYPE_PS_POLL0xa0))
2161 desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL)(((1) & 0x3) << 2);
2162
2163 desc->phy = zyd_plcp_signal(rate);
2164 if (ZYD_RATE_IS_OFDM(rate)((rate) >= 12 && (rate) != 22)) {
2165 desc->phy |= ZYD_TX_PHY_OFDM(1 << 4);
2166 if (ic->ic_curmode == IEEE80211_MODE_11A)
2167 desc->phy |= ZYD_TX_PHY_5GHZ(1 << 5);
2168 } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000))
2169 desc->phy |= ZYD_TX_PHY_SHPREAMBLE(1 << 5);
2170
2171 /* actual transmit length (XXX why +10?) */
2172 pktlen = sizeof (struct zyd_tx_desc) + 10;
2173 if (sc->mac_rev == ZYD_ZD12110)
2174 pktlen += totlen;
2175 desc->pktlen = htole16(pktlen)((__uint16_t)(pktlen));
2176
2177 desc->plcp_length = htole16((16 * totlen + rate - 1) / rate)((__uint16_t)((16 * totlen + rate - 1) / rate));
2178 desc->plcp_service = 0;
2179 if (rate == 22) {
2180 const int remainder = (16 * totlen) % 22;
2181 if (remainder != 0 && remainder < 7)
2182 desc->plcp_service |= ZYD_PLCP_LENGEXT0x80;
2183 }
2184
2185#if NBPFILTER1 > 0
2186 if (sc->sc_drvbpf != NULL((void *)0)) {
2187 struct mbuf mb;
2188 struct zyd_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
2189
2190 tap->wt_flags = 0;
2191 tap->wt_rate = rate;
2192 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
2193 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
2194
2195 mb.m_datam_hdr.mh_data = (caddr_t)tap;
2196 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
2197 mb.m_nextm_hdr.mh_next = m;
2198 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
2199 mb.m_typem_hdr.mh_type = 0;
2200 mb.m_flagsm_hdr.mh_flags = 0;
2201 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
2202 }
2203#endif
2204
2205 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len,
2206 data->buf + sizeof (struct zyd_tx_desc));
2207
2208 DPRINTFN(10, ("%s: sending data frame len=%u rate=%u xferlen=%u\n",
2209 sc->sc_dev.dv_xname, m->m_pkthdr.len, rate, xferlen));
2210
2211 m_freem(m); /* mbuf no longer needed */
2212
2213 usbd_setup_xfer(data->xfer, sc->zyd_ep[ZYD_ENDPT_BOUT0], data,
2214 data->buf, xferlen, USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01,
2215 ZYD_TX_TIMEOUT10000, zyd_txeof);
2216 error = usbd_transfer(data->xfer);
2217 if (error != USBD_IN_PROGRESS && error != 0) {
2218 data->ni = NULL((void *)0);
2219 ifp->if_oerrorsif_data.ifi_oerrors++;
2220 return EIO5;
2221 }
2222 sc->tx_queued++;
2223
2224 return 0;
2225}
2226
2227void
2228zyd_start(struct ifnet *ifp)
2229{
2230 struct zyd_softc *sc = ifp->if_softc;
2231 struct ieee80211com *ic = &sc->sc_ic;
2232 struct ieee80211_node *ni;
2233 struct mbuf *m;
2234
2235 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
2236 return;
2237
2238 for (;;) {
2239 if (sc->tx_queued >= ZYD_TX_LIST_CNT1) {
2240 ifq_set_oactive(&ifp->if_snd);
2241 break;
2242 }
2243 /* send pending management frames first */
2244 m = mq_dequeue(&ic->ic_mgtq);
2245 if (m != NULL((void *)0)) {
2246 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
2247 goto sendit;
2248 }
2249 if (ic->ic_state != IEEE80211_S_RUN)
2250 break;
2251
2252 /* encapsulate and send data frames */
2253 m = ifq_dequeue(&ifp->if_snd);
2254 if (m == NULL((void *)0))
2255 break;
2256#if NBPFILTER1 > 0
2257 if (ifp->if_bpf != NULL((void *)0))
2258 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
2259#endif
2260 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
2261 continue;
2262sendit:
2263#if NBPFILTER1 > 0
2264 if (ic->ic_rawbpf != NULL((void *)0))
2265 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
2266#endif
2267 if (zyd_tx(sc, m, ni) != 0) {
2268 ieee80211_release_node(ic, ni);
2269 ifp->if_oerrorsif_data.ifi_oerrors++;
2270 continue;
2271 }
2272
2273 sc->tx_timer = 5;
2274 ifp->if_timer = 1;
2275 }
2276}
2277
2278void
2279zyd_watchdog(struct ifnet *ifp)
2280{
2281 struct zyd_softc *sc = ifp->if_softc;
2282
2283 ifp->if_timer = 0;
2284
2285 if (sc->tx_timer > 0) {
2286 if (--sc->tx_timer == 0) {
2287 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
2288 /* zyd_init(ifp); XXX needs a process context ? */
2289 ifp->if_oerrorsif_data.ifi_oerrors++;
2290 return;
2291 }
2292 ifp->if_timer = 1;
2293 }
2294
2295 ieee80211_watchdog(ifp);
2296}
2297
2298int
2299zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
2300{
2301 struct zyd_softc *sc = ifp->if_softc;
2302 struct ieee80211com *ic = &sc->sc_ic;
2303 struct ifreq *ifr;
2304 int s, error = 0;
2305
2306 s = splnet()splraise(0x7);
2307
2308 switch (cmd) {
2309 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
2310 ifp->if_flags |= IFF_UP0x1;
2311 /* FALLTHROUGH */
2312 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
2313 if (ifp->if_flags & IFF_UP0x1) {
2314 /*
2315 * If only the PROMISC or ALLMULTI flag changes, then
2316 * don't do a full re-init of the chip, just update
2317 * the Rx filter.
2318 */
2319 if ((ifp->if_flags & IFF_RUNNING0x40) &&
2320 ((ifp->if_flags ^ sc->sc_if_flags) &
2321 (IFF_ALLMULTI0x200 | IFF_PROMISC0x100)) != 0) {
2322 zyd_set_multi(sc);
2323 } else {
2324 if (!(ifp->if_flags & IFF_RUNNING0x40))
2325 zyd_init(ifp);
2326 }
2327 } else {
2328 if (ifp->if_flags & IFF_RUNNING0x40)
2329 zyd_stop(ifp, 1);
2330 }
2331 sc->sc_if_flags = ifp->if_flags;
2332 break;
2333
2334 case SIOCADDMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((49)))
:
2335 case SIOCDELMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((50)))
:
2336 ifr = (struct ifreq *)data;
2337 error = (cmd == SIOCADDMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((49)))
) ?
2338 ether_addmulti(ifr, &ic->ic_ac) :
2339 ether_delmulti(ifr, &ic->ic_ac);
2340 if (error == ENETRESET52) {
2341 if (ifp->if_flags & IFF_RUNNING0x40)
2342 zyd_set_multi(sc);
2343 error = 0;
2344 }
2345 break;
2346
2347 case SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq
) & 0x1fff) << 16) | ((('i')) << 8) | ((238))
)
:
2348 /*
2349 * This allows for fast channel switching in monitor mode
2350 * (used by kismet). In IBSS mode, we must explicitly reset
2351 * the interface to generate a new beacon frame.
2352 */
2353 error = ieee80211_ioctl(ifp, cmd, data);
2354 if (error == ENETRESET52 &&
2355 ic->ic_opmode == IEEE80211_M_MONITOR) {
2356 zyd_set_chan(sc, ic->ic_ibss_chan);
2357 error = 0;
2358 }
2359 break;
2360
2361 default:
2362 error = ieee80211_ioctl(ifp, cmd, data);
2363 }
2364
2365 if (error == ENETRESET52) {
2366 if ((ifp->if_flags & (IFF_RUNNING0x40 | IFF_UP0x1)) ==
2367 (IFF_RUNNING0x40 | IFF_UP0x1))
2368 zyd_init(ifp);
2369 error = 0;
2370 }
2371
2372 splx(s)spllower(s);
2373
2374 return error;
2375}
2376
2377int
2378zyd_init(struct ifnet *ifp)
2379{
2380 struct zyd_softc *sc = ifp->if_softc;
2381 struct ieee80211com *ic = &sc->sc_ic;
2382 int i, error;
2383
2384 zyd_stop(ifp, 0);
2385
2386 IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl))__builtin_memcpy((ic->ic_myaddr), (((caddr_t)((ifp->if_sadl
)->sdl_data + (ifp->if_sadl)->sdl_nlen))), (6))
;
2387 DPRINTF(("setting MAC address to %s\n", ether_sprintf(ic->ic_myaddr)));
2388 zyd_set_macaddr(sc, ic->ic_myaddr);
2389
2390 /* we'll do software WEP decryption for now */
2391 DPRINTF(("setting encryption type\n"));
2392 error = zyd_write32(sc, ZYD_MAC_ENCRYPTION_TYPE0x9678, ZYD_ENC_SNIFFER8);
2393 if (error != 0)
2394 return error;
2395
2396 /* promiscuous mode */
2397 (void)zyd_write32(sc, ZYD_MAC_SNIFFER0x9674,
2398 (ic->ic_opmode == IEEE80211_M_MONITOR) ? 1 : 0);
2399
2400 (void)zyd_set_rxfilter(sc);
2401
2402 /* switch radio transmitter ON */
2403 (void)zyd_switch_radio(sc, 1);
2404
2405 /* set basic rates */
2406 if (ic->ic_curmode == IEEE80211_MODE_11B)
2407 (void)zyd_write32(sc, ZYD_MAC_BAS_RATE0x9630, 0x0003);
2408 else if (ic->ic_curmode == IEEE80211_MODE_11A)
2409 (void)zyd_write32(sc, ZYD_MAC_BAS_RATE0x9630, 0x1500);
2410 else /* assumes 802.11b/g */
2411 (void)zyd_write32(sc, ZYD_MAC_BAS_RATE0x9630, 0x000f);
2412
2413 /* set mandatory rates */
2414 if (ic->ic_curmode == IEEE80211_MODE_11B)
2415 (void)zyd_write32(sc, ZYD_MAC_MAN_RATE0x9634, 0x000f);
2416 else if (ic->ic_curmode == IEEE80211_MODE_11A)
2417 (void)zyd_write32(sc, ZYD_MAC_MAN_RATE0x9634, 0x1500);
2418 else /* assumes 802.11b/g */
2419 (void)zyd_write32(sc, ZYD_MAC_MAN_RATE0x9634, 0x150f);
2420
2421 /* set default BSS channel */
2422 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2423 zyd_set_chan(sc, ic->ic_bss->ni_chan);
2424
2425 /* enable interrupts */
2426 (void)zyd_write32(sc, ZYD_CR_INTERRUPT0x9510, ZYD_HWINT_MASK0x004f0000);
2427
2428 /*
2429 * Allocate Tx and Rx xfer queues.
2430 */
2431 if ((error = zyd_alloc_tx_list(sc)) != 0) {
2432 printf("%s: could not allocate Tx list\n",
2433 sc->sc_dev.dv_xname);
2434 goto fail;
2435 }
2436 if ((error = zyd_alloc_rx_list(sc)) != 0) {
2437 printf("%s: could not allocate Rx list\n",
2438 sc->sc_dev.dv_xname);
2439 goto fail;
2440 }
2441
2442 /*
2443 * Start up the receive pipe.
2444 */
2445 for (i = 0; i < ZYD_RX_LIST_CNT1; i++) {
2446 struct zyd_rx_data *data = &sc->rx_data[i];
2447
2448 usbd_setup_xfer(data->xfer, sc->zyd_ep[ZYD_ENDPT_BIN1], data,
2449 NULL((void *)0), ZYX_MAX_RXBUFSZ((sizeof (struct zyd_plcphdr) + (2300 + 4 + (3 + 1 + 4)) + sizeof
(struct zyd_rx_stat)) * 3 + sizeof (struct zyd_rx_desc))
, USBD_NO_COPY0x01 | USBD_SHORT_XFER_OK0x04,
2450 USBD_NO_TIMEOUT0, zyd_rxeof);
2451 error = usbd_transfer(data->xfer);
2452 if (error != USBD_IN_PROGRESS && error != 0) {
2453 printf("%s: could not queue Rx transfer\n",
2454 sc->sc_dev.dv_xname);
2455 goto fail;
2456 }
2457 }
2458
2459 ifq_clr_oactive(&ifp->if_snd);
2460 ifp->if_flags |= IFF_RUNNING0x40;
2461
2462 if (ic->ic_opmode == IEEE80211_M_MONITOR)
2463 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
2464 else
2465 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
2466
2467 return 0;
2468
2469fail: zyd_stop(ifp, 1);
2470 return error;
2471}
2472
2473void
2474zyd_stop(struct ifnet *ifp, int disable)
2475{
2476 struct zyd_softc *sc = ifp->if_softc;
2477 struct ieee80211com *ic = &sc->sc_ic;
2478
2479 sc->tx_timer = 0;
2480 ifp->if_timer = 0;
2481 ifp->if_flags &= ~IFF_RUNNING0x40;
2482 ifq_clr_oactive(&ifp->if_snd);
2483
2484 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1))); /* free all nodes */
2485
2486 /* switch radio transmitter OFF */
2487 (void)zyd_switch_radio(sc, 0);
2488
2489 /* disable Rx */
2490 (void)zyd_write32(sc, ZYD_MAC_RXFILTER0x968c, 0);
2491
2492 /* disable interrupts */
2493 (void)zyd_write32(sc, ZYD_CR_INTERRUPT0x9510, 0);
2494
2495 usbd_abort_pipe(sc->zyd_ep[ZYD_ENDPT_BIN1]);
2496 usbd_abort_pipe(sc->zyd_ep[ZYD_ENDPT_BOUT0]);
2497
2498 zyd_free_rx_list(sc);
2499 zyd_free_tx_list(sc);
2500}
2501
2502int
2503zyd_loadfirmware(struct zyd_softc *sc, u_char *fw, size_t size)
2504{
2505 usb_device_request_t req;
2506 uint16_t addr;
2507 uint8_t stat;
2508
2509 DPRINTF(("firmware size=%zd\n", size));
2510
2511 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
2512 req.bRequest = ZYD_DOWNLOADREQ0x30;
2513 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
2514
2515 addr = ZYD_FIRMWARE_START_ADDR0xee00;
2516 while (size > 0) {
2517 const int mlen = min(size, 4096);
2518
2519 DPRINTF(("loading firmware block: len=%d, addr=0x%x\n", mlen,
2520 addr));
2521
2522 USETW(req.wValue, addr)(*(u_int16_t *)(req.wValue) = (addr));
2523 USETW(req.wLength, mlen)(*(u_int16_t *)(req.wLength) = (mlen));
2524 if (usbd_do_request(sc->sc_udev, &req, fw) != 0)
2525 return EIO5;
2526
2527 addr += mlen / 2;
2528 fw += mlen;
2529 size -= mlen;
2530 }
2531
2532 /* check whether the upload succeeded */
2533 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
2534 req.bRequest = ZYD_DOWNLOADSTS0x31;
2535 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
2536 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
2537 USETW(req.wLength, sizeof stat)(*(u_int16_t *)(req.wLength) = (sizeof stat));
2538 if (usbd_do_request(sc->sc_udev, &req, &stat) != 0)
2539 return EIO5;
2540
2541 return (stat & 0x80) ? EIO5 : 0;
2542}
2543
2544void
2545zyd_iter_func(void *arg, struct ieee80211_node *ni)
2546{
2547 struct zyd_softc *sc = arg;
2548 struct zyd_node *zn = (struct zyd_node *)ni;
2549
2550 ieee80211_amrr_choose(&sc->amrr, ni, &zn->amn);
2551}
2552
2553void
2554zyd_amrr_timeout(void *arg)
2555{
2556 struct zyd_softc *sc = arg;
2557 struct ieee80211com *ic = &sc->sc_ic;
2558 int s;
2559
2560 s = splnet()splraise(0x7);
2561 if (ic->ic_opmode == IEEE80211_M_STA)
2562 zyd_iter_func(sc, ic->ic_bss);
2563 else
2564 ieee80211_iterate_nodes(ic, zyd_iter_func, sc);
2565 splx(s)spllower(s);
2566
2567 timeout_add_sec(&sc->amrr_to, 1);
2568}
2569
2570void
2571zyd_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
2572{
2573 struct zyd_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
2574 int i;
2575
2576 ieee80211_amrr_node_init(&sc->amrr, &((struct zyd_node *)ni)->amn);
2577
2578 /* set rate to some reasonable initial value */
2579 for (i = ni->ni_rates.rs_nrates - 1;
2580 i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL0x7f) > 72;
2581 i--);
2582 ni->ni_txrate = i;
2583}