diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/Kconfig | 25 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/Makefile | 37 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/bmi.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/debug.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/hif.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/htc.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/usb.c | 431 |
8 files changed, 20 insertions, 501 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index d755a5e7ed20..3d5f8be20eac 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig | |||
@@ -1,29 +1,12 @@ | |||
1 | config ATH6KL | 1 | config ATH6KL |
2 | tristate "Atheros mobile chipsets support" | 2 | tristate "Atheros ath6kl support" |
3 | |||
4 | config ATH6KL_SDIO | ||
5 | tristate "Atheros ath6kl SDIO support" | ||
6 | depends on ATH6KL | ||
7 | depends on MMC | 3 | depends on MMC |
8 | depends on CFG80211 | 4 | depends on CFG80211 |
9 | ---help--- | 5 | ---help--- |
10 | This module adds support for wireless adapters based on | 6 | This module adds support for wireless adapters based on |
11 | Atheros AR6003 and AR6004 chipsets running over SDIO. If you | 7 | Atheros AR6003 chipset running over SDIO. If you choose to |
12 | choose to build it as a module, it will be called ath6kl_sdio. | 8 | build it as a module, it will be called ath6kl. Pls note |
13 | Please note that AR6002 and AR6001 are not supported by this | 9 | that AR6002 and AR6001 are not supported by this driver. |
14 | driver. | ||
15 | |||
16 | config ATH6KL_USB | ||
17 | tristate "Atheros ath6kl USB support" | ||
18 | depends on ATH6KL | ||
19 | depends on USB | ||
20 | depends on CFG80211 | ||
21 | depends on EXPERIMENTAL | ||
22 | ---help--- | ||
23 | This module adds support for wireless adapters based on | ||
24 | Atheros AR6004 chipset running over USB. This is still under | ||
25 | implementation and it isn't functional. If you choose to | ||
26 | build it as a module, it will be called ath6kl_usb. | ||
27 | 10 | ||
28 | config ATH6KL_DEBUG | 11 | config ATH6KL_DEBUG |
29 | bool "Atheros ath6kl debugging" | 12 | bool "Atheros ath6kl debugging" |
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index e14cef9c3c0e..707069303550 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile | |||
@@ -21,30 +21,17 @@ | |||
21 | # Author(s): ="Atheros" | 21 | # Author(s): ="Atheros" |
22 | #------------------------------------------------------------------------------ | 22 | #------------------------------------------------------------------------------ |
23 | 23 | ||
24 | obj-$(CONFIG_ATH6KL_SDIO) := ath6kl_sdio.o | 24 | obj-$(CONFIG_ATH6KL) := ath6kl.o |
25 | ath6kl_sdio-y += debug.o | 25 | ath6kl-y += debug.o |
26 | ath6kl_sdio-y += hif.o | 26 | ath6kl-y += hif.o |
27 | ath6kl_sdio-y += htc.o | 27 | ath6kl-y += htc.o |
28 | ath6kl_sdio-y += bmi.o | 28 | ath6kl-y += bmi.o |
29 | ath6kl_sdio-y += cfg80211.o | 29 | ath6kl-y += cfg80211.o |
30 | ath6kl_sdio-y += init.o | 30 | ath6kl-y += init.o |
31 | ath6kl_sdio-y += main.o | 31 | ath6kl-y += main.o |
32 | ath6kl_sdio-y += txrx.o | 32 | ath6kl-y += txrx.o |
33 | ath6kl_sdio-y += wmi.o | 33 | ath6kl-y += wmi.o |
34 | ath6kl_sdio-y += sdio.o | 34 | ath6kl-y += sdio.o |
35 | ath6kl_sdio-$(CONFIG_NL80211_TESTMODE) += testmode.o | 35 | ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o |
36 | |||
37 | obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o | ||
38 | ath6kl_usb-y += debug.o | ||
39 | ath6kl_usb-y += hif.o | ||
40 | ath6kl_usb-y += htc.o | ||
41 | ath6kl_usb-y += bmi.o | ||
42 | ath6kl_usb-y += cfg80211.o | ||
43 | ath6kl_usb-y += init.o | ||
44 | ath6kl_usb-y += main.o | ||
45 | ath6kl_usb-y += txrx.o | ||
46 | ath6kl_usb-y += wmi.o | ||
47 | ath6kl_usb-y += usb.o | ||
48 | ath6kl_usb-$(CONFIG_NL80211_TESTMODE) += testmode.o | ||
49 | 36 | ||
50 | ccflags-y += -D__CHECK_ENDIAN__ | 37 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c index aef00d5a1438..bce3575c310a 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.c +++ b/drivers/net/wireless/ath/ath6kl/bmi.c | |||
@@ -57,14 +57,8 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, | |||
57 | return ret; | 57 | return ret; |
58 | } | 58 | } |
59 | 59 | ||
60 | if (ar->hif_type == ATH6KL_HIF_TYPE_USB) { | 60 | ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, |
61 | ret = ath6kl_hif_bmi_read(ar, (u8 *)targ_info, | 61 | sizeof(targ_info->version)); |
62 | sizeof(*targ_info)); | ||
63 | } else { | ||
64 | ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, | ||
65 | sizeof(targ_info->version)); | ||
66 | } | ||
67 | |||
68 | if (ret) { | 62 | if (ret) { |
69 | ath6kl_err("Unable to recv target info: %d\n", ret); | 63 | ath6kl_err("Unable to recv target info: %d\n", ret); |
70 | return ret; | 64 | return ret; |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index e569c652e35c..9853c9c125c1 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -41,7 +41,6 @@ enum ATH6K_DEBUG_MASK { | |||
41 | ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ | 41 | ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ |
42 | ATH6KL_DBG_WMI_DUMP = BIT(19), | 42 | ATH6KL_DBG_WMI_DUMP = BIT(19), |
43 | ATH6KL_DBG_SUSPEND = BIT(20), | 43 | ATH6KL_DBG_SUSPEND = BIT(20), |
44 | ATH6KL_DBG_USB = BIT(21), | ||
45 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ | 44 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ |
46 | }; | 45 | }; |
47 | 46 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index 0772ef650174..e57da35e59fa 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c | |||
@@ -689,11 +689,6 @@ int ath6kl_hif_setup(struct ath6kl_device *dev) | |||
689 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", | 689 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", |
690 | dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); | 690 | dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); |
691 | 691 | ||
692 | /* usb doesn't support enabling interrupts */ | ||
693 | /* FIXME: remove check once USB support is implemented */ | ||
694 | if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) | ||
695 | return 0; | ||
696 | |||
697 | status = ath6kl_hif_disable_intrs(dev); | 692 | status = ath6kl_hif_disable_intrs(dev); |
698 | 693 | ||
699 | fail_setup: | 694 | fail_setup: |
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index b01702258faf..f3b63ca25c7e 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c | |||
@@ -2543,12 +2543,6 @@ int ath6kl_htc_wait_target(struct htc_target *target) | |||
2543 | struct htc_service_connect_resp resp; | 2543 | struct htc_service_connect_resp resp; |
2544 | int status; | 2544 | int status; |
2545 | 2545 | ||
2546 | /* FIXME: remove once USB support is implemented */ | ||
2547 | if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) { | ||
2548 | ath6kl_err("HTC doesn't support USB yet. Patience!\n"); | ||
2549 | return -EOPNOTSUPP; | ||
2550 | } | ||
2551 | |||
2552 | /* we should be getting 1 control message that the target is ready */ | 2546 | /* we should be getting 1 control message that the target is ready */ |
2553 | packet = htc_wait_for_ctrl_msg(target); | 2547 | packet = htc_wait_for_ctrl_msg(target); |
2554 | 2548 | ||
@@ -2778,9 +2772,7 @@ void ath6kl_htc_cleanup(struct htc_target *target) | |||
2778 | { | 2772 | { |
2779 | struct htc_packet *packet, *tmp_packet; | 2773 | struct htc_packet *packet, *tmp_packet; |
2780 | 2774 | ||
2781 | /* FIXME: remove check once USB support is implemented */ | 2775 | ath6kl_hif_cleanup_scatter(target->dev->ar); |
2782 | if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB) | ||
2783 | ath6kl_hif_cleanup_scatter(target->dev->ar); | ||
2784 | 2776 | ||
2785 | list_for_each_entry_safe(packet, tmp_packet, | 2777 | list_for_each_entry_safe(packet, tmp_packet, |
2786 | &target->free_ctrl_txbuf, list) { | 2778 | &target->free_ctrl_txbuf, list) { |
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 15c3f56caf4f..9475e2d0d0b7 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -1332,7 +1332,7 @@ static const struct sdio_device_id ath6kl_sdio_devices[] = { | |||
1332 | MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); | 1332 | MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); |
1333 | 1333 | ||
1334 | static struct sdio_driver ath6kl_sdio_driver = { | 1334 | static struct sdio_driver ath6kl_sdio_driver = { |
1335 | .name = "ath6kl_sdio", | 1335 | .name = "ath6kl", |
1336 | .id_table = ath6kl_sdio_devices, | 1336 | .id_table = ath6kl_sdio_devices, |
1337 | .probe = ath6kl_sdio_probe, | 1337 | .probe = ath6kl_sdio_probe, |
1338 | .remove = ath6kl_sdio_remove, | 1338 | .remove = ath6kl_sdio_remove, |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c deleted file mode 100644 index e3cf397fcafe..000000000000 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ /dev/null | |||
@@ -1,431 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | |||
20 | #include "debug.h" | ||
21 | #include "core.h" | ||
22 | |||
23 | /* usb device object */ | ||
24 | struct ath6kl_usb { | ||
25 | struct usb_device *udev; | ||
26 | struct usb_interface *interface; | ||
27 | u8 *diag_cmd_buffer; | ||
28 | u8 *diag_resp_buffer; | ||
29 | struct ath6kl *ar; | ||
30 | }; | ||
31 | |||
32 | /* diagnostic command defnitions */ | ||
33 | #define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1 | ||
34 | #define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2 | ||
35 | #define ATH6KL_USB_CONTROL_REQ_DIAG_CMD 3 | ||
36 | #define ATH6KL_USB_CONTROL_REQ_DIAG_RESP 4 | ||
37 | |||
38 | #define ATH6KL_USB_CTRL_DIAG_CC_READ 0 | ||
39 | #define ATH6KL_USB_CTRL_DIAG_CC_WRITE 1 | ||
40 | |||
41 | struct ath6kl_usb_ctrl_diag_cmd_write { | ||
42 | __le32 cmd; | ||
43 | __le32 address; | ||
44 | __le32 value; | ||
45 | __le32 _pad[1]; | ||
46 | } __packed; | ||
47 | |||
48 | struct ath6kl_usb_ctrl_diag_cmd_read { | ||
49 | __le32 cmd; | ||
50 | __le32 address; | ||
51 | } __packed; | ||
52 | |||
53 | struct ath6kl_usb_ctrl_diag_resp_read { | ||
54 | __le32 value; | ||
55 | } __packed; | ||
56 | |||
57 | #define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)) | ||
58 | #define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read)) | ||
59 | |||
60 | static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb) | ||
61 | { | ||
62 | usb_set_intfdata(ar_usb->interface, NULL); | ||
63 | |||
64 | kfree(ar_usb->diag_cmd_buffer); | ||
65 | kfree(ar_usb->diag_resp_buffer); | ||
66 | |||
67 | kfree(ar_usb); | ||
68 | } | ||
69 | |||
70 | static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface) | ||
71 | { | ||
72 | struct ath6kl_usb *ar_usb = NULL; | ||
73 | struct usb_device *dev = interface_to_usbdev(interface); | ||
74 | int status = 0; | ||
75 | |||
76 | ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL); | ||
77 | if (ar_usb == NULL) | ||
78 | goto fail_ath6kl_usb_create; | ||
79 | |||
80 | memset(ar_usb, 0, sizeof(struct ath6kl_usb)); | ||
81 | usb_set_intfdata(interface, ar_usb); | ||
82 | ar_usb->udev = dev; | ||
83 | ar_usb->interface = interface; | ||
84 | |||
85 | ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL); | ||
86 | if (ar_usb->diag_cmd_buffer == NULL) { | ||
87 | status = -ENOMEM; | ||
88 | goto fail_ath6kl_usb_create; | ||
89 | } | ||
90 | |||
91 | ar_usb->diag_resp_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_RESP, | ||
92 | GFP_KERNEL); | ||
93 | if (ar_usb->diag_resp_buffer == NULL) { | ||
94 | status = -ENOMEM; | ||
95 | goto fail_ath6kl_usb_create; | ||
96 | } | ||
97 | |||
98 | fail_ath6kl_usb_create: | ||
99 | if (status != 0) { | ||
100 | ath6kl_usb_destroy(ar_usb); | ||
101 | ar_usb = NULL; | ||
102 | } | ||
103 | return ar_usb; | ||
104 | } | ||
105 | |||
106 | static void ath6kl_usb_device_detached(struct usb_interface *interface) | ||
107 | { | ||
108 | struct ath6kl_usb *ar_usb; | ||
109 | |||
110 | ar_usb = usb_get_intfdata(interface); | ||
111 | if (ar_usb == NULL) | ||
112 | return; | ||
113 | |||
114 | ath6kl_stop_txrx(ar_usb->ar); | ||
115 | |||
116 | ath6kl_core_cleanup(ar_usb->ar); | ||
117 | |||
118 | ath6kl_usb_destroy(ar_usb); | ||
119 | } | ||
120 | |||
121 | static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, | ||
122 | u8 req, u16 value, u16 index, void *data, | ||
123 | u32 size) | ||
124 | { | ||
125 | u8 *buf = NULL; | ||
126 | int ret; | ||
127 | |||
128 | if (size > 0) { | ||
129 | buf = kmalloc(size, GFP_KERNEL); | ||
130 | if (buf == NULL) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | memcpy(buf, data, size); | ||
134 | } | ||
135 | |||
136 | /* note: if successful returns number of bytes transfered */ | ||
137 | ret = usb_control_msg(ar_usb->udev, | ||
138 | usb_sndctrlpipe(ar_usb->udev, 0), | ||
139 | req, | ||
140 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
141 | USB_RECIP_DEVICE, value, index, buf, | ||
142 | size, 1000); | ||
143 | |||
144 | if (ret < 0) { | ||
145 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | ||
146 | __func__, ret); | ||
147 | } | ||
148 | |||
149 | kfree(buf); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, | ||
155 | u8 req, u16 value, u16 index, void *data, | ||
156 | u32 size) | ||
157 | { | ||
158 | u8 *buf = NULL; | ||
159 | int ret; | ||
160 | |||
161 | if (size > 0) { | ||
162 | buf = kmalloc(size, GFP_KERNEL); | ||
163 | if (buf == NULL) | ||
164 | return -ENOMEM; | ||
165 | } | ||
166 | |||
167 | /* note: if successful returns number of bytes transfered */ | ||
168 | ret = usb_control_msg(ar_usb->udev, | ||
169 | usb_rcvctrlpipe(ar_usb->udev, 0), | ||
170 | req, | ||
171 | USB_DIR_IN | USB_TYPE_VENDOR | | ||
172 | USB_RECIP_DEVICE, value, index, buf, | ||
173 | size, 2 * HZ); | ||
174 | |||
175 | if (ret < 0) { | ||
176 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | ||
177 | __func__, ret); | ||
178 | } | ||
179 | |||
180 | memcpy((u8 *) data, buf, size); | ||
181 | |||
182 | kfree(buf); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int ath6kl_usb_ctrl_msg_exchange(struct ath6kl_usb *ar_usb, | ||
188 | u8 req_val, u8 *req_buf, u32 req_len, | ||
189 | u8 resp_val, u8 *resp_buf, u32 *resp_len) | ||
190 | { | ||
191 | int ret; | ||
192 | |||
193 | /* send command */ | ||
194 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, req_val, 0, 0, | ||
195 | req_buf, req_len); | ||
196 | |||
197 | if (ret != 0) | ||
198 | return ret; | ||
199 | |||
200 | if (resp_buf == NULL) { | ||
201 | /* no expected response */ | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | /* get response */ | ||
206 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, resp_val, 0, 0, | ||
207 | resp_buf, *resp_len); | ||
208 | |||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data) | ||
213 | { | ||
214 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
215 | struct ath6kl_usb_ctrl_diag_resp_read *resp; | ||
216 | struct ath6kl_usb_ctrl_diag_cmd_read *cmd; | ||
217 | u32 resp_len; | ||
218 | int ret; | ||
219 | |||
220 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_read *) ar_usb->diag_cmd_buffer; | ||
221 | |||
222 | memset(cmd, 0, sizeof(*cmd)); | ||
223 | cmd->cmd = ATH6KL_USB_CTRL_DIAG_CC_READ; | ||
224 | cmd->address = cpu_to_le32(address); | ||
225 | resp_len = sizeof(*resp); | ||
226 | |||
227 | ret = ath6kl_usb_ctrl_msg_exchange(ar_usb, | ||
228 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, | ||
229 | (u8 *) cmd, | ||
230 | sizeof(struct ath6kl_usb_ctrl_diag_cmd_write), | ||
231 | ATH6KL_USB_CONTROL_REQ_DIAG_RESP, | ||
232 | ar_usb->diag_resp_buffer, &resp_len); | ||
233 | |||
234 | if (ret) | ||
235 | return ret; | ||
236 | |||
237 | resp = (struct ath6kl_usb_ctrl_diag_resp_read *) | ||
238 | ar_usb->diag_resp_buffer; | ||
239 | |||
240 | *data = le32_to_cpu(resp->value); | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) | ||
246 | { | ||
247 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
248 | struct ath6kl_usb_ctrl_diag_cmd_write *cmd; | ||
249 | |||
250 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; | ||
251 | |||
252 | memset(cmd, 0, sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)); | ||
253 | cmd->cmd = cpu_to_le32(ATH6KL_USB_CTRL_DIAG_CC_WRITE); | ||
254 | cmd->address = cpu_to_le32(address); | ||
255 | cmd->value = data; | ||
256 | |||
257 | return ath6kl_usb_ctrl_msg_exchange(ar_usb, | ||
258 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, | ||
259 | (u8 *) cmd, | ||
260 | sizeof(*cmd), | ||
261 | 0, NULL, NULL); | ||
262 | |||
263 | } | ||
264 | |||
265 | static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | ||
266 | { | ||
267 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
268 | int ret; | ||
269 | |||
270 | /* get response */ | ||
271 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, | ||
272 | ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, | ||
273 | 0, 0, buf, len); | ||
274 | if (ret != 0) { | ||
275 | ath6kl_err("Unable to read the bmi data from the device: %d\n", | ||
276 | ret); | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | ||
284 | { | ||
285 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
286 | int ret; | ||
287 | |||
288 | /* send command */ | ||
289 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, | ||
290 | ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, | ||
291 | 0, 0, buf, len); | ||
292 | if (ret != 0) { | ||
293 | ath6kl_err("unable to send the bmi data to the device: %d\n", | ||
294 | ret); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int ath6kl_usb_power_on(struct ath6kl *ar) | ||
302 | { | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int ath6kl_usb_power_off(struct ath6kl *ar) | ||
307 | { | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { | ||
312 | .diag_read32 = ath6kl_usb_diag_read32, | ||
313 | .diag_write32 = ath6kl_usb_diag_write32, | ||
314 | .bmi_read = ath6kl_usb_bmi_read, | ||
315 | .bmi_write = ath6kl_usb_bmi_write, | ||
316 | .power_on = ath6kl_usb_power_on, | ||
317 | .power_off = ath6kl_usb_power_off, | ||
318 | }; | ||
319 | |||
320 | /* ath6kl usb driver registered functions */ | ||
321 | static int ath6kl_usb_probe(struct usb_interface *interface, | ||
322 | const struct usb_device_id *id) | ||
323 | { | ||
324 | struct usb_device *dev = interface_to_usbdev(interface); | ||
325 | struct ath6kl *ar; | ||
326 | struct ath6kl_usb *ar_usb = NULL; | ||
327 | int vendor_id, product_id; | ||
328 | int ret = 0; | ||
329 | |||
330 | usb_get_dev(dev); | ||
331 | |||
332 | vendor_id = le16_to_cpu(dev->descriptor.idVendor); | ||
333 | product_id = le16_to_cpu(dev->descriptor.idProduct); | ||
334 | |||
335 | ath6kl_dbg(ATH6KL_DBG_USB, "vendor_id = %04x\n", vendor_id); | ||
336 | ath6kl_dbg(ATH6KL_DBG_USB, "product_id = %04x\n", product_id); | ||
337 | |||
338 | if (interface->cur_altsetting) | ||
339 | ath6kl_dbg(ATH6KL_DBG_USB, "USB Interface %d\n", | ||
340 | interface->cur_altsetting->desc.bInterfaceNumber); | ||
341 | |||
342 | |||
343 | if (dev->speed == USB_SPEED_HIGH) | ||
344 | ath6kl_dbg(ATH6KL_DBG_USB, "USB 2.0 Host\n"); | ||
345 | else | ||
346 | ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n"); | ||
347 | |||
348 | ar_usb = ath6kl_usb_create(interface); | ||
349 | |||
350 | if (ar_usb == NULL) { | ||
351 | ret = -ENOMEM; | ||
352 | goto err_usb_put; | ||
353 | } | ||
354 | |||
355 | ar = ath6kl_core_alloc(&ar_usb->udev->dev); | ||
356 | if (ar == NULL) { | ||
357 | ath6kl_err("Failed to alloc ath6kl core\n"); | ||
358 | ret = -ENOMEM; | ||
359 | goto err_usb_destroy; | ||
360 | } | ||
361 | |||
362 | ar->hif_priv = ar_usb; | ||
363 | ar->hif_type = ATH6KL_HIF_TYPE_USB; | ||
364 | ar->hif_ops = &ath6kl_usb_ops; | ||
365 | ar->mbox_info.block_size = 16; | ||
366 | ar->bmi.max_data_size = 252; | ||
367 | |||
368 | ar_usb->ar = ar; | ||
369 | |||
370 | ret = ath6kl_core_init(ar); | ||
371 | if (ret) { | ||
372 | ath6kl_err("Failed to init ath6kl core: %d\n", ret); | ||
373 | goto err_core_free; | ||
374 | } | ||
375 | |||
376 | return ret; | ||
377 | |||
378 | err_core_free: | ||
379 | ath6kl_core_free(ar); | ||
380 | err_usb_destroy: | ||
381 | ath6kl_usb_destroy(ar_usb); | ||
382 | err_usb_put: | ||
383 | usb_put_dev(dev); | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | static void ath6kl_usb_remove(struct usb_interface *interface) | ||
389 | { | ||
390 | usb_put_dev(interface_to_usbdev(interface)); | ||
391 | ath6kl_usb_device_detached(interface); | ||
392 | } | ||
393 | |||
394 | /* table of devices that work with this driver */ | ||
395 | static struct usb_device_id ath6kl_usb_ids[] = { | ||
396 | {USB_DEVICE(0x0cf3, 0x9374)}, | ||
397 | { /* Terminating entry */ }, | ||
398 | }; | ||
399 | |||
400 | MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids); | ||
401 | |||
402 | static struct usb_driver ath6kl_usb_driver = { | ||
403 | .name = "ath6kl_usb", | ||
404 | .probe = ath6kl_usb_probe, | ||
405 | .disconnect = ath6kl_usb_remove, | ||
406 | .id_table = ath6kl_usb_ids, | ||
407 | }; | ||
408 | |||
409 | static int ath6kl_usb_init(void) | ||
410 | { | ||
411 | usb_register(&ath6kl_usb_driver); | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static void ath6kl_usb_exit(void) | ||
416 | { | ||
417 | usb_deregister(&ath6kl_usb_driver); | ||
418 | } | ||
419 | |||
420 | module_init(ath6kl_usb_init); | ||
421 | module_exit(ath6kl_usb_exit); | ||
422 | |||
423 | MODULE_AUTHOR("Atheros Communications, Inc."); | ||
424 | MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices"); | ||
425 | MODULE_LICENSE("Dual BSD/GPL"); | ||
426 | MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); | ||
427 | MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); | ||
428 | MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | ||
429 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); | ||
430 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | ||
431 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | ||