hc
2024-05-10 61598093bbdd283a7edc367d900f223070ead8d2
add ax88772C AX88772C_eeprom_tools
16 files added
2 files modified
14327 ■■■■■ changed files
kernel/arch/arm64/configs/rockchip_linux_defconfig 8 ●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/Makefile 1 ●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/asix.c 4528 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/asix.h 575 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/axusbnet.c 1488 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/axusbnet.h 212 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/command.h 67 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/ioctl.c 481 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/ioctl.h 75 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/ioctl_readme 61 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/AX88772C_eeprom/readme 92 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/Makefile 2 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/ax88772C/Makefile 1 ●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/ax88772C/asix.c 4369 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/ax88772C/asix.h 575 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/ax88772C/axusbnet.c 1488 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/ax88772C/axusbnet.h 212 ●●●●● patch | view | raw | blame | history
kernel/drivers/net/usb/ax88772C/readme 92 ●●●●● patch | view | raw | blame | history
kernel/arch/arm64/configs/rockchip_linux_defconfig
....@@ -2076,11 +2076,11 @@
20762076 CONFIG_USB_RTL8152=y
20772077 # CONFIG_USB_LAN78XX is not set
20782078 CONFIG_USB_USBNET=y
2079
-CONFIG_USB_NET_AX8817X=y
2080
-CONFIG_USB_NET_AX88179_178A=y
2079
+# CONFIG_USB_NET_AX8817X is not set
2080
+# CONFIG_USB_NET_AX88179_178A is not set
20812081 CONFIG_USB_NET_CDCETHER=y
20822082 # CONFIG_USB_NET_CDC_EEM is not set
2083
-CONFIG_USB_NET_CDC_NCM=y
2083
+# CONFIG_USB_NET_CDC_NCM is not set
20842084 # CONFIG_USB_NET_HUAWEI_CDC_NCM is not set
20852085 # CONFIG_USB_NET_CDC_MBIM is not set
20862086 # CONFIG_USB_NET_DM9601 is not set
....@@ -2089,7 +2089,7 @@
20892089 # CONFIG_USB_NET_SMSC75XX is not set
20902090 # CONFIG_USB_NET_SMSC95XX is not set
20912091 # CONFIG_USB_NET_GL620A is not set
2092
-CONFIG_USB_NET_NET1080=y
2092
+# CONFIG_USB_NET_NET1080 is not set
20932093 # CONFIG_USB_NET_PLUSB is not set
20942094 # CONFIG_USB_NET_MCS7830 is not set
20952095 # CONFIG_USB_NET_RNDIS_HOST is not set
kernel/drivers/net/usb/AX88772C_eeprom/Makefile
....@@ -0,0 +1 @@
1
+obj-m += asix.o
kernel/drivers/net/usb/AX88772C_eeprom/asix.c
....@@ -0,0 +1,4528 @@
1
+/*
2
+ * ASIX AX8817X based USB 2.0 Ethernet Devices
3
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
4
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
5
+ * Copyright (c) 2002-2003 TiVo Inc.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+/* debug messages, extra info */
23
+/* #define DEBUG */
24
+
25
+#include <linux/version.h>
26
+/* #include <linux/config.h> */
27
+#ifdef CONFIG_USB_DEBUG
28
+# define DEBUG
29
+#endif
30
+#include <linux/module.h>
31
+#include <linux/kmod.h>
32
+#include <linux/sched.h>
33
+#include <linux/init.h>
34
+#include <linux/netdevice.h>
35
+#include <linux/etherdevice.h>
36
+#include <linux/ethtool.h>
37
+#include <linux/workqueue.h>
38
+#include <linux/mii.h>
39
+#include <linux/usb.h>
40
+#include <linux/crc32.h>
41
+
42
+#include "axusbnet.c"
43
+#include "asix.h"
44
+#include "command.h"
45
+
46
+#define DRV_VERSION "4.24.100"
47
+
48
+static char version[] =
49
+KERN_INFO "ASIX USB Ethernet Adapter:v" DRV_VERSION
50
+ " http://www.asix.com.tw\n";
51
+
52
+/* configuration of maximum bulk in size */
53
+static int bsize = AX88772B_MAX_BULKIN_16K;
54
+module_param(bsize, int, 0);
55
+MODULE_PARM_DESC(bsize, "Maximum transfer size per bulk");
56
+
57
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
58
+static void ax88772b_link_reset(void *data);
59
+static void ax88772a_link_reset(void *data);
60
+static void ax88772_link_reset(void *data);
61
+#else
62
+static void ax88772b_link_reset(struct work_struct *work);
63
+static void ax88772a_link_reset(struct work_struct *work);
64
+static void ax88772_link_reset(struct work_struct *work);
65
+#endif
66
+static int ax88772a_phy_powerup(struct usbnet *dev);
67
+static void ax8817x_mdio_write_le(struct net_device *netdev, int phy_id,
68
+ int loc, int val);
69
+static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc);
70
+static int ax88772b_set_csums(struct usbnet *dev);
71
+static int ax88772b_external_phyinit(struct usbnet *dev);
72
+
73
+/* ASIX AX8817X based USB 2.0 Ethernet Devices */
74
+
75
+static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
76
+ u16 size, void *data)
77
+{
78
+ return usb_control_msg(
79
+ dev->udev,
80
+ usb_rcvctrlpipe(dev->udev, 0),
81
+ cmd,
82
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
83
+ value,
84
+ index,
85
+ data,
86
+ size,
87
+ USB_CTRL_GET_TIMEOUT);
88
+}
89
+
90
+static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
91
+ u16 size, void *data)
92
+{
93
+ return usb_control_msg(
94
+ dev->udev,
95
+ usb_sndctrlpipe(dev->udev, 0),
96
+ cmd,
97
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
98
+ value,
99
+ index,
100
+ data,
101
+ size,
102
+ USB_CTRL_SET_TIMEOUT);
103
+}
104
+
105
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
106
+static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
107
+#else
108
+static void ax8817x_async_cmd_callback(struct urb *urb)
109
+#endif
110
+{
111
+ struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
112
+
113
+ if (urb->status < 0)
114
+ printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
115
+ urb->status);
116
+
117
+ kfree(req);
118
+ usb_free_urb(urb);
119
+}
120
+
121
+static int ax8817x_set_mac_addr(struct net_device *net, void *p)
122
+{
123
+ struct usbnet *dev = netdev_priv(net);
124
+ struct sockaddr *addr = p;
125
+ int ret;
126
+
127
+ memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
128
+
129
+ /* Set the MAC address */
130
+ ret = ax8817x_write_cmd(dev, AX88772_CMD_WRITE_NODE_ID,
131
+ 0, 0, ETH_ALEN, net->dev_addr);
132
+ if (ret < 0)
133
+ return ret;
134
+
135
+ return 0;
136
+}
137
+
138
+static void ax88178_status(struct usbnet *dev, struct urb *urb)
139
+{
140
+ struct ax88172_int_data *event;
141
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
142
+ int link;
143
+
144
+ if (urb->actual_length < 8)
145
+ return;
146
+
147
+ if (ax178dataptr->EepromData == PHY_MODE_MAC_TO_MAC_GMII)
148
+ return;
149
+
150
+ event = urb->transfer_buffer;
151
+ link = event->link & 0x01;
152
+ if (netif_carrier_ok(dev->net) != link) {
153
+ if (link) {
154
+ netif_carrier_on(dev->net);
155
+ axusbnet_defer_kevent(dev, EVENT_LINK_RESET);
156
+ } else
157
+ netif_carrier_off(dev->net);
158
+ devwarn(dev, "ax88178 - Link status is: %d", link);
159
+ }
160
+}
161
+
162
+static void ax8817x_status(struct usbnet *dev, struct urb *urb)
163
+{
164
+ struct ax88172_int_data *event;
165
+ int link;
166
+
167
+ if (urb->actual_length < 8)
168
+ return;
169
+
170
+ event = urb->transfer_buffer;
171
+ link = event->link & 0x01;
172
+ if (netif_carrier_ok(dev->net) != link) {
173
+ if (link) {
174
+ netif_carrier_on(dev->net);
175
+ axusbnet_defer_kevent(dev, EVENT_LINK_RESET);
176
+ } else
177
+ netif_carrier_off(dev->net);
178
+ devwarn(dev, "ax8817x - Link status is: %d", link);
179
+ }
180
+}
181
+
182
+static void ax88772_status(struct usbnet *dev, struct urb *urb)
183
+{
184
+ struct ax88172_int_data *event;
185
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
186
+ int link;
187
+
188
+ if (urb->actual_length < 8)
189
+ return;
190
+
191
+ event = urb->transfer_buffer;
192
+ link = event->link & 0x01;
193
+
194
+ if (netif_carrier_ok(dev->net) != link) {
195
+ if (link) {
196
+ netif_carrier_on(dev->net);
197
+ ax772_data->Event = AX_SET_RX_CFG;
198
+ } else {
199
+ netif_carrier_off(dev->net);
200
+ if (ax772_data->Event == AX_NOP) {
201
+ ax772_data->Event = PHY_POWER_DOWN;
202
+ ax772_data->TickToExpire = 25;
203
+ }
204
+ }
205
+
206
+ devwarn(dev, "ax88772 - Link status is: %d", link);
207
+ }
208
+
209
+ if (ax772_data->Event)
210
+ queue_work(ax772_data->ax_work, &ax772_data->check_link);
211
+}
212
+
213
+static void ax88772a_status(struct usbnet *dev, struct urb *urb)
214
+{
215
+ struct ax88172_int_data *event;
216
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
217
+ int link;
218
+ int powsave = (ax772a_data->EepromData >> 14);
219
+
220
+ if (urb->actual_length < 8)
221
+ return;
222
+
223
+ event = urb->transfer_buffer;
224
+ link = event->link & 0x01;
225
+
226
+ if (netif_carrier_ok(dev->net) != link) {
227
+
228
+ if (link) {
229
+ netif_carrier_on(dev->net);
230
+ ax772a_data->Event = AX_SET_RX_CFG;
231
+ } else if ((powsave == 0x3) || (powsave == 0x1)) {
232
+ netif_carrier_off(dev->net);
233
+ if (ax772a_data->Event == AX_NOP) {
234
+ ax772a_data->Event = CHK_CABLE_EXIST;
235
+ ax772a_data->TickToExpire = 14;
236
+ }
237
+ } else {
238
+ netif_carrier_off(dev->net);
239
+ ax772a_data->Event = AX_NOP;
240
+ }
241
+
242
+ devwarn(dev, "ax88772a - Link status is: %d", link);
243
+ }
244
+
245
+ if (ax772a_data->Event)
246
+ queue_work(ax772a_data->ax_work, &ax772a_data->check_link);
247
+}
248
+
249
+static int ax88772b_stop(struct usbnet *dev)
250
+{
251
+ u16 *medium;
252
+
253
+ medium = kmalloc(2, GFP_ATOMIC);
254
+ if (medium) {
255
+ ax8817x_read_cmd(dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, medium);
256
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
257
+ (*medium & ~AX88772_MEDIUM_RX_ENABLE),
258
+ 0, 0, NULL);
259
+
260
+ kfree(medium);
261
+ return 0;
262
+ }
263
+ return -EINVAL;
264
+}
265
+
266
+static int ax88772b_reset(struct usbnet *dev)
267
+{
268
+ int ret;
269
+
270
+ /* Set the MAC address */
271
+ ret = ax8817x_write_cmd(dev, AX88772_CMD_WRITE_NODE_ID,
272
+ 0, 0, ETH_ALEN, dev->net->dev_addr);
273
+ if (ret < 0)
274
+ deverr(dev, "set MAC address failed: %d", ret);
275
+
276
+ /* stop MAC operation */
277
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, AX_RX_CTL_STOP,
278
+ 0, 0, NULL);
279
+ if (ret < 0)
280
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
281
+
282
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
283
+ AX88772_MEDIUM_DEFAULT, 0, 0,
284
+ NULL);
285
+ if (ret < 0)
286
+ deverr(dev, "Write medium mode register: %d", ret);
287
+
288
+ return ret;
289
+}
290
+
291
+static void ax88772b_status(struct usbnet *dev, struct urb *urb)
292
+{
293
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
294
+ struct ax88172_int_data *event;
295
+ int link;
296
+
297
+ if (urb->actual_length < 8)
298
+ return;
299
+
300
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
301
+ return;
302
+
303
+ event = urb->transfer_buffer;
304
+ if (ax772b_data->PhySelect == 0 &&
305
+ ax772b_data->OperationMode == OPERATION_MAC_MODE)
306
+ link = (event->link & AX_INT_SPLS_LINK) >> 1;
307
+ else
308
+ link = event->link & AX_INT_PPLS_LINK;
309
+
310
+ if (netif_carrier_ok(dev->net) != link) {
311
+ if (link) {
312
+ netif_carrier_on(dev->net);
313
+ ax772b_data->Event = AX_SET_RX_CFG;
314
+ } else {
315
+ netif_carrier_off(dev->net);
316
+ ax772b_data->time_to_chk = jiffies;
317
+ }
318
+ devwarn(dev, "ax88772b - Link status is: %d", link);
319
+ }
320
+
321
+ if (!link) {
322
+
323
+ int no_cable = (event->link & AX_INT_CABOFF_UNPLUG) ? 1 : 0;
324
+
325
+ if (no_cable) {
326
+ if ((ax772b_data->psc &
327
+ (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) &&
328
+ !ax772b_data->pw_enabled) {
329
+ /*
330
+ * AX88772B already entered power saving state
331
+ */
332
+ ax772b_data->pw_enabled = 1;
333
+ }
334
+ if (ax772b_data->psc & AX_SWRESET_AUTODETACH)
335
+ ax772b_data->Event = AX_CHK_AUTODETACH;
336
+
337
+ } else {
338
+ /* AX88772B resumed from power saving state */
339
+ if (ax772b_data->pw_enabled ||
340
+ (jiffies > (ax772b_data->time_to_chk +
341
+ AX88772B_WATCHDOG))) {
342
+ if (ax772b_data->pw_enabled)
343
+ ax772b_data->pw_enabled = 0;
344
+ ax772b_data->Event = PHY_POWER_UP;
345
+ ax772b_data->time_to_chk = jiffies;
346
+ }
347
+ }
348
+ }
349
+
350
+ if (ax772b_data->Event)
351
+ queue_work(ax772b_data->ax_work, &ax772b_data->check_link);
352
+}
353
+
354
+static void ax88772c_status(struct usbnet *dev, struct urb *urb)
355
+{
356
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
357
+ struct ax88172_int_data *event;
358
+ int link;
359
+
360
+ if (urb->actual_length < 8)
361
+ return;
362
+
363
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
364
+ return;
365
+
366
+ event = urb->transfer_buffer;
367
+ if (ax772b_data->PhySelect == 0 &&
368
+ ax772b_data->OperationMode == OPERATION_MAC_MODE)
369
+ link = (event->link & AX_INT_SPLS_LINK) >> 1;
370
+ else
371
+ link = event->link & AX_INT_PPLS_LINK;
372
+
373
+ if (netif_carrier_ok(dev->net) != link) {
374
+ if (link) {
375
+ netif_carrier_on(dev->net);
376
+ ax772b_data->Event = AX_SET_RX_CFG;
377
+ } else {
378
+ netif_carrier_off(dev->net);
379
+ ax772b_data->time_to_chk = jiffies;
380
+ }
381
+ devwarn(dev, "ax88772c - Link status is: %d", link);
382
+ }
383
+
384
+ if (!link) {
385
+
386
+ int no_cable = (event->link & AX_INT_CABOFF_UNPLUG) ? 1 : 0;
387
+
388
+ if (no_cable) {
389
+ if ((ax772b_data->psc &
390
+ (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) &&
391
+ !ax772b_data->pw_enabled) {
392
+ /*
393
+ * AX88772B already entered power saving state
394
+ */
395
+ ax772b_data->pw_enabled = 1;
396
+ }
397
+ if (ax772b_data->psc & AX_SWRESET_AUTODETACH)
398
+ ax772b_data->Event = AX_CHK_AUTODETACH;
399
+ } else {
400
+ /* AX88772B resumed from power saving state */
401
+ if (ax772b_data->pw_enabled ||
402
+ (jiffies > (ax772b_data->time_to_chk +
403
+ AX88772B_WATCHDOG))) {
404
+ if (ax772b_data->pw_enabled)
405
+ ax772b_data->pw_enabled = 0;
406
+ ax772b_data->Event = PHY_POWER_UP;
407
+ ax772b_data->time_to_chk = jiffies;
408
+ }
409
+ }
410
+ }
411
+
412
+ if (ax772b_data->Event)
413
+ queue_work(ax772b_data->ax_work, &ax772b_data->check_link);
414
+}
415
+
416
+void
417
+ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
418
+ u16 size, void *data)
419
+{
420
+ struct usb_ctrlrequest *req;
421
+ int status;
422
+ struct urb *urb;
423
+
424
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
425
+ if (urb == NULL) {
426
+ deverr(dev, "Error allocating URB in write_cmd_async!");
427
+ return;
428
+ }
429
+
430
+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
431
+ if (req == NULL) {
432
+ deverr(dev, "Failed to allocate memory for control request");
433
+ usb_free_urb(urb);
434
+ return;
435
+ }
436
+
437
+ req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
438
+ req->bRequest = cmd;
439
+ req->wValue = cpu_to_le16(value);
440
+ req->wIndex = cpu_to_le16(index);
441
+ req->wLength = cpu_to_le16(size);
442
+
443
+ usb_fill_control_urb(urb, dev->udev,
444
+ usb_sndctrlpipe(dev->udev, 0),
445
+ (void *)req, data, size,
446
+ ax8817x_async_cmd_callback, req);
447
+
448
+ status = usb_submit_urb(urb, GFP_ATOMIC);
449
+ if (status < 0) {
450
+ deverr(dev, "Error submitting the control message: status=%d",
451
+ status);
452
+ kfree(req);
453
+ usb_free_urb(urb);
454
+ }
455
+}
456
+
457
+static void ax8817x_set_multicast(struct net_device *net)
458
+{
459
+ struct usbnet *dev = netdev_priv(net);
460
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
461
+ u8 rx_ctl = AX_RX_CTL_START | AX_RX_CTL_AB;
462
+ int mc_count;
463
+
464
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
465
+ mc_count = net->mc_count;
466
+#else
467
+ mc_count = netdev_mc_count(net);
468
+#endif
469
+
470
+ if (net->flags & IFF_PROMISC) {
471
+ rx_ctl |= AX_RX_CTL_PRO;
472
+ } else if (net->flags & IFF_ALLMULTI
473
+ || mc_count > AX_MAX_MCAST) {
474
+ rx_ctl |= AX_RX_CTL_AMALL;
475
+ } else if (mc_count == 0) {
476
+ /* just broadcast and directed */
477
+ } else {
478
+ /* We use the 20 byte dev->data
479
+ * for our 8 byte filter buffer
480
+ * to avoid allocating memory that
481
+ * is tricky to free later */
482
+ u32 crc_bits;
483
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
484
+ struct dev_mc_list *mc_list = net->mc_list;
485
+ int i;
486
+
487
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
488
+
489
+ /* Build the multicast hash filter. */
490
+ for (i = 0; i < net->mc_count; i++) {
491
+ crc_bits =
492
+ ether_crc(ETH_ALEN,
493
+ mc_list->dmi_addr) >> 26;
494
+ data->multi_filter[crc_bits >> 3] |=
495
+ 1 << (crc_bits & 7);
496
+ mc_list = mc_list->next;
497
+ }
498
+#else
499
+ struct netdev_hw_addr *ha = NULL;
500
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
501
+ netdev_for_each_mc_addr(ha, net) {
502
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
503
+ data->multi_filter[crc_bits >> 3] |=
504
+ 1 << (crc_bits & 7);
505
+ }
506
+#endif
507
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
508
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
509
+
510
+ rx_ctl |= AX_RX_CTL_AM;
511
+ }
512
+
513
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
514
+}
515
+
516
+static void ax88178_set_multicast(struct net_device *net)
517
+{
518
+ struct usbnet *dev = netdev_priv(net);
519
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
520
+ u16 rx_ctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_MFB);
521
+ int mc_count;
522
+
523
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
524
+ mc_count = net->mc_count;
525
+#else
526
+ mc_count = netdev_mc_count(net);
527
+#endif
528
+
529
+ if (net->flags & IFF_PROMISC) {
530
+ rx_ctl |= AX_RX_CTL_PRO;
531
+ } else if (net->flags & IFF_ALLMULTI
532
+ || mc_count > AX_MAX_MCAST) {
533
+ rx_ctl |= AX_RX_CTL_AMALL;
534
+ } else if (mc_count == 0) {
535
+ /* just broadcast and directed */
536
+ } else {
537
+ /* We use the 20 byte dev->data
538
+ * for our 8 byte filter buffer
539
+ * to avoid allocating memory that
540
+ * is tricky to free later */
541
+ u32 crc_bits;
542
+
543
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
544
+ struct dev_mc_list *mc_list = net->mc_list;
545
+ int i;
546
+
547
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
548
+
549
+ /* Build the multicast hash filter. */
550
+ for (i = 0; i < net->mc_count; i++) {
551
+ crc_bits =
552
+ ether_crc(ETH_ALEN,
553
+ mc_list->dmi_addr) >> 26;
554
+ data->multi_filter[crc_bits >> 3] |=
555
+ 1 << (crc_bits & 7);
556
+ mc_list = mc_list->next;
557
+ }
558
+#else
559
+ struct netdev_hw_addr *ha = NULL;
560
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
561
+ netdev_for_each_mc_addr(ha, net) {
562
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
563
+ data->multi_filter[crc_bits >> 3] |=
564
+ 1 << (crc_bits & 7);
565
+ }
566
+#endif
567
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
568
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
569
+
570
+ rx_ctl |= AX_RX_CTL_AM;
571
+ }
572
+
573
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
574
+}
575
+
576
+static void ax88772b_set_multicast(struct net_device *net)
577
+{
578
+ struct usbnet *dev = netdev_priv(net);
579
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
580
+ u16 rx_ctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_HEADER_DEFAULT);
581
+ int mc_count;
582
+
583
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
584
+ mc_count = net->mc_count;
585
+#else
586
+ mc_count = netdev_mc_count(net);
587
+#endif
588
+
589
+ if (net->flags & IFF_PROMISC) {
590
+ rx_ctl |= AX_RX_CTL_PRO;
591
+ } else if (net->flags & IFF_ALLMULTI
592
+ || mc_count > AX_MAX_MCAST) {
593
+ rx_ctl |= AX_RX_CTL_AMALL;
594
+ } else if (mc_count == 0) {
595
+ /* just broadcast and directed */
596
+ } else {
597
+ /* We use the 20 byte dev->data
598
+ * for our 8 byte filter buffer
599
+ * to avoid allocating memory that
600
+ * is tricky to free later */
601
+ u32 crc_bits;
602
+
603
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
604
+ struct dev_mc_list *mc_list = net->mc_list;
605
+ int i;
606
+
607
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
608
+
609
+ /* Build the multicast hash filter. */
610
+ for (i = 0; i < net->mc_count; i++) {
611
+ crc_bits =
612
+ ether_crc(ETH_ALEN,
613
+ mc_list->dmi_addr) >> 26;
614
+ data->multi_filter[crc_bits >> 3] |=
615
+ 1 << (crc_bits & 7);
616
+ mc_list = mc_list->next;
617
+ }
618
+#else
619
+ struct netdev_hw_addr *ha = NULL;
620
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
621
+ netdev_for_each_mc_addr(ha, net) {
622
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
623
+ data->multi_filter[crc_bits >> 3] |=
624
+ 1 << (crc_bits & 7);
625
+ }
626
+#endif
627
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
628
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
629
+
630
+ rx_ctl |= AX_RX_CTL_AM;
631
+ }
632
+
633
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
634
+}
635
+
636
+static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
637
+{
638
+ struct usbnet *dev = netdev_priv(netdev);
639
+ u16 *res, ret;
640
+ u8* smsr;
641
+ int i = 0;
642
+
643
+ res = kmalloc(2, GFP_ATOMIC);
644
+ if (!res)
645
+ return 0;
646
+
647
+ do {
648
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
649
+
650
+ msleep(1);
651
+
652
+ smsr = (u8*) res;
653
+ ax8817x_read_cmd(dev, AX_CMD_READ_STATMNGSTS_REG, 0, 0, 1, smsr);
654
+ } while (!(*smsr & AX_HOST_EN) && (i++ < 30));
655
+
656
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, res);
657
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
658
+
659
+ ret = *res & 0xffff;
660
+ kfree(res);
661
+
662
+ return ret;
663
+}
664
+
665
+static int
666
+ax8817x_swmii_mdio_read(struct net_device *netdev, int phy_id, int loc)
667
+{
668
+ struct usbnet *dev = netdev_priv(netdev);
669
+ u16 *res;
670
+ u16 ret;
671
+
672
+ res = kmalloc(2, GFP_ATOMIC);
673
+ if (!res)
674
+ return 0;
675
+
676
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
677
+ (__u16)loc, 2, res);
678
+
679
+ ret = *res & 0xffff;
680
+ kfree(res);
681
+
682
+ return ret;
683
+}
684
+
685
+/* same as above, but converts resulting value to cpu byte order */
686
+static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
687
+{
688
+ return le16_to_cpu(ax8817x_mdio_read(netdev, phy_id, loc));
689
+}
690
+
691
+static int
692
+ax8817x_swmii_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
693
+{
694
+ return le16_to_cpu(ax8817x_swmii_mdio_read(netdev, phy_id, loc));
695
+}
696
+
697
+static void
698
+ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
699
+{
700
+ struct usbnet *dev = netdev_priv(netdev);
701
+ u16 *res;
702
+ u8* smsr;
703
+ int i = 0;
704
+
705
+ res = kmalloc(2, GFP_ATOMIC);
706
+ if (!res)
707
+ return;
708
+ smsr = (u8 *) res;
709
+
710
+ do {
711
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
712
+
713
+ msleep(1);
714
+
715
+ ax8817x_read_cmd(dev, AX_CMD_READ_STATMNGSTS_REG, 0, 0, 1, smsr);
716
+ } while (!(*smsr & AX_HOST_EN) && (i++ < 30));
717
+
718
+ *res = val;
719
+
720
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
721
+ (__u16)loc, 2, res);
722
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
723
+
724
+ kfree(res);
725
+}
726
+
727
+static void ax8817x_swmii_mdio_write(struct net_device *netdev, int phy_id,
728
+ int loc, int val)
729
+{
730
+ struct usbnet *dev = netdev_priv(netdev);
731
+ u16 *res;
732
+
733
+ res = kmalloc(2, GFP_ATOMIC);
734
+ if (!res)
735
+ return;
736
+ *res = val;
737
+
738
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
739
+ (__u16)loc, 2, res);
740
+
741
+ kfree(res);
742
+}
743
+
744
+static void
745
+ax88772b_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
746
+{
747
+ struct usbnet *dev = netdev_priv(netdev);
748
+ u16 *res;
749
+
750
+ res = kmalloc(2, GFP_ATOMIC);
751
+ if (!res)
752
+ return;
753
+ *res = val;
754
+
755
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
756
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
757
+ (__u16)loc, 2, res);
758
+
759
+ if (loc == MII_ADVERTISE) {
760
+ *res = cpu_to_le16(BMCR_ANENABLE | BMCR_ANRESTART);
761
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
762
+ (__u16)MII_BMCR, 2, res);
763
+ }
764
+
765
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
766
+
767
+ kfree(res);
768
+}
769
+
770
+/* same as above, but converts new value to le16 byte order before writing */
771
+static void
772
+ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
773
+{
774
+ ax8817x_mdio_write(netdev, phy_id, loc, cpu_to_le16(val));
775
+}
776
+
777
+static void ax8817x_swmii_mdio_write_le(struct net_device *netdev,
778
+ int phy_id, int loc, int val)
779
+{
780
+ ax8817x_swmii_mdio_write(netdev, phy_id, loc, cpu_to_le16(val));
781
+}
782
+
783
+static void
784
+ax88772b_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
785
+{
786
+ ax88772b_mdio_write(netdev, phy_id, loc, cpu_to_le16(val));
787
+}
788
+
789
+static int ax88772_suspend(struct usb_interface *intf,
790
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
791
+ pm_message_t message)
792
+#else
793
+ u32 message)
794
+#endif
795
+{
796
+ struct usbnet *dev = usb_get_intfdata(intf);
797
+ u16 *medium;
798
+
799
+ medium = kmalloc(2, GFP_ATOMIC);
800
+ if (!medium)
801
+ return axusbnet_suspend(intf, message);
802
+
803
+ ax8817x_read_cmd(dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, medium);
804
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
805
+ (*medium & ~AX88772_MEDIUM_RX_ENABLE), 0, 0, NULL);
806
+
807
+ kfree(medium);
808
+ return axusbnet_suspend(intf, message);
809
+}
810
+
811
+static int ax88772b_suspend(struct usb_interface *intf,
812
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
813
+ pm_message_t message)
814
+#else
815
+ u32 message)
816
+#endif
817
+{
818
+ struct usbnet *dev = usb_get_intfdata(intf);
819
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
820
+ u16 *tmp16;
821
+ u8 *opt;
822
+
823
+ tmp16 = kmalloc(2, GFP_ATOMIC);
824
+ if (!tmp16)
825
+ return axusbnet_suspend(intf, message);
826
+ opt = (u8 *)tmp16;
827
+#if 0
828
+ /* Read Wake-up Frame Array Register (Mask Wakeup Timer) */
829
+ ax8817x_read_cmd(dev, AX_CMD_READ_WKFARY, 0x11, 0, 4, &tmp32);
830
+ tmp32 &= 0xFFF0FFFF;
831
+ /* 8 second */
832
+ tmp32 |= 0x00020000;
833
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_WKFARY, 0x11, 0, 4, &tmp32);
834
+#endif
835
+ /* Preserve BMCR for restoring */
836
+ ax772b_data->presvd_phy_bmcr = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
837
+
838
+ /* Preserve Advertisement control reg for restoring */
839
+ ax772b_data->presvd_phy_advertise = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
840
+
841
+ ax8817x_read_cmd(dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, tmp16);
842
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
843
+ (*tmp16 & ~AX88772_MEDIUM_RX_ENABLE),
844
+ 0, 0, NULL);
845
+
846
+ ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, opt);
847
+ if (!(*opt & AX_MONITOR_LINK) && !(*opt & AX_MONITOR_MAGIC)) {
848
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
849
+ AX_SWRESET_IPRL | AX_SWRESET_IPPD,
850
+ 0, 0, NULL);
851
+
852
+ } else {
853
+
854
+ if (ax772b_data->psc & AX_SWRESET_WOLLP) {
855
+ *tmp16 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
856
+ MII_BMCR);
857
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id,
858
+ MII_BMCR, *tmp16 | BMCR_ANENABLE);
859
+
860
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
861
+ AX_SWRESET_IPRL | ax772b_data->psc,
862
+ 0, 0, NULL);
863
+ }
864
+
865
+ if (ax772b_data->psc &
866
+ (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) {
867
+ *opt |= AX_MONITOR_LINK;
868
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, *opt,
869
+ 0, 0, NULL);
870
+ }
871
+ }
872
+
873
+ kfree(tmp16);
874
+ return axusbnet_suspend(intf, message);
875
+}
876
+
877
+static int ax88772_resume(struct usb_interface *intf)
878
+{
879
+ struct usbnet *dev = usb_get_intfdata(intf);
880
+
881
+ netif_carrier_off(dev->net);
882
+
883
+ return axusbnet_resume(intf);
884
+}
885
+
886
+static int ax88772b_resume(struct usb_interface *intf)
887
+{
888
+ struct usbnet *dev = usb_get_intfdata(intf);
889
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
890
+
891
+ if (ax772b_data->psc & AX_SWRESET_WOLLP) {
892
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
893
+ AX_SWRESET_IPRL | (ax772b_data->psc & 0x7FFF),
894
+ 0, 0, NULL);
895
+ }
896
+
897
+ if (ax772b_data->psc & (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1))
898
+ ax88772a_phy_powerup(dev);
899
+
900
+ netif_carrier_off(dev->net);
901
+
902
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
903
+ netif_carrier_on(dev->net);
904
+
905
+ return axusbnet_resume(intf);
906
+}
907
+
908
+static int ax88172_link_reset(struct usbnet *dev)
909
+{
910
+ u16 lpa;
911
+ u16 adv;
912
+ u16 res;
913
+ u8 mode;
914
+
915
+ mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
916
+ lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
917
+ adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
918
+ res = mii_nway_result(lpa|adv);
919
+ if (res & LPA_DUPLEX)
920
+ mode |= AX_MEDIUM_FULL_DUPLEX;
921
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
922
+
923
+ return 0;
924
+}
925
+
926
+static void
927
+ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
928
+{
929
+ struct usbnet *dev = netdev_priv(net);
930
+ u8 *opt;
931
+
932
+ wolinfo->supported = 0;
933
+ wolinfo->wolopts = 0;
934
+
935
+ opt = kmalloc(1, GFP_KERNEL);
936
+ if (!opt)
937
+ return;
938
+
939
+ if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, opt) < 0) {
940
+ kfree(opt);
941
+ return;
942
+ }
943
+
944
+ wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
945
+
946
+ if (*opt & AX_MONITOR_LINK)
947
+ wolinfo->wolopts |= WAKE_PHY;
948
+ if (*opt & AX_MONITOR_MAGIC)
949
+ wolinfo->wolopts |= WAKE_MAGIC;
950
+
951
+ kfree(opt);
952
+}
953
+
954
+static int
955
+ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
956
+{
957
+ struct usbnet *dev = netdev_priv(net);
958
+ u8 *opt;
959
+
960
+ opt = kmalloc(1, GFP_KERNEL);
961
+ if (!opt)
962
+ return -ENOMEM;
963
+
964
+ *opt = 0;
965
+ if (wolinfo->wolopts & WAKE_PHY)
966
+ *opt |= AX_MONITOR_LINK;
967
+ if (wolinfo->wolopts & WAKE_MAGIC)
968
+ *opt |= AX_MONITOR_MAGIC;
969
+
970
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, *opt, 0, 0, NULL);
971
+
972
+ kfree(opt);
973
+ return 0;
974
+}
975
+
976
+static int ax8817x_get_eeprom_len(struct net_device *net)
977
+{
978
+ return AX_EEPROM_LEN;
979
+}
980
+
981
+static int ax8817x_get_eeprom(struct net_device *net,
982
+ struct ethtool_eeprom *eeprom, u8 *data)
983
+{
984
+ struct usbnet *dev = netdev_priv(net);
985
+ u16 *ebuf = (u16 *)data;
986
+ int i;
987
+
988
+ /* Crude hack to ensure that we don't overwrite memory
989
+ * if an odd length is supplied
990
+ */
991
+ if (eeprom->len % 2)
992
+ return -EINVAL;
993
+
994
+ eeprom->magic = AX_EEPROM_MAGIC;
995
+
996
+ /* ax8817x returns 2 bytes from eeprom on read */
997
+ for (i = 0; i < eeprom->len / 2; i++) {
998
+ if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
999
+ eeprom->offset + i, 0, 2,
1000
+ &ebuf[i]) < 0)
1001
+ return -EINVAL;
1002
+ }
1003
+ return 0;
1004
+}
1005
+
1006
+static void ax8817x_get_drvinfo(struct net_device *net,
1007
+ struct ethtool_drvinfo *info)
1008
+{
1009
+ /* Inherit standard device info */
1010
+ axusbnet_get_drvinfo(net, info);
1011
+ info->eedump_len = 0x3e;
1012
+}
1013
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1014
+static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
1015
+{
1016
+ struct usbnet *dev = netdev_priv(net);
1017
+ return mii_ethtool_gset(&dev->mii, cmd);
1018
+}
1019
+
1020
+static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
1021
+{
1022
+ struct usbnet *dev = netdev_priv(net);
1023
+ return mii_ethtool_sset(&dev->mii, cmd);
1024
+}
1025
+#else
1026
+static int ax8817x_get_link_ksettings(struct net_device *net,
1027
+ struct ethtool_link_ksettings *cmd)
1028
+{
1029
+ struct usbnet *dev = netdev_priv(net);
1030
+
1031
+ if (!dev->mii.mdio_read)
1032
+ return -EOPNOTSUPP;
1033
+
1034
+ mii_ethtool_get_link_ksettings(&dev->mii, cmd);
1035
+
1036
+ return 0;
1037
+}
1038
+
1039
+static int ax8817x_set_link_ksettings(struct net_device *net,
1040
+ const struct ethtool_link_ksettings *cmd)
1041
+{
1042
+ struct usbnet *dev = netdev_priv(net);
1043
+
1044
+ if (!dev->mii.mdio_write)
1045
+ return -EOPNOTSUPP;
1046
+
1047
+ return mii_ethtool_set_link_ksettings(&dev->mii, cmd);
1048
+}
1049
+#endif
1050
+/* We need to override some ethtool_ops so we require our
1051
+ own structure so we don't interfere with other usbnet
1052
+ devices that may be connected at the same time. */
1053
+static struct ethtool_ops ax8817x_ethtool_ops = {
1054
+ .get_drvinfo = ax8817x_get_drvinfo,
1055
+ .get_link = ethtool_op_get_link,
1056
+ .get_msglevel = axusbnet_get_msglevel,
1057
+ .set_msglevel = axusbnet_set_msglevel,
1058
+ .get_wol = ax8817x_get_wol,
1059
+ .set_wol = ax8817x_set_wol,
1060
+ .get_eeprom_len = ax8817x_get_eeprom_len,
1061
+ .get_eeprom = ax8817x_get_eeprom,
1062
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1063
+ .get_settings = ax8817x_get_settings,
1064
+ .set_settings = ax8817x_set_settings,
1065
+#else
1066
+ .get_link_ksettings = ax8817x_get_link_ksettings,
1067
+ .set_link_ksettings = ax8817x_set_link_ksettings,
1068
+#endif
1069
+};
1070
+
1071
+int ioctl_signature(struct usbnet *dev, AX_IOCTL_COMMAND *info)
1072
+{
1073
+ strncpy(info->sig, AX88772B_SIGNATURE, strlen(AX88772B_SIGNATURE));
1074
+
1075
+ return 0;
1076
+}
1077
+
1078
+static void debug_func(const char *func_name, unsigned short *buf, unsigned long wLen)
1079
+{
1080
+#if (DEBUG_PARAM & DEB_DRIVER)
1081
+ int i;
1082
+ char str_buf[50];
1083
+ printk("%s :\n", func_name);
1084
+ printk("---------------------------------------\n");
1085
+ for (i = 0; i < wLen / 8; i++) {
1086
+ int j = 8 * i;
1087
+ snprintf(str_buf, 50,
1088
+ "%04x %04x %04x %04x %04x %04x "
1089
+ "%04x %04x\n",
1090
+ *(buf + j + 0), *(buf + j + 1),
1091
+ *(buf + j + 2), *(buf + j + 3),
1092
+ *(buf + j + 4), *(buf + j + 5),
1093
+ *(buf + j + 6), *(buf + j + 7));
1094
+ printk("%s", str_buf);
1095
+ }
1096
+ printk("------------------------------------%3ld\n", wLen);
1097
+#endif
1098
+}
1099
+
1100
+int ioctl_read_eeprom(struct usbnet *dev, AX_IOCTL_COMMAND *info)
1101
+{
1102
+ int i, retval = 0;
1103
+ u16 * buf;
1104
+
1105
+ if (down_interruptible(&dev->sem)) {
1106
+ return -ERESTARTSYS;
1107
+ }
1108
+
1109
+ buf = kmalloc((sizeof(u16) * info->size), GFP_KERNEL);
1110
+ if (!buf) {
1111
+ return -ERESTARTSYS;
1112
+ }
1113
+
1114
+ for (i = 0; i < info->size; i++) {
1115
+ retval = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, i,
1116
+ 0, 2, &buf[i]);
1117
+
1118
+ if(retval < 0) {
1119
+ kfree(buf);
1120
+ up(&dev->sem);
1121
+ return retval;
1122
+ }
1123
+ buf[i] = be16_to_cpu(buf[i]);
1124
+ }
1125
+
1126
+ if (copy_to_user(info->buf, buf, (sizeof(unsigned short) * info->size))) {
1127
+ retval = -EFAULT;
1128
+ }
1129
+ kfree(buf);
1130
+ up(&dev->sem);
1131
+
1132
+ return retval;
1133
+
1134
+}
1135
+
1136
+int ioctl_write_eeprom(struct usbnet *dev, AX_IOCTL_COMMAND *info)
1137
+{
1138
+ int i, retval;
1139
+ u16 * buf;
1140
+
1141
+ if (down_interruptible(&dev->sem))
1142
+ return -ERESTARTSYS;
1143
+
1144
+ buf = kmalloc((sizeof(u16) * info->size), GFP_KERNEL);
1145
+ if (!buf) {
1146
+ return -ERESTARTSYS;
1147
+ }
1148
+
1149
+ if (copy_from_user(buf, info->buf, (sizeof(u16) * info->size))) {
1150
+ kfree(buf);
1151
+ up(&dev->sem);
1152
+ return -EFAULT;
1153
+ }
1154
+
1155
+ retval = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_EN, 0,
1156
+ 0, 0, NULL);
1157
+ if (retval < 0) {
1158
+ kfree(buf);
1159
+ up(&dev->sem);
1160
+ return retval;
1161
+ }
1162
+
1163
+ mdelay(info->delay);
1164
+
1165
+ for (i = 0; i < info->size; i++){
1166
+ retval = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM, i,
1167
+ cpu_to_be16(buf[i]), 0, NULL);
1168
+
1169
+ if (retval < 0) {
1170
+ DPRINT_D("Failed to command Write EEPROM(retval:%d, offset:%d)\n", retval, i);
1171
+ kfree(buf);
1172
+ up(&dev->sem);
1173
+ return retval;
1174
+ }
1175
+ mdelay(info->delay);
1176
+ }
1177
+
1178
+ debug_func(__FUNCTION__, buf, i);
1179
+
1180
+ retval = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_DIS, 0,
1181
+ 0, 0, NULL);
1182
+ if (retval < 0) {
1183
+ kfree(buf);
1184
+ up(&dev->sem);
1185
+ return retval;
1186
+ }
1187
+
1188
+ mdelay(info->delay);
1189
+
1190
+ retval = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_RSE, 0, 0, NULL);
1191
+
1192
+ mdelay(info->delay);
1193
+
1194
+ kfree(buf);
1195
+ up(&dev->sem);
1196
+
1197
+ return retval;
1198
+}
1199
+
1200
+typedef int (*IOCTRL_TABLE)(struct usbnet *dev, AX_IOCTL_COMMAND *info);
1201
+
1202
+IOCTRL_TABLE ioctl_tbl[] = {
1203
+ ioctl_signature, //AX_SIGNATURE
1204
+ ioctl_read_eeprom,
1205
+ ioctl_write_eeprom,
1206
+};
1207
+
1208
+static int ax8817x_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
1209
+{
1210
+ struct usbnet *dev = netdev_priv(net);
1211
+
1212
+ AX_IOCTL_COMMAND info;
1213
+ AX_IOCTL_COMMAND *uptr = (AX_IOCTL_COMMAND*) rq->ifr_data;
1214
+ int private_cmd;
1215
+
1216
+ switch (cmd) {
1217
+ case AX_PRIVATE :
1218
+ if (copy_from_user(&info, uptr, sizeof(AX_IOCTL_COMMAND))) {
1219
+ return -EFAULT;
1220
+ }
1221
+
1222
+ private_cmd = info.ioctl_cmd;
1223
+ if ((*ioctl_tbl[private_cmd])(dev,&info) < 0) {
1224
+ return -EFAULT;
1225
+ }
1226
+
1227
+ if (copy_to_user(uptr, &info, sizeof(AX_IOCTL_COMMAND))) {
1228
+ return -EFAULT;
1229
+ }
1230
+
1231
+ break;
1232
+
1233
+ default :
1234
+ return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
1235
+ }
1236
+ return 0;
1237
+}
1238
+
1239
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1240
+static const struct net_device_ops ax88x72_netdev_ops = {
1241
+ .ndo_open = axusbnet_open,
1242
+ .ndo_stop = axusbnet_stop,
1243
+ .ndo_start_xmit = axusbnet_start_xmit,
1244
+ .ndo_tx_timeout = axusbnet_tx_timeout,
1245
+ .ndo_change_mtu = axusbnet_change_mtu,
1246
+ .ndo_get_stats = axusbnet_get_stats,
1247
+ .ndo_do_ioctl = ax8817x_ioctl,
1248
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
1249
+ .ndo_validate_addr = eth_validate_addr,
1250
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 2, 0)
1251
+ .ndo_set_multicast_list = ax8817x_set_multicast,
1252
+#else
1253
+ .ndo_set_rx_mode = ax8817x_set_multicast,
1254
+#endif
1255
+};
1256
+#endif
1257
+
1258
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1259
+static const struct net_device_ops ax88178_netdev_ops = {
1260
+ .ndo_open = axusbnet_open,
1261
+ .ndo_stop = axusbnet_stop,
1262
+ .ndo_start_xmit = axusbnet_start_xmit,
1263
+ .ndo_tx_timeout = axusbnet_tx_timeout,
1264
+ .ndo_change_mtu = axusbnet_change_mtu,
1265
+ .ndo_get_stats = axusbnet_get_stats,
1266
+ .ndo_do_ioctl = ax8817x_ioctl,
1267
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
1268
+ .ndo_validate_addr = eth_validate_addr,
1269
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 2, 0)
1270
+ .ndo_set_multicast_list = ax88178_set_multicast,
1271
+#else
1272
+ .ndo_set_rx_mode = ax88178_set_multicast,
1273
+#endif
1274
+};
1275
+#endif
1276
+
1277
+static int access_eeprom_mac(struct usbnet *dev, u8 *buf, u8 offset, bool wflag)
1278
+{
1279
+ int ret = 0, i;
1280
+ u16* tmp = (u16*)buf;
1281
+
1282
+ if (wflag) {
1283
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_EN,
1284
+ 0, 0, 0, NULL);
1285
+ if (ret < 0)
1286
+ return ret;
1287
+
1288
+ mdelay(15);
1289
+ }
1290
+
1291
+ for (i = 0; i < (ETH_ALEN >> 1); i++) {
1292
+ if (wflag) {
1293
+ u16 wd = cpu_to_le16(*(tmp + i));
1294
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM, offset + i,
1295
+ wd, 0, NULL);
1296
+ if (ret < 0)
1297
+ break;
1298
+
1299
+ mdelay(15);
1300
+ }
1301
+ else {
1302
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
1303
+ offset + i, 0, 2, tmp + i);
1304
+ if (ret < 0)
1305
+ break;
1306
+ }
1307
+ }
1308
+
1309
+ if (!wflag) {
1310
+ if (ret < 0) {
1311
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
1312
+ netdev_dbg(dev->net, "Failed to read MAC address from EEPROM: %d\n", ret);
1313
+ #else
1314
+ devdbg(dev, "Failed to read MAC address from EEPROM: %d\n", ret);
1315
+ #endif
1316
+ return ret;
1317
+ }
1318
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
1319
+ }
1320
+ else {
1321
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_DIS,
1322
+ 0, 0, 0, NULL);
1323
+ if (ret < 0)
1324
+ return ret;
1325
+
1326
+ /* reload eeprom data */
1327
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
1328
+ AXGPIOS_RSE, 0, 0, NULL);
1329
+ if (ret < 0)
1330
+ return ret;
1331
+ }
1332
+
1333
+ return 0;
1334
+}
1335
+
1336
+static int ax8817x_check_ether_addr(struct usbnet *dev)
1337
+{
1338
+ unsigned char *tmp = (unsigned char*)dev->net->dev_addr;
1339
+ u8 default_mac[6] = {0, 0x0e, 0xc6, 0x87, 0x72, 0x01};
1340
+
1341
+ if (((*((u8*)tmp) == 0) && (*((u8*)tmp + 1) == 0) && (*((u8*)tmp + 2) == 0)) ||
1342
+ !is_valid_ether_addr((u8*)tmp) ||
1343
+ !memcmp(dev->net->dev_addr, default_mac, ETH_ALEN)) {
1344
+ printk("Found invalid EEPROM MAC address value ");
1345
+ printk("%02X-%02X-%02X-%02X-%02X-%02X\n", *((u8*)tmp + 0),
1346
+ *((u8*)tmp + 1),
1347
+ *((u8*)tmp + 2),
1348
+ *((u8*)tmp + 3),
1349
+ *((u8*)tmp + 4),
1350
+ *((u8*)tmp + 5));
1351
+
1352
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1353
+ eth_hw_addr_random(dev->net);
1354
+#else
1355
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
1356
+ dev->net->addr_assign_type |= NET_ADDR_RANDOM;
1357
+#endif
1358
+ random_ether_addr(dev->net->dev_addr);
1359
+#endif
1360
+ *tmp = 0;
1361
+ *(tmp + 1) = 0x0E;
1362
+ *(tmp + 2) = 0xC6;
1363
+ *(tmp + 3) = 0x8F;
1364
+
1365
+ return -EADDRNOTAVAIL;
1366
+ }
1367
+ return 0;
1368
+}
1369
+
1370
+static int ax8817x_get_mac(struct usbnet *dev, u8* buf)
1371
+{
1372
+ int ret, i;
1373
+
1374
+
1375
+ ret = access_eeprom_mac(dev, buf, 0x04, 0);
1376
+ if (ret < 0)
1377
+ goto out;
1378
+
1379
+ if (ax8817x_check_ether_addr(dev)) {
1380
+ ret = access_eeprom_mac(dev, dev->net->dev_addr, 0x04, 1);
1381
+ if (ret < 0) {
1382
+ deverr(dev, "Failed to write MAC to EEPROM: %d", ret);
1383
+ goto out;
1384
+ }
1385
+
1386
+ msleep(5);
1387
+
1388
+ ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
1389
+ 0, 0, ETH_ALEN, buf);
1390
+ if (ret < 0) {
1391
+ deverr(dev, "Failed to read MAC address: %d", ret);
1392
+ goto out;
1393
+ }
1394
+
1395
+ for (i = 0; i < ETH_ALEN; i++)
1396
+ if (*(dev->net->dev_addr + i) != *((u8*)buf + i)) {
1397
+ devwarn(dev, "Found invalid EEPROM part or non-EEPROM");
1398
+ break;
1399
+ }
1400
+ }
1401
+
1402
+ memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
1403
+
1404
+ /* Set the MAC address */
1405
+ ax8817x_write_cmd (dev, AX88772_CMD_WRITE_NODE_ID, 0, 0,
1406
+ ETH_ALEN, dev->net->dev_addr);
1407
+
1408
+ if (ret < 0) {
1409
+ deverr(dev, "Failed to write MAC address: %d", ret);
1410
+ goto out;
1411
+ }
1412
+
1413
+ return 0;
1414
+out:
1415
+ return ret;
1416
+}
1417
+
1418
+static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
1419
+{
1420
+ int ret = 0;
1421
+ void *buf;
1422
+ int i;
1423
+ unsigned long gpio_bits = dev->driver_info->data;
1424
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
1425
+
1426
+ axusbnet_get_endpoints(dev, intf);
1427
+
1428
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
1429
+ if (!buf) {
1430
+ ret = -ENOMEM;
1431
+ goto out1;
1432
+ }
1433
+
1434
+ /* Toggle the GPIOs in a manufacturer/model specific way */
1435
+ for (i = 2; i >= 0; i--) {
1436
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
1437
+ (gpio_bits >> (i * 8)) & 0xff,
1438
+ 0, 0, NULL);
1439
+ if (ret < 0)
1440
+ goto out2;
1441
+
1442
+ msleep(5);
1443
+ }
1444
+
1445
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, NULL);
1446
+ if (ret < 0) {
1447
+ deverr(dev, "send AX_CMD_WRITE_RX_CTL failed: %d", ret);
1448
+ goto out2;
1449
+ }
1450
+
1451
+ /* Get the MAC address */
1452
+ memset(buf, 0, ETH_ALEN);
1453
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf);
1454
+ if (ret < 0) {
1455
+ deverr(dev, "read AX_CMD_READ_NODE_ID failed: %d", ret);
1456
+ goto out2;
1457
+ }
1458
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
1459
+
1460
+ /* Get the PHY id */
1461
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
1462
+ if (ret < 0) {
1463
+ deverr(dev, "error on read AX_CMD_READ_PHY_ID: %02x", ret);
1464
+ goto out2;
1465
+ } else if (ret < 2) {
1466
+ /* this should always return 2 bytes */
1467
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
1468
+ ret);
1469
+ ret = -EIO;
1470
+ goto out2;
1471
+ }
1472
+
1473
+ /* Initialize MII structure */
1474
+ dev->mii.dev = dev->net;
1475
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
1476
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
1477
+ dev->mii.phy_id_mask = 0x3f;
1478
+ dev->mii.reg_num_mask = 0x1f;
1479
+ dev->mii.phy_id = *((u8 *)buf + 1);
1480
+
1481
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1482
+ dev->net->do_ioctl = ax8817x_ioctl;
1483
+ dev->net->set_multicast_list = ax8817x_set_multicast;
1484
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
1485
+#else
1486
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
1487
+#endif
1488
+
1489
+ dev->net->ethtool_ops = &ax8817x_ethtool_ops;
1490
+
1491
+ /* Register suspend and resume functions */
1492
+ data->suspend = axusbnet_suspend;
1493
+ data->resume = axusbnet_resume;
1494
+
1495
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
1496
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
1497
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
1498
+ mii_nway_restart(&dev->mii);
1499
+
1500
+ printk(version);
1501
+
1502
+ return 0;
1503
+out2:
1504
+ kfree(buf);
1505
+out1:
1506
+ return ret;
1507
+}
1508
+
1509
+static struct ethtool_ops ax88772_ethtool_ops = {
1510
+ .get_drvinfo = ax8817x_get_drvinfo,
1511
+ .get_link = ethtool_op_get_link,
1512
+ .get_msglevel = axusbnet_get_msglevel,
1513
+ .set_msglevel = axusbnet_set_msglevel,
1514
+ .get_wol = ax8817x_get_wol,
1515
+ .set_wol = ax8817x_set_wol,
1516
+ .get_eeprom_len = ax8817x_get_eeprom_len,
1517
+ .get_eeprom = ax8817x_get_eeprom,
1518
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1519
+ .get_settings = ax8817x_get_settings,
1520
+ .set_settings = ax8817x_set_settings,
1521
+#else
1522
+ .get_link_ksettings = ax8817x_get_link_ksettings,
1523
+ .set_link_ksettings = ax8817x_set_link_ksettings,
1524
+#endif
1525
+};
1526
+
1527
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
1528
+{
1529
+ int ret;
1530
+ void *buf;
1531
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
1532
+ struct ax88772_data *ax772_data = NULL;
1533
+
1534
+ axusbnet_get_endpoints(dev, intf);
1535
+
1536
+ buf = kmalloc(6, GFP_KERNEL);
1537
+ if (!buf) {
1538
+ deverr(dev, "Cannot allocate memory for buffer");
1539
+ ret = -ENOMEM;
1540
+ goto out1;
1541
+ }
1542
+
1543
+ ax772_data = kmalloc(sizeof(*ax772_data), GFP_KERNEL);
1544
+ if (!ax772_data) {
1545
+ deverr(dev, "Cannot allocate memory for AX88772 data");
1546
+ kfree(buf);
1547
+ return -ENOMEM;
1548
+ }
1549
+
1550
+ memset(ax772_data, 0, sizeof(*ax772_data));
1551
+ dev->priv = ax772_data;
1552
+
1553
+ ax772_data->ax_work = create_singlethread_workqueue("ax88772");
1554
+ if (!ax772_data->ax_work) {
1555
+ kfree(ax772_data);
1556
+ kfree(buf);
1557
+ return -ENOMEM;
1558
+ }
1559
+
1560
+ ax772_data->dev = dev;
1561
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
1562
+ INIT_WORK(&ax772_data->check_link, ax88772_link_reset, dev);
1563
+#else
1564
+ INIT_WORK(&ax772_data->check_link, ax88772_link_reset);
1565
+#endif
1566
+
1567
+ /* reload eeprom data */
1568
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, 0x00B0, 0, 0, NULL);
1569
+ if (ret < 0)
1570
+ goto out2;
1571
+
1572
+ msleep(5);
1573
+
1574
+ /* Initialize MII structure */
1575
+ dev->mii.dev = dev->net;
1576
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
1577
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
1578
+ dev->mii.phy_id_mask = 0xff;
1579
+ dev->mii.reg_num_mask = 0xff;
1580
+
1581
+ /* Get the PHY id */
1582
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
1583
+ if (ret < 0) {
1584
+ deverr(dev, "Error reading PHY ID: %02x", ret);
1585
+ goto out2;
1586
+ } else if (ret < 2) {
1587
+ /* this should always return 2 bytes */
1588
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
1589
+ ret);
1590
+ ret = -EIO;
1591
+ goto out2;
1592
+ }
1593
+ dev->mii.phy_id = *((u8 *)buf + 1);
1594
+
1595
+ if (dev->mii.phy_id == 0x10) {
1596
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
1597
+ 0x0001, 0, 0, NULL);
1598
+ if (ret < 0) {
1599
+ deverr(dev, "Select PHY #1 failed: %d", ret);
1600
+ goto out2;
1601
+ }
1602
+
1603
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
1604
+ 0, 0, NULL);
1605
+ if (ret < 0) {
1606
+ deverr(dev, "Failed to power down PHY: %d", ret);
1607
+ goto out2;
1608
+ }
1609
+
1610
+ msleep(150);
1611
+
1612
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
1613
+ 0, 0, NULL);
1614
+ if (ret < 0) {
1615
+ deverr(dev, "Failed to perform software reset: %d",
1616
+ ret);
1617
+ goto out2;
1618
+ }
1619
+
1620
+ msleep(150);
1621
+
1622
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1623
+ AX_SWRESET_IPRL | AX_SWRESET_PRL,
1624
+ 0, 0, NULL);
1625
+ if (ret < 0) {
1626
+ deverr(dev,
1627
+ "Failed to set PHY reset control: %d", ret);
1628
+ goto out2;
1629
+ }
1630
+ } else {
1631
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
1632
+ 0x0000, 0, 0, NULL);
1633
+ if (ret < 0) {
1634
+ deverr(dev, "Select PHY #1 failed: %d", ret);
1635
+ goto out2;
1636
+ }
1637
+
1638
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1639
+ AX_SWRESET_IPPD | AX_SWRESET_PRL,
1640
+ 0, 0, NULL);
1641
+ if (ret < 0) {
1642
+ deverr(dev, "Failed to power down internal PHY: %d",
1643
+ ret);
1644
+ goto out2;
1645
+ }
1646
+ }
1647
+
1648
+ msleep(150);
1649
+
1650
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
1651
+ 0x0000, 0, 0, NULL);
1652
+ if (ret < 0) {
1653
+ deverr(dev, "Failed to reset RX_CTL: %d", ret);
1654
+ goto out2;
1655
+ }
1656
+
1657
+ /* Get the MAC address */
1658
+ memset(buf, 0, ETH_ALEN);
1659
+ ret = ax8817x_get_mac(dev, buf);
1660
+ if (ret < 0) {
1661
+ deverr(dev, "Get HW address failed: %d", ret);
1662
+ goto out2;
1663
+ }
1664
+
1665
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
1666
+ if (ret < 0) {
1667
+ deverr(dev, "Enabling software MII failed: %d", ret);
1668
+ goto out2;
1669
+ }
1670
+
1671
+ if (dev->mii.phy_id == 0x10) {
1672
+ ret = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 2);
1673
+ if (ret != 0x003b) {
1674
+ deverr(dev, "Read PHY register 2 must be 0x3b00: %d",
1675
+ ret);
1676
+ goto out2;
1677
+ }
1678
+
1679
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL,
1680
+ 0, 0, NULL);
1681
+ if (ret < 0) {
1682
+ deverr(dev, "Set external PHY reset pin level: %d",
1683
+ ret);
1684
+ goto out2;
1685
+ }
1686
+ msleep(150);
1687
+
1688
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1689
+ AX_SWRESET_IPRL | AX_SWRESET_PRL,
1690
+ 0, 0, NULL);
1691
+ if (ret < 0) {
1692
+ deverr(dev,
1693
+ "Set Internal/External PHY reset control: %d",
1694
+ ret);
1695
+ goto out2;
1696
+ }
1697
+ msleep(150);
1698
+ }
1699
+
1700
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1701
+ dev->net->do_ioctl = ax8817x_ioctl;
1702
+ dev->net->set_multicast_list = ax8817x_set_multicast;
1703
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
1704
+#else
1705
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
1706
+#endif
1707
+
1708
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
1709
+
1710
+ /* Register suspend and resume functions */
1711
+ data->suspend = ax88772_suspend;
1712
+ data->resume = ax88772_resume;
1713
+
1714
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
1715
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
1716
+ ADVERTISE_ALL | ADVERTISE_CSMA);
1717
+
1718
+ mii_nway_restart(&dev->mii);
1719
+ ax772_data->autoneg_start = jiffies;
1720
+ ax772_data->Event = WAIT_AUTONEG_COMPLETE;
1721
+
1722
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 0, 0, 0, NULL);
1723
+ if (ret < 0) {
1724
+ deverr(dev, "Write medium mode register: %d", ret);
1725
+ goto out2;
1726
+ }
1727
+
1728
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
1729
+ AX88772_IPG0_DEFAULT |
1730
+ (AX88772_IPG1_DEFAULT << 8),
1731
+ AX88772_IPG2_DEFAULT, 0, NULL);
1732
+ if (ret < 0) {
1733
+ deverr(dev, "Write IPG,IPG1,IPG2 failed: %d", ret);
1734
+ goto out2;
1735
+ }
1736
+
1737
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
1738
+ if (ret < 0) {
1739
+ deverr(dev, "Failed to set hardware MII: %02x", ret);
1740
+ goto out2;
1741
+ }
1742
+
1743
+ /* Set RX_CTL to default values with 2k buffer, and enable cactus */
1744
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0, NULL);
1745
+ if (ret < 0) {
1746
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
1747
+ goto out2;
1748
+ }
1749
+
1750
+ /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
1751
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
1752
+ /* hard_mtu is still the default - the device does not support
1753
+ jumbo eth frames */
1754
+ dev->rx_urb_size = 2048;
1755
+ }
1756
+
1757
+ kfree(buf);
1758
+ printk(version);
1759
+ return 0;
1760
+
1761
+out2:
1762
+ destroy_workqueue(ax772_data->ax_work);
1763
+ kfree(ax772_data);
1764
+ kfree(buf);
1765
+out1:
1766
+ return ret;
1767
+}
1768
+
1769
+static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
1770
+{
1771
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
1772
+
1773
+ if (ax772_data) {
1774
+ flush_workqueue(ax772_data->ax_work);
1775
+ destroy_workqueue(ax772_data->ax_work);
1776
+
1777
+ /* stop MAC operation */
1778
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, AX_RX_CTL_STOP,
1779
+ 0, 0, NULL);
1780
+
1781
+ /* Power down PHY */
1782
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
1783
+ 0, 0, NULL);
1784
+
1785
+ kfree(ax772_data);
1786
+ }
1787
+}
1788
+
1789
+static int ax88772a_phy_powerup(struct usbnet *dev)
1790
+{
1791
+ int ret;
1792
+ /* set the embedded Ethernet PHY in power-down state */
1793
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1794
+ AX_SWRESET_IPPD | AX_SWRESET_IPRL, 0, 0, NULL);
1795
+ if (ret < 0) {
1796
+ deverr(dev, "Failed to power down PHY: %d", ret);
1797
+ return ret;
1798
+ }
1799
+
1800
+ msleep(10);
1801
+
1802
+ /* set the embedded Ethernet PHY in power-up state */
1803
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL,
1804
+ 0, 0, NULL);
1805
+ if (ret < 0) {
1806
+ deverr(dev, "Failed to reset PHY: %d", ret);
1807
+ return ret;
1808
+ }
1809
+
1810
+ msleep(600);
1811
+
1812
+ /* set the embedded Ethernet PHY in reset state */
1813
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
1814
+ 0, 0, NULL);
1815
+ if (ret < 0) {
1816
+ deverr(dev, "Failed to power up PHY: %d", ret);
1817
+ return ret;
1818
+ }
1819
+
1820
+ /* set the embedded Ethernet PHY in power-up state */
1821
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL,
1822
+ 0, 0, NULL);
1823
+ if (ret < 0) {
1824
+ deverr(dev, "Failed to reset PHY: %d", ret);
1825
+ return ret;
1826
+ }
1827
+
1828
+ return 0;
1829
+}
1830
+
1831
+static int ax88772a_bind(struct usbnet *dev, struct usb_interface *intf)
1832
+{
1833
+ int ret = -EIO;
1834
+ void *buf;
1835
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
1836
+ struct ax88772a_data *ax772a_data = NULL;
1837
+
1838
+ printk(version);
1839
+
1840
+ axusbnet_get_endpoints(dev, intf);
1841
+
1842
+ buf = kmalloc(6, GFP_KERNEL);
1843
+ if (!buf) {
1844
+ deverr(dev, "Cannot allocate memory for buffer");
1845
+ ret = -ENOMEM;
1846
+ goto out1;
1847
+ }
1848
+
1849
+ ax772a_data = kmalloc(sizeof(*ax772a_data), GFP_KERNEL);
1850
+ if (!ax772a_data) {
1851
+ deverr(dev, "Cannot allocate memory for AX88772A data");
1852
+ kfree(buf);
1853
+ return -ENOMEM;
1854
+ }
1855
+ memset(ax772a_data, 0, sizeof(*ax772a_data));
1856
+ dev->priv = ax772a_data;
1857
+
1858
+ ax772a_data->ax_work = create_singlethread_workqueue("ax88772a");
1859
+ if (!ax772a_data->ax_work) {
1860
+ kfree(ax772a_data);
1861
+ kfree(buf);
1862
+ return -ENOMEM;
1863
+ }
1864
+
1865
+ ax772a_data->dev = dev;
1866
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
1867
+ INIT_WORK(&ax772a_data->check_link, ax88772a_link_reset, dev);
1868
+#else
1869
+ INIT_WORK(&ax772a_data->check_link, ax88772a_link_reset);
1870
+#endif
1871
+
1872
+ /* Get the EEPROM data*/
1873
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2,
1874
+ (void *)&ax772a_data->EepromData);
1875
+ if (ret < 0) {
1876
+ deverr(dev, "read SROM address 17h failed: %d", ret);
1877
+ goto out2;
1878
+ }
1879
+ le16_to_cpus(&ax772a_data->EepromData);
1880
+ /* End of get EEPROM data */
1881
+
1882
+ /* reload eeprom data */
1883
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
1884
+ AXGPIOS_RSE, 0, 0, NULL);
1885
+ if (ret < 0)
1886
+ goto out2;
1887
+
1888
+ msleep(5);
1889
+
1890
+ /* Initialize MII structure */
1891
+ dev->mii.dev = dev->net;
1892
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
1893
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
1894
+ dev->mii.phy_id_mask = 0xff;
1895
+ dev->mii.reg_num_mask = 0xff;
1896
+
1897
+ /* Get the PHY id */
1898
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
1899
+ if (ret < 0) {
1900
+ deverr(dev, "Error reading PHY ID: %02x", ret);
1901
+ goto out2;
1902
+ } else if (ret < 2) {
1903
+ /* this should always return 2 bytes */
1904
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
1905
+ ret);
1906
+ goto out2;
1907
+ }
1908
+ dev->mii.phy_id = *((u8 *)buf + 1);
1909
+
1910
+ if (dev->mii.phy_id != 0x10) {
1911
+ deverr(dev, "Got wrong PHY ID: %02x", dev->mii.phy_id);
1912
+ goto out2;
1913
+ }
1914
+
1915
+ /* select the embedded 10/100 Ethernet PHY */
1916
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
1917
+ AX_PHYSEL_SSEN | AX_PHYSEL_PSEL | AX_PHYSEL_SSMII,
1918
+ 0, 0, NULL);
1919
+ if (ret < 0) {
1920
+ deverr(dev, "Select PHY #1 failed: %d", ret);
1921
+ goto out2;
1922
+ }
1923
+
1924
+ ret = ax88772a_phy_powerup(dev);
1925
+ if (ret < 0)
1926
+ goto out2;
1927
+
1928
+ /* stop MAC operation */
1929
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, AX_RX_CTL_STOP,
1930
+ 0, 0, NULL);
1931
+ if (ret < 0) {
1932
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
1933
+ goto out2;
1934
+ }
1935
+
1936
+ /* Get the MAC address */
1937
+ memset(buf, 0, ETH_ALEN);
1938
+ ret = ax8817x_get_mac(dev, buf);
1939
+ if (ret < 0) {
1940
+ deverr(dev, "Get HW address failed: %d", ret);
1941
+ goto out2;
1942
+ }
1943
+
1944
+ /* make sure the driver can enable sw mii operation */
1945
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
1946
+ if (ret < 0) {
1947
+ deverr(dev, "Enabling software MII failed: %d", ret);
1948
+ goto out2;
1949
+ }
1950
+
1951
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1952
+ dev->net->do_ioctl = ax8817x_ioctl;
1953
+ dev->net->set_multicast_list = ax8817x_set_multicast;
1954
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
1955
+#else
1956
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
1957
+#endif
1958
+
1959
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
1960
+
1961
+ /* Register suspend and resume functions */
1962
+ data->suspend = ax88772_suspend;
1963
+ data->resume = ax88772_resume;
1964
+
1965
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
1966
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
1967
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
1968
+
1969
+ mii_nway_restart(&dev->mii);
1970
+ ax772a_data->autoneg_start = jiffies;
1971
+ ax772a_data->Event = WAIT_AUTONEG_COMPLETE;
1972
+
1973
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
1974
+ 0, 0, 0, NULL);
1975
+ if (ret < 0) {
1976
+ deverr(dev, "Write medium mode register: %d", ret);
1977
+ goto out2;
1978
+ }
1979
+
1980
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
1981
+ AX88772A_IPG0_DEFAULT | AX88772A_IPG1_DEFAULT << 8,
1982
+ AX88772A_IPG2_DEFAULT, 0, NULL);
1983
+ if (ret < 0) {
1984
+ deverr(dev, "Write IPG,IPG1,IPG2 failed: %d", ret);
1985
+ goto out2;
1986
+ }
1987
+
1988
+ memset(buf, 0, 4);
1989
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_IPG012, 0, 0, 3, buf);
1990
+ *((u8 *)buf + 3) = 0x00;
1991
+ if (ret < 0) {
1992
+ deverr(dev, "Failed to read IPG,IPG1,IPG2 failed: %d", ret);
1993
+ goto out2;
1994
+ } else {
1995
+ __u32 tmp32 = *((u32*)buf);
1996
+ le32_to_cpus(&tmp32);
1997
+ if (tmp32 != (AX88772A_IPG2_DEFAULT << 16 |
1998
+ AX88772A_IPG1_DEFAULT << 8 | AX88772A_IPG0_DEFAULT)) {
1999
+ printk("Non-authentic ASIX product\nASIX does not support it\n");
2000
+ ret = -ENODEV;
2001
+ goto out2;
2002
+ }
2003
+ }
2004
+
2005
+ /* Set RX_CTL to default values with 2k buffer, and enable cactus */
2006
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
2007
+ (AX_RX_CTL_START | AX_RX_CTL_AB),
2008
+ 0, 0, NULL);
2009
+ if (ret < 0) {
2010
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2011
+ goto out2;
2012
+ }
2013
+
2014
+ /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
2015
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
2016
+ /* hard_mtu is still the default - the device does not support
2017
+ jumbo eth frames */
2018
+ dev->rx_urb_size = 2048;
2019
+ }
2020
+
2021
+ kfree(buf);
2022
+
2023
+ return ret;
2024
+out2:
2025
+ destroy_workqueue(ax772a_data->ax_work);
2026
+ kfree(ax772a_data);
2027
+ kfree(buf);
2028
+out1:
2029
+ return ret;
2030
+}
2031
+
2032
+static void ax88772a_unbind(struct usbnet *dev, struct usb_interface *intf)
2033
+{
2034
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
2035
+
2036
+ if (ax772a_data) {
2037
+
2038
+ flush_workqueue(ax772a_data->ax_work);
2039
+ destroy_workqueue(ax772a_data->ax_work);
2040
+
2041
+ /* stop MAC operation */
2042
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
2043
+ AX_RX_CTL_STOP, 0, 0, NULL);
2044
+
2045
+ /* Power down PHY */
2046
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
2047
+ AX_SWRESET_IPPD, 0, 0, NULL);
2048
+
2049
+ kfree(ax772a_data);
2050
+ }
2051
+}
2052
+
2053
+static int ax88772b_set_csums(struct usbnet *dev)
2054
+{
2055
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2056
+ u16 checksum;
2057
+
2058
+ if (ax772b_data->checksum & AX_RX_CHECKSUM)
2059
+ checksum = AX_RXCOE_DEF_CSUM;
2060
+ else
2061
+ checksum = 0;
2062
+
2063
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RXCOE_CTL,
2064
+ checksum, 0, 0, NULL);
2065
+
2066
+ if (ax772b_data->checksum & AX_TX_CHECKSUM)
2067
+ checksum = AX_TXCOE_DEF_CSUM;
2068
+ else
2069
+ checksum = 0;
2070
+
2071
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_TXCOE_CTL,
2072
+ checksum, 0, 0, NULL);
2073
+
2074
+ return 0;
2075
+}
2076
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
2077
+static u32 ax88772b_get_tx_csum(struct net_device *netdev)
2078
+{
2079
+ struct usbnet *dev = netdev_priv(netdev);
2080
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2081
+
2082
+ return ax772b_data->checksum & AX_TX_CHECKSUM;
2083
+}
2084
+
2085
+static u32 ax88772b_get_rx_csum(struct net_device *netdev)
2086
+{
2087
+ struct usbnet *dev = netdev_priv(netdev);
2088
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2089
+
2090
+ return ax772b_data->checksum & AX_RX_CHECKSUM;
2091
+}
2092
+
2093
+static int ax88772b_set_rx_csum(struct net_device *netdev, u32 val)
2094
+{
2095
+ struct usbnet *dev = netdev_priv(netdev);
2096
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2097
+
2098
+ if (val)
2099
+ ax772b_data->checksum |= AX_RX_CHECKSUM;
2100
+ else
2101
+ ax772b_data->checksum &= ~AX_RX_CHECKSUM;
2102
+
2103
+ return ax88772b_set_csums(dev);
2104
+}
2105
+
2106
+static int ax88772b_set_tx_csum(struct net_device *netdev, u32 val)
2107
+{
2108
+ struct usbnet *dev = netdev_priv(netdev);
2109
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2110
+
2111
+ if (val)
2112
+ ax772b_data->checksum |= AX_TX_CHECKSUM;
2113
+ else
2114
+ ax772b_data->checksum &= ~AX_TX_CHECKSUM;
2115
+
2116
+ ethtool_op_set_tx_csum(netdev, val);
2117
+
2118
+ return ax88772b_set_csums(dev);
2119
+}
2120
+#endif
2121
+static struct ethtool_ops ax88772b_ethtool_ops = {
2122
+ .get_drvinfo = ax8817x_get_drvinfo,
2123
+ .get_link = ethtool_op_get_link,
2124
+ .get_msglevel = axusbnet_get_msglevel,
2125
+ .set_msglevel = axusbnet_set_msglevel,
2126
+ .get_wol = ax8817x_get_wol,
2127
+ .set_wol = ax8817x_set_wol,
2128
+ .get_eeprom_len = ax8817x_get_eeprom_len,
2129
+ .get_eeprom = ax8817x_get_eeprom,
2130
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
2131
+ .get_settings = ax8817x_get_settings,
2132
+ .set_settings = ax8817x_set_settings,
2133
+#else
2134
+ .get_link_ksettings = ax8817x_get_link_ksettings,
2135
+ .set_link_ksettings = ax8817x_set_link_ksettings,
2136
+#endif
2137
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
2138
+ .set_tx_csum = ax88772b_set_tx_csum,
2139
+ .get_tx_csum = ax88772b_get_tx_csum,
2140
+ .get_rx_csum = ax88772b_get_rx_csum,
2141
+ .set_rx_csum = ax88772b_set_rx_csum,
2142
+#endif
2143
+};
2144
+
2145
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
2146
+static const struct net_device_ops ax88772b_netdev_ops = {
2147
+ .ndo_open = axusbnet_open,
2148
+ .ndo_stop = axusbnet_stop,
2149
+ .ndo_start_xmit = axusbnet_start_xmit,
2150
+ .ndo_tx_timeout = axusbnet_tx_timeout,
2151
+ .ndo_change_mtu = axusbnet_change_mtu,
2152
+ .ndo_do_ioctl = ax8817x_ioctl,
2153
+ .ndo_get_stats = axusbnet_get_stats,
2154
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
2155
+ .ndo_validate_addr = eth_validate_addr,
2156
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 2, 0)
2157
+ .ndo_set_multicast_list = ax88772b_set_multicast,
2158
+#else
2159
+ .ndo_set_rx_mode = ax88772b_set_multicast,
2160
+#endif
2161
+};
2162
+#endif
2163
+
2164
+static int ax88772b_bind(struct usbnet *dev, struct usb_interface *intf)
2165
+{
2166
+ int ret;
2167
+ void *buf;
2168
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
2169
+ struct ax88772b_data *ax772b_data;
2170
+ u16 *tmp16;
2171
+ u8 *tmp8;
2172
+ u8 tempphyselect;
2173
+ bool internalphy;
2174
+
2175
+ printk(version);
2176
+ axusbnet_get_endpoints(dev, intf);
2177
+ buf = kmalloc(6, GFP_KERNEL);
2178
+ if (!buf) {
2179
+ deverr(dev, "Cannot allocate memory for buffer");
2180
+ return -ENOMEM;
2181
+ }
2182
+ tmp16 = (u16 *)buf;
2183
+ ax772b_data = kmalloc(sizeof(*ax772b_data), GFP_KERNEL);
2184
+ if (!ax772b_data) {
2185
+ deverr(dev, "Cannot allocate memory for AX88772B data");
2186
+ kfree(buf);
2187
+ return -ENOMEM;
2188
+ }
2189
+ memset(ax772b_data, 0, sizeof(*ax772b_data));
2190
+ dev->priv = ax772b_data;
2191
+ ax772b_data->ax_work = create_singlethread_workqueue("ax88772b");
2192
+ if (!ax772b_data->ax_work) {
2193
+ kfree(buf);
2194
+ kfree(ax772b_data);
2195
+ return -ENOMEM;
2196
+ }
2197
+
2198
+ ax772b_data->dev = dev;
2199
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
2200
+ INIT_WORK(&ax772b_data->check_link, ax88772b_link_reset, dev);
2201
+#else
2202
+ INIT_WORK(&ax772b_data->check_link, ax88772b_link_reset);
2203
+#endif
2204
+
2205
+ tmp8 = (u8 *)buf;
2206
+ ret = ax8817x_read_cmd(dev, AX_CMD_SW_PHY_STATUS,
2207
+ 0, 0, 1, tmp8);
2208
+
2209
+ if (ret < 0) {
2210
+ deverr(dev,
2211
+ "read SW interface selection status register failed: %d\n",
2212
+ ret);
2213
+ goto err_out;
2214
+ }
2215
+ tempphyselect = *tmp8;
2216
+ tempphyselect &= 0x0C;
2217
+
2218
+ if (tempphyselect == AX_PHYSEL_SSRMII) {
2219
+ internalphy = false;
2220
+ ax772b_data->OperationMode = OPERATION_MAC_MODE;
2221
+ ax772b_data->PhySelect = 0x00;
2222
+ } else if (tempphyselect == AX_PHYSEL_SSRRMII) {
2223
+ internalphy = true;
2224
+ ax772b_data->OperationMode = OPERATION_PHY_MODE;
2225
+ ax772b_data->PhySelect = 0x00;
2226
+ } else if (tempphyselect == AX_PHYSEL_SSMII) {
2227
+ internalphy = true;
2228
+ ax772b_data->OperationMode = OPERATION_MAC_MODE;
2229
+ ax772b_data->PhySelect = 0x01;
2230
+ } else {
2231
+ deverr(dev, "Unknown MII type\n");
2232
+ goto err_out;
2233
+ }
2234
+
2235
+ /* reload eeprom data */
2236
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_RSE,
2237
+ 0, 0, NULL);
2238
+ if (ret < 0) {
2239
+ deverr(dev, "Failed to enable GPIO function: %d", ret);
2240
+ goto err_out;
2241
+ }
2242
+ msleep(5);
2243
+
2244
+ /* Get the EEPROM data*/
2245
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 0x18, 0, 2,
2246
+ (void *)tmp16);
2247
+ if (ret < 0) {
2248
+ deverr(dev, "read SROM address 18h failed: %d", ret);
2249
+ goto err_out;
2250
+ }
2251
+ le16_to_cpus(tmp16);
2252
+ ax772b_data->psc = *tmp16 & 0xFF00;
2253
+ /* End of get EEPROM data */
2254
+
2255
+ /* Get the MAC address */
2256
+ memset(buf, 0, ETH_ALEN);
2257
+ ret = ax8817x_get_mac(dev, buf);
2258
+ if (ret < 0) {
2259
+ deverr(dev, "Get HW address failed: %d", ret);
2260
+ goto err_out;
2261
+ }
2262
+
2263
+ /* Initialize MII structure */
2264
+ dev->mii.dev = dev->net;
2265
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
2266
+ dev->mii.mdio_write = ax88772b_mdio_write_le;
2267
+ dev->mii.phy_id_mask = 0xff;
2268
+ dev->mii.reg_num_mask = 0xff;
2269
+
2270
+ /* Get the PHY id */
2271
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
2272
+ if (ret < 0) {
2273
+ deverr(dev, "Error reading PHY ID: %02x", ret);
2274
+ goto err_out;
2275
+ } else if (ret < 2) {
2276
+ /* this should always return 2 bytes */
2277
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
2278
+ ret);
2279
+ ret = -EIO;
2280
+ goto err_out;
2281
+ }
2282
+
2283
+ if (internalphy)
2284
+ dev->mii.phy_id = *((u8 *)buf + 1);
2285
+ else
2286
+ dev->mii.phy_id = *((u8 *)buf);
2287
+
2288
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
2289
+ ax772b_data->PhySelect, 0, 0, NULL);
2290
+ if (ret < 0) {
2291
+ deverr(dev, "Select PHY #1 failed: %d", ret);
2292
+ goto err_out;
2293
+ }
2294
+
2295
+#if 0
2296
+ /* select the embedded 10/100 Ethernet PHY */
2297
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
2298
+ AX_PHYSEL_SSEN | AX_PHYSEL_PSEL | AX_PHYSEL_SSMII,
2299
+ 0, 0, NULL);
2300
+ if (ret < 0) {
2301
+ deverr(dev, "Select PHY #1 failed: %d", ret);
2302
+ goto err_out;
2303
+ }
2304
+
2305
+ if (dev->mii.phy_id != 0x10) {
2306
+ deverr(dev, "Got wrong PHY ID: %02x", dev->mii.phy_id);
2307
+ ret = -EIO;
2308
+ goto err_out;
2309
+ }
2310
+#endif
2311
+ ret = ax88772a_phy_powerup(dev);
2312
+ if (ret < 0)
2313
+ goto err_out;
2314
+
2315
+ /* stop MAC operation */
2316
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
2317
+ AX_RX_CTL_STOP, 0, 0, NULL);
2318
+ if (ret < 0) {
2319
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2320
+ goto err_out;
2321
+ }
2322
+
2323
+ /* make sure the driver can enable sw mii operation */
2324
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
2325
+ if (ret < 0) {
2326
+ deverr(dev, "Enabling software MII failed: %d", ret);
2327
+ goto err_out;
2328
+ }
2329
+
2330
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
2331
+ dev->net->do_ioctl = ax8817x_ioctl;
2332
+ dev->net->set_multicast_list = ax88772b_set_multicast;
2333
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
2334
+#else
2335
+ dev->net->netdev_ops = &ax88772b_netdev_ops;
2336
+#endif
2337
+
2338
+ dev->net->ethtool_ops = &ax88772b_ethtool_ops;
2339
+
2340
+ /* Register suspend and resume functions */
2341
+ data->suspend = ax88772b_suspend;
2342
+ data->resume = ax88772b_resume;
2343
+
2344
+ if ((ax772b_data->OperationMode == OPERATION_MAC_MODE) &&
2345
+ (ax772b_data->PhySelect == 0x00)) {
2346
+ if (ax88772b_external_phyinit(dev) != 0x00) {
2347
+ deverr(dev, "Failed to initial the external phy");
2348
+ goto err_out;
2349
+ }
2350
+ }
2351
+
2352
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
2353
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id
2354
+ , MII_BMCR, 0x3900);
2355
+
2356
+ if (dev->mii.phy_id != 0x10)
2357
+ ax8817x_mdio_write_le(dev->net, 0x10, MII_BMCR, 0x3900);
2358
+
2359
+ if (dev->mii.phy_id == 0x10 && ax772b_data->OperationMode
2360
+ != OPERATION_PHY_MODE) {
2361
+
2362
+ *tmp16 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
2363
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, 0x12,
2364
+ ((*tmp16 & 0xFF9F) | 0x0040));
2365
+ }
2366
+
2367
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
2368
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
2369
+
2370
+ mii_nway_restart(&dev->mii);
2371
+
2372
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
2373
+ 0, 0, 0, NULL);
2374
+ if (ret < 0) {
2375
+ deverr(dev, "Failed to write medium mode: %d", ret);
2376
+ goto err_out;
2377
+ }
2378
+
2379
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
2380
+ AX88772A_IPG0_DEFAULT | AX88772A_IPG1_DEFAULT << 8,
2381
+ AX88772A_IPG2_DEFAULT, 0, NULL);
2382
+ if (ret < 0) {
2383
+ deverr(dev, "Failed to write interframe gap: %d", ret);
2384
+ goto err_out;
2385
+ }
2386
+
2387
+ memset(buf, 0, 4);
2388
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_IPG012, 0, 0, 3, buf);
2389
+ *((u8 *)buf + 3) = 0x00;
2390
+ if (ret < 0) {
2391
+ deverr(dev, "Failed to read IPG,IPG1,IPG2 failed: %d", ret);
2392
+ goto err_out;
2393
+ } else {
2394
+ __u32 tmp32 = *((u32*)buf);
2395
+ le32_to_cpus(&tmp32);
2396
+ if (tmp32 != (AX88772A_IPG2_DEFAULT << 16 |
2397
+ AX88772A_IPG1_DEFAULT << 8 | AX88772A_IPG0_DEFAULT)) {
2398
+ printk("Non-authentic ASIX product\nASIX does not support it\n");
2399
+ ret = -ENODEV;
2400
+ goto err_out;
2401
+ }
2402
+ }
2403
+
2404
+ dev->net->features |= NETIF_F_IP_CSUM;
2405
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
2406
+ dev->net->features |= NETIF_F_IPV6_CSUM;
2407
+#endif
2408
+
2409
+ ax772b_data->checksum = AX_RX_CHECKSUM | AX_TX_CHECKSUM;
2410
+ ret = ax88772b_set_csums(dev);
2411
+ if (ret < 0) {
2412
+ deverr(dev, "Write RX_COE/TX_COE failed: %d", ret);
2413
+ goto err_out;
2414
+ }
2415
+
2416
+ dev->rx_size = bsize & 0x07;
2417
+ if (dev->udev->speed == USB_SPEED_HIGH) {
2418
+
2419
+ ret = ax8817x_write_cmd(dev, 0x2A,
2420
+ AX88772B_BULKIN_SIZE[dev->rx_size].byte_cnt,
2421
+ AX88772B_BULKIN_SIZE[dev->rx_size].threshold,
2422
+ 0, NULL);
2423
+ if (ret < 0) {
2424
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2425
+ goto err_out;
2426
+ }
2427
+
2428
+ dev->rx_urb_size = AX88772B_BULKIN_SIZE[dev->rx_size].size;
2429
+ } else {
2430
+ ret = ax8817x_write_cmd(dev, 0x2A,
2431
+ 0x8000, 0x8001, 0, NULL);
2432
+ if (ret < 0) {
2433
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2434
+ goto err_out;
2435
+ }
2436
+ dev->rx_urb_size = 2048;
2437
+ }
2438
+
2439
+ /* Configure RX header type */
2440
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
2441
+ (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_HEADER_DEFAULT),
2442
+ 0, 0, NULL);
2443
+ if (ret < 0) {
2444
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2445
+ goto err_out;
2446
+ }
2447
+
2448
+ /* Overwrite power saving configuration from eeprom */
2449
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL |
2450
+ (ax772b_data->psc & 0x7FFF), 0, 0, NULL);
2451
+
2452
+ if (ret < 0) {
2453
+ deverr(dev, "Failed to configure PHY power saving: %d", ret);
2454
+ goto err_out;
2455
+ }
2456
+
2457
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
2458
+ netif_carrier_on(dev->net);
2459
+
2460
+ kfree(buf);
2461
+
2462
+ return ret;
2463
+err_out:
2464
+ destroy_workqueue(ax772b_data->ax_work);
2465
+ kfree(buf);
2466
+ kfree(ax772b_data);
2467
+ return ret;
2468
+}
2469
+
2470
+static int ax88772b_external_phyinit(struct usbnet *dev) {
2471
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2472
+ u16 phyid1, phyid2;
2473
+
2474
+ phyid1 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x02);
2475
+ phyid2 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x03);
2476
+ ax772b_data->ext_phy_oui = EXTPHY_ID_MASK_OUI(phyid1, phyid2);
2477
+ ax772b_data->ext_phy_model = EXTPHY_ID_MASK_MODEL(phyid2);
2478
+
2479
+ if (ax772b_data->ext_phy_oui == EXTPHY_BROADCOM_OUI) {
2480
+ if(ax772b_data->ext_phy_model == EXTPHY_BCM89811_MODEL) {
2481
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x0, 0x8000);
2482
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2483
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2484
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2485
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2486
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2487
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2488
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1F, 0x0c00);
2489
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1E, 0x030A);
2490
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1F, 0x3440);
2491
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1E, 0x0166);
2492
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1F, 0x0020);
2493
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x012D);
2494
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x9B52);
2495
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x012E);
2496
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0xA04D);
2497
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0123);
2498
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x00c0);
2499
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0154);
2500
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x81C4);
2501
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0811);
2502
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0000);
2503
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x01D3);
2504
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0064);
2505
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x01C1);
2506
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0xA5F7);
2507
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2508
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0400);
2509
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x001D);
2510
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x3411);
2511
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0820);
2512
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0401);
2513
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x002F);
2514
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0xF167);
2515
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0045);
2516
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0500);
2517
+ return 0;
2518
+ }
2519
+ }
2520
+
2521
+ return 0;
2522
+}
2523
+
2524
+static void ax88772b_unbind(struct usbnet *dev, struct usb_interface *intf)
2525
+{
2526
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2527
+
2528
+ if (ax772b_data) {
2529
+
2530
+ flush_workqueue(ax772b_data->ax_work);
2531
+ destroy_workqueue(ax772b_data->ax_work);
2532
+
2533
+ /* stop MAC operation */
2534
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
2535
+ AX_RX_CTL_STOP, 0, 0, NULL);
2536
+
2537
+ /* Power down PHY */
2538
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
2539
+ AX_SWRESET_IPPD, 0, 0, NULL);
2540
+
2541
+ kfree(ax772b_data);
2542
+ }
2543
+}
2544
+
2545
+static int
2546
+ax88178_media_check(struct usbnet *dev, struct ax88178_data *ax178dataptr)
2547
+{
2548
+ int fullduplex, i = 0;
2549
+ u16 tempshort = 0;
2550
+ u16 media;
2551
+ u16 advertise, lpa, result, stat1000, _lpa, _stat1000, delay = 5 * HZ;
2552
+ unsigned long jtimeout;
2553
+
2554
+ jtimeout = jiffies + delay;
2555
+ do {
2556
+ _lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
2557
+ _stat1000 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
2558
+ MII_STAT1000);
2559
+
2560
+ lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
2561
+ stat1000 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
2562
+ MII_STAT1000);
2563
+
2564
+ if (time_after(jiffies, jtimeout))
2565
+ break;
2566
+
2567
+ } while ((_lpa != lpa) || (_stat1000 != stat1000) || i++ < 3);
2568
+
2569
+ advertise = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
2570
+ MII_ADVERTISE);
2571
+ result = advertise & lpa;
2572
+
2573
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2574
+ (ax178dataptr->LedMode == 1)) {
2575
+ tempshort = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
2576
+ MARVELL_MANUAL_LED) & 0xfc0f;
2577
+ }
2578
+
2579
+ fullduplex = 1;
2580
+ if (stat1000 & LPA_1000FULL) {
2581
+ media = MEDIUM_GIGA_MODE | MEDIUM_FULL_DUPLEX_MODE |
2582
+ MEDIUM_ENABLE_125MHZ | MEDIUM_ENABLE_RECEIVE;
2583
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2584
+ (ax178dataptr->LedMode == 1))
2585
+ tempshort |= 0x3e0;
2586
+ } else if (result & LPA_100FULL) {
2587
+ media = MEDIUM_FULL_DUPLEX_MODE | MEDIUM_ENABLE_RECEIVE |
2588
+ MEDIUM_MII_100M_MODE;
2589
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2590
+ (ax178dataptr->LedMode == 1))
2591
+ tempshort |= 0x3b0;
2592
+ } else if (result & LPA_100HALF) {
2593
+ fullduplex = 0;
2594
+ media = MEDIUM_ENABLE_RECEIVE | MEDIUM_MII_100M_MODE;
2595
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2596
+ (ax178dataptr->LedMode == 1))
2597
+ tempshort |= 0x3b0;
2598
+ } else if (result & LPA_10FULL) {
2599
+ media = MEDIUM_FULL_DUPLEX_MODE | MEDIUM_ENABLE_RECEIVE;
2600
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2601
+ (ax178dataptr->LedMode == 1))
2602
+ tempshort |= 0x2f0;
2603
+ } else {
2604
+ media = MEDIUM_ENABLE_RECEIVE;
2605
+ fullduplex = 0;
2606
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2607
+ (ax178dataptr->LedMode == 1))
2608
+ tempshort |= 0x02f0;
2609
+ }
2610
+
2611
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2612
+ (ax178dataptr->LedMode == 1)) {
2613
+ ax8817x_mdio_write_le(dev->net,
2614
+ dev->mii.phy_id, MARVELL_MANUAL_LED, tempshort);
2615
+ }
2616
+
2617
+ media |= 0x0004;
2618
+ if (ax178dataptr->UseRgmii)
2619
+ media |= 0x0008;
2620
+ if (fullduplex) {
2621
+ media |= 0x0020; /* ebable tx flow control as default; */
2622
+ media |= 0x0010; /* ebable rx flow control as default; */
2623
+ }
2624
+
2625
+ return media;
2626
+}
2627
+
2628
+static void Vitess_8601_Init(struct usbnet *dev, int state)
2629
+{
2630
+ u16 reg;
2631
+
2632
+ switch (state) {
2633
+ case 0: /* tx, rx clock skew */
2634
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 31, 1);
2635
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 28, 0);
2636
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 31, 0);
2637
+ break;
2638
+
2639
+ case 1:
2640
+ ax8817x_swmii_mdio_write_le(dev->net,
2641
+ dev->mii.phy_id, 31, 0x52B5);
2642
+ ax8817x_swmii_mdio_write_le(dev->net,
2643
+ dev->mii.phy_id, 18, 0x009E);
2644
+ ax8817x_swmii_mdio_write_le(dev->net,
2645
+ dev->mii.phy_id, 17, 0xDD39);
2646
+ ax8817x_swmii_mdio_write_le(dev->net,
2647
+ dev->mii.phy_id, 16, 0x87AA);
2648
+
2649
+ ax8817x_swmii_mdio_write_le(dev->net,
2650
+ dev->mii.phy_id, 16, 0xA7B4);
2651
+
2652
+ ax8817x_swmii_mdio_write_le(dev->net,
2653
+ dev->mii.phy_id, 18,
2654
+ ax8817x_swmii_mdio_read_le(dev->net,
2655
+ dev->mii.phy_id, 18));
2656
+
2657
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2658
+ dev->mii.phy_id, 17) & ~0x003f) | 0x003c;
2659
+ ax8817x_swmii_mdio_write_le(dev->net,
2660
+ dev->mii.phy_id, 17, reg);
2661
+ ax8817x_swmii_mdio_write_le(dev->net,
2662
+ dev->mii.phy_id, 16, 0x87B4);
2663
+
2664
+ ax8817x_swmii_mdio_write_le(dev->net,
2665
+ dev->mii.phy_id, 16, 0xa794);
2666
+
2667
+ ax8817x_swmii_mdio_write_le(dev->net,
2668
+ dev->mii.phy_id, 18,
2669
+ ax8817x_swmii_mdio_read_le(dev->net,
2670
+ dev->mii.phy_id, 18));
2671
+
2672
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2673
+ dev->mii.phy_id, 17) & ~0x003f) | 0x003e;
2674
+ ax8817x_swmii_mdio_write_le(dev->net,
2675
+ dev->mii.phy_id, 17, reg);
2676
+ ax8817x_swmii_mdio_write_le(dev->net,
2677
+ dev->mii.phy_id, 16, 0x8794);
2678
+
2679
+ ax8817x_swmii_mdio_write_le(dev->net,
2680
+ dev->mii.phy_id, 18, 0x00f7);
2681
+ ax8817x_swmii_mdio_write_le(dev->net,
2682
+ dev->mii.phy_id, 17, 0xbe36);
2683
+ ax8817x_swmii_mdio_write_le(dev->net,
2684
+ dev->mii.phy_id, 16, 0x879e);
2685
+
2686
+ ax8817x_swmii_mdio_write_le(dev->net,
2687
+ dev->mii.phy_id, 16, 0xa7a0);
2688
+
2689
+ ax8817x_swmii_mdio_write_le(dev->net,
2690
+ dev->mii.phy_id, 18,
2691
+ ax8817x_swmii_mdio_read_le(dev->net,
2692
+ dev->mii.phy_id, 18));
2693
+
2694
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2695
+ dev->mii.phy_id, 17) & ~0x003f) | 0x0034;
2696
+ ax8817x_swmii_mdio_write_le(dev->net,
2697
+ dev->mii.phy_id, 17, reg);
2698
+ ax8817x_swmii_mdio_write_le(dev->net,
2699
+ dev->mii.phy_id, 16, 0x87a0);
2700
+
2701
+ ax8817x_swmii_mdio_write_le(dev->net,
2702
+ dev->mii.phy_id, 18, 0x003c);
2703
+ ax8817x_swmii_mdio_write_le(dev->net,
2704
+ dev->mii.phy_id, 17, 0xf3cf);
2705
+ ax8817x_swmii_mdio_write_le(dev->net,
2706
+ dev->mii.phy_id, 16, 0x87a2);
2707
+
2708
+ ax8817x_swmii_mdio_write_le(dev->net,
2709
+ dev->mii.phy_id, 18, 0x003c);
2710
+ ax8817x_swmii_mdio_write_le(dev->net,
2711
+ dev->mii.phy_id, 17, 0xf3cf);
2712
+ ax8817x_swmii_mdio_write_le(dev->net,
2713
+ dev->mii.phy_id, 16, 0x87a4);
2714
+
2715
+ ax8817x_swmii_mdio_write_le(dev->net,
2716
+ dev->mii.phy_id, 18, 0x003c);
2717
+ ax8817x_swmii_mdio_write_le(dev->net,
2718
+ dev->mii.phy_id, 17, 0xd287);
2719
+ ax8817x_swmii_mdio_write_le(dev->net,
2720
+ dev->mii.phy_id, 16, 0x87a6);
2721
+
2722
+ ax8817x_swmii_mdio_write_le(dev->net,
2723
+ dev->mii.phy_id, 16, 0xa7a8);
2724
+
2725
+ ax8817x_swmii_mdio_write_le(dev->net,
2726
+ dev->mii.phy_id, 18,
2727
+ ax8817x_swmii_mdio_read_le(dev->net,
2728
+ dev->mii.phy_id, 18));
2729
+
2730
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2731
+ dev->mii.phy_id, 17) & ~0x0fff) | 0x0125;
2732
+ ax8817x_swmii_mdio_write_le(dev->net,
2733
+ dev->mii.phy_id, 17, reg);
2734
+ ax8817x_swmii_mdio_write_le(dev->net,
2735
+ dev->mii.phy_id, 16, 0x87a8);
2736
+
2737
+ /* Enable Smart Pre-emphasis */
2738
+ ax8817x_swmii_mdio_write_le(dev->net,
2739
+ dev->mii.phy_id, 16, 0xa7fa);
2740
+
2741
+ ax8817x_swmii_mdio_write_le(dev->net,
2742
+ dev->mii.phy_id, 18,
2743
+ ax8817x_swmii_mdio_read_le(dev->net,
2744
+ dev->mii.phy_id, 18));
2745
+
2746
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2747
+ dev->mii.phy_id, 17) & ~0x0008) | 0x0008;
2748
+
2749
+ ax8817x_swmii_mdio_write_le(dev->net,
2750
+ dev->mii.phy_id, 17, reg);
2751
+ ax8817x_swmii_mdio_write_le(dev->net,
2752
+ dev->mii.phy_id, 16, 0x87fa);
2753
+
2754
+ ax8817x_swmii_mdio_write_le(dev->net,
2755
+ dev->mii.phy_id, 31, 0);
2756
+
2757
+ break;
2758
+ }
2759
+}
2760
+
2761
+static void
2762
+marvell_88E1510_magic_init(struct usbnet *dev)
2763
+{
2764
+ ax8817x_swmii_mdio_write_le(dev->net,
2765
+ dev->mii.phy_id, 22, 0xff);
2766
+ ax8817x_swmii_mdio_write_le(dev->net,
2767
+ dev->mii.phy_id, 17, 0x214b);
2768
+ ax8817x_swmii_mdio_write_le(dev->net,
2769
+ dev->mii.phy_id, 16, 0x2144);
2770
+ ax8817x_swmii_mdio_write_le(dev->net,
2771
+ dev->mii.phy_id, 17, 0x0c28);
2772
+ ax8817x_swmii_mdio_write_le(dev->net,
2773
+ dev->mii.phy_id, 16, 0x2146);
2774
+ ax8817x_swmii_mdio_write_le(dev->net,
2775
+ dev->mii.phy_id, 17, 0xb233);
2776
+ ax8817x_swmii_mdio_write_le(dev->net,
2777
+ dev->mii.phy_id, 16, 0x214d);
2778
+ ax8817x_swmii_mdio_write_le(dev->net,
2779
+ dev->mii.phy_id, 17, 0xcc0c);
2780
+ ax8817x_swmii_mdio_write_le(dev->net,
2781
+ dev->mii.phy_id, 16, 0x2159);
2782
+ ax8817x_swmii_mdio_write_le(dev->net,
2783
+ dev->mii.phy_id, 22, 0x00fb);
2784
+ ax8817x_swmii_mdio_write_le(dev->net,
2785
+ dev->mii.phy_id, 7, 0xc00d);
2786
+ ax8817x_swmii_mdio_write_le(dev->net,
2787
+ dev->mii.phy_id, 22, 0);
2788
+}
2789
+
2790
+static int
2791
+ax88178_phy_init(struct usbnet *dev, struct ax88178_data *ax178dataptr)
2792
+{
2793
+ int i;
2794
+ u16 phyanar, phyauxctrl, phyctrl, tempshort, phyid1;
2795
+ u16 phyreg = 0;
2796
+
2797
+ /* Disable MII operation of AX88178 Hardware */
2798
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
2799
+
2800
+
2801
+ /* Read SROM - MiiPhy Address (ID) */
2802
+ ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, &dev->mii.phy_id);
2803
+ le32_to_cpus(&dev->mii.phy_id);
2804
+
2805
+ /* Initialize MII structure */
2806
+ dev->mii.phy_id >>= 8;
2807
+ dev->mii.phy_id &= PHY_ID_MASK;
2808
+ dev->mii.dev = dev->net;
2809
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
2810
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
2811
+ dev->mii.phy_id_mask = 0x3f;
2812
+ dev->mii.reg_num_mask = 0x1f;
2813
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 11)
2814
+ dev->mii.supports_gmii = 1;
2815
+#endif
2816
+
2817
+ if (ax178dataptr->PhyMode == PHY_MODE_MAC_TO_MAC_GMII) {
2818
+ ax178dataptr->UseRgmii = 0;
2819
+ ax178dataptr->MediaLink = MEDIUM_GIGA_MODE |
2820
+ MEDIUM_FULL_DUPLEX_MODE |
2821
+ MEDIUM_ENABLE_125MHZ |
2822
+ MEDIUM_ENABLE_RECEIVE |
2823
+ MEDIUM_ENABLE_RX_FLOWCTRL |
2824
+ MEDIUM_ENABLE_TX_FLOWCTRL;
2825
+ goto SKIPPHYSETTING;
2826
+ }
2827
+
2828
+ /* test read phy register 2 */
2829
+ if (!ax178dataptr->UseGpio0) {
2830
+ i = 1000;
2831
+ while (i--) {
2832
+ phyid1 = ax8817x_swmii_mdio_read_le(dev->net,
2833
+ dev->mii.phy_id, GMII_PHY_OUI);
2834
+ if ((phyid1 == 0x000f) || (phyid1 == 0x0141) ||
2835
+ (phyid1 == 0x0282) || (phyid1 == 0x004d) ||
2836
+ (phyid1 == 0x0243) || (phyid1 == 0x001C) ||
2837
+ (phyid1 == 0x0007))
2838
+ break;
2839
+ msleep(5);
2840
+ }
2841
+ if (i < 0)
2842
+ return -EIO;
2843
+ }
2844
+
2845
+ ax178dataptr->UseRgmii = 0;
2846
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
2847
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
2848
+ dev->mii.phy_id, 27);
2849
+ if (!(phyreg & 4) && !(ax178dataptr->LedMode & 0x10)) {
2850
+ ax178dataptr->UseRgmii = 1;
2851
+ ax8817x_swmii_mdio_write_le(dev->net,
2852
+ dev->mii.phy_id, 20, 0x82);
2853
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2854
+ } else if (ax178dataptr->LedMode & 0x10) {
2855
+
2856
+ ax178dataptr->UseRgmii = 1;
2857
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2858
+ marvell_88E1510_magic_init(dev);
2859
+
2860
+ ax8817x_swmii_mdio_write_le(dev->net,
2861
+ dev->mii.phy_id, 22, 2);
2862
+
2863
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
2864
+ dev->mii.phy_id, 21);
2865
+
2866
+ ax8817x_swmii_mdio_write_le(dev->net,
2867
+ dev->mii.phy_id, 21, phyreg | 0x30);
2868
+
2869
+ ax8817x_swmii_mdio_write_le(dev->net,
2870
+ dev->mii.phy_id, 22, 0);
2871
+ }
2872
+ } else if ((ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) ||
2873
+ (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0_GMII)) {
2874
+ if (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) {
2875
+ ax178dataptr->UseRgmii = 1;
2876
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2877
+ }
2878
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V1) {
2879
+ /* not Cameo */
2880
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode) {
2881
+ ax178dataptr->UseRgmii = 1;
2882
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2883
+ }
2884
+
2885
+ for (i = 0; i < (sizeof(CICADA_FAMILY_HWINIT) /
2886
+ sizeof(CICADA_FAMILY_HWINIT[0])); i++) {
2887
+ ax8817x_swmii_mdio_write_le(dev->net,
2888
+ dev->mii.phy_id,
2889
+ CICADA_FAMILY_HWINIT[i].offset,
2890
+ CICADA_FAMILY_HWINIT[i].value);
2891
+ }
2892
+
2893
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2) {
2894
+ /* not Cameo */
2895
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode) {
2896
+ ax178dataptr->UseRgmii = 1;
2897
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2898
+ }
2899
+
2900
+ for (i = 0; i < (sizeof(CICADA_V2_HWINIT) /
2901
+ sizeof(CICADA_V2_HWINIT[0])); i++) {
2902
+ ax8817x_swmii_mdio_write_le(dev->net,
2903
+ dev->mii.phy_id, CICADA_V2_HWINIT[i].offset,
2904
+ CICADA_V2_HWINIT[i].value);
2905
+ }
2906
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX) {
2907
+ /* not Cameo */
2908
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode) {
2909
+ ax178dataptr->UseRgmii = 1;
2910
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2911
+ }
2912
+
2913
+ for (i = 0; i < (sizeof(CICADA_V2_HWINIT) /
2914
+ sizeof(CICADA_V2_HWINIT[0])); i++) {
2915
+ ax8817x_swmii_mdio_write_le(dev->net,
2916
+ dev->mii.phy_id, CICADA_V2_HWINIT[i].offset,
2917
+ CICADA_V2_HWINIT[i].value);
2918
+ }
2919
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211CL) {
2920
+ ax178dataptr->UseRgmii = 1;
2921
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2922
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211BN) {
2923
+ ax178dataptr->UseRgmii = 1;
2924
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2925
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8251CL) {
2926
+ ax178dataptr->UseRgmii = 1;
2927
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2928
+ } else if (ax178dataptr->PhyMode == PHY_MODE_VSC8601) {
2929
+ ax178dataptr->UseRgmii = 1;
2930
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2931
+ /* Vitess_8601_Init (dev, 0); */
2932
+ }
2933
+
2934
+ if (ax178dataptr->PhyMode != PHY_MODE_ATTANSIC_V0) {
2935
+ /* software reset */
2936
+ ax8817x_swmii_mdio_write_le(
2937
+ dev->net, dev->mii.phy_id, GMII_PHY_CONTROL,
2938
+ ax8817x_swmii_mdio_read_le(
2939
+ dev->net, dev->mii.phy_id, GMII_PHY_CONTROL)
2940
+ | GMII_CONTROL_RESET);
2941
+ msleep(1);
2942
+ }
2943
+
2944
+ if ((ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) ||
2945
+ (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0_GMII)) {
2946
+ if (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) {
2947
+ i = 1000;
2948
+ while (i--) {
2949
+ ax8817x_swmii_mdio_write_le(dev->net,
2950
+ dev->mii.phy_id, 21, 0x1001);
2951
+
2952
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
2953
+ dev->mii.phy_id, 21);
2954
+ if ((phyreg & 0xf00f) == 0x1001)
2955
+ break;
2956
+ }
2957
+ if (i < 0)
2958
+ return -EIO;
2959
+ }
2960
+
2961
+ if (ax178dataptr->LedMode == 4) {
2962
+ ax8817x_swmii_mdio_write_le(dev->net,
2963
+ dev->mii.phy_id, 28, 0x7417);
2964
+ } else if (ax178dataptr->LedMode == 9) {
2965
+ ax8817x_swmii_mdio_write_le(dev->net,
2966
+ dev->mii.phy_id, 28, 0x7a10);
2967
+ } else if (ax178dataptr->LedMode == 10) {
2968
+ ax8817x_swmii_mdio_write_le(dev->net,
2969
+ dev->mii.phy_id, 28, 0x7a13);
2970
+ }
2971
+
2972
+ for (i = 0; i < (sizeof(AGERE_FAMILY_HWINIT) /
2973
+ sizeof(AGERE_FAMILY_HWINIT[0])); i++) {
2974
+ ax8817x_swmii_mdio_write_le(dev->net,
2975
+ dev->mii.phy_id, AGERE_FAMILY_HWINIT[i].offset,
2976
+ AGERE_FAMILY_HWINIT[i].value);
2977
+ }
2978
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211CL) {
2979
+
2980
+ ax8817x_swmii_mdio_write_le(dev->net,
2981
+ dev->mii.phy_id, 0x1f, 0x0005);
2982
+ ax8817x_swmii_mdio_write_le(dev->net,
2983
+ dev->mii.phy_id, 0x0c, 0);
2984
+
2985
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 0x01,
2986
+ (ax8817x_swmii_mdio_read_le(dev->net,
2987
+ dev->mii.phy_id, 0x01) | 0x0080));
2988
+ ax8817x_swmii_mdio_write_le(dev->net,
2989
+ dev->mii.phy_id, 0x1f, 0);
2990
+
2991
+ if (ax178dataptr->LedMode == 12) {
2992
+ ax8817x_swmii_mdio_write_le(dev->net,
2993
+ dev->mii.phy_id, 0x1f, 0x0002);
2994
+ ax8817x_swmii_mdio_write_le(dev->net,
2995
+ dev->mii.phy_id, 0x1a, 0x00cb);
2996
+ ax8817x_swmii_mdio_write_le(dev->net,
2997
+ dev->mii.phy_id, 0x1f, 0);
2998
+ }
2999
+ } else if (ax178dataptr->PhyMode == PHY_MODE_VSC8601) {
3000
+ Vitess_8601_Init(dev, 1);
3001
+ }
3002
+
3003
+ /* read phy register 0 */
3004
+ phyctrl = ax8817x_swmii_mdio_read_le(dev->net,
3005
+ dev->mii.phy_id, GMII_PHY_CONTROL);
3006
+ tempshort = phyctrl;
3007
+ phyctrl &= ~(GMII_CONTROL_POWER_DOWN | GMII_CONTROL_ISOLATE);
3008
+ if (phyctrl != tempshort) {
3009
+ ax8817x_swmii_mdio_write_le(dev->net,
3010
+ dev->mii.phy_id, GMII_PHY_CONTROL, phyctrl);
3011
+ }
3012
+
3013
+ /* LED */
3014
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
3015
+ if (ax178dataptr->LedMode == 1) {
3016
+
3017
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
3018
+ dev->mii.phy_id, 24) & 0xf8ff) | (1 + 0x100);
3019
+ ax8817x_swmii_mdio_write_le(dev->net,
3020
+ dev->mii.phy_id, 24, phyreg);
3021
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
3022
+ dev->mii.phy_id, 25) & 0xfc0f;
3023
+ } else if (ax178dataptr->LedMode == 2) {
3024
+
3025
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
3026
+ dev->mii.phy_id, 24) & 0xf886) |
3027
+ (1 + 0x10 + 0x300);
3028
+ ax8817x_swmii_mdio_write_le(dev->net,
3029
+ dev->mii.phy_id, 24, phyreg);
3030
+ } else if (ax178dataptr->LedMode == 5) {
3031
+
3032
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
3033
+ dev->mii.phy_id, 24) & 0xf8be) |
3034
+ (1 + 0x40 + 0x300);
3035
+ ax8817x_swmii_mdio_write_le(dev->net,
3036
+ dev->mii.phy_id, 24, phyreg);
3037
+ } else if (ax178dataptr->LedMode == 7) {
3038
+
3039
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
3040
+ dev->mii.phy_id, 24) & 0xf8ff) |
3041
+ (1 + 0x100);
3042
+ ax8817x_swmii_mdio_write_le(dev->net,
3043
+ dev->mii.phy_id, 24, phyreg);
3044
+
3045
+ } else if (ax178dataptr->LedMode == 8) {
3046
+
3047
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
3048
+ dev->mii.phy_id, 24) & 0xf8be) |
3049
+ (1 + 0x40 + 0x100);
3050
+ ax8817x_swmii_mdio_write_le(dev->net,
3051
+ dev->mii.phy_id, 24, phyreg);
3052
+
3053
+ } else if (ax178dataptr->LedMode == 11) {
3054
+
3055
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
3056
+ dev->mii.phy_id, 24) & 0x4106;
3057
+ ax8817x_swmii_mdio_write_le(dev->net,
3058
+ dev->mii.phy_id, 24, phyreg);
3059
+ } else if (ax178dataptr->LedMode == 0x10) {
3060
+ /* MARVEL 88e1510 use default led setting */
3061
+ }
3062
+
3063
+ } else if ((ax178dataptr->PhyMode == PHY_MODE_CICADA_V1) ||
3064
+ (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2) ||
3065
+ (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX)) {
3066
+
3067
+ if (ax178dataptr->LedMode == 3) {
3068
+
3069
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
3070
+ dev->mii.phy_id, 27) & 0xFCFF) | 0x0100;
3071
+ ax8817x_swmii_mdio_write_le(dev->net,
3072
+ dev->mii.phy_id, 27, phyreg);
3073
+ }
3074
+
3075
+ }
3076
+
3077
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
3078
+ if (ax178dataptr->LedMode == 1)
3079
+ phyreg |= 0x3f0;
3080
+ }
3081
+
3082
+ phyanar = 1 | (GMII_ANAR_PAUSE | GMII_ANAR_100TXFD | GMII_ANAR_100TX |
3083
+ GMII_ANAR_10TFD | GMII_ANAR_10T | GMII_ANAR_ASYM_PAUSE);
3084
+
3085
+ phyauxctrl = GMII_1000_AUX_CTRL_FD_CAPABLE;
3086
+
3087
+ ax8817x_swmii_mdio_write_le(dev->net,
3088
+ dev->mii.phy_id, GMII_PHY_ANAR, phyanar);
3089
+ ax8817x_swmii_mdio_write_le(dev->net,
3090
+ dev->mii.phy_id, GMII_PHY_1000BT_CONTROL, phyauxctrl);
3091
+
3092
+ if (ax178dataptr->PhyMode == PHY_MODE_VSC8601) {
3093
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
3094
+ 31, 0x52B5);
3095
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
3096
+ 16, 0xA7F8);
3097
+
3098
+ tempshort = ax8817x_swmii_mdio_read_le(dev->net,
3099
+ dev->mii.phy_id, 17) & (~0x0018);
3100
+
3101
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
3102
+ 17, tempshort);
3103
+
3104
+ tempshort = ax8817x_swmii_mdio_read_le(dev->net,
3105
+ dev->mii.phy_id, 18);
3106
+
3107
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 18,
3108
+ tempshort);
3109
+
3110
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
3111
+ 16, 0x87F8);
3112
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
3113
+ 31, 0);
3114
+ }
3115
+
3116
+ if (ax178dataptr->PhyMode == PHY_MODE_ATTANSIC_V0) {
3117
+ ax8817x_swmii_mdio_write_le(dev->net,
3118
+ dev->mii.phy_id, GMII_PHY_CONTROL, 0x9000);
3119
+
3120
+ } else {
3121
+ phyctrl &= ~GMII_CONTROL_LOOPBACK;
3122
+ phyctrl |= (GMII_CONTROL_ENABLE_AUTO | GMII_CONTROL_START_AUTO);
3123
+
3124
+ ax8817x_swmii_mdio_write_le(dev->net,
3125
+ dev->mii.phy_id, GMII_PHY_CONTROL, phyctrl);
3126
+ }
3127
+
3128
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
3129
+ if (ax178dataptr->LedMode == 1)
3130
+ ax8817x_swmii_mdio_write_le(dev->net,
3131
+ dev->mii.phy_id, 25, phyreg);
3132
+ }
3133
+
3134
+SKIPPHYSETTING:
3135
+
3136
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
3137
+ ax178dataptr->MediaLink, 0, 0, NULL);
3138
+
3139
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
3140
+ AX88772_IPG0_DEFAULT | (AX88772_IPG1_DEFAULT << 8),
3141
+ AX88772_IPG2_DEFAULT, 0, NULL);
3142
+
3143
+ msleep(1);
3144
+
3145
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
3146
+
3147
+ return 0;
3148
+}
3149
+
3150
+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
3151
+{
3152
+ int ret;
3153
+ void *buf;
3154
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
3155
+ struct ax88178_data *ax178dataptr = NULL;
3156
+
3157
+ axusbnet_get_endpoints(dev, intf);
3158
+
3159
+ buf = kmalloc(6, GFP_KERNEL);
3160
+ if (!buf) {
3161
+ deverr(dev, "Cannot allocate memory for buffer");
3162
+ return -ENOMEM;
3163
+ }
3164
+
3165
+ /* allocate 178 data */
3166
+ ax178dataptr = kmalloc(sizeof(*ax178dataptr), GFP_KERNEL);
3167
+ if (!ax178dataptr) {
3168
+ deverr(dev, "Cannot allocate memory for AX88178 data");
3169
+ ret = -ENOMEM;
3170
+ goto error_out;
3171
+ }
3172
+ memset(ax178dataptr, 0, sizeof(struct ax88178_data));
3173
+ dev->priv = ax178dataptr;
3174
+ /* end of allocate 178 data */
3175
+
3176
+ /* Get the EEPROM data*/
3177
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2,
3178
+ (void *)(&ax178dataptr->EepromData));
3179
+ if (ret < 0) {
3180
+ deverr(dev, "read SROM address 17h failed: %d", ret);
3181
+ goto error_out;
3182
+ }
3183
+ le16_to_cpus(&ax178dataptr->EepromData);
3184
+ /* End of get EEPROM data */
3185
+
3186
+ if (ax178dataptr->EepromData == 0xffff) {
3187
+ ax178dataptr->PhyMode = PHY_MODE_MARVELL;
3188
+ ax178dataptr->LedMode = 0;
3189
+ ax178dataptr->UseGpio0 = 1; /* True */
3190
+ } else {
3191
+ ax178dataptr->PhyMode = (u8)(ax178dataptr->EepromData &
3192
+ EEPROMMASK);
3193
+ ax178dataptr->LedMode = (u8)(ax178dataptr->EepromData >> 8);
3194
+
3195
+ /* for buffalo new (use gpio2) */
3196
+ if (ax178dataptr->LedMode == 6)
3197
+ ax178dataptr->LedMode = 1;
3198
+ else if (ax178dataptr->LedMode == 1)
3199
+ ax178dataptr->BuffaloOld = 1;
3200
+
3201
+
3202
+ if (ax178dataptr->EepromData & 0x80)
3203
+ ax178dataptr->UseGpio0 = 0; /* MARVEL se and other */
3204
+ else
3205
+ ax178dataptr->UseGpio0 = 1; /* cameo */
3206
+ }
3207
+
3208
+ if (ax178dataptr->UseGpio0) {
3209
+
3210
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
3211
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3212
+ AXGPIOS_GPO0EN | AXGPIOS_RSE,
3213
+ 0, 0, NULL);
3214
+ if (ret < 0) {
3215
+ deverr(dev, "write GPIO failed: %d", ret);
3216
+ goto error_out;
3217
+ }
3218
+
3219
+ msleep(25);
3220
+
3221
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3222
+ (AXGPIOS_GPO2 | AXGPIOS_GPO2EN |
3223
+ AXGPIOS_GPO0EN), 0, 0, NULL);
3224
+ if (ret < 0) {
3225
+ deverr(dev, "write GPIO failed: %d", ret);
3226
+ goto error_out;
3227
+ }
3228
+
3229
+ msleep(15);
3230
+
3231
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3232
+ AXGPIOS_GPO2EN | AXGPIOS_GPO0EN,
3233
+ 0, 0, NULL);
3234
+ if (ret < 0) {
3235
+ deverr(dev, "write GPIO failed: %d", ret);
3236
+ goto error_out;
3237
+ }
3238
+
3239
+ msleep(245);
3240
+
3241
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3242
+ (AXGPIOS_GPO2 | AXGPIOS_GPO2EN |
3243
+ AXGPIOS_GPO0EN), 0, 0, NULL);
3244
+ if (ret < 0) {
3245
+ deverr(dev, "write GPIO failed: %d", ret);
3246
+ goto error_out;
3247
+ }
3248
+
3249
+ } else { /* vitesse */
3250
+
3251
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3252
+ (AXGPIOS_RSE | AXGPIOS_GPO0EN |
3253
+ AXGPIOS_GPO0), 0, 0, NULL);
3254
+ if (ret < 0) {
3255
+ deverr(dev, "write GPIO failed: %d", ret);
3256
+ goto error_out;
3257
+ }
3258
+
3259
+ msleep(25);
3260
+
3261
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3262
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
3263
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
3264
+ 0, 0, NULL);
3265
+ if (ret < 0) {
3266
+ deverr(dev, "write GPIO failed: %d", ret);
3267
+ goto error_out;
3268
+ }
3269
+
3270
+ msleep(25);
3271
+
3272
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3273
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
3274
+ AXGPIOS_GPO2EN), 0, 0, NULL);
3275
+ if (ret < 0) {
3276
+ deverr(dev, "write GPIO failed: %d", ret);
3277
+ goto error_out;
3278
+ }
3279
+
3280
+ msleep(245);
3281
+
3282
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3283
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
3284
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
3285
+ 0, 0, NULL);
3286
+ if (ret < 0) {
3287
+ deverr(dev, "write GPIO failed: %d", ret);
3288
+ goto error_out;
3289
+ }
3290
+ }
3291
+ } else { /* use gpio1 */
3292
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3293
+ (AXGPIOS_GPO1 | AXGPIOS_GPO1EN |
3294
+ AXGPIOS_RSE), 0, 0, NULL);
3295
+ if (ret < 0) {
3296
+ deverr(dev, "write GPIO failed: %d", ret);
3297
+ goto error_out;
3298
+ }
3299
+
3300
+ if (ax178dataptr->BuffaloOld) {
3301
+ msleep(350);
3302
+
3303
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3304
+ AXGPIOS_GPO1EN, 0, 0, NULL);
3305
+ if (ret < 0) {
3306
+ deverr(dev, "write GPIO failed: %d", ret);
3307
+ goto error_out;
3308
+ }
3309
+
3310
+ msleep(350);
3311
+
3312
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3313
+ AXGPIOS_GPO1EN | AXGPIOS_GPO1,
3314
+ 0, 0, NULL);
3315
+ if (ret < 0) {
3316
+ deverr(dev, "write GPIO failed: %d", ret);
3317
+ goto error_out;
3318
+ }
3319
+ } else {
3320
+ msleep(25);
3321
+
3322
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3323
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
3324
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
3325
+ 0, 0, NULL);
3326
+ if (ret < 0) {
3327
+ deverr(dev, "write GPIO failed: %d", ret);
3328
+ goto error_out;
3329
+ }
3330
+
3331
+ msleep(25);
3332
+
3333
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3334
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
3335
+ AXGPIOS_GPO2EN), 0, 0, NULL);
3336
+ if (ret < 0) {
3337
+ deverr(dev, "write GPIO failed: %d", ret);
3338
+ goto error_out;
3339
+ }
3340
+
3341
+ msleep(245);
3342
+
3343
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3344
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
3345
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
3346
+ 0, 0, NULL);
3347
+ if (ret < 0) {
3348
+ deverr(dev, "write GPIO failed: %d", ret);
3349
+ goto error_out;
3350
+ }
3351
+ }
3352
+ }
3353
+
3354
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL);
3355
+ if (ret < 0) {
3356
+ deverr(dev, "Select PHY failed: %d", ret);
3357
+ goto error_out;
3358
+ }
3359
+
3360
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD |
3361
+ AX_SWRESET_PRL, 0, 0, NULL);
3362
+ if (ret < 0) {
3363
+ deverr(dev, "Issue sw reset failed: %d", ret);
3364
+ goto error_out;
3365
+ }
3366
+
3367
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0, 0, 0, NULL);
3368
+ if (ret < 0) {
3369
+ deverr(dev, "Issue rx ctrl failed: %d", ret);
3370
+ goto error_out;
3371
+ }
3372
+
3373
+ /* Get the MAC address */
3374
+ memset(buf, 0, ETH_ALEN);
3375
+ ax8817x_get_mac(dev, buf);
3376
+ if (ret < 0)
3377
+ goto error_out;
3378
+ /* End of get MAC address */
3379
+
3380
+ ret = ax88178_phy_init(dev, ax178dataptr);
3381
+ if (ret < 0)
3382
+ goto error_out;
3383
+
3384
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
3385
+ dev->net->do_ioctl = ax8817x_ioctl;
3386
+ dev->net->set_multicast_list = ax88178_set_multicast;
3387
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
3388
+#else
3389
+ dev->net->netdev_ops = &ax88178_netdev_ops;
3390
+#endif
3391
+ dev->net->ethtool_ops = &ax8817x_ethtool_ops;
3392
+
3393
+ /* Register suspend and resume functions */
3394
+ data->suspend = ax88772_suspend;
3395
+ data->resume = ax88772_resume;
3396
+
3397
+ if (dev->driver_info->flags & FLAG_FRAMING_AX)
3398
+ dev->rx_urb_size = 16384;
3399
+
3400
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, (AX_RX_CTL_MFB |
3401
+ AX_RX_CTL_START | AX_RX_CTL_AB), 0, 0, NULL);
3402
+ if (ret < 0) {
3403
+ deverr(dev, "write RX ctrl reg failed: %d", ret);
3404
+ goto error_out;
3405
+ }
3406
+
3407
+ kfree(buf);
3408
+ printk(version);
3409
+ return ret;
3410
+
3411
+error_out:
3412
+ kfree(ax178dataptr);
3413
+ kfree(buf);
3414
+ return ret;
3415
+}
3416
+
3417
+static void ax88178_unbind(struct usbnet *dev, struct usb_interface *intf)
3418
+{
3419
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
3420
+
3421
+ if (ax178dataptr) {
3422
+
3423
+ /* stop MAC operation */
3424
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
3425
+ AX_RX_CTL_STOP, 0, 0, NULL);
3426
+
3427
+ kfree(ax178dataptr);
3428
+ }
3429
+}
3430
+
3431
+static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
3432
+{
3433
+ u8 *head;
3434
+ u32 header;
3435
+ char *packet;
3436
+ struct sk_buff *ax_skb = NULL;
3437
+ u16 size;
3438
+
3439
+ head = (u8 *) skb->data;
3440
+ memcpy(&header, head, sizeof(header));
3441
+ le32_to_cpus(&header);
3442
+ packet = head + sizeof(header);
3443
+
3444
+ skb_pull(skb, 4);
3445
+
3446
+ while (skb->len > 0) {
3447
+ if ((short)(header & 0x00007ff) !=
3448
+ ~((short)(((header & 0xffff0000) | 0xf8000000) >> 16))) {
3449
+ deverr(dev, "header length data is error 0x%08x, %d\n",
3450
+ header, skb->len);
3451
+ }
3452
+ /* get the packet length */
3453
+ size = (u16) (header & 0x00007ff);
3454
+
3455
+ if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
3456
+
3457
+ /* Make sure ip header is aligned on 32-bit boundary */
3458
+ if (!((unsigned long)skb->data & 0x02)) {
3459
+ memmove(skb->data - 2, skb->data, size);
3460
+ skb->data -= 2;
3461
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3462
+ skb->tail = skb->data + size;
3463
+#else
3464
+ skb_set_tail_pointer(skb, size);
3465
+#endif
3466
+ }
3467
+ skb->truesize = size + sizeof(struct sk_buff);
3468
+ skb->len = size;
3469
+
3470
+ return 2;
3471
+ }
3472
+
3473
+ if (size > ETH_FRAME_LEN) {
3474
+ deverr(dev, "invalid rx length %d", size);
3475
+ return 0;
3476
+ }
3477
+#ifndef RX_SKB_COPY
3478
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
3479
+#else
3480
+ ax_skb = alloc_skb(size + NET_IP_ALIGN, GFP_ATOMIC);
3481
+ skb_reserve(ax_skb, NET_IP_ALIGN);
3482
+#endif
3483
+ if (ax_skb) {
3484
+#ifndef RX_SKB_COPY
3485
+ /* Make sure ip header is aligned on 32-bit boundary */
3486
+ if (!((unsigned long)packet & 0x02)) {
3487
+ memmove(packet - 2, packet, size);
3488
+ packet -= 2;
3489
+ }
3490
+ ax_skb->data = packet;
3491
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3492
+ ax_skb->tail = packet + size;
3493
+#else
3494
+ skb_set_tail_pointer(ax_skb, size);
3495
+#endif
3496
+
3497
+#else
3498
+ skb_put(ax_skb, size);
3499
+ memcpy(ax_skb->data, packet , size);
3500
+#endif
3501
+ ax_skb->truesize = size + sizeof(struct sk_buff);
3502
+ axusbnet_skb_return(dev, ax_skb);
3503
+
3504
+ } else {
3505
+ return 0;
3506
+ }
3507
+
3508
+ skb_pull(skb, (size + 1) & 0xfffe);
3509
+
3510
+ if (skb->len == 0)
3511
+ break;
3512
+
3513
+ head = (u8 *) skb->data;
3514
+ memcpy(&header, head, sizeof(header));
3515
+ le32_to_cpus(&header);
3516
+ packet = head + sizeof(header);
3517
+ skb_pull(skb, 4);
3518
+ }
3519
+
3520
+ if (skb->len < 0) {
3521
+ deverr(dev, "invalid rx length %d", skb->len);
3522
+ return 0;
3523
+ }
3524
+ return 1;
3525
+}
3526
+
3527
+static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
3528
+ gfp_t flags)
3529
+{
3530
+ int padlen = ((skb->len + 4) % 512) ? 0 : 4;
3531
+ u32 packet_len;
3532
+ u32 padbytes = 0xffff0000;
3533
+
3534
+#if (!AX_FORCE_BUFF_ALIGN)
3535
+ int headroom = skb_headroom(skb);
3536
+ int tailroom = skb_tailroom(skb);
3537
+
3538
+ if ((!skb_cloned(skb))
3539
+ && ((headroom + tailroom) >= (4 + padlen))) {
3540
+ if ((headroom < 4) || (tailroom < padlen)) {
3541
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
3542
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3543
+ skb->tail = skb->data + skb->len;
3544
+#else
3545
+ skb_set_tail_pointer(skb, skb->len);
3546
+#endif
3547
+ }
3548
+ } else
3549
+#endif
3550
+ {
3551
+ struct sk_buff *skb2;
3552
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
3553
+ dev_kfree_skb_any(skb);
3554
+ skb = skb2;
3555
+ if (!skb)
3556
+ return NULL;
3557
+ }
3558
+
3559
+ skb_push(skb, 4);
3560
+ packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
3561
+ cpu_to_le32s(&packet_len);
3562
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3563
+ memcpy(skb->data, &packet_len, sizeof(packet_len));
3564
+#else
3565
+ skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
3566
+#endif
3567
+
3568
+ if ((skb->len % 512) == 0) {
3569
+ cpu_to_le32s(&padbytes);
3570
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3571
+ memcpy(skb->tail, &padbytes, sizeof(padbytes));
3572
+#else
3573
+ memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
3574
+#endif
3575
+ skb_put(skb, sizeof(padbytes));
3576
+ }
3577
+ return skb;
3578
+}
3579
+
3580
+static void
3581
+ax88772b_rx_checksum(struct sk_buff *skb, struct ax88772b_rx_header *rx_hdr)
3582
+{
3583
+ skb->ip_summed = CHECKSUM_NONE;
3584
+
3585
+ /* checksum error bit is set */
3586
+ if (rx_hdr->l3_csum_err || rx_hdr->l4_csum_err)
3587
+ return;
3588
+
3589
+ /* It must be a TCP or UDP packet with a valid checksum */
3590
+ if ((rx_hdr->l4_type == AX_RXHDR_L4_TYPE_TCP) ||
3591
+ (rx_hdr->l4_type == AX_RXHDR_L4_TYPE_UDP)) {
3592
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
3593
+ }
3594
+}
3595
+
3596
+static int ax88772b_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
3597
+{
3598
+ struct ax88772b_rx_header rx_hdr;
3599
+ struct sk_buff *ax_skb = NULL;
3600
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
3601
+
3602
+ while (skb->len > 0) {
3603
+
3604
+ le16_to_cpus((u16 *)skb->data);
3605
+ le16_to_cpus(((u16 *)skb->data) + 1);
3606
+
3607
+ memcpy(&rx_hdr, skb->data, sizeof(struct ax88772b_rx_header));
3608
+
3609
+ if ((short)rx_hdr.len != (~((short)rx_hdr.len_bar) & 0x7FF))
3610
+ return 0;
3611
+
3612
+ if (rx_hdr.len > (ETH_FRAME_LEN + 4)) {
3613
+ deverr(dev, "invalid rx length %d", rx_hdr.len);
3614
+ return 0;
3615
+ }
3616
+
3617
+ if (skb->len - ((rx_hdr.len +
3618
+ sizeof(struct ax88772b_rx_header) + 3) &
3619
+ 0xfffc) == 0) {
3620
+ skb_pull(skb, sizeof(struct ax88772b_rx_header));
3621
+ skb->len = rx_hdr.len;
3622
+
3623
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3624
+ skb->tail = skb->data + rx_hdr.len;
3625
+#else
3626
+ skb_set_tail_pointer(skb, rx_hdr.len);
3627
+#endif
3628
+ skb->truesize = rx_hdr.len + sizeof(struct sk_buff);
3629
+
3630
+ if (ax772b_data->checksum & AX_RX_CHECKSUM)
3631
+ ax88772b_rx_checksum(skb, &rx_hdr);
3632
+
3633
+ return 2;
3634
+ }
3635
+#ifndef RX_SKB_COPY
3636
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
3637
+#else
3638
+ ax_skb = alloc_skb(rx_hdr.len + NET_IP_ALIGN, GFP_ATOMIC);
3639
+ skb_reserve(ax_skb, NET_IP_ALIGN);
3640
+#endif
3641
+ if (ax_skb) {
3642
+#ifndef RX_SKB_COPY
3643
+ ax_skb->len = rx_hdr.len;
3644
+ ax_skb->data = skb->data +
3645
+ sizeof(struct ax88772b_rx_header);
3646
+
3647
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3648
+ ax_skb->tail = ax_skb->data + rx_hdr.len;
3649
+#else
3650
+ skb_set_tail_pointer(ax_skb, rx_hdr.len);
3651
+#endif
3652
+
3653
+#else
3654
+ skb_put(ax_skb, rx_hdr.len);
3655
+ memcpy(ax_skb->data, skb->data + sizeof(struct ax88772b_rx_header), rx_hdr.len);
3656
+#endif
3657
+
3658
+ ax_skb->truesize = rx_hdr.len + sizeof(struct sk_buff);
3659
+
3660
+ if (ax772b_data->checksum & AX_RX_CHECKSUM)
3661
+ ax88772b_rx_checksum(ax_skb, &rx_hdr);
3662
+
3663
+ axusbnet_skb_return(dev, ax_skb);
3664
+
3665
+ } else {
3666
+ return 0;
3667
+ }
3668
+
3669
+ skb_pull(skb, ((rx_hdr.len +
3670
+ sizeof(struct ax88772b_rx_header) + 3)
3671
+ & 0xfffc));
3672
+ }
3673
+
3674
+ if (skb->len < 0) {
3675
+ deverr(dev, "invalid rx length %d", skb->len);
3676
+ return 0;
3677
+ }
3678
+ return 1;
3679
+}
3680
+
3681
+static struct sk_buff *
3682
+ax88772b_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
3683
+{
3684
+ int padlen = ((skb->len + 4) % 512) ? 0 : 4;
3685
+ u32 packet_len;
3686
+ u32 padbytes = 0xffff0000;
3687
+
3688
+#if (!AX_FORCE_BUFF_ALIGN)
3689
+ int headroom = skb_headroom(skb);
3690
+ int tailroom = skb_tailroom(skb);
3691
+
3692
+ if ((!skb_cloned(skb))
3693
+ && ((headroom + tailroom) >= (4 + padlen))) {
3694
+ if ((headroom < 4) || (tailroom < padlen)) {
3695
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
3696
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3697
+ skb->tail = skb->data + skb->len;
3698
+#else
3699
+ skb_set_tail_pointer(skb, skb->len);
3700
+#endif
3701
+ }
3702
+ } else
3703
+#endif
3704
+ {
3705
+ struct sk_buff *skb2;
3706
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
3707
+ dev_kfree_skb_any(skb);
3708
+ skb = skb2;
3709
+ if (!skb)
3710
+ return NULL;
3711
+ }
3712
+
3713
+ skb_push(skb, 4);
3714
+ packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
3715
+
3716
+ cpu_to_le32s(&packet_len);
3717
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3718
+ memcpy(skb->data, &packet_len, sizeof(packet_len));
3719
+#else
3720
+ skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
3721
+#endif
3722
+
3723
+ if ((skb->len % 512) == 0) {
3724
+ cpu_to_le32s(&padbytes);
3725
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3726
+ memcpy(skb->tail, &padbytes, sizeof(padbytes));
3727
+#else
3728
+ memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
3729
+#endif
3730
+ skb_put(skb, sizeof(padbytes));
3731
+ }
3732
+
3733
+ return skb;
3734
+}
3735
+
3736
+static const u8 chkcntsel[6][3] = {
3737
+ {12, 23, 31},
3738
+ {12, 31, 23},
3739
+ {23, 31, 12},
3740
+ {23, 12, 31},
3741
+ {31, 12, 23},
3742
+ {31, 23, 12}
3743
+};
3744
+
3745
+static void ax88772_save_bmcr_anar(struct usbnet *dev)
3746
+{
3747
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
3748
+
3749
+ if (ax772_data) {
3750
+ /* Preserve BMCR for restoring */
3751
+ ax772_data->presvd_phy_bmcr =
3752
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
3753
+
3754
+ /* Preserve Advertisement control reg for restoring */
3755
+ ax772_data->presvd_phy_advertise =
3756
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
3757
+ }
3758
+}
3759
+
3760
+static void ax88772_restore_bmcr_anar(struct usbnet *dev)
3761
+{
3762
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
3763
+
3764
+ if (ax772_data && ax772_data->presvd_phy_advertise && ax772_data->presvd_phy_bmcr) {
3765
+ /* Restore Advertisement control reg */
3766
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
3767
+ ax772_data->presvd_phy_advertise);
3768
+ /* Restore BMCR */
3769
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR,
3770
+ ax772_data->presvd_phy_bmcr);
3771
+ ax772_data->presvd_phy_advertise = 0;
3772
+ ax772_data->presvd_phy_bmcr = 0;
3773
+ }
3774
+}
3775
+
3776
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
3777
+static void ax88772_link_reset(void *data)
3778
+{
3779
+ struct usbnet *dev = (struct usbnet *)data;
3780
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
3781
+#else
3782
+static void ax88772_link_reset(struct work_struct *work)
3783
+{
3784
+ struct ax88772_data *ax772_data = container_of(work,
3785
+ struct ax88772_data,
3786
+ check_link);
3787
+ struct usbnet *dev = ax772_data->dev;
3788
+#endif
3789
+ if (ax772_data->Event == AX_SET_RX_CFG) {
3790
+ u16 bmcr;
3791
+ u16 mode;
3792
+
3793
+ ax772_data->Event = AX_NOP;
3794
+
3795
+ mode = AX88772_MEDIUM_DEFAULT;
3796
+
3797
+ bmcr = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
3798
+ MII_BMCR);
3799
+ if (!(bmcr & BMCR_FULLDPLX))
3800
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
3801
+ if (!(bmcr & BMCR_SPEED100))
3802
+ mode &= ~AX88772_MEDIUM_100MB;
3803
+
3804
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
3805
+ mode, 0, 0, NULL);
3806
+ return;
3807
+ }
3808
+
3809
+ switch (ax772_data->Event) {
3810
+ case WAIT_AUTONEG_COMPLETE:
3811
+ if (jiffies > (ax772_data->autoneg_start + 5 * HZ)) {
3812
+ ax772_data->Event = PHY_POWER_DOWN;
3813
+ ax772_data->TickToExpire = 23;
3814
+ }
3815
+ break;
3816
+ case PHY_POWER_DOWN:
3817
+ if (ax772_data->TickToExpire == 23) {
3818
+ ax88772_save_bmcr_anar(dev);
3819
+ /* Set Phy Power Down */
3820
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
3821
+ 0, 0, NULL);
3822
+ --ax772_data->TickToExpire;
3823
+ } else if (--ax772_data->TickToExpire == 0) {
3824
+ /* Set Phy Power Up */
3825
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3826
+ AX_SWRESET_IPRL, 0, 0, NULL);
3827
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3828
+ AX_SWRESET_IPPD | AX_SWRESET_IPRL, 0, 0, NULL);
3829
+ msleep(10);
3830
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3831
+ AX_SWRESET_IPRL, 0, 0, NULL);
3832
+ msleep(60);
3833
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3834
+ AX_SWRESET_CLEAR, 0, 0, NULL);
3835
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3836
+ AX_SWRESET_IPRL, 0, 0, NULL);
3837
+
3838
+ if (ax772_data->presvd_phy_advertise && ax772_data->presvd_phy_bmcr) {
3839
+ ax88772_restore_bmcr_anar(dev);
3840
+
3841
+ } else {
3842
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id,
3843
+ MII_ADVERTISE,
3844
+ ADVERTISE_ALL | ADVERTISE_CSMA |
3845
+ ADVERTISE_PAUSE_CAP);
3846
+ mii_nway_restart(&dev->mii);
3847
+ }
3848
+
3849
+ ax772_data->Event = PHY_POWER_UP;
3850
+ ax772_data->TickToExpire = 47;
3851
+ }
3852
+ break;
3853
+ case PHY_POWER_UP:
3854
+ if (--ax772_data->TickToExpire == 0) {
3855
+ ax772_data->Event = PHY_POWER_DOWN;
3856
+ ax772_data->TickToExpire = 23;
3857
+ }
3858
+ break;
3859
+ default:
3860
+ break;
3861
+ }
3862
+ return;
3863
+}
3864
+
3865
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
3866
+static void ax88772a_link_reset(void *data)
3867
+{
3868
+ struct usbnet *dev = (struct usbnet *)data;
3869
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
3870
+#else
3871
+static void ax88772a_link_reset(struct work_struct *work)
3872
+{
3873
+ struct ax88772a_data *ax772a_data = container_of(work,
3874
+ struct ax88772a_data,
3875
+ check_link);
3876
+ struct usbnet *dev = ax772a_data->dev;
3877
+#endif
3878
+ int powsave = (ax772a_data->EepromData >> 14);
3879
+ u16 phy_reg;
3880
+
3881
+ if (ax772a_data->Event == AX_SET_RX_CFG) {
3882
+ u16 bmcr;
3883
+ u16 mode;
3884
+
3885
+ ax772a_data->Event = AX_NOP;
3886
+
3887
+ mode = AX88772_MEDIUM_DEFAULT;
3888
+
3889
+ bmcr = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
3890
+ MII_BMCR);
3891
+ if (!(bmcr & BMCR_FULLDPLX))
3892
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
3893
+ if (!(bmcr & BMCR_SPEED100))
3894
+ mode &= ~AX88772_MEDIUM_100MB;
3895
+
3896
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode,
3897
+ 0, 0, NULL);
3898
+
3899
+ if (ax772a_data->presvd_phy_advertise && ax772a_data->presvd_phy_bmcr) {
3900
+
3901
+ /* Restore Advertisement control reg */
3902
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
3903
+ ax772a_data->presvd_phy_advertise);
3904
+ /* Restore BMCR */
3905
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR,
3906
+ ax772a_data->presvd_phy_bmcr);
3907
+ ax772a_data->presvd_phy_advertise = 0;
3908
+ ax772a_data->presvd_phy_bmcr = 0;
3909
+ }
3910
+
3911
+ return;
3912
+ }
3913
+
3914
+ switch (ax772a_data->Event) {
3915
+ case WAIT_AUTONEG_COMPLETE:
3916
+ if (jiffies > (ax772a_data->autoneg_start + 5 * HZ)) {
3917
+ ax772a_data->Event = CHK_CABLE_EXIST;
3918
+ ax772a_data->TickToExpire = 14;
3919
+ }
3920
+ break;
3921
+ case CHK_CABLE_EXIST:
3922
+ phy_reg = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
3923
+ if ((phy_reg != 0x8012) && (phy_reg != 0x8013)) {
3924
+ ax8817x_mdio_write_le(dev->net,
3925
+ dev->mii.phy_id, 0x16, 0x4040);
3926
+ mii_nway_restart(&dev->mii);
3927
+ ax772a_data->Event = CHK_CABLE_STATUS;
3928
+ ax772a_data->TickToExpire = 31;
3929
+ } else if (--ax772a_data->TickToExpire == 0) {
3930
+ mii_nway_restart(&dev->mii);
3931
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
3932
+ if (powsave == 0x03) {
3933
+ ax772a_data->TickToExpire = 47;
3934
+ } else if (powsave == 0x01) {
3935
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
3936
+ ax772a_data->DlySel = 0;
3937
+ ax772a_data->TickToExpire =
3938
+ chkcntsel[ax772a_data->DlyIndex][ax772a_data->DlySel];
3939
+ }
3940
+ }
3941
+ break;
3942
+ case CHK_CABLE_EXIST_AGAIN:
3943
+ /* if cable disconnected */
3944
+ phy_reg = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
3945
+ if ((phy_reg != 0x8012) && (phy_reg != 0x8013)) {
3946
+ mii_nway_restart(&dev->mii);
3947
+ ax772a_data->Event = CHK_CABLE_STATUS;
3948
+ ax772a_data->TickToExpire = 31;
3949
+ } else if (--ax772a_data->TickToExpire == 0) {
3950
+ if (!ax772a_data->presvd_phy_advertise && !ax772a_data->presvd_phy_bmcr) {
3951
+ /* Preserve BMCR for restoring */
3952
+ ax772a_data->presvd_phy_bmcr =
3953
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
3954
+
3955
+ /* Preserve Advertisement control reg for restoring */
3956
+ ax772a_data->presvd_phy_advertise =
3957
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
3958
+ }
3959
+
3960
+
3961
+ /* Power down PHY */
3962
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3963
+ AX_SWRESET_IPPD,
3964
+ 0, 0, NULL);
3965
+ ax772a_data->Event = PHY_POWER_DOWN;
3966
+ if (powsave == 0x03)
3967
+ ax772a_data->TickToExpire = 23;
3968
+ else if (powsave == 0x01)
3969
+ ax772a_data->TickToExpire = 31;
3970
+ }
3971
+ break;
3972
+ case PHY_POWER_DOWN:
3973
+ if (--ax772a_data->TickToExpire == 0)
3974
+ ax772a_data->Event = PHY_POWER_UP;
3975
+ break;
3976
+ case CHK_CABLE_STATUS:
3977
+ if (--ax772a_data->TickToExpire == 0) {
3978
+ ax8817x_mdio_write_le(dev->net,
3979
+ dev->mii.phy_id, 0x16, 0x4040);
3980
+ mii_nway_restart(&dev->mii);
3981
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
3982
+ if (powsave == 0x03) {
3983
+ ax772a_data->TickToExpire = 47;
3984
+ } else if (powsave == 0x01) {
3985
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
3986
+ ax772a_data->DlySel = 0;
3987
+ ax772a_data->TickToExpire =
3988
+ chkcntsel[ax772a_data->DlyIndex][ax772a_data->DlySel];
3989
+ }
3990
+ }
3991
+ break;
3992
+ case PHY_POWER_UP:
3993
+
3994
+ if (!ax772a_data->presvd_phy_advertise && !ax772a_data->presvd_phy_bmcr) {
3995
+ /* Preserve BMCR for restoring */
3996
+ ax772a_data->presvd_phy_bmcr =
3997
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
3998
+
3999
+ /* Preserve Advertisement control reg for restoring */
4000
+ ax772a_data->presvd_phy_advertise =
4001
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
4002
+ }
4003
+
4004
+ ax88772a_phy_powerup(dev);
4005
+
4006
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
4007
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
4008
+
4009
+ mii_nway_restart(&dev->mii);
4010
+
4011
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
4012
+
4013
+ if (powsave == 0x03) {
4014
+ ax772a_data->TickToExpire = 47;
4015
+ } else if (powsave == 0x01) {
4016
+ if (++ax772a_data->DlySel >= 3) {
4017
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
4018
+ ax772a_data->DlySel = 0;
4019
+ }
4020
+ ax772a_data->TickToExpire =
4021
+ chkcntsel[ax772a_data->DlyIndex][ax772a_data->DlySel];
4022
+ }
4023
+ break;
4024
+ default:
4025
+ break;
4026
+ }
4027
+
4028
+ return;
4029
+}
4030
+
4031
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
4032
+static void ax88772b_link_reset(void *data)
4033
+{
4034
+ struct usbnet *dev = (struct usbnet *)data;
4035
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
4036
+#else
4037
+static void ax88772b_link_reset(struct work_struct *work)
4038
+{
4039
+ struct ax88772b_data *ax772b_data = container_of(work,
4040
+ struct ax88772b_data,
4041
+ check_link);
4042
+ struct usbnet *dev = ax772b_data->dev;
4043
+#endif
4044
+
4045
+ switch (ax772b_data->Event) {
4046
+
4047
+ case AX_SET_RX_CFG:
4048
+ {
4049
+ u16 bmcr = ax8817x_mdio_read_le(dev->net,
4050
+ dev->mii.phy_id, MII_BMCR);
4051
+ u16 mode = AX88772_MEDIUM_DEFAULT;
4052
+
4053
+ if (!(bmcr & BMCR_FULLDPLX))
4054
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
4055
+ if (!(bmcr & BMCR_SPEED100))
4056
+ mode &= ~AX88772_MEDIUM_100MB;
4057
+
4058
+ if (ax772b_data->ext_phy_oui == EXTPHY_BROADCOM_OUI) {
4059
+ if(ax772b_data->ext_phy_model == EXTPHY_BCM89811_MODEL) {
4060
+ mode = AX88772_MEDIUM_DEFAULT;
4061
+ }
4062
+ }
4063
+
4064
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode,
4065
+ 0, 0, NULL);
4066
+ break;
4067
+ }
4068
+ case PHY_POWER_UP:
4069
+ {
4070
+ u16 tmp16;
4071
+
4072
+ if (!ax772b_data->presvd_phy_advertise && !ax772b_data->presvd_phy_bmcr) {
4073
+ /* Preserve BMCR for restoring */
4074
+ ax772b_data->presvd_phy_bmcr =
4075
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
4076
+
4077
+ /* Preserve Advertisement control reg for restoring */
4078
+ ax772b_data->presvd_phy_advertise =
4079
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
4080
+ }
4081
+
4082
+ ax88772a_phy_powerup(dev);
4083
+ tmp16 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
4084
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, 0x12,
4085
+ ((tmp16 & 0xFF9F) | 0x0040));
4086
+
4087
+ /* Restore Advertisement control reg */
4088
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
4089
+ ax772b_data->presvd_phy_advertise);
4090
+ /* Restore BMCR */
4091
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR,
4092
+ ax772b_data->presvd_phy_bmcr);
4093
+ ax772b_data->presvd_phy_advertise = 0;
4094
+ ax772b_data->presvd_phy_bmcr = 0;
4095
+
4096
+ break;
4097
+ }
4098
+
4099
+ case AX_CHK_AUTODETACH:
4100
+ {
4101
+ int ret;
4102
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
4103
+ AX_SWRESET_IPRL |
4104
+ (ax772b_data->psc & 0x7FFF),
4105
+ 0, 0, NULL);
4106
+ if (ret < 0) {
4107
+ deverr(dev, "Failed to configure PHY power saving: %d",
4108
+ ret);
4109
+ }
4110
+
4111
+ break;
4112
+ }
4113
+ default:
4114
+ break;
4115
+ }
4116
+
4117
+ ax772b_data->Event = AX_NOP;
4118
+
4119
+ return;
4120
+}
4121
+
4122
+static int ax88178_set_media(struct usbnet *dev)
4123
+{
4124
+ int ret;
4125
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
4126
+ int media;
4127
+
4128
+ media = ax88178_media_check(dev, ax178dataptr);
4129
+ if (media < 0)
4130
+ return media;
4131
+
4132
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, media, 0,
4133
+ 0, NULL);
4134
+ if (ret < 0) {
4135
+ deverr(dev, "write mode medium reg failed: %d", ret);
4136
+ return ret;
4137
+ }
4138
+
4139
+ return 0;
4140
+}
4141
+
4142
+static int ax88178_link_reset(struct usbnet *dev)
4143
+{
4144
+ return ax88178_set_media(dev);
4145
+}
4146
+
4147
+static int ax_suspend(struct usb_interface *intf,
4148
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
4149
+ pm_message_t message)
4150
+#else
4151
+ u32 message)
4152
+#endif
4153
+{
4154
+ struct usbnet *dev = usb_get_intfdata(intf);
4155
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
4156
+
4157
+ return data->suspend(intf, message);
4158
+}
4159
+
4160
+static int ax_resume(struct usb_interface *intf)
4161
+{
4162
+ struct usbnet *dev = usb_get_intfdata(intf);
4163
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
4164
+
4165
+ return data->resume(intf);
4166
+}
4167
+
4168
+static const struct driver_info ax88178_info = {
4169
+ .description = "ASIX AX88178 USB 2.0 Ethernet",
4170
+ .bind = ax88178_bind,
4171
+ .unbind = ax88178_unbind,
4172
+ .status = ax88178_status,
4173
+ .link_reset = ax88178_link_reset,
4174
+ .reset = ax88178_link_reset,
4175
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4176
+ .stop = ax88772b_stop,
4177
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4178
+#else
4179
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4180
+#endif
4181
+ .rx_fixup = ax88772_rx_fixup,
4182
+ .tx_fixup = ax88772_tx_fixup,
4183
+};
4184
+
4185
+static const struct driver_info belkin178_info = {
4186
+ .description = "Belkin Gigabit USB 2.0 Network Adapter",
4187
+ .bind = ax88178_bind,
4188
+ .unbind = ax88178_unbind,
4189
+ .status = ax88178_status,
4190
+ .link_reset = ax88178_link_reset,
4191
+ .reset = ax88178_link_reset,
4192
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4193
+ .stop = ax88772b_stop,
4194
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4195
+#else
4196
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4197
+#endif
4198
+ .rx_fixup = ax88772_rx_fixup,
4199
+ .tx_fixup = ax88772_tx_fixup,
4200
+};
4201
+
4202
+static const struct driver_info ax8817x_info = {
4203
+ .description = "ASIX AX8817x USB 2.0 Ethernet",
4204
+ .bind = ax8817x_bind,
4205
+ .status = ax8817x_status,
4206
+ .link_reset = ax88172_link_reset,
4207
+ .reset = ax88172_link_reset,
4208
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4209
+ .stop = ax88772b_stop,
4210
+ .flags = FLAG_ETHER | FLAG_AVOID_UNLINK_URBS,
4211
+#else
4212
+ .flags = FLAG_ETHER,
4213
+#endif
4214
+};
4215
+
4216
+static const struct driver_info dlink_dub_e100_info = {
4217
+ .description = "DLink DUB-E100 USB Ethernet",
4218
+ .bind = ax8817x_bind,
4219
+ .status = ax8817x_status,
4220
+ .link_reset = ax88172_link_reset,
4221
+ .reset = ax88172_link_reset,
4222
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4223
+ .stop = ax88772b_stop,
4224
+ .flags = FLAG_ETHER | FLAG_AVOID_UNLINK_URBS,
4225
+#else
4226
+ .flags = FLAG_ETHER,
4227
+#endif
4228
+};
4229
+
4230
+static const struct driver_info netgear_fa120_info = {
4231
+ .description = "Netgear FA-120 USB Ethernet",
4232
+ .bind = ax8817x_bind,
4233
+ .status = ax8817x_status,
4234
+ .link_reset = ax88172_link_reset,
4235
+ .reset = ax88172_link_reset,
4236
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4237
+ .stop = ax88772b_stop,
4238
+ .flags = FLAG_ETHER | FLAG_AVOID_UNLINK_URBS,
4239
+#else
4240
+ .flags = FLAG_ETHER,
4241
+#endif
4242
+};
4243
+
4244
+static const struct driver_info hawking_uf200_info = {
4245
+ .description = "Hawking UF200 USB Ethernet",
4246
+ .bind = ax8817x_bind,
4247
+ .status = ax8817x_status,
4248
+ .link_reset = ax88172_link_reset,
4249
+ .reset = ax88172_link_reset,
4250
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4251
+ .stop = ax88772b_stop,
4252
+ .flags = FLAG_ETHER | FLAG_AVOID_UNLINK_URBS,
4253
+#else
4254
+ .flags = FLAG_ETHER,
4255
+#endif
4256
+};
4257
+
4258
+static const struct driver_info ax88772_info = {
4259
+ .description = "ASIX AX88772 USB 2.0 Ethernet",
4260
+ .bind = ax88772_bind,
4261
+ .unbind = ax88772_unbind,
4262
+ .status = ax88772_status,
4263
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4264
+ .stop = ax88772b_stop,
4265
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4266
+#else
4267
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4268
+#endif
4269
+ .rx_fixup = ax88772_rx_fixup,
4270
+ .tx_fixup = ax88772_tx_fixup,
4271
+ .reset = ax88772b_reset,
4272
+};
4273
+
4274
+static const struct driver_info dlink_dub_e100b_info = {
4275
+ .description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
4276
+ .bind = ax88772_bind,
4277
+ .unbind = ax88772_unbind,
4278
+ .status = ax88772_status,
4279
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4280
+ .stop = ax88772b_stop,
4281
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4282
+#else
4283
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4284
+#endif
4285
+ .rx_fixup = ax88772_rx_fixup,
4286
+ .tx_fixup = ax88772_tx_fixup,
4287
+ .reset = ax88772b_reset,
4288
+};
4289
+
4290
+static const struct driver_info dlink_dub_e100_772b_info = {
4291
+ .description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
4292
+ .bind = ax88772b_bind,
4293
+ .unbind = ax88772b_unbind,
4294
+ .status = ax88772b_status,
4295
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4296
+ .stop = ax88772b_stop,
4297
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT | FLAG_AVOID_UNLINK_URBS,
4298
+#else
4299
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
4300
+#endif
4301
+ .rx_fixup = ax88772b_rx_fixup,
4302
+ .tx_fixup = ax88772b_tx_fixup,
4303
+ .reset = ax88772b_reset,
4304
+};
4305
+
4306
+static const struct driver_info dlink_dub_e100_772c_info = {
4307
+ .description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
4308
+ .bind = ax88772b_bind,
4309
+ .unbind = ax88772b_unbind,
4310
+ .status = ax88772b_status,
4311
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4312
+ .stop = ax88772b_stop,
4313
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT | FLAG_AVOID_UNLINK_URBS,
4314
+#else
4315
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
4316
+#endif
4317
+ .rx_fixup = ax88772b_rx_fixup,
4318
+ .tx_fixup = ax88772b_tx_fixup,
4319
+ .reset = ax88772b_reset,
4320
+};
4321
+
4322
+static const struct driver_info ax88772a_info = {
4323
+ .description = "ASIX AX88772A USB 2.0 Ethernet",
4324
+ .bind = ax88772a_bind,
4325
+ .unbind = ax88772a_unbind,
4326
+ .status = ax88772a_status,
4327
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4328
+ .stop = ax88772b_stop,
4329
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4330
+#else
4331
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4332
+#endif
4333
+ .rx_fixup = ax88772_rx_fixup,
4334
+ .tx_fixup = ax88772_tx_fixup,
4335
+ .reset = ax88772b_reset,
4336
+};
4337
+
4338
+static const struct driver_info ax88772b_info = {
4339
+ .description = "ASIX AX88772B USB 2.0 Ethernet",
4340
+ .bind = ax88772b_bind,
4341
+ .unbind = ax88772b_unbind,
4342
+ .status = ax88772b_status,
4343
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4344
+ .stop = ax88772b_stop,
4345
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT | FLAG_AVOID_UNLINK_URBS,
4346
+#else
4347
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
4348
+#endif
4349
+ .rx_fixup = ax88772b_rx_fixup,
4350
+ .tx_fixup = ax88772b_tx_fixup,
4351
+ .reset = ax88772b_reset,
4352
+};
4353
+
4354
+static const struct driver_info ax88772c_info = {
4355
+ .description = "ASIX AX88772C USB 2.0 Ethernet",
4356
+ .bind = ax88772b_bind,
4357
+ .unbind = ax88772b_unbind,
4358
+ .status = ax88772c_status,
4359
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4360
+ .stop = ax88772b_stop,
4361
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT | FLAG_AVOID_UNLINK_URBS,
4362
+#else
4363
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
4364
+#endif
4365
+ .rx_fixup = ax88772b_rx_fixup,
4366
+ .tx_fixup = ax88772b_tx_fixup,
4367
+ .reset = ax88772b_reset,
4368
+};
4369
+
4370
+static const struct usb_device_id products[] = {
4371
+{
4372
+ /* 88178 */
4373
+ USB_DEVICE(0x0b95, 0x1780),
4374
+ .driver_info = (unsigned long) &ax88178_info,
4375
+}, {
4376
+ /* 88178 for billianton linksys */
4377
+ USB_DEVICE(0x077b, 0x2226),
4378
+ .driver_info = (unsigned long) &ax88178_info,
4379
+}, {
4380
+ /* ABOCOM for linksys */
4381
+ USB_DEVICE(0x1737, 0x0039),
4382
+ .driver_info = (unsigned long) &ax88178_info,
4383
+}, {
4384
+ /* ABOCOM for pci */
4385
+ USB_DEVICE(0x14ea, 0xab11),
4386
+ .driver_info = (unsigned long) &ax88178_info,
4387
+}, {
4388
+ /* Belkin */
4389
+ USB_DEVICE(0x050d, 0x5055),
4390
+ .driver_info = (unsigned long) &belkin178_info,
4391
+}, {
4392
+ /* Linksys USB200M */
4393
+ USB_DEVICE(0x077b, 0x2226),
4394
+ .driver_info = (unsigned long) &ax8817x_info,
4395
+}, {
4396
+ /* Netgear FA120 */
4397
+ USB_DEVICE(0x0846, 0x1040),
4398
+ .driver_info = (unsigned long) &netgear_fa120_info,
4399
+}, {
4400
+ /* DLink DUB-E100 */
4401
+ USB_DEVICE(0x2001, 0x1a00),
4402
+ .driver_info = (unsigned long) &dlink_dub_e100_info,
4403
+}, {
4404
+ /* DLink DUB-E100B */
4405
+ USB_DEVICE(0x2001, 0x3c05),
4406
+ .driver_info = (unsigned long) &dlink_dub_e100b_info,
4407
+}, {
4408
+ /* DLink DUB-E100B */
4409
+ USB_DEVICE(0x07d1, 0x3c05),
4410
+ .driver_info = (unsigned long) &dlink_dub_e100b_info,
4411
+}, {
4412
+ /* DLink DUB-E100 (AX88772B)*/
4413
+ USB_DEVICE_VER(0x2001, 0x1a02, 0, 1),
4414
+ .driver_info = (unsigned long) &dlink_dub_e100_772b_info,
4415
+}, {
4416
+ /* DLink DUB-E100 (AX88772C)*/
4417
+ USB_DEVICE_VER(0x2001, 0x1a02, 0, 2),
4418
+ .driver_info = (unsigned long) &dlink_dub_e100_772c_info,
4419
+}, {
4420
+ /* Intellinet, ST Lab USB Ethernet */
4421
+ USB_DEVICE(0x0b95, 0x1720),
4422
+ .driver_info = (unsigned long) &ax8817x_info,
4423
+}, {
4424
+ /* Hawking UF200, TrendNet TU2-ET100 */
4425
+ USB_DEVICE(0x07b8, 0x420a),
4426
+ .driver_info = (unsigned long) &hawking_uf200_info,
4427
+}, {
4428
+ /* Billionton Systems, USB2AR */
4429
+ USB_DEVICE(0x08dd, 0x90ff),
4430
+ .driver_info = (unsigned long) &ax8817x_info,
4431
+}, {
4432
+ /* ATEN UC210T */
4433
+ USB_DEVICE(0x0557, 0x2009),
4434
+ .driver_info = (unsigned long) &ax8817x_info,
4435
+}, {
4436
+ /* Buffalo LUA-U2-KTX */
4437
+ USB_DEVICE(0x0411, 0x003d),
4438
+ .driver_info = (unsigned long) &ax8817x_info,
4439
+}, {
4440
+ /* Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter" */
4441
+ USB_DEVICE(0x6189, 0x182d),
4442
+ .driver_info = (unsigned long) &ax8817x_info,
4443
+}, {
4444
+ /* corega FEther USB2-TX */
4445
+ USB_DEVICE(0x07aa, 0x0017),
4446
+ .driver_info = (unsigned long) &ax8817x_info,
4447
+}, {
4448
+ /* Surecom EP-1427X-2 */
4449
+ USB_DEVICE(0x1189, 0x0893),
4450
+ .driver_info = (unsigned long) &ax8817x_info,
4451
+}, {
4452
+ /* goodway corp usb gwusb2e */
4453
+ USB_DEVICE(0x1631, 0x6200),
4454
+ .driver_info = (unsigned long) &ax8817x_info,
4455
+}, {
4456
+ /* ASIX AX88772 10/100 */
4457
+ USB_DEVICE(0x0b95, 0x7720),
4458
+ .driver_info = (unsigned long) &ax88772_info,
4459
+}, {
4460
+ /* ASIX AX88772 10/100 */
4461
+ USB_DEVICE(0x125E, 0x180D),
4462
+ .driver_info = (unsigned long) &ax88772_info,
4463
+}, {
4464
+ /* ASIX AX88772A 10/100 */
4465
+ USB_DEVICE(0x0b95, 0x772A),
4466
+ .driver_info = (unsigned long) &ax88772a_info,
4467
+}, {
4468
+ /* ASIX AX88772A 10/100 */
4469
+ USB_DEVICE(0x0db0, 0xA877),
4470
+ .driver_info = (unsigned long) &ax88772a_info,
4471
+}, {
4472
+ /* ASIX AX88772A 10/100 */
4473
+ USB_DEVICE(0x0421, 0x772A),
4474
+ .driver_info = (unsigned long) &ax88772a_info,
4475
+}, {
4476
+ /* Linksys 200M */
4477
+ USB_DEVICE(0x13B1, 0x0018),
4478
+ .driver_info = (unsigned long) &ax88772a_info,
4479
+}, {
4480
+ USB_DEVICE(0x05ac, 0x1402),
4481
+ .driver_info = (unsigned long) &ax88772a_info,
4482
+}, {
4483
+ /* ASIX AX88772B 10/100 */
4484
+ USB_DEVICE_VER(0x0b95, 0x772B, 0, 1),
4485
+ .driver_info = (unsigned long) &ax88772b_info,
4486
+}, {
4487
+ /* Asus AX88772B 10/100 */
4488
+ USB_DEVICE_VER(0x0b95, 0x7e2b, 0, 1),
4489
+ .driver_info = (unsigned long) &ax88772b_info,
4490
+}, {
4491
+ /* Lenovo AX88772B 10/100 */
4492
+ USB_DEVICE_VER(0x17ef, 0x7203, 0, 1),
4493
+ .driver_info = (unsigned long) &ax88772b_info,
4494
+},{
4495
+ /* ASIX AX88772B ver.2 10/100 */
4496
+ USB_DEVICE_VER(0x0b95, 0x772B, 0, 2),
4497
+ .driver_info = (unsigned long) &ax88772c_info,
4498
+},
4499
+ { }, /* END */
4500
+};
4501
+MODULE_DEVICE_TABLE(usb, products);
4502
+
4503
+static struct usb_driver asix_driver = {
4504
+ /* .owner = THIS_MODULE, */
4505
+ .name = "asix",
4506
+ .id_table = products,
4507
+ .probe = axusbnet_probe,
4508
+ .suspend = ax_suspend,
4509
+ .resume = ax_resume,
4510
+ .disconnect = axusbnet_disconnect,
4511
+};
4512
+
4513
+static int __init asix_init(void)
4514
+{
4515
+ return usb_register(&asix_driver);
4516
+}
4517
+module_init(asix_init);
4518
+
4519
+static void __exit asix_exit(void)
4520
+{
4521
+ usb_deregister(&asix_driver);
4522
+}
4523
+module_exit(asix_exit);
4524
+
4525
+MODULE_AUTHOR("David Hollis");
4526
+MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices");
4527
+MODULE_LICENSE("GPL");
4528
+
kernel/drivers/net/usb/AX88772C_eeprom/asix.h
....@@ -0,0 +1,575 @@
1
+#ifndef __LINUX_USBNET_ASIX_H
2
+#define __LINUX_USBNET_ASIX_H
3
+
4
+/*
5
+ * Turn on this flag if the implementation of your USB host controller
6
+ * cannot handle non-double word aligned buffer.
7
+ * When turn on this flag, driver will fixup egress packet aligned on double
8
+ * word boundary before deliver to USB host controller. And will Disable the
9
+ * function "skb_reserve (skb, NET_IP_ALIGN)" to retain the buffer aligned on
10
+ * double word alignment for ingress packets.
11
+ */
12
+#define AX_FORCE_BUFF_ALIGN 0
13
+
14
+//#define RX_SKB_COPY
15
+
16
+#define AX_MONITOR_MODE 0x01
17
+#define AX_MONITOR_LINK 0x02
18
+#define AX_MONITOR_MAGIC 0x04
19
+#define AX_MONITOR_HSFS 0x10
20
+
21
+/* AX88172 Medium Status Register values */
22
+#define AX_MEDIUM_FULL_DUPLEX 0x02
23
+#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
24
+#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
25
+#define AX_MCAST_FILTER_SIZE 8
26
+#define AX_MAX_MCAST 64
27
+
28
+#define AX_EEPROM_LEN 0x40
29
+
30
+#define AX_SWRESET_CLEAR 0x00
31
+#define AX_SWRESET_RR 0x01
32
+#define AX_SWRESET_RT 0x02
33
+#define AX_SWRESET_PRTE 0x04
34
+#define AX_SWRESET_PRL 0x08
35
+#define AX_SWRESET_BZ 0x10
36
+#define AX_SWRESET_IPRL 0x20
37
+#define AX_SWRESET_IPPD 0x40
38
+#define AX_SWRESET_IPOSC 0x0080
39
+#define AX_SWRESET_IPPSL_0 0x0100
40
+#define AX_SWRESET_IPPSL_1 0x0200
41
+#define AX_SWRESET_IPCOPS 0x0400
42
+#define AX_SWRESET_IPCOPSC 0x0800
43
+#define AX_SWRESET_AUTODETACH 0x1000
44
+#define AX_SWRESET_WOLLP 0x8000
45
+
46
+#define AX88772_IPG0_DEFAULT 0x15
47
+#define AX88772_IPG1_DEFAULT 0x0c
48
+#define AX88772_IPG2_DEFAULT 0x0E
49
+
50
+#define AX88772A_IPG0_DEFAULT 0x15
51
+#define AX88772A_IPG1_DEFAULT 0x16
52
+#define AX88772A_IPG2_DEFAULT 0x1A
53
+
54
+#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
55
+#define AX88772_MEDIUM_RESERVED 0x0004
56
+#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
57
+#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
58
+#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
59
+#define AX88772_MEDIUM_RX_ENABLE 0x0100
60
+#define AX88772_MEDIUM_100MB 0x0200
61
+#define AX88772_MEDIUM_DEFAULT \
62
+ (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
63
+ AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
64
+ AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE)
65
+
66
+#define AX_CMD_SET_SW_MII 0x06
67
+#define AX_CMD_READ_MII_REG 0x07
68
+#define AX_CMD_WRITE_MII_REG 0x08
69
+#define AX_CMD_READ_STATMNGSTS_REG 0x09
70
+ #define AX_HOST_EN 0x01
71
+
72
+#define AX_CMD_SET_HW_MII 0x0a
73
+#define AX_CMD_READ_EEPROM 0x0b
74
+#define AX_CMD_WRITE_EEPROM 0x0c
75
+#define AX_CMD_WRITE_EEPROM_EN 0x0d
76
+#define AX_CMD_WRITE_EEPROM_DIS 0x0e
77
+#define AX_CMD_WRITE_RX_CTL 0x10
78
+#define AX_CMD_READ_IPG012 0x11
79
+#define AX_CMD_WRITE_IPG0 0x12
80
+#define AX_CMD_WRITE_IPG1 0x13
81
+#define AX_CMD_WRITE_IPG2 0x14
82
+#define AX_CMD_WRITE_MULTI_FILTER 0x16
83
+#define AX_CMD_READ_NODE_ID 0x17
84
+#define AX_CMD_READ_PHY_ID 0x19
85
+#define AX_CMD_READ_MEDIUM_MODE 0x1a
86
+#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
87
+#define AX_CMD_READ_MONITOR_MODE 0x1c
88
+#define AX_CMD_WRITE_MONITOR_MODE 0x1d
89
+#define AX_CMD_WRITE_GPIOS 0x1f
90
+#define AX_CMD_SW_RESET 0x20
91
+#define AX_CMD_SW_PHY_STATUS 0x21
92
+#define AX_CMD_SW_PHY_SELECT 0x22
93
+ #define AX_PHYSEL_PSEL (1 << 0)
94
+ #define AX_PHYSEL_ASEL (1 << 1)
95
+ #define AX_PHYSEL_SSMII (0 << 2)
96
+ #define AX_PHYSEL_SSRMII (1 << 2)
97
+ #define AX_PHYSEL_SSRRMII (3 << 2)
98
+ #define AX_PHYSEL_SSEN (1 << 4)
99
+#define AX88772_CMD_READ_NODE_ID 0x13
100
+#define AX88772_CMD_WRITE_NODE_ID 0x14
101
+#define AX_CMD_READ_WKFARY 0x23
102
+#define AX_CMD_WRITE_WKFARY 0x24
103
+#define AX_CMD_READ_RXCOE_CTL 0x2b
104
+#define AX_CMD_WRITE_RXCOE_CTL 0x2c
105
+#define AX_CMD_READ_TXCOE_CTL 0x2d
106
+#define AX_CMD_WRITE_TXCOE_CTL 0x2e
107
+
108
+#define REG_LENGTH 2
109
+#define PHY_ID_MASK 0x1f
110
+
111
+#define AX_RXCOE_IPCE 0x0001
112
+#define AX_RXCOE_IPVE 0x0002
113
+#define AX_RXCOE_V6VE 0x0004
114
+#define AX_RXCOE_TCPE 0x0008
115
+#define AX_RXCOE_UDPE 0x0010
116
+#define AX_RXCOE_ICMP 0x0020
117
+#define AX_RXCOE_IGMP 0x0040
118
+#define AX_RXCOE_ICV6 0x0080
119
+#define AX_RXCOE_TCPV6 0x0100
120
+#define AX_RXCOE_UDPV6 0x0200
121
+#define AX_RXCOE_ICMV6 0x0400
122
+#define AX_RXCOE_IGMV6 0x0800
123
+#define AX_RXCOE_ICV6V6 0x1000
124
+#define AX_RXCOE_FOPC 0x8000
125
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
126
+#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
127
+ AX_RXCOE_V6VE | AX_RXCOE_TCPE | \
128
+ AX_RXCOE_UDPE | AX_RXCOE_ICV6 | \
129
+ AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6)
130
+#else
131
+#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
132
+ AX_RXCOE_TCPE | AX_RXCOE_UDPE)
133
+#endif
134
+
135
+#define AX_RXCOE_64TE 0x0100
136
+#define AX_RXCOE_PPPOE 0x0200
137
+#define AX_RXCOE_RPCE 0x8000
138
+
139
+#define AX_TXCOE_IP 0x0001
140
+#define AX_TXCOE_TCP 0x0002
141
+#define AX_TXCOE_UDP 0x0004
142
+#define AX_TXCOE_ICMP 0x0008
143
+#define AX_TXCOE_IGMP 0x0010
144
+#define AX_TXCOE_ICV6 0x0020
145
+
146
+#define AX_TXCOE_TCPV6 0x0100
147
+#define AX_TXCOE_UDPV6 0x0200
148
+#define AX_TXCOE_ICMV6 0x0400
149
+#define AX_TXCOE_IGMV6 0x0800
150
+#define AX_TXCOE_ICV6V6 0x1000
151
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
152
+#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \
153
+ AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6)
154
+#else
155
+#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP)
156
+#endif
157
+
158
+#define AX_TXCOE_64TE 0x0001
159
+#define AX_TXCOE_PPPE 0x0002
160
+
161
+#define AX88772B_MAX_BULKIN_2K 0
162
+#define AX88772B_MAX_BULKIN_4K 1
163
+#define AX88772B_MAX_BULKIN_6K 2
164
+#define AX88772B_MAX_BULKIN_8K 3
165
+#define AX88772B_MAX_BULKIN_16K 4
166
+#define AX88772B_MAX_BULKIN_20K 5
167
+#define AX88772B_MAX_BULKIN_24K 6
168
+#define AX88772B_MAX_BULKIN_32K 7
169
+struct {unsigned short size, byte_cnt, threshold; } AX88772B_BULKIN_SIZE[] = {
170
+ /* 2k */
171
+ {2048, 0x8000, 0x8001},
172
+ /* 4k */
173
+ {4096, 0x8100, 0x8147},
174
+ /* 6k */
175
+ {6144, 0x8200, 0x81EB},
176
+ /* 8k */
177
+ {8192, 0x8300, 0x83D7},
178
+ /* 16 */
179
+ {16384, 0x8400, 0x851E},
180
+ /* 20k */
181
+ {20480, 0x8500, 0x8666},
182
+ /* 24k */
183
+ {24576, 0x8600, 0x87AE},
184
+ /* 32k */
185
+ {32768, 0x8700, 0x8A3D},
186
+};
187
+
188
+
189
+#define AX_RX_CTL_RH1M 0x0100 /* Enable RX-Header mode 0 */
190
+#define AX_RX_CTL_RH2M 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */
191
+#define AX_RX_CTL_RH3M 0x0400 /* checksum value in rx header 3 */
192
+#define AX_RX_HEADER_DEFAULT (AX_RX_CTL_RH1M | AX_RX_CTL_RH2M)
193
+
194
+#define AX_RX_CTL_MFB 0x0300 /* Maximum Frame size 16384bytes */
195
+#define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */
196
+#define AX_RX_CTL_AP 0x0020 /* Accept physcial address from Multicast array */
197
+#define AX_RX_CTL_AM 0x0010
198
+#define AX_RX_CTL_AB 0x0008 /* Accetp Brocadcast frames*/
199
+#define AX_RX_CTL_SEP 0x0004 /* Save error packets */
200
+#define AX_RX_CTL_AMALL 0x0002 /* Accetp all multicast frames */
201
+#define AX_RX_CTL_PRO 0x0001 /* Promiscuous Mode */
202
+#define AX_RX_CTL_STOP 0x0000 /* Stop MAC */
203
+
204
+#define AX_MONITOR_MODE 0x01
205
+#define AX_MONITOR_LINK 0x02
206
+#define AX_MONITOR_MAGIC 0x04
207
+#define AX_MONITOR_HSFS 0x10
208
+
209
+#define AX_MCAST_FILTER_SIZE 8
210
+#define AX_MAX_MCAST 64
211
+#define AX_INTERRUPT_BUFSIZE 8
212
+
213
+#define AX_EEPROM_LEN 0x40
214
+#define AX_EEPROM_MAGIC 0xdeadbeef
215
+#define EEPROMMASK 0x7f
216
+
217
+/* GPIO REGISTER */
218
+#define AXGPIOS_GPO0EN 0X01 /* 1 << 0 */
219
+#define AXGPIOS_GPO0 0X02 /* 1 << 1 */
220
+#define AXGPIOS_GPO1EN 0X04 /* 1 << 2 */
221
+#define AXGPIOS_GPO1 0X08 /* 1 << 3 */
222
+#define AXGPIOS_GPO2EN 0X10 /* 1 << 4 */
223
+#define AXGPIOS_GPO2 0X20 /* 1 << 5 */
224
+#define AXGPIOS_RSE 0X80 /* 1 << 7 */
225
+
226
+/* TX-header format */
227
+#define AX_TX_HDR_CPHI 0x4000
228
+#define AX_TX_HDR_DICF 0x8000
229
+
230
+/* GMII register definitions */
231
+#define GMII_PHY_CONTROL 0x00 /* control reg */
232
+#define GMII_PHY_STATUS 0x01 /* status reg */
233
+#define GMII_PHY_OUI 0x02 /* most of the OUI bits */
234
+#define GMII_PHY_MODEL 0x03 /* model/rev bits, and rest of OUI */
235
+#define GMII_PHY_ANAR 0x04 /* AN advertisement reg */
236
+#define GMII_PHY_ANLPAR 0x05 /* AN Link Partner */
237
+#define GMII_PHY_ANER 0x06 /* AN expansion reg */
238
+#define GMII_PHY_1000BT_CONTROL 0x09 /* control reg for 1000BT */
239
+#define GMII_PHY_1000BT_STATUS 0x0A /* status reg for 1000BT */
240
+
241
+/* Bit definitions: GMII Control */
242
+#define GMII_CONTROL_RESET 0x8000 /* reset bit in control reg */
243
+#define GMII_CONTROL_LOOPBACK 0x4000 /* loopback bit in control reg */
244
+#define GMII_CONTROL_10MB 0x0000 /* 10 Mbit */
245
+#define GMII_CONTROL_100MB 0x2000 /* 100Mbit */
246
+#define GMII_CONTROL_1000MB 0x0040 /* 1000Mbit */
247
+#define GMII_CONTROL_SPEED_BITS 0x2040 /* speed bit mask */
248
+#define GMII_CONTROL_ENABLE_AUTO 0x1000 /* autonegotiate enable */
249
+#define GMII_CONTROL_POWER_DOWN 0x0800
250
+#define GMII_CONTROL_ISOLATE 0x0400 /* islolate bit */
251
+#define GMII_CONTROL_START_AUTO 0x0200 /* restart autonegotiate */
252
+#define GMII_CONTROL_FULL_DUPLEX 0x0100
253
+
254
+/* Bit definitions: GMII Status */
255
+#define GMII_STATUS_100MB_MASK 0xE000 /* any of these indicate 100 Mbit */
256
+#define GMII_STATUS_10MB_MASK 0x1800 /* either of these indicate 10 Mbit */
257
+#define GMII_STATUS_AUTO_DONE 0x0020 /* auto negotiation complete */
258
+#define GMII_STATUS_AUTO 0x0008 /* auto negotiation is available */
259
+#define GMII_STATUS_LINK_UP 0x0004 /* link status bit */
260
+#define GMII_STATUS_EXTENDED 0x0001 /* extended regs exist */
261
+#define GMII_STATUS_100T4 0x8000 /* capable of 100BT4 */
262
+#define GMII_STATUS_100TXFD 0x4000 /* capable of 100BTX full duplex */
263
+#define GMII_STATUS_100TX 0x2000 /* capable of 100BTX */
264
+#define GMII_STATUS_10TFD 0x1000 /* capable of 10BT full duplex */
265
+#define GMII_STATUS_10T 0x0800 /* capable of 10BT */
266
+
267
+/* Bit definitions: Auto-Negotiation Advertisement */
268
+#define GMII_ANAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
269
+#define GMII_ANAR_PAUSE 0x0400 /* support pause packets */
270
+#define GMII_ANAR_100T4 0x0200 /* support 100BT4 */
271
+#define GMII_ANAR_100TXFD 0x0100 /* support 100BTX full duplex */
272
+#define GMII_ANAR_100TX 0x0080 /* support 100BTX half duplex */
273
+#define GMII_ANAR_10TFD 0x0040 /* support 10BT full duplex */
274
+#define GMII_ANAR_10T 0x0020 /* support 10BT half duplex */
275
+#define GMII_SELECTOR_FIELD 0x001F /* selector field. */
276
+
277
+/* Bit definitions: Auto-Negotiation Link Partner Ability */
278
+#define GMII_ANLPAR_100T4 0x0200 /* support 100BT4 */
279
+#define GMII_ANLPAR_100TXFD 0x0100 /* support 100BTX full duplex */
280
+#define GMII_ANLPAR_100TX 0x0080 /* support 100BTX half duplex */
281
+#define GMII_ANLPAR_10TFD 0x0040 /* support 10BT full duplex */
282
+#define GMII_ANLPAR_10T 0x0020 /* support 10BT half duplex */
283
+#define GMII_ANLPAR_PAUSE 0x0400 /* support pause packets */
284
+#define GMII_ANLPAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
285
+#define GMII_ANLPAR_ACK 0x4000 /* means LCB was successfully rx'd */
286
+#define GMII_SELECTOR_8023 0x0001;
287
+
288
+/* Bit definitions: 1000BaseT AUX Control */
289
+#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000
290
+#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 /* full duplex capable */
291
+#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 /* half duplex capable */
292
+
293
+/* Bit definitions: 1000BaseT AUX Status */
294
+#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 /* full duplex capable */
295
+#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 /* half duplex capable */
296
+
297
+/* Cicada MII Registers */
298
+#define GMII_AUX_CTRL_STATUS 0x1C
299
+#define GMII_AUX_ANEG_CPLT 0x8000
300
+#define GMII_AUX_FDX 0x0020
301
+#define GMII_AUX_SPEED_1000 0x0010
302
+#define GMII_AUX_SPEED_100 0x0008
303
+
304
+#ifndef ADVERTISE_PAUSE_CAP
305
+#define ADVERTISE_PAUSE_CAP 0x0400
306
+#endif
307
+
308
+#ifndef MII_STAT1000
309
+#define MII_STAT1000 0x000A
310
+#endif
311
+
312
+#ifndef LPA_1000FULL
313
+#define LPA_1000FULL 0x0800
314
+#endif
315
+
316
+/* medium mode register */
317
+#define MEDIUM_GIGA_MODE 0x0001
318
+#define MEDIUM_FULL_DUPLEX_MODE 0x0002
319
+#define MEDIUM_TX_ABORT_MODE 0x0004
320
+#define MEDIUM_ENABLE_125MHZ 0x0008
321
+#define MEDIUM_ENABLE_RX_FLOWCTRL 0x0010
322
+#define MEDIUM_ENABLE_TX_FLOWCTRL 0x0020
323
+#define MEDIUM_ENABLE_JUMBO_FRAME 0x0040
324
+#define MEDIUM_CHECK_PAUSE_FRAME_MODE 0x0080
325
+#define MEDIUM_ENABLE_RECEIVE 0x0100
326
+#define MEDIUM_MII_100M_MODE 0x0200
327
+#define MEDIUM_ENABLE_JAM_PATTERN 0x0400
328
+#define MEDIUM_ENABLE_STOP_BACKPRESSURE 0x0800
329
+#define MEDIUM_ENABLE_SUPPER_MAC_SUPPORT 0x1000
330
+
331
+/* PHY mode */
332
+#define PHY_MODE_MARVELL 0
333
+#define PHY_MODE_CICADA_FAMILY 1
334
+#define PHY_MODE_CICADA_V1 1
335
+#define PHY_MODE_AGERE_FAMILY 2
336
+#define PHY_MODE_AGERE_V0 2
337
+#define PHY_MODE_CICADA_V2 5
338
+#define PHY_MODE_AGERE_V0_GMII 6
339
+#define PHY_MODE_CICADA_V2_ASIX 9
340
+#define PHY_MODE_VSC8601 10
341
+#define PHY_MODE_RTL8211CL 12
342
+#define PHY_MODE_RTL8211BN 13
343
+#define PHY_MODE_RTL8251CL 14
344
+#define PHY_MODE_ATTANSIC_V0 0x40
345
+#define PHY_MODE_ATTANSIC_FAMILY 0x40
346
+#define PHY_MODE_MAC_TO_MAC_GMII 0x7C
347
+
348
+/* */
349
+#define LED_MODE_MARVELL 0
350
+#define LED_MODE_CAMEO 1
351
+
352
+#define MARVELL_LED_CTRL 0x18
353
+#define MARVELL_MANUAL_LED 0x19
354
+
355
+#define PHY_IDENTIFIER 0x0002
356
+#define PHY_AGERE_IDENTIFIER 0x0282
357
+#define PHY_CICADA_IDENTIFIER 0x000f
358
+#define PHY_MARVELL_IDENTIFIER 0x0141
359
+
360
+#define PHY_MARVELL_STATUS 0x001b
361
+#define MARVELL_STATUS_HWCFG 0x0004 /* SGMII without clock */
362
+
363
+#define PHY_MARVELL_CTRL 0x0014
364
+#define MARVELL_CTRL_RXDELAY 0x0080
365
+#define MARVELL_CTRL_TXDELAY 0x0002
366
+
367
+#define PHY_CICADA_EXTPAGE 0x001f
368
+#define CICADA_EXTPAGE_EN 0x0001
369
+#define CICADA_EXTPAGE_DIS 0x0000
370
+
371
+/* External ethernet phy */
372
+#define EXTPHY_ID_MASK_OUI(phyid1, phyid2) ((phyid1 << 6) | ((phyid2 & 0xFC00) >> 10))
373
+#define EXTPHY_ID_MASK_MODEL(phyid2) ((phyid2 & 0x3F0) >> 4)
374
+
375
+#define EXTPHY_BROADCOM_OUI 0x2B8094
376
+#define EXTPHY_BCM89811_MODEL 0x02
377
+
378
+struct {unsigned short value, offset; } CICADA_FAMILY_HWINIT[] = {
379
+ {0x0001, 0x001f}, {0x1c25, 0x0017}, {0x2a30, 0x001f}, {0x234c, 0x0010},
380
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa7fa, 0x0000},
381
+ {0x0012, 0x0002}, {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f},
382
+ {0xafac, 0x0000}, {0x000d, 0x0002}, {0x001c, 0x0001}, {0x8fac, 0x0000},
383
+ {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x2a30, 0x001f}, {0x0400, 0x0014},
384
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa760, 0x0000},
385
+ {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000}, {0x52b5, 0x001f},
386
+ {0xa760, 0x0000}, {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000},
387
+ {0x52b5, 0x001f}, {0xafae, 0x0000}, {0x0004, 0x0002}, {0x0671, 0x0001},
388
+ {0x8fae, 0x0000}, {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x0000, 0x001f},
389
+};
390
+
391
+struct {unsigned short value, offset; } CICADA_V2_HWINIT[] = {
392
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x000f, 0x0002},
393
+ {0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
394
+ {0x0000, 0x001f},
395
+};
396
+
397
+struct {unsigned short value, offset; } CICADA_V2_ASIX_HWINIT[] = {
398
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x0012, 0x0002},
399
+ {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f}, {0x000f, 0x0002},
400
+ {0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
401
+ {0x0000, 0x001f},
402
+};
403
+
404
+struct {unsigned short value, offset; } AGERE_FAMILY_HWINIT[] = {
405
+ {0x0800, 0x0000}, {0x0007, 0x0012}, {0x8805, 0x0010}, {0xb03e, 0x0011},
406
+ {0x8808, 0x0010}, {0xe110, 0x0011}, {0x8806, 0x0010}, {0xb03e, 0x0011},
407
+ {0x8807, 0x0010}, {0xff00, 0x0011}, {0x880e, 0x0010}, {0xb4d3, 0x0011},
408
+ {0x880f, 0x0010}, {0xb4d3, 0x0011}, {0x8810, 0x0010}, {0xb4d3, 0x0011},
409
+ {0x8817, 0x0010}, {0x1c00, 0x0011}, {0x300d, 0x0010}, {0x0001, 0x0011},
410
+ {0x0002, 0x0012},
411
+};
412
+
413
+struct ax88178_data {
414
+ u16 EepromData;
415
+ u16 MediaLink;
416
+ int UseGpio0;
417
+ int UseRgmii;
418
+ u8 PhyMode;
419
+ u8 LedMode;
420
+ u8 BuffaloOld;
421
+};
422
+
423
+enum watchdog_state {
424
+ AX_NOP = 0,
425
+ CHK_LINK, /* Routine A */
426
+ CHK_CABLE_EXIST, /* Called by A */
427
+ CHK_CABLE_EXIST_AGAIN, /* Routine B */
428
+ PHY_POWER_UP, /* Called by B */
429
+ PHY_POWER_UP_BH,
430
+ PHY_POWER_DOWN,
431
+ CHK_CABLE_STATUS, /* Routine C */
432
+ WAIT_AUTONEG_COMPLETE,
433
+ AX_SET_RX_CFG,
434
+ AX_CHK_AUTODETACH,
435
+};
436
+
437
+struct ax88772b_data {
438
+ struct usbnet *dev;
439
+ struct workqueue_struct *ax_work;
440
+ struct work_struct check_link;
441
+ unsigned long time_to_chk;
442
+ u16 psc;
443
+ u8 pw_enabled;
444
+ u8 Event;
445
+ u8 checksum;
446
+ u8 PhySelect:1;
447
+ u8 OperationMode:1;
448
+ u16 presvd_phy_advertise;
449
+ u16 presvd_phy_bmcr;
450
+
451
+ u32 ext_phy_oui;
452
+ u8 ext_phy_model;
453
+};
454
+
455
+/* define for MAC or PHY mode */
456
+#define OPERATION_MAC_MODE 0
457
+#define OPERATION_PHY_MODE 1
458
+
459
+struct ax88772a_data {
460
+ struct usbnet *dev;
461
+ struct workqueue_struct *ax_work;
462
+ struct work_struct check_link;
463
+ unsigned long autoneg_start;
464
+#define AX88772B_WATCHDOG (6 * HZ)
465
+ u8 Event;
466
+ u8 TickToExpire;
467
+ u8 DlyIndex;
468
+ u8 DlySel;
469
+ u16 EepromData;
470
+ u16 presvd_phy_advertise;
471
+ u16 presvd_phy_bmcr;
472
+};
473
+
474
+struct ax88772_data {
475
+ struct usbnet *dev;
476
+ struct workqueue_struct *ax_work;
477
+ struct work_struct check_link;
478
+ unsigned long autoneg_start;
479
+ u8 Event;
480
+ u8 TickToExpire;
481
+ u16 presvd_phy_advertise;
482
+ u16 presvd_phy_bmcr;
483
+};
484
+
485
+#define AX_RX_CHECKSUM 1
486
+#define AX_TX_CHECKSUM 2
487
+
488
+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
489
+struct ax8817x_data {
490
+ u8 multi_filter[AX_MCAST_FILTER_SIZE];
491
+ int (*resume) (struct usb_interface *intf);
492
+ int (*suspend) (struct usb_interface *intf,
493
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
494
+ pm_message_t message);
495
+#else
496
+ u32 message);
497
+#endif
498
+};
499
+
500
+struct ax88172_int_data {
501
+ u16 res1;
502
+#define AX_INT_PPLS_LINK (1 << 0)
503
+#define AX_INT_SPLS_LINK (1 << 1)
504
+#define AX_INT_CABOFF_UNPLUG (1 << 7)
505
+ u8 link;
506
+ u16 res2;
507
+ u8 status;
508
+ u16 res3;
509
+} __attribute__ ((packed));
510
+
511
+#define AX_RXHDR_L4_ERR (1 << 8)
512
+#define AX_RXHDR_L3_ERR (1 << 9)
513
+
514
+#define AX_RXHDR_L4_TYPE_UDP 1
515
+#define AX_RXHDR_L4_TYPE_ICMP 2
516
+#define AX_RXHDR_L4_TYPE_IGMP 3
517
+#define AX_RXHDR_L4_TYPE_TCP 4
518
+#define AX_RXHDR_L4_TYPE_TCMPV6 5
519
+#define AX_RXHDR_L4_TYPE_MASK 7
520
+
521
+#define AX_RXHDR_L3_TYPE_IP 1
522
+#define AX_RXHDR_L3_TYPE_IPV6 2
523
+
524
+struct ax88772b_rx_header {
525
+#if defined(__LITTLE_ENDIAN_BITFIELD)
526
+ u16 len:11,
527
+ res1:1,
528
+ crc:1,
529
+ mii:1,
530
+ runt:1,
531
+ mc_bc:1;
532
+
533
+ u16 len_bar:11,
534
+ res2:5;
535
+
536
+ u8 vlan_ind:3,
537
+ vlan_tag_striped:1,
538
+ pri:3,
539
+ res3:1;
540
+
541
+ u8 l4_csum_err:1,
542
+ l3_csum_err:1,
543
+ l4_type:3,
544
+ l3_type:2,
545
+ ce:1;
546
+#elif defined(__BIG_ENDIAN_BITFIELD)
547
+ u16 mc_bc:1,
548
+ runt:1,
549
+ mii:1,
550
+ crc:1,
551
+ res1:1,
552
+ len:11;
553
+
554
+ u16 res2:5,
555
+ len_bar:11;
556
+
557
+ u8 res3:1,
558
+ pri:3,
559
+ vlan_tag_striped:1,
560
+ vlan_ind:3;
561
+
562
+ u8 ce:1,
563
+ l3_type:2,
564
+ l4_type:3,
565
+ l3_csum_err:1,
566
+ l4_csum_err:1;
567
+#else
568
+#error "Please fix <asm/byteorder.h>"
569
+#endif
570
+
571
+} __attribute__ ((packed));
572
+
573
+
574
+#endif /* __LINUX_USBNET_ASIX_H */
575
+
kernel/drivers/net/usb/AX88772C_eeprom/axusbnet.c
....@@ -0,0 +1,1488 @@
1
+/*
2
+ * USB Network driver infrastructure
3
+ * Copyright (C) 2000-2005 by David Brownell
4
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ */
20
+
21
+/*
22
+ * This is a generic "USB networking" framework that works with several
23
+ * kinds of full and high speed networking devices: host-to-host cables,
24
+ * smart usb peripherals, and actual Ethernet adapters.
25
+ *
26
+ * These devices usually differ in terms of control protocols (if they
27
+ * even have one!) and sometimes they define new framing to wrap or batch
28
+ * Ethernet packets. Otherwise, they talk to USB pretty much the same,
29
+ * so interface (un)binding, endpoint I/O queues, fault handling, and other
30
+ * issues can usefully be addressed by this framework.
31
+ */
32
+
33
+/* error path messages, extra info */
34
+#define DEBUG
35
+/* more; success messages */
36
+/* #define VERBOSE */
37
+
38
+#include <linux/module.h>
39
+#include <linux/init.h>
40
+#include <linux/netdevice.h>
41
+#include <linux/etherdevice.h>
42
+#include <linux/ctype.h>
43
+#include <linux/ethtool.h>
44
+#include <linux/workqueue.h>
45
+#include <linux/mii.h>
46
+#include <linux/usb.h>
47
+/*#include <linux/usb/usbnet.h>*/
48
+
49
+#include "asix.h"
50
+#include "axusbnet.h"
51
+
52
+#define DRIVER_VERSION "22-Aug-2005"
53
+
54
+static void axusbnet_unlink_rx_urbs(struct usbnet *);
55
+
56
+static void
57
+ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
58
+ u16 size, void *data);
59
+
60
+/*-------------------------------------------------------------------------*/
61
+
62
+/*
63
+ * Nineteen USB 1.1 max size bulk transactions per frame (ms), max.
64
+ * Several dozen bytes of IPv4 data can fit in two such transactions.
65
+ * One maximum size Ethernet packet takes twenty four of them.
66
+ * For high speed, each frame comfortably fits almost 36 max size
67
+ * Ethernet packets (so queues should be bigger).
68
+ *
69
+ * REVISIT qlens should be members of 'struct usbnet'; the goal is to
70
+ * let the USB host controller be busy for 5msec or more before an irq
71
+ * is required, under load. Jumbograms change the equation.
72
+ */
73
+#define RX_MAX_QUEUE_MEMORY (60 * 1518)
74
+#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
75
+ (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4)
76
+#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
77
+ (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4)
78
+
79
+/* reawaken network queue this soon after stopping; else watchdog barks */
80
+/* #define TX_TIMEOUT_JIFFIES (5 * HZ) */
81
+#define TX_TIMEOUT_JIFFIES (30 * HZ)
82
+
83
+/* throttle rx/tx briefly after some faults, so khubd might disconnect() */
84
+/* us (it polls at HZ/4 usually) before we report too many false errors. */
85
+#define THROTTLE_JIFFIES (HZ / 8)
86
+
87
+/* between wakeups */
88
+#define UNLINK_TIMEOUT_MS 3
89
+
90
+/*-------------------------------------------------------------------------*/
91
+
92
+static const char driver_name[] = "axusbnet";
93
+
94
+/* use ethtool to change the level for any given device */
95
+static int msg_level = -1;
96
+module_param(msg_level, int, 0);
97
+MODULE_PARM_DESC(msg_level, "Override default message level");
98
+
99
+/*-------------------------------------------------------------------------*/
100
+
101
+/* handles CDC Ethernet and many other network "bulk data" interfaces */
102
+static
103
+int axusbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
104
+{
105
+ int tmp;
106
+ struct usb_host_interface *alt = NULL;
107
+ struct usb_host_endpoint *in = NULL, *out = NULL;
108
+ struct usb_host_endpoint *status = NULL;
109
+
110
+ for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
111
+ unsigned ep;
112
+
113
+ in = out = status = NULL;
114
+ alt = intf->altsetting + tmp;
115
+
116
+ /* take the first altsetting with in-bulk + out-bulk;
117
+ * remember any status endpoint, just in case;
118
+ * ignore other endpoints and altsetttings.
119
+ */
120
+ for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
121
+ struct usb_host_endpoint *e;
122
+ int intr = 0;
123
+
124
+ e = alt->endpoint + ep;
125
+ switch (e->desc.bmAttributes) {
126
+ case USB_ENDPOINT_XFER_INT:
127
+ if (!(e->desc.bEndpointAddress & USB_DIR_IN))
128
+ continue;
129
+ intr = 1;
130
+ /* FALLTHROUGH */
131
+ case USB_ENDPOINT_XFER_BULK:
132
+ break;
133
+ default:
134
+ continue;
135
+ }
136
+ if (e->desc.bEndpointAddress & USB_DIR_IN) {
137
+ if (!intr && !in) {
138
+ in = e;
139
+ } else if (intr && !status) {
140
+ status = e;
141
+ }
142
+ } else {
143
+ if (!out) {
144
+ out = e;
145
+ }
146
+ }
147
+ }
148
+ if (in && out)
149
+ break;
150
+ }
151
+ if (!alt || !in || !out)
152
+ return -EINVAL;
153
+
154
+ if (alt->desc.bAlternateSetting != 0
155
+ || !(dev->driver_info->flags & FLAG_NO_SETINT)) {
156
+ tmp = usb_set_interface(dev->udev, alt->desc.bInterfaceNumber,
157
+ alt->desc.bAlternateSetting);
158
+ if (tmp < 0)
159
+ return tmp;
160
+ }
161
+
162
+ dev->in = usb_rcvbulkpipe(dev->udev,
163
+ in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
164
+ dev->out = usb_sndbulkpipe(dev->udev,
165
+ out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
166
+ dev->status = status;
167
+ return 0;
168
+}
169
+
170
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
171
+static void intr_complete(struct urb *urb, struct pt_regs *regs);
172
+#else
173
+static void intr_complete(struct urb *urb);
174
+#endif
175
+
176
+static int init_status(struct usbnet *dev, struct usb_interface *intf)
177
+{
178
+ char *buf = NULL;
179
+ unsigned pipe = 0;
180
+ unsigned maxp;
181
+ unsigned period;
182
+
183
+ if (!dev->driver_info->status)
184
+ return 0;
185
+
186
+ pipe = usb_rcvintpipe(dev->udev,
187
+ dev->status->desc.bEndpointAddress
188
+ & USB_ENDPOINT_NUMBER_MASK);
189
+ maxp = usb_maxpacket(dev->udev, pipe, 0);
190
+
191
+ /* avoid 1 msec chatter: min 8 msec poll rate */
192
+ period = max((int) dev->status->desc.bInterval,
193
+ (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
194
+
195
+ buf = kmalloc(maxp, GFP_KERNEL);
196
+ if (buf) {
197
+ dev->interrupt = usb_alloc_urb(0, GFP_KERNEL);
198
+ if (!dev->interrupt) {
199
+ kfree(buf);
200
+ return -ENOMEM;
201
+ } else {
202
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
203
+ dev->interrupt->transfer_flags |= URB_ASYNC_UNLINK;
204
+#endif
205
+ usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
206
+ buf, maxp, intr_complete, dev, period);
207
+ devdbg(dev,
208
+ "status ep%din, %d bytes period %d",
209
+ usb_pipeendpoint(pipe), maxp, period);
210
+ }
211
+ }
212
+ return 0;
213
+}
214
+
215
+/* Passes this packet up the stack, updating its accounting.
216
+ * Some link protocols batch packets, so their rx_fixup paths
217
+ * can return clones as well as just modify the original skb.
218
+ */
219
+static
220
+void axusbnet_skb_return(struct usbnet *dev, struct sk_buff *skb)
221
+{
222
+ int status;
223
+
224
+ skb->dev = dev->net;
225
+ skb->protocol = eth_type_trans(skb, dev->net);
226
+ dev->stats.rx_packets++;
227
+ dev->stats.rx_bytes += skb->len;
228
+
229
+ if (netif_msg_rx_status(dev))
230
+ devdbg(dev, "< rx, len %zu, type 0x%x",
231
+ skb->len + sizeof(struct ethhdr), skb->protocol);
232
+ memset(skb->cb, 0, sizeof(struct skb_data));
233
+ status = netif_rx(skb);
234
+ if (status != NET_RX_SUCCESS && netif_msg_rx_err(dev))
235
+ devdbg(dev, "netif_rx status %d", status);
236
+}
237
+
238
+/*-------------------------------------------------------------------------
239
+ *
240
+ * Network Device Driver (peer link to "Host Device", from USB host)
241
+ *
242
+ *-------------------------------------------------------------------------*/
243
+
244
+static
245
+int axusbnet_change_mtu(struct net_device *net, int new_mtu)
246
+{
247
+ struct usbnet *dev = netdev_priv(net);
248
+ int ll_mtu = new_mtu + net->hard_header_len;
249
+ int old_hard_mtu = dev->hard_mtu;
250
+ int old_rx_urb_size = dev->rx_urb_size;
251
+
252
+ if (new_mtu <= 0)
253
+ return -EINVAL;
254
+ /* no second zero-length packet read wanted after mtu-sized packets */
255
+ if ((ll_mtu % dev->maxpacket) == 0)
256
+ return -EDOM;
257
+ net->mtu = new_mtu;
258
+
259
+ dev->hard_mtu = net->mtu + net->hard_header_len;
260
+ if (dev->rx_urb_size == old_hard_mtu) {
261
+ dev->rx_urb_size = dev->hard_mtu;
262
+ if (dev->rx_urb_size > old_rx_urb_size)
263
+ axusbnet_unlink_rx_urbs(dev);
264
+ }
265
+
266
+ return 0;
267
+}
268
+
269
+static struct net_device_stats *axusbnet_get_stats(struct net_device *net)
270
+{
271
+ struct usbnet *dev = netdev_priv(net);
272
+ return &dev->stats;
273
+}
274
+
275
+/*-------------------------------------------------------------------------*/
276
+
277
+/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
278
+ * completion callbacks. 2.5 should have fixed those bugs...
279
+ */
280
+
281
+static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
282
+ struct sk_buff_head *list, enum skb_state state)
283
+{
284
+ unsigned long flags;
285
+ enum skb_state old_state;
286
+ struct skb_data *entry = (struct skb_data *) skb->cb;
287
+
288
+ spin_lock_irqsave(&list->lock, flags);
289
+ old_state = entry->state;
290
+ entry->state = state;
291
+ __skb_unlink(skb, list);
292
+
293
+ /* defer_bh() is never called with list == &dev->done.
294
+ * spin_lock_nested() tells lockdep that it is OK to take
295
+ * dev->done.lock here with list->lock held.
296
+ */
297
+ spin_lock_nested(&dev->done.lock, SINGLE_DEPTH_NESTING);
298
+
299
+ __skb_queue_tail(&dev->done, skb);
300
+ if (dev->done.qlen == 1)
301
+ tasklet_schedule(&dev->bh);
302
+
303
+ spin_unlock(&dev->done.lock);
304
+ spin_unlock_irqrestore(&list->lock, flags);
305
+
306
+ return old_state;
307
+}
308
+
309
+/* some work can't be done in tasklets, so we use keventd
310
+ *
311
+ * NOTE: annoying asymmetry: if it's active, schedule_work() fails,
312
+ * but tasklet_schedule() doesn't. hope the failure is rare.
313
+ */
314
+static
315
+void axusbnet_defer_kevent(struct usbnet *dev, int work)
316
+{
317
+ set_bit(work, &dev->flags);
318
+ if (!schedule_work(&dev->kevent))
319
+ deverr(dev, "kevent %d may have been dropped", work);
320
+ else
321
+ devdbg(dev, "kevent %d scheduled", work);
322
+}
323
+
324
+/*-------------------------------------------------------------------------*/
325
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
326
+static void rx_complete(struct urb *urb, struct pt_regs *regs);
327
+#else
328
+static void rx_complete(struct urb *urb);
329
+#endif
330
+
331
+static void rx_submit(struct usbnet *dev, struct urb *urb, gfp_t flags)
332
+{
333
+ struct sk_buff *skb;
334
+ struct skb_data *entry;
335
+ int retval = 0;
336
+ unsigned long lockflags;
337
+ size_t size = dev->rx_urb_size;
338
+ struct driver_info *info = dev->driver_info;
339
+ u8 align;
340
+
341
+ /* prevent rx skb allocation when error ratio is high */
342
+ if (test_bit(EVENT_RX_KILL, &dev->flags)) {
343
+ usb_free_urb(urb);
344
+ return;
345
+ }
346
+
347
+#if (AX_FORCE_BUFF_ALIGN)
348
+ align = 0;
349
+#else
350
+ if (!(info->flags & FLAG_HW_IP_ALIGNMENT))
351
+ align = NET_IP_ALIGN;
352
+ else
353
+ align = 0;
354
+#endif
355
+ skb = alloc_skb(size + align, flags);
356
+ if (skb == NULL) {
357
+
358
+ if (netif_msg_rx_err(dev))
359
+ devdbg(dev, "no rx skb");
360
+
361
+ if ((dev->rx_urb_size > 2048) && dev->rx_size) {
362
+ dev->rx_size--;
363
+ dev->rx_urb_size =
364
+ AX88772B_BULKIN_SIZE[dev->rx_size].size;
365
+
366
+ ax8817x_write_cmd_async(dev, 0x2A,
367
+ AX88772B_BULKIN_SIZE[dev->rx_size].byte_cnt,
368
+ AX88772B_BULKIN_SIZE[dev->rx_size].threshold,
369
+ 0, NULL);
370
+ }
371
+
372
+ if (!(dev->flags & EVENT_RX_MEMORY))
373
+ axusbnet_defer_kevent(dev, EVENT_RX_MEMORY);
374
+ usb_free_urb(urb);
375
+ return;
376
+ }
377
+
378
+ if (align)
379
+ skb_reserve(skb, NET_IP_ALIGN);
380
+
381
+ entry = (struct skb_data *) skb->cb;
382
+ entry->urb = urb;
383
+ entry->dev = dev;
384
+ entry->state = rx_start;
385
+ entry->length = 0;
386
+
387
+ usb_fill_bulk_urb(urb, dev->udev, dev->in, skb->data,
388
+ size, rx_complete, skb);
389
+
390
+ spin_lock_irqsave(&dev->rxq.lock, lockflags);
391
+
392
+ if (netif_running(dev->net)
393
+ && netif_device_present(dev->net)
394
+ && !test_bit(EVENT_RX_HALT, &dev->flags)) {
395
+ switch (retval = usb_submit_urb(urb, GFP_ATOMIC)) {
396
+ case -EPIPE:
397
+ axusbnet_defer_kevent(dev, EVENT_RX_HALT);
398
+ break;
399
+ case -ENOMEM:
400
+ axusbnet_defer_kevent(dev, EVENT_RX_MEMORY);
401
+ break;
402
+ case -ENODEV:
403
+ if (netif_msg_ifdown(dev))
404
+ devdbg(dev, "device gone");
405
+ netif_device_detach(dev->net);
406
+ break;
407
+ default:
408
+ if (netif_msg_rx_err(dev))
409
+ devdbg(dev, "rx submit, %d", retval);
410
+ tasklet_schedule(&dev->bh);
411
+ break;
412
+ case 0:
413
+ __skb_queue_tail(&dev->rxq, skb);
414
+ }
415
+ } else {
416
+ if (netif_msg_ifdown(dev))
417
+ devdbg(dev, "rx: stopped");
418
+ retval = -ENOLINK;
419
+ }
420
+ spin_unlock_irqrestore(&dev->rxq.lock, lockflags);
421
+ if (retval) {
422
+ dev_kfree_skb_any(skb);
423
+ usb_free_urb(urb);
424
+ }
425
+}
426
+
427
+
428
+/*-------------------------------------------------------------------------*/
429
+
430
+static inline void rx_process(struct usbnet *dev, struct sk_buff *skb)
431
+{
432
+ if (dev->driver_info->rx_fixup
433
+ && !dev->driver_info->rx_fixup(dev, skb))
434
+ goto error;
435
+ /* else network stack removes extra byte if we forced a short packet */
436
+
437
+ if (skb->len)
438
+ axusbnet_skb_return(dev, skb);
439
+ else {
440
+ if (netif_msg_rx_err(dev))
441
+ devdbg(dev, "drop");
442
+error:
443
+ dev->stats.rx_errors++;
444
+ skb_queue_tail(&dev->done, skb);
445
+ }
446
+}
447
+
448
+/*-------------------------------------------------------------------------*/
449
+
450
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
451
+static void rx_complete(struct urb *urb, struct pt_regs *regs)
452
+#else
453
+static void rx_complete(struct urb *urb)
454
+#endif
455
+{
456
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
457
+ struct skb_data *entry = (struct skb_data *) skb->cb;
458
+ struct usbnet *dev = entry->dev;
459
+ int urb_status = urb->status;
460
+ enum skb_state state;
461
+
462
+ skb_put(skb, urb->actual_length);
463
+ state = rx_done;
464
+ entry->urb = NULL;
465
+
466
+ switch (urb_status) {
467
+ /* success */
468
+ case 0:
469
+ if (skb->len < dev->net->hard_header_len) {
470
+ entry->state = rx_cleanup;
471
+ dev->stats.rx_errors++;
472
+ dev->stats.rx_length_errors++;
473
+ if (netif_msg_rx_err(dev))
474
+ devdbg(dev, "rx length %d", skb->len);
475
+ }
476
+ break;
477
+
478
+ /* stalls need manual reset. this is rare ... except that
479
+ * when going through USB 2.0 TTs, unplug appears this way.
480
+ * we avoid the highspeed version of the ETIMEDOUT/EILSEQ
481
+ * storm, recovering as needed.
482
+ */
483
+ case -EPIPE:
484
+ dev->stats.rx_errors++;
485
+ axusbnet_defer_kevent(dev, EVENT_RX_HALT);
486
+ /* FALLTHROUGH */
487
+
488
+ /* software-driven interface shutdown */
489
+ case -ECONNRESET: /* async unlink */
490
+ case -ESHUTDOWN: /* hardware gone */
491
+ if (netif_msg_ifdown(dev))
492
+ devdbg(dev, "rx shutdown, code %d", urb_status);
493
+ goto block;
494
+
495
+ /* we get controller i/o faults during khubd disconnect() delays.
496
+ * throttle down resubmits, to avoid log floods; just temporarily,
497
+ * so we still recover when the fault isn't a khubd delay.
498
+ */
499
+ case -EPROTO:
500
+ case -ETIME:
501
+ case -EILSEQ:
502
+ dev->stats.rx_errors++;
503
+ if (!timer_pending(&dev->delay)) {
504
+ mod_timer(&dev->delay, jiffies + THROTTLE_JIFFIES);
505
+ if (netif_msg_link(dev))
506
+ devdbg(dev, "rx throttle %d", urb_status);
507
+ }
508
+block:
509
+ state = rx_cleanup;
510
+ entry->urb = urb;
511
+ urb = NULL;
512
+ break;
513
+
514
+ /* data overrun ... flush fifo? */
515
+ case -EOVERFLOW:
516
+ dev->stats.rx_over_errors++;
517
+ /* FALLTHROUGH */
518
+
519
+ default:
520
+ state = rx_cleanup;
521
+ dev->stats.rx_errors++;
522
+ if (netif_msg_rx_err(dev))
523
+ devdbg(dev, "rx status %d", urb_status);
524
+ break;
525
+ }
526
+
527
+ /* stop rx if packet error rate is high */
528
+ if (++dev->pkt_cnt > 30) {
529
+ dev->pkt_cnt = 0;
530
+ dev->pkt_err = 0;
531
+ } else {
532
+ if (state == rx_cleanup)
533
+ dev->pkt_err++;
534
+ if (dev->pkt_err > 20)
535
+ set_bit(EVENT_RX_KILL, &dev->flags);
536
+ }
537
+
538
+ state = defer_bh(dev, skb, &dev->rxq, state);
539
+
540
+ if (urb) {
541
+ if (netif_running(dev->net) &&
542
+ !test_bit(EVENT_RX_HALT, &dev->flags) &&
543
+ state != unlink_start) {
544
+ rx_submit(dev, urb, GFP_ATOMIC);
545
+ return;
546
+ }
547
+ usb_free_urb(urb);
548
+ }
549
+ if (netif_msg_rx_err(dev))
550
+ devdbg(dev, "no read resubmitted");
551
+}
552
+
553
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
554
+static void intr_complete(struct urb *urb, struct pt_regs *regs)
555
+#else
556
+static void intr_complete(struct urb *urb)
557
+#endif
558
+{
559
+ struct usbnet *dev = urb->context;
560
+ int status = urb->status;
561
+
562
+ switch (status) {
563
+ /* success */
564
+ case 0:
565
+ dev->driver_info->status(dev, urb);
566
+ break;
567
+
568
+ /* software-driven interface shutdown */
569
+ case -ENOENT: /* urb killed */
570
+ case -ESHUTDOWN: /* hardware gone */
571
+ if (netif_msg_ifdown(dev))
572
+ devdbg(dev, "intr shutdown, code %d", status);
573
+ return;
574
+
575
+ /* NOTE: not throttling like RX/TX, since this endpoint
576
+ * already polls infrequently
577
+ */
578
+ default:
579
+ devdbg(dev, "intr status %d", status);
580
+ break;
581
+ }
582
+
583
+ if (!netif_running(dev->net))
584
+ return;
585
+
586
+ memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
587
+ status = usb_submit_urb(urb, GFP_ATOMIC);
588
+ if (status != 0 && netif_msg_timer(dev))
589
+ deverr(dev, "intr resubmit --> %d", status);
590
+}
591
+
592
+/*-------------------------------------------------------------------------*/
593
+
594
+/* unlink pending rx/tx; completion handlers do all other cleanup */
595
+
596
+static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
597
+{
598
+ unsigned long flags;
599
+ struct sk_buff *skb = NULL;
600
+ int count = 0;
601
+
602
+ spin_lock_irqsave (&q->lock, flags);
603
+ while (!skb_queue_empty(q)) {
604
+ struct skb_data *entry;
605
+ struct urb *urb;
606
+ int retval;
607
+
608
+ skb_queue_walk(q, skb) {
609
+ entry = (struct skb_data *) skb->cb;
610
+ if (entry->state != unlink_start)
611
+ goto found;
612
+ }
613
+ break;
614
+found:
615
+ entry->state = unlink_start;
616
+ urb = entry->urb;
617
+
618
+ /*
619
+ * Get reference count of the URB to avoid it to be
620
+ * freed during usb_unlink_urb, which may trigger
621
+ * use-after-free problem inside usb_unlink_urb since
622
+ * usb_unlink_urb is always racing with .complete
623
+ * handler(include defer_bh).
624
+ */
625
+ usb_get_urb(urb);
626
+ spin_unlock_irqrestore(&q->lock, flags);
627
+ // during some PM-driven resume scenarios,
628
+ // these (async) unlinks complete immediately
629
+ retval = usb_unlink_urb (urb);
630
+ if (retval != -EINPROGRESS && retval != 0)
631
+ printk(DEBUG "unlink urb err, %d\n", retval);
632
+ else
633
+ count++;
634
+ usb_put_urb(urb);
635
+ spin_lock_irqsave(&q->lock, flags);
636
+ }
637
+ spin_unlock_irqrestore (&q->lock, flags);
638
+
639
+ return count;
640
+}
641
+
642
+/* Flush all pending rx urbs */
643
+/* minidrivers may need to do this when the MTU changes */
644
+
645
+static
646
+void axusbnet_unlink_rx_urbs(struct usbnet *dev)
647
+{
648
+ if (netif_running(dev->net)) {
649
+ (void) unlink_urbs(dev, &dev->rxq);
650
+ tasklet_schedule(&dev->bh);
651
+ }
652
+}
653
+
654
+/*-------------------------------------------------------------------------*/
655
+
656
+/* precondition: never called in_interrupt */
657
+
658
+static
659
+int axusbnet_stop(struct net_device *net)
660
+{
661
+ struct usbnet *dev = netdev_priv(net);
662
+ struct driver_info *info = dev->driver_info;
663
+
664
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)
665
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
666
+#else
667
+ DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
668
+#endif
669
+ DECLARE_WAITQUEUE(wait, current);
670
+
671
+ netif_stop_queue(net);
672
+
673
+ if (netif_msg_ifdown(dev))
674
+ devinfo(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
675
+ dev->stats.rx_packets, dev->stats.tx_packets,
676
+ dev->stats.rx_errors, dev->stats.tx_errors);
677
+
678
+ /* allow minidriver to stop correctly (wireless devices to turn off
679
+ * radio etc) */
680
+ if (info->stop) {
681
+ int retval;
682
+ retval = info->stop(dev);
683
+ if (retval < 0 && netif_msg_ifdown(dev))
684
+ devinfo(dev,
685
+ "stop fail (%d) usbnet usb-%s-%s, %s",
686
+ retval,
687
+ dev->udev->bus->bus_name, dev->udev->devpath,
688
+ info->description);
689
+ }
690
+
691
+ if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
692
+ int temp;
693
+ /* ensure there are no more active urbs */
694
+ add_wait_queue(&unlink_wakeup, &wait);
695
+ dev->wait = &unlink_wakeup;
696
+ temp = unlink_urbs(dev, &dev->txq) +
697
+ unlink_urbs(dev, &dev->rxq);
698
+
699
+ /* maybe wait for deletions to finish. */
700
+ while (!skb_queue_empty(&dev->rxq)
701
+ && !skb_queue_empty(&dev->txq)
702
+ && !skb_queue_empty(&dev->done)) {
703
+ msleep(UNLINK_TIMEOUT_MS);
704
+ if (netif_msg_ifdown(dev))
705
+ devdbg(dev, "waited for %d urb completions",
706
+ temp);
707
+ }
708
+ dev->wait = NULL;
709
+ remove_wait_queue(&unlink_wakeup, &wait);
710
+ }
711
+
712
+ usb_kill_urb(dev->interrupt);
713
+
714
+ /* deferred work (task, timer, softirq) must also stop.
715
+ * can't flush_scheduled_work() until we drop rtnl (later),
716
+ * else workers could deadlock; so make workers a NOP.
717
+ */
718
+ dev->flags = 0;
719
+ del_timer_sync(&dev->delay);
720
+ tasklet_kill(&dev->bh);
721
+
722
+ return 0;
723
+}
724
+
725
+/*-------------------------------------------------------------------------*/
726
+
727
+/* posts reads, and enables write queuing */
728
+
729
+/* precondition: never called in_interrupt */
730
+
731
+static
732
+int axusbnet_open(struct net_device *net)
733
+{
734
+ struct usbnet *dev = netdev_priv(net);
735
+ int retval = 0;
736
+ struct driver_info *info = dev->driver_info;
737
+
738
+ /* put into "known safe" state */
739
+ if (info->reset) {
740
+ retval = info->reset(dev);
741
+ if (retval < 0) {
742
+ if (netif_msg_ifup(dev))
743
+ devinfo(dev,
744
+ "open reset fail (%d) usbnet usb-%s-%s, %s",
745
+ retval,
746
+ dev->udev->bus->bus_name,
747
+ dev->udev->devpath,
748
+ info->description);
749
+ goto done;
750
+ }
751
+ }
752
+
753
+ /* insist peer be connected */
754
+ if (info->check_connect) {
755
+ retval = info->check_connect(dev);
756
+ if (retval < 0) {
757
+ if (netif_msg_ifup(dev))
758
+ devdbg(dev, "can't open; %d", retval);
759
+ goto done;
760
+ }
761
+ }
762
+
763
+ /* start any status interrupt transfer */
764
+ if (dev->interrupt) {
765
+ retval = usb_submit_urb(dev->interrupt, GFP_KERNEL);
766
+ if (retval < 0) {
767
+ if (netif_msg_ifup(dev))
768
+ deverr(dev, "intr submit %d", retval);
769
+ goto done;
770
+ }
771
+ }
772
+
773
+ /* reset rx error state */
774
+ dev->pkt_cnt = 0;
775
+ dev->pkt_err = 0;
776
+ clear_bit(EVENT_RX_KILL, &dev->flags);
777
+
778
+ netif_start_queue(net);
779
+ if (netif_msg_ifup(dev)) {
780
+ char *framing;
781
+
782
+ if (dev->driver_info->flags & FLAG_FRAMING_NC)
783
+ framing = "NetChip";
784
+ else if (dev->driver_info->flags & FLAG_FRAMING_GL)
785
+ framing = "GeneSys";
786
+ else if (dev->driver_info->flags & FLAG_FRAMING_Z)
787
+ framing = "Zaurus";
788
+ else if (dev->driver_info->flags & FLAG_FRAMING_RN)
789
+ framing = "RNDIS";
790
+ else if (dev->driver_info->flags & FLAG_FRAMING_AX)
791
+ framing = "ASIX";
792
+ else
793
+ framing = "simple";
794
+
795
+ devinfo(dev, "open: enable queueing (rx %d, tx %d) mtu %d %s framing",
796
+ (int)RX_QLEN(dev), (int)TX_QLEN(dev), dev->net->mtu,
797
+ framing);
798
+ }
799
+
800
+ /* delay posting reads until we're fully open */
801
+ tasklet_schedule(&dev->bh);
802
+ return retval;
803
+done:
804
+ return retval;
805
+}
806
+
807
+/*-------------------------------------------------------------------------*/
808
+
809
+/* ethtool methods; minidrivers may need to add some more, but
810
+ * they'll probably want to use this base set.
811
+ */
812
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
813
+static
814
+int axusbnet_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
815
+{
816
+ struct usbnet *dev = netdev_priv(net);
817
+
818
+ if (!dev->mii.mdio_read)
819
+ return -EOPNOTSUPP;
820
+
821
+ return mii_ethtool_gset(&dev->mii, cmd);
822
+}
823
+
824
+static
825
+int axusbnet_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
826
+{
827
+ struct usbnet *dev = netdev_priv(net);
828
+ int retval;
829
+
830
+ if (!dev->mii.mdio_write)
831
+ return -EOPNOTSUPP;
832
+
833
+ retval = mii_ethtool_sset(&dev->mii, cmd);
834
+
835
+ /* link speed/duplex might have changed */
836
+ if (dev->driver_info->link_reset)
837
+ dev->driver_info->link_reset(dev);
838
+
839
+ return retval;
840
+
841
+}
842
+#endif
843
+static
844
+u32 axusbnet_get_link(struct net_device *net)
845
+{
846
+ struct usbnet *dev = netdev_priv(net);
847
+
848
+ /* If a check_connect is defined, return its result */
849
+ if (dev->driver_info->check_connect)
850
+ return dev->driver_info->check_connect(dev) == 0;
851
+
852
+ /* if the device has mii operations, use those */
853
+ if (dev->mii.mdio_read)
854
+ return mii_link_ok(&dev->mii);
855
+
856
+ /* Otherwise, dtrt for drivers calling netif_carrier_{on,off} */
857
+ return ethtool_op_get_link(net);
858
+}
859
+
860
+static
861
+int axusbnet_nway_reset(struct net_device *net)
862
+{
863
+ struct usbnet *dev = netdev_priv(net);
864
+
865
+ if (!dev->mii.mdio_write)
866
+ return -EOPNOTSUPP;
867
+
868
+ return mii_nway_restart(&dev->mii);
869
+}
870
+
871
+static
872
+void axusbnet_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
873
+{
874
+ struct usbnet *dev = netdev_priv(net);
875
+
876
+ strncpy(info->driver, dev->driver_name, sizeof(info->driver));
877
+ strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
878
+ strncpy(info->fw_version, dev->driver_info->description,
879
+ sizeof(info->fw_version));
880
+ usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info));
881
+}
882
+
883
+static
884
+u32 axusbnet_get_msglevel(struct net_device *net)
885
+{
886
+ struct usbnet *dev = netdev_priv(net);
887
+
888
+ return dev->msg_enable;
889
+}
890
+
891
+static
892
+void axusbnet_set_msglevel(struct net_device *net, u32 level)
893
+{
894
+ struct usbnet *dev = netdev_priv(net);
895
+
896
+ dev->msg_enable = level;
897
+}
898
+
899
+/* drivers may override default ethtool_ops in their bind() routine */
900
+static struct ethtool_ops axusbnet_ethtool_ops = {
901
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
902
+ .get_settings = axusbnet_get_settings,
903
+ .set_settings = axusbnet_set_settings,
904
+#endif
905
+ .get_link = axusbnet_get_link,
906
+ .nway_reset = axusbnet_nway_reset,
907
+ .get_drvinfo = axusbnet_get_drvinfo,
908
+ .get_msglevel = axusbnet_get_msglevel,
909
+ .set_msglevel = axusbnet_set_msglevel,
910
+};
911
+
912
+/*-------------------------------------------------------------------------*/
913
+
914
+/* work that cannot be done in interrupt context uses keventd.
915
+ *
916
+ * NOTE: with 2.5 we could do more of this using completion callbacks,
917
+ * especially now that control transfers can be queued.
918
+ */
919
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
920
+static void kevent(void *data)
921
+{
922
+ struct usbnet *dev = (struct usbnet *)data;
923
+#else
924
+static void kevent(struct work_struct *work)
925
+{
926
+ struct usbnet *dev =
927
+ container_of(work, struct usbnet, kevent);
928
+#endif
929
+ int status;
930
+
931
+ /* usb_clear_halt() needs a thread context */
932
+ if (test_bit(EVENT_TX_HALT, &dev->flags)) {
933
+
934
+ unlink_urbs(dev, &dev->txq);
935
+ status = usb_clear_halt(dev->udev, dev->out);
936
+ if (status < 0
937
+ && status != -EPIPE
938
+ && status != -ESHUTDOWN) {
939
+ if (netif_msg_tx_err(dev))
940
+ deverr(dev, "can't clear tx halt, status %d",
941
+ status);
942
+ } else {
943
+ clear_bit(EVENT_TX_HALT, &dev->flags);
944
+ if (status != -ESHUTDOWN)
945
+ netif_wake_queue(dev->net);
946
+ }
947
+ }
948
+ if (test_bit(EVENT_RX_HALT, &dev->flags)) {
949
+
950
+ unlink_urbs(dev, &dev->rxq);
951
+ status = usb_clear_halt(dev->udev, dev->in);
952
+ if (status < 0
953
+ && status != -EPIPE
954
+ && status != -ESHUTDOWN) {
955
+ if (netif_msg_rx_err(dev))
956
+ deverr(dev, "can't clear rx halt, status %d",
957
+ status);
958
+ } else {
959
+ clear_bit(EVENT_RX_HALT, &dev->flags);
960
+ tasklet_schedule(&dev->bh);
961
+ }
962
+ }
963
+
964
+ /* tasklet could resubmit itself forever if memory is tight */
965
+ if (test_bit(EVENT_RX_MEMORY, &dev->flags)) {
966
+ struct urb *urb = NULL;
967
+
968
+ if (netif_running(dev->net))
969
+ urb = usb_alloc_urb(0, GFP_KERNEL);
970
+ else
971
+ clear_bit(EVENT_RX_MEMORY, &dev->flags);
972
+ if (urb != NULL) {
973
+ clear_bit(EVENT_RX_MEMORY, &dev->flags);
974
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
975
+ urb->transfer_flags |= URB_ASYNC_UNLINK;
976
+#endif
977
+ rx_submit(dev, urb, GFP_KERNEL);
978
+ tasklet_schedule(&dev->bh);
979
+ }
980
+ }
981
+
982
+ if (test_bit(EVENT_LINK_RESET, &dev->flags)) {
983
+ struct driver_info *info = dev->driver_info;
984
+
985
+ clear_bit(EVENT_LINK_RESET, &dev->flags);
986
+ if (info->link_reset) {
987
+ int retval;
988
+ retval = info->link_reset(dev);
989
+ if (retval < 0) {
990
+ devinfo(dev,
991
+ "link reset failed (%d) usbnet usb-%s-%s, %s",
992
+ retval,
993
+ dev->udev->bus->bus_name,
994
+ dev->udev->devpath,
995
+ info->description);
996
+ }
997
+ }
998
+ }
999
+
1000
+ if (dev->flags)
1001
+ devdbg(dev, "kevent done, flags = 0x%lx", dev->flags);
1002
+}
1003
+
1004
+/*-------------------------------------------------------------------------*/
1005
+
1006
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
1007
+static void tx_complete(struct urb *urb, struct pt_regs *regs)
1008
+#else
1009
+static void tx_complete(struct urb *urb)
1010
+#endif
1011
+{
1012
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
1013
+ struct skb_data *entry = (struct skb_data *) skb->cb;
1014
+ struct usbnet *dev = entry->dev;
1015
+
1016
+ if (urb->status == 0) {
1017
+ dev->stats.tx_packets++;
1018
+ dev->stats.tx_bytes += entry->length;
1019
+ } else {
1020
+ dev->stats.tx_errors++;
1021
+
1022
+ switch (urb->status) {
1023
+ case -EPIPE:
1024
+ axusbnet_defer_kevent(dev, EVENT_TX_HALT);
1025
+ break;
1026
+
1027
+ /* software-driven interface shutdown */
1028
+ case -ECONNRESET: /* async unlink */
1029
+ case -ESHUTDOWN: /* hardware gone */
1030
+ break;
1031
+
1032
+ /* like rx, tx gets controller i/o faults during khubd delays */
1033
+ /* and so it uses the same throttling mechanism. */
1034
+ case -EPROTO:
1035
+ case -ETIME:
1036
+ case -EILSEQ:
1037
+ if (!timer_pending(&dev->delay)) {
1038
+ mod_timer(&dev->delay,
1039
+ jiffies + THROTTLE_JIFFIES);
1040
+ if (netif_msg_link(dev))
1041
+ devdbg(dev, "tx throttle %d",
1042
+ urb->status);
1043
+ }
1044
+ netif_stop_queue(dev->net);
1045
+ break;
1046
+ default:
1047
+ if (netif_msg_tx_err(dev))
1048
+ devdbg(dev, "tx err %d", entry->urb->status);
1049
+ break;
1050
+ }
1051
+ }
1052
+
1053
+ urb->dev = NULL;
1054
+ entry->state = tx_done;
1055
+ (void) defer_bh(dev, skb, &dev->txq, tx_done);
1056
+}
1057
+
1058
+/*-------------------------------------------------------------------------*/
1059
+
1060
+static
1061
+void axusbnet_tx_timeout(struct net_device *net)
1062
+{
1063
+ struct usbnet *dev = netdev_priv(net);
1064
+ struct driver_info *info = dev->driver_info;
1065
+
1066
+ if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
1067
+ unlink_urbs(dev, &dev->txq);
1068
+ }
1069
+ tasklet_schedule(&dev->bh);
1070
+
1071
+ /* FIXME: device recovery -- reset? */
1072
+}
1073
+
1074
+/*-------------------------------------------------------------------------*/
1075
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
1076
+static int
1077
+#else
1078
+static netdev_tx_t
1079
+#endif
1080
+axusbnet_start_xmit(struct sk_buff *skb, struct net_device *net)
1081
+{
1082
+ struct usbnet *dev = netdev_priv(net);
1083
+ int length;
1084
+ struct urb *urb = NULL;
1085
+ struct skb_data *entry;
1086
+ struct driver_info *info = dev->driver_info;
1087
+ unsigned long flags;
1088
+ int retval;
1089
+
1090
+ /* some devices want funky USB-level framing, for */
1091
+ /* win32 driver (usually) and/or hardware quirks */
1092
+ if (info->tx_fixup) {
1093
+ skb = info->tx_fixup(dev, skb, GFP_ATOMIC);
1094
+ if (!skb) {
1095
+ if (netif_msg_tx_err(dev))
1096
+ devdbg(dev, "can't tx_fixup skb");
1097
+ goto drop;
1098
+ }
1099
+ }
1100
+ length = skb->len;
1101
+
1102
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
1103
+ if (!urb) {
1104
+ if (netif_msg_tx_err(dev))
1105
+ devdbg(dev, "no urb");
1106
+ goto drop;
1107
+ }
1108
+
1109
+ entry = (struct skb_data *) skb->cb;
1110
+ entry->urb = urb;
1111
+ entry->dev = dev;
1112
+ entry->state = tx_start;
1113
+ entry->length = length;
1114
+
1115
+ usb_fill_bulk_urb(urb, dev->udev, dev->out, skb->data,
1116
+ skb->len, tx_complete, skb);
1117
+
1118
+ /* don't assume the hardware handles USB_ZERO_PACKET
1119
+ * NOTE: strictly conforming cdc-ether devices should expect
1120
+ * the ZLP here, but ignore the one-byte packet.
1121
+ */
1122
+ if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
1123
+ urb->transfer_buffer_length++;
1124
+ if (skb_tailroom(skb)) {
1125
+ skb->data[skb->len] = 0;
1126
+ __skb_put(skb, 1);
1127
+ }
1128
+ }
1129
+
1130
+ spin_lock_irqsave(&dev->txq.lock, flags);
1131
+
1132
+ switch ((retval = usb_submit_urb(urb, GFP_ATOMIC))) {
1133
+ case -EPIPE:
1134
+ netif_stop_queue(net);
1135
+ axusbnet_defer_kevent(dev, EVENT_TX_HALT);
1136
+ break;
1137
+ default:
1138
+ if (netif_msg_tx_err(dev))
1139
+ devdbg(dev, "tx: submit urb err %d", retval);
1140
+ break;
1141
+ case 0:
1142
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
1143
+ net->trans_start = jiffies;
1144
+#else
1145
+ netif_trans_update(net);
1146
+#endif
1147
+ __skb_queue_tail(&dev->txq, skb);
1148
+ if (dev->txq.qlen >= TX_QLEN(dev))
1149
+ netif_stop_queue(net);
1150
+ }
1151
+ spin_unlock_irqrestore(&dev->txq.lock, flags);
1152
+
1153
+ if (retval) {
1154
+ if (netif_msg_tx_err(dev))
1155
+ devdbg(dev, "drop, code %d", retval);
1156
+drop:
1157
+ dev->stats.tx_dropped++;
1158
+ if (skb)
1159
+ dev_kfree_skb_any(skb);
1160
+ usb_free_urb(urb);
1161
+ } else if (netif_msg_tx_queued(dev)) {
1162
+ devdbg(dev, "> tx, len %d, type 0x%x",
1163
+ length, skb->protocol);
1164
+ }
1165
+ return NETDEV_TX_OK;
1166
+}
1167
+
1168
+/*-------------------------------------------------------------------------*/
1169
+
1170
+/* tasklet (work deferred from completions, in_irq) or timer */
1171
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
1172
+static void axusbnet_bh(unsigned long param)
1173
+#else
1174
+static void axusbnet_bh (struct timer_list *t)
1175
+#endif
1176
+{
1177
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
1178
+ struct usbnet *dev = (struct usbnet *) param;
1179
+#else
1180
+ struct usbnet *dev = from_timer(dev, t, delay);
1181
+#endif
1182
+ struct sk_buff *skb;
1183
+ struct skb_data *entry = NULL;
1184
+
1185
+ while ((skb = skb_dequeue(&dev->done))) {
1186
+ entry = (struct skb_data *) skb->cb;
1187
+ switch (entry->state) {
1188
+ case rx_done:
1189
+ entry->state = rx_cleanup;
1190
+ rx_process(dev, skb);
1191
+ continue;
1192
+ case tx_done:
1193
+ case rx_cleanup:
1194
+ usb_free_urb(entry->urb);
1195
+ dev_kfree_skb(skb);
1196
+ continue;
1197
+ default:
1198
+ devdbg(dev, "bogus skb state %d", entry->state);
1199
+ }
1200
+ }
1201
+
1202
+ /* restart RX again after disabling due to high error rate */
1203
+ clear_bit(EVENT_RX_KILL, &dev->flags);
1204
+
1205
+ /* waiting for all pending urbs to complete? */
1206
+ if (dev->wait) {
1207
+ if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0)
1208
+ wake_up(dev->wait);
1209
+
1210
+ /* or are we maybe short a few urbs? */
1211
+ } else if (netif_running(dev->net)
1212
+ && netif_device_present(dev->net)
1213
+ && !timer_pending(&dev->delay)
1214
+ && !test_bit(EVENT_RX_HALT, &dev->flags)) {
1215
+ int temp = dev->rxq.qlen;
1216
+ int qlen = RX_QLEN(dev);
1217
+
1218
+ if (temp < qlen) {
1219
+ struct urb *urb = NULL;
1220
+ int i;
1221
+
1222
+ /* don't refill the queue all at once */
1223
+ for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
1224
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
1225
+ if (urb != NULL) {
1226
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
1227
+ urb->transfer_flags |= URB_ASYNC_UNLINK;
1228
+#endif
1229
+ rx_submit(dev, urb, GFP_ATOMIC);
1230
+ }
1231
+ }
1232
+ if (temp != dev->rxq.qlen && netif_msg_link(dev))
1233
+ devdbg(dev, "rxqlen %d --> %d",
1234
+ temp, dev->rxq.qlen);
1235
+ if (dev->rxq.qlen < qlen)
1236
+ tasklet_schedule(&dev->bh);
1237
+ }
1238
+ if (dev->txq.qlen < TX_QLEN(dev))
1239
+ netif_wake_queue(dev->net);
1240
+ }
1241
+}
1242
+
1243
+
1244
+/*-------------------------------------------------------------------------
1245
+ *
1246
+ * USB Device Driver support
1247
+ *
1248
+ *-------------------------------------------------------------------------*/
1249
+
1250
+/* precondition: never called in_interrupt */
1251
+
1252
+static
1253
+void axusbnet_disconnect(struct usb_interface *intf)
1254
+{
1255
+ struct usbnet *dev;
1256
+ struct usb_device *xdev;
1257
+ struct net_device *net;
1258
+
1259
+ dev = usb_get_intfdata(intf);
1260
+ usb_set_intfdata(intf, NULL);
1261
+ if (!dev)
1262
+ return;
1263
+
1264
+ xdev = interface_to_usbdev(intf);
1265
+
1266
+ if (netif_msg_probe(dev))
1267
+ devinfo(dev, "unregister '%s' usb-%s-%s, %s",
1268
+ intf->dev.driver->name,
1269
+ xdev->bus->bus_name, xdev->devpath,
1270
+ dev->driver_info->description);
1271
+
1272
+ net = dev->net;
1273
+ unregister_netdev(net);
1274
+
1275
+ /* we don't hold rtnl here ... */
1276
+ flush_scheduled_work();
1277
+
1278
+ if (dev->driver_info->unbind)
1279
+ dev->driver_info->unbind(dev, intf);
1280
+
1281
+ free_netdev(net);
1282
+ usb_put_dev(xdev);
1283
+}
1284
+
1285
+/*-------------------------------------------------------------------------*/
1286
+
1287
+/* precondition: never called in_interrupt */
1288
+
1289
+static int
1290
+axusbnet_probe(struct usb_interface *udev, const struct usb_device_id *prod)
1291
+{
1292
+ struct usbnet *dev;
1293
+ struct net_device *net;
1294
+ struct usb_host_interface *interface;
1295
+ struct driver_info *info;
1296
+ struct usb_device *xdev;
1297
+ int status;
1298
+ const char *name;
1299
+
1300
+ name = udev->dev.driver->name;
1301
+ info = (struct driver_info *) prod->driver_info;
1302
+ if (!info) {
1303
+ printk(KERN_ERR "blacklisted by %s\n", name);
1304
+ return -ENODEV;
1305
+ }
1306
+ xdev = interface_to_usbdev(udev);
1307
+ interface = udev->cur_altsetting;
1308
+
1309
+ usb_get_dev(xdev);
1310
+
1311
+ status = -ENOMEM;
1312
+
1313
+ /* set up our own records */
1314
+ net = alloc_etherdev(sizeof(*dev));
1315
+ if (!net) {
1316
+ printk(KERN_ERR "can't kmalloc dev");
1317
+ goto out;
1318
+ }
1319
+
1320
+ dev = netdev_priv(net);
1321
+ dev->udev = xdev;
1322
+ dev->intf = udev;
1323
+ dev->driver_info = info;
1324
+ dev->driver_name = name;
1325
+ dev->msg_enable = netif_msg_init(msg_level, NETIF_MSG_DRV |
1326
+ NETIF_MSG_PROBE | NETIF_MSG_LINK);
1327
+ skb_queue_head_init(&dev->rxq);
1328
+ skb_queue_head_init(&dev->txq);
1329
+ skb_queue_head_init(&dev->done);
1330
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
1331
+ dev->bh.func = axusbnet_bh;
1332
+ dev->bh.data = (unsigned long) dev;
1333
+#else
1334
+ dev->bh.func = (void (*)(unsigned long))axusbnet_bh;
1335
+ dev->bh.data = (unsigned long)&dev->delay;
1336
+#endif
1337
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
1338
+ INIT_WORK(&dev->kevent, kevent, dev);
1339
+#else
1340
+ INIT_WORK(&dev->kevent, kevent);
1341
+#endif
1342
+
1343
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
1344
+ dev->delay.function = axusbnet_bh;
1345
+ dev->delay.data = (unsigned long) dev;
1346
+ init_timer(&dev->delay);
1347
+#else
1348
+ timer_setup(&dev->delay, axusbnet_bh, 0);
1349
+#endif
1350
+ /* mutex_init(&dev->phy_mutex); */
1351
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
1352
+ init_MUTEX (&dev->sem);
1353
+#else
1354
+ sema_init(&dev->sem,1);
1355
+#endif
1356
+ dev->net = net;
1357
+
1358
+ /* rx and tx sides can use different message sizes;
1359
+ * bind() should set rx_urb_size in that case.
1360
+ */
1361
+ dev->hard_mtu = net->mtu + net->hard_header_len;
1362
+
1363
+#if 0
1364
+ /* dma_supported() is deeply broken on almost all architectures */
1365
+ /* possible with some EHCI controllers */
1366
+ if (dma_supported(&udev->dev, DMA_BIT_MASK(64)))
1367
+ net->features |= NETIF_F_HIGHDMA;
1368
+#endif
1369
+
1370
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1371
+ net->open = axusbnet_open,
1372
+ net->stop = axusbnet_stop,
1373
+ net->hard_start_xmit = axusbnet_start_xmit,
1374
+ net->tx_timeout = axusbnet_tx_timeout,
1375
+ net->get_stats = axusbnet_get_stats;
1376
+#endif
1377
+
1378
+ net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
1379
+ net->ethtool_ops = &axusbnet_ethtool_ops;
1380
+
1381
+ /* allow device-specific bind/init procedures */
1382
+ /* NOTE net->name still not usable ... */
1383
+ status = info->bind(dev, udev);
1384
+ if (status < 0) {
1385
+ deverr(dev, "Binding device failed: %d", status);
1386
+ goto out1;
1387
+ }
1388
+
1389
+ /* maybe the remote can't receive an Ethernet MTU */
1390
+ if (net->mtu > (dev->hard_mtu - net->hard_header_len))
1391
+ net->mtu = dev->hard_mtu - net->hard_header_len;
1392
+
1393
+ status = init_status(dev, udev);
1394
+ if (status < 0)
1395
+ goto out3;
1396
+
1397
+ if (!dev->rx_urb_size)
1398
+ dev->rx_urb_size = dev->hard_mtu;
1399
+ dev->maxpacket = usb_maxpacket(dev->udev, dev->out, 1);
1400
+
1401
+ SET_NETDEV_DEV(net, &udev->dev);
1402
+ status = register_netdev(net);
1403
+ if (status) {
1404
+ deverr(dev, "net device registration failed: %d", status);
1405
+ goto out3;
1406
+ }
1407
+
1408
+ if (netif_msg_probe(dev))
1409
+ devinfo(dev, "register '%s' at usb-%s-%s, %s, %pM",
1410
+ udev->dev.driver->name,
1411
+ xdev->bus->bus_name, xdev->devpath,
1412
+ dev->driver_info->description,
1413
+ net->dev_addr);
1414
+
1415
+ /* ok, it's ready to go. */
1416
+ usb_set_intfdata(udev, dev);
1417
+
1418
+ /* start as if the link is up */
1419
+ netif_device_attach(net);
1420
+
1421
+ return 0;
1422
+
1423
+out3:
1424
+ if (info->unbind)
1425
+ info->unbind(dev, udev);
1426
+out1:
1427
+ free_netdev(net);
1428
+out:
1429
+ usb_put_dev(xdev);
1430
+ return status;
1431
+}
1432
+
1433
+/*-------------------------------------------------------------------------*/
1434
+
1435
+/*
1436
+ * suspend the whole driver as soon as the first interface is suspended
1437
+ * resume only when the last interface is resumed
1438
+ */
1439
+
1440
+static int axusbnet_suspend(struct usb_interface *intf,
1441
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
1442
+pm_message_t message)
1443
+#else
1444
+u32 message)
1445
+#endif
1446
+{
1447
+ struct usbnet *dev = usb_get_intfdata(intf);
1448
+
1449
+ if (!dev->suspend_count++) {
1450
+ /*
1451
+ * accelerate emptying of the rx and queues, to avoid
1452
+ * having everything error out.
1453
+ */
1454
+ netif_device_detach(dev->net);
1455
+ (void) unlink_urbs(dev, &dev->rxq);
1456
+ (void) unlink_urbs(dev, &dev->txq);
1457
+ usb_kill_urb(dev->interrupt);
1458
+ /*
1459
+ * reattach so runtime management can use and
1460
+ * wake the device
1461
+ */
1462
+ netif_device_attach(dev->net);
1463
+ }
1464
+ return 0;
1465
+}
1466
+
1467
+static int
1468
+axusbnet_resume(struct usb_interface *intf)
1469
+{
1470
+ struct usbnet *dev = usb_get_intfdata(intf);
1471
+ int retval = 0;
1472
+
1473
+ if (!--dev->suspend_count)
1474
+ tasklet_schedule(&dev->bh);
1475
+
1476
+ retval = init_status(dev, intf);
1477
+ if (retval < 0)
1478
+ return retval;
1479
+
1480
+ if (dev->interrupt) {
1481
+ retval = usb_submit_urb(dev->interrupt, GFP_KERNEL);
1482
+ if (retval < 0 && netif_msg_ifup(dev))
1483
+ deverr(dev, "intr submit %d", retval);
1484
+ }
1485
+
1486
+ return retval;
1487
+}
1488
+
kernel/drivers/net/usb/AX88772C_eeprom/axusbnet.h
....@@ -0,0 +1,212 @@
1
+/*
2
+ * USB Networking Link Interface
3
+ *
4
+ * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net>
5
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+#ifndef __LINUX_USB_USBNET_H
23
+#define __LINUX_USB_USBNET_H
24
+
25
+#ifndef gfp_t
26
+#define gfp_t int
27
+#endif
28
+
29
+/* interface from usbnet core to each USB networking link we handle */
30
+struct usbnet {
31
+ /* housekeeping */
32
+ struct usb_device *udev;
33
+ struct usb_interface *intf;
34
+ struct driver_info *driver_info;
35
+ const char *driver_name;
36
+ void *driver_priv;
37
+ wait_queue_head_t *wait;
38
+ /* struct mutex phy_mutex; */
39
+ unsigned char suspend_count;
40
+ unsigned char pkt_cnt, pkt_err;
41
+
42
+ /* i/o info: pipes etc */
43
+ unsigned in, out;
44
+ struct usb_host_endpoint *status;
45
+ unsigned maxpacket;
46
+ struct timer_list delay;
47
+
48
+ /* protocol/interface state */
49
+ struct net_device *net;
50
+ struct net_device_stats stats;
51
+ int msg_enable;
52
+ unsigned long data[5];
53
+ u32 xid;
54
+ u32 hard_mtu; /* count any extra framing */
55
+ size_t rx_urb_size; /* size for rx urbs */
56
+ struct mii_if_info mii;
57
+
58
+ /* various kinds of pending driver work */
59
+ struct sk_buff_head rxq;
60
+ struct sk_buff_head txq;
61
+ struct sk_buff_head done;
62
+ struct sk_buff_head rxq_pause;
63
+ struct urb *interrupt;
64
+ struct tasklet_struct bh;
65
+
66
+ struct work_struct kevent;
67
+ struct semaphore sem;
68
+ unsigned long flags;
69
+# define EVENT_TX_HALT 0
70
+# define EVENT_RX_HALT 1
71
+# define EVENT_RX_MEMORY 2
72
+# define EVENT_STS_SPLIT 3
73
+# define EVENT_LINK_RESET 4
74
+# define EVENT_RX_PAUSED 5
75
+# define EVENT_RX_KILL 10
76
+
77
+ void *priv; /* point to minidriver private data */
78
+ unsigned char rx_size;
79
+};
80
+
81
+static inline struct usb_driver *driver_of(struct usb_interface *intf)
82
+{
83
+ return to_usb_driver(intf->dev.driver);
84
+}
85
+
86
+/* interface from the device/framing level "minidriver" to core */
87
+struct driver_info {
88
+ char *description;
89
+
90
+ int flags;
91
+/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */
92
+#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
93
+#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
94
+#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */
95
+#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */
96
+
97
+#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
98
+#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
99
+
100
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
101
+#define FLAG_WLAN 0x0080 /* use "wlan%d" names */
102
+#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
103
+#define FLAG_SEND_ZLP 0x0200 /* hw requires ZLPs are sent */
104
+#define FLAG_HW_IP_ALIGNMENT 0x0400 /* AX88772B support hardware IP alignment */
105
+
106
+
107
+ /* init device ... can sleep, or cause probe() failure */
108
+ int (*bind)(struct usbnet *, struct usb_interface *);
109
+
110
+ /* cleanup device ... can sleep, but can't fail */
111
+ void (*unbind)(struct usbnet *, struct usb_interface *);
112
+
113
+ /* reset device ... can sleep */
114
+ int (*reset)(struct usbnet *);
115
+
116
+ /* stop device ... can sleep */
117
+ int (*stop)(struct usbnet *);
118
+
119
+ /* see if peer is connected ... can sleep */
120
+ int (*check_connect)(struct usbnet *);
121
+
122
+ /* for status polling */
123
+ void (*status)(struct usbnet *, struct urb *);
124
+
125
+ /* link reset handling, called from defer_kevent */
126
+ int (*link_reset)(struct usbnet *);
127
+
128
+ /* fixup rx packet (strip framing) */
129
+ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
130
+
131
+ /* fixup tx packet (add framing) */
132
+ struct sk_buff *(*tx_fixup)(struct usbnet *dev,
133
+ struct sk_buff *skb, gfp_t flags);
134
+
135
+ /* early initialization code, can sleep. This is for minidrivers
136
+ * having 'subminidrivers' that need to do extra initialization
137
+ * right after minidriver have initialized hardware. */
138
+ int (*early_init)(struct usbnet *dev);
139
+
140
+ /* called by minidriver when receiving indication */
141
+ void (*indication)(struct usbnet *dev, void *ind, int indlen);
142
+
143
+ /* for new devices, use the descriptor-reading code instead */
144
+ int in; /* rx endpoint */
145
+ int out; /* tx endpoint */
146
+
147
+ unsigned long data; /* Misc driver specific data */
148
+};
149
+
150
+/* Drivers that reuse some of the standard USB CDC infrastructure
151
+ * (notably, using multiple interfaces according to the CDC
152
+ * union descriptor) get some helper code.
153
+ */
154
+struct cdc_state {
155
+ struct usb_cdc_header_desc *header;
156
+ struct usb_cdc_union_desc *u;
157
+ struct usb_cdc_ether_desc *ether;
158
+ struct usb_interface *control;
159
+ struct usb_interface *data;
160
+};
161
+
162
+/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
163
+#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
164
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
165
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
166
+ |USB_CDC_PACKET_TYPE_DIRECTED)
167
+
168
+
169
+/* we record the state for each of our queued skbs */
170
+enum skb_state {
171
+ illegal = 0,
172
+ tx_start, tx_done,
173
+ rx_start, rx_done, rx_cleanup,
174
+ unlink_start
175
+};
176
+
177
+struct skb_data { /* skb->cb is one of these */
178
+ struct urb *urb;
179
+ struct usbnet *dev;
180
+ enum skb_state state;
181
+ size_t length;
182
+};
183
+
184
+#ifndef skb_queue_walk_safe
185
+#define skb_queue_walk_safe(queue, skb, tmp) \
186
+ for (skb = (queue)->next, tmp = skb->next; \
187
+ skb != (struct sk_buff *)(queue); \
188
+ skb = tmp, tmp = skb->next)
189
+#endif
190
+
191
+/* messaging support includes the interface name, so it must not be
192
+ * used before it has one ... notably, in minidriver bind() calls.
193
+ */
194
+#ifdef DEBUG
195
+#define devdbg(usbnet, fmt, arg...) \
196
+ printk("%s: " fmt "\n" , (usbnet)->net->name , ## arg)
197
+#else
198
+#define devdbg(usbnet, fmt, arg...) \
199
+ ({ if (0) printk("%s: " fmt "\n" , (usbnet)->net->name , \
200
+ ## arg); 0; })
201
+#endif
202
+
203
+#define deverr(usbnet, fmt, arg...) \
204
+ printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
205
+#define devwarn(usbnet, fmt, arg...) \
206
+ printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
207
+
208
+#define devinfo(usbnet, fmt, arg...) \
209
+ printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
210
+
211
+
212
+#endif /* __LINUX_USB_USBNET_H */
kernel/drivers/net/usb/AX88772C_eeprom/command.h
....@@ -0,0 +1,67 @@
1
+/*
2
+ *********************************************************************************
3
+ * Copyright (c) 2005 ASIX Electronic Corporation All rights reserved.
4
+ *
5
+ * This is unpublished proprietary source code of ASIX Electronic Corporation
6
+ *
7
+ * The copyright notice above does not evidence any actual or intended
8
+ * publication of such source code.
9
+ *********************************************************************************
10
+ */
11
+
12
+#ifndef __COMMAND_H__
13
+#define __COMMAND_H__
14
+
15
+/*
16
+
17
+#include <linux/module.h>
18
+#include <linux/version.h>
19
+#include <linux/kernel.h>
20
+#include <linux/errno.h>
21
+#include <linux/pci.h>
22
+#include <linux/init.h>
23
+#include <linux/interrupt.h>
24
+#include <linux/ethtool.h>
25
+#include <linux/netdevice.h>
26
+#include <linux/etherdevice.h>
27
+#include <linux/delay.h>
28
+#include <linux/random.h>
29
+#include <linux/mii.h>
30
+
31
+#include <linux/in.h>
32
+
33
+#include <asm/system.h>
34
+#include <asm/io.h>
35
+#include <asm/uaccess.h>
36
+*/
37
+/* NAMING CONSTANT DECLARATIONS */
38
+#define AX88772B_SIGNATURE "AX88772B"
39
+#define AX88772B_DRV_NAME "AX88772B"
40
+
41
+#define DEBUG_PARAM (DEB_NONE)
42
+#define DEB_NONE (0)
43
+#define DEB_TOOL (1 << 0)
44
+#define DEB_DRIVER (1 << 1)
45
+#define DPRINT_D(...) while (1) { \
46
+ if (DEBUG_PARAM & DEB_DRIVER) \
47
+ printk(__VA_ARGS__); \
48
+ break; \
49
+ }
50
+
51
+/* ioctl Command Definition */
52
+#define AX_PRIVATE SIOCDEVPRIVATE
53
+
54
+/* private Command Definition */
55
+#define AX_SIGNATURE 0
56
+#define AX_READ_EEPROM 1
57
+#define AX_WRITE_EEPROM 2
58
+
59
+typedef struct _AX_IOCTL_COMMAND {
60
+ unsigned short ioctl_cmd;
61
+ unsigned char sig[16];
62
+ unsigned short *buf;
63
+ unsigned short size;
64
+ unsigned char delay;
65
+}AX_IOCTL_COMMAND;
66
+
67
+#endif /* end of command.h */
kernel/drivers/net/usb/AX88772C_eeprom/ioctl.c
....@@ -0,0 +1,481 @@
1
+/*==========================================================================
2
+ * Module Name : console_debug.c
3
+ * Purpose :
4
+ * Author :
5
+ * Date :
6
+ * Notes :
7
+ * $Log$
8
+ *==========================================================================
9
+ */
10
+
11
+/* INCLUDE FILE DECLARATIONS */
12
+#include <string.h>
13
+#include <sys/socket.h>
14
+#include <sys/ioctl.h>
15
+#include <net/if.h>
16
+#include <stdio.h>
17
+#include <sys/types.h>
18
+#include <sys/stat.h>
19
+#include <fcntl.h>
20
+#include <termios.h>
21
+#include <netinet/in.h>
22
+#include <arpa/inet.h>
23
+#include <linux/sockios.h>
24
+#include <ctype.h>
25
+#include <stdlib.h>
26
+#if NET_INTERFACE == INTERFACE_SCAN
27
+#include <ifaddrs.h>
28
+#endif
29
+#include "ioctl.h"
30
+
31
+/* STATIC VARIABLE DECLARATIONS */
32
+#define AX88772C_IOCTL_VERSION "AX88772C/AX88772B/AX88772A/AX88760/AX88772/AX88178 Linux SROM IOCTL Tool version 1.6.0"
33
+
34
+/* LOCAL SUBPROGRAM DECLARATIONS */
35
+static unsigned long STR_TO_U32(const char *cp,char **endp,unsigned int base);
36
+
37
+
38
+/* LOCAL SUBPROGRAM BODIES */
39
+static void debug_func(char *func_name, unsigned short *buf, unsigned long wLen)
40
+{
41
+#if (DEBUG_PARAM & DEB_TOOL)
42
+ int i;
43
+ char str_buf[50];
44
+ printf("%s :\n", func_name);
45
+ printf("---------------------------------------\n");
46
+ for (i = 0; i < wLen / 8; i++) {
47
+ int j = 8 * i;
48
+ snprintf(str_buf, 50,
49
+ "%04x %04x %04x %04x %04x %04x "
50
+ "%04x %04x\n",
51
+ *(buf + j + 0), *(buf + j + 1),
52
+ *(buf + j + 2), *(buf + j + 3),
53
+ *(buf + j + 4), *(buf + j + 5),
54
+ *(buf + j + 6), *(buf + j + 7));
55
+ printf("%s", str_buf);
56
+ }
57
+ printf("------------------------------------%3ld\n", wLen);
58
+#endif
59
+}
60
+
61
+
62
+static void show_usage(void)
63
+{
64
+ int i;
65
+ printf ("\n%s\n",AX88772C_IOCTL_VERSION);
66
+ printf ("Usage:\n");
67
+ for (i = 0; command_list[i].cmd != NULL; i++)
68
+ printf ("%s\n", command_list[i].help_ins);
69
+}
70
+
71
+static unsigned long STR_TO_U32(const char *cp,char **endp,unsigned int base)
72
+{
73
+ unsigned long result = 0,value;
74
+
75
+ if (*cp == '0') {
76
+ cp++;
77
+ if ((*cp == 'x') && isxdigit(cp[1])) {
78
+ base = 16;
79
+ cp++;
80
+ }
81
+ if (!base) {
82
+ base = 8;
83
+ }
84
+ }
85
+ if (!base) {
86
+ base = 10;
87
+ }
88
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
89
+ ? toupper(*cp) : *cp)-'A'+10) < base) {
90
+ result = result*base + value;
91
+ cp++;
92
+ }
93
+ if (endp)
94
+ *endp = (char *)cp;
95
+
96
+ return result;
97
+}
98
+
99
+void help_func (struct ax_command_info *info)
100
+{
101
+ int i;
102
+
103
+ if (info->argv[2] == NULL) {
104
+ for(i=0; command_list[i].cmd != NULL; i++) {
105
+ printf ("%s%s\n", command_list[i].help_ins, command_list[i].help_desc);
106
+ }
107
+ }
108
+
109
+ for (i = 0; command_list[i].cmd != NULL; i++)
110
+ {
111
+ if (strncmp(info->argv[1], command_list[i].cmd, strlen(command_list[i].cmd)) == 0 ) {
112
+ printf ("%s%s\n", command_list[i].help_ins, command_list[i].help_desc);
113
+ return;
114
+ }
115
+ }
116
+
117
+}
118
+
119
+int compare_file(struct ax_command_info *info)
120
+{
121
+ struct ifreq *ifr = (struct ifreq *)info->ifr;
122
+ unsigned short *rout_buf;
123
+ unsigned short *ori_buf;
124
+ AX_IOCTL_COMMAND *ioctl_cmd = (AX_IOCTL_COMMAND *)(ifr->ifr_data);
125
+ int i;
126
+
127
+ rout_buf = malloc(sizeof(unsigned short) * ioctl_cmd->size);
128
+
129
+ ori_buf = ioctl_cmd->buf;
130
+
131
+ ioctl_cmd->ioctl_cmd = AX_READ_EEPROM;
132
+ ioctl_cmd->buf = rout_buf;
133
+
134
+ if (ioctl(info->inet_sock, AX_PRIVATE, ifr) < 0) {
135
+ perror("ioctl");
136
+ return -1;
137
+ }
138
+
139
+
140
+
141
+ for (i = 0; i < ioctl_cmd->size; i++) {
142
+ if (*(ioctl_cmd->buf + i) != *(ori_buf + i)) {
143
+ debug_func("compare_file reeprom", rout_buf, ioctl_cmd->size);
144
+ ioctl_cmd->buf = ori_buf;
145
+ free(rout_buf);
146
+ return -2;
147
+ }
148
+ }
149
+
150
+ ioctl_cmd->buf = ori_buf;
151
+ free(rout_buf);
152
+ return 0;
153
+}
154
+
155
+void readeeprom_func(struct ax_command_info *info)
156
+{
157
+ struct ifreq *ifr = (struct ifreq *)info->ifr;
158
+ AX_IOCTL_COMMAND ioctl_cmd;
159
+ unsigned short *buf;
160
+ unsigned short wLen;
161
+ char str_buf[50];
162
+ FILE *pFile;
163
+ int i;
164
+
165
+ if (info->argc < 4) {
166
+ for(i=0; command_list[i].cmd != NULL; i++) {
167
+ if (strncmp(info->argv[1], command_list[i].cmd,
168
+ strlen(command_list[i].cmd)) == 0 ) {
169
+ printf ("%s%s\n", command_list[i].help_ins,
170
+ command_list[i].help_desc);
171
+ return;
172
+ }
173
+ }
174
+ }
175
+
176
+ wLen = STR_TO_U32(info->argv[3], NULL, 0) / 2;
177
+
178
+ pFile = fopen(info->argv[2],"w");
179
+ buf = (unsigned short *)malloc((sizeof(unsigned short) * wLen));
180
+
181
+ ioctl_cmd.ioctl_cmd = info->ioctl_cmd;
182
+ ioctl_cmd.size = wLen;
183
+ ioctl_cmd.buf = buf;
184
+ ioctl_cmd.delay = 0;
185
+
186
+ ifr->ifr_data = (caddr_t)&ioctl_cmd;
187
+ if (ioctl(info->inet_sock, AX_PRIVATE, ifr) < 0) {
188
+ perror("ioctl");
189
+ free(buf);
190
+ fclose(pFile);
191
+ return;
192
+ }
193
+ for (i = 0; i < wLen / 8; i++) {
194
+ int j = 8 * i;
195
+ snprintf(str_buf, 50,
196
+ "%04x %04x %04x %04x %04x %04x "
197
+ "%04x %04x\n",
198
+ *(buf + j + 0), *(buf + j + 1),
199
+ *(buf + j + 2), *(buf + j + 3),
200
+ *(buf + j + 4), *(buf + j + 5),
201
+ *(buf + j + 6), *(buf + j + 7));
202
+ fputs(str_buf, pFile);
203
+ }
204
+ printf("Read completely\n\n");
205
+ free(buf);
206
+ fclose(pFile);
207
+ return;
208
+}
209
+
210
+void writeeeprom_func(struct ax_command_info *info)
211
+{
212
+ struct ifreq *ifr = (struct ifreq *)info->ifr;
213
+ AX_IOCTL_COMMAND ioctl_cmd;
214
+ int i;
215
+ unsigned short *buf;
216
+ unsigned short wLen;
217
+ char c[2] = {'\0'};
218
+ FILE *pFile;
219
+ unsigned char retried = 0;
220
+
221
+ if (info->argc < 4) {
222
+ for(i=0; command_list[i].cmd != NULL; i++) {
223
+ if (strncmp(info->argv[1], command_list[i].cmd,
224
+ strlen(command_list[i].cmd)) == 0) {
225
+ printf ("%s%s\n", command_list[i].help_ins,
226
+ command_list[i].help_desc);
227
+ return;
228
+ }
229
+ }
230
+ }
231
+
232
+ pFile = fopen(info->argv[2], "r");
233
+
234
+ wLen = STR_TO_U32(info->argv[3], NULL, 0) / 2;
235
+
236
+ buf = (unsigned short *)malloc(sizeof(unsigned short) * wLen);
237
+
238
+ for (i = 0; i < wLen / 8; i++) {
239
+ int j = 8 * i;
240
+ fscanf(pFile, "%04X %04X %04X %04X %04X %04X %04X %04X%c",
241
+ (unsigned int *)&buf[j + 0], (unsigned int *)&buf[j + 1],
242
+ (unsigned int *)&buf[j + 2], (unsigned int *)&buf[j + 3],
243
+ (unsigned int *)&buf[j + 4], (unsigned int *)&buf[j + 5],
244
+ (unsigned int *)&buf[j + 6], (unsigned int *)&buf[j + 7], c);
245
+ }
246
+
247
+ ioctl_cmd.ioctl_cmd = info->ioctl_cmd;
248
+ ioctl_cmd.size = wLen;
249
+ ioctl_cmd.buf = buf;
250
+ ioctl_cmd.delay = 5;
251
+io:
252
+ ifr->ifr_data = (caddr_t)&ioctl_cmd;
253
+
254
+debug_func("writeeeprom_func", buf, wLen);
255
+
256
+ if (ioctl(info->inet_sock, AX_PRIVATE, ifr) < 0) {
257
+ free(buf);
258
+ fclose(pFile);
259
+ perror("ioctl");
260
+ return;
261
+ }
262
+ else {
263
+ if (compare_file(info) && retried < 3) {
264
+ ioctl_cmd.delay += 5;
265
+ ioctl_cmd.ioctl_cmd = info->ioctl_cmd;
266
+ retried++;
267
+ goto io;
268
+ }
269
+ if (retried == 3) {
270
+ printf("Failure to write\n\n");
271
+ free(buf);
272
+ fclose(pFile);
273
+ return;
274
+ }
275
+ }
276
+
277
+ printf("Write completely\n\n");
278
+ free(buf);
279
+ fclose(pFile);
280
+ return;
281
+}
282
+
283
+void chgmac_func(struct ax_command_info *info)
284
+{
285
+ struct ifreq *ifr = (struct ifreq *)info->ifr;
286
+ AX_IOCTL_COMMAND ioctl_cmd;
287
+ int i;
288
+ unsigned short *buf;
289
+ unsigned int tmp;
290
+ unsigned short wLen;
291
+ unsigned char retried = 0;
292
+ char * pch;
293
+ unsigned int MAC[6] = {0};
294
+ int ret = 0;
295
+
296
+ if (info->argc < 4) {
297
+ for(i=0; command_list[i].cmd != NULL; i++) {
298
+ if (strncmp(info->argv[1], command_list[i].cmd,
299
+ strlen(command_list[i].cmd)) == 0) {
300
+ printf ("%s%s\n", command_list[i].help_ins,
301
+ command_list[i].help_desc);
302
+ return;
303
+ }
304
+ }
305
+ }
306
+
307
+ wLen = STR_TO_U32(info->argv[3], NULL, 0) / 2;
308
+
309
+ buf = (unsigned short *)malloc(sizeof(unsigned short) * wLen);
310
+
311
+ ioctl_cmd.ioctl_cmd = AX_READ_EEPROM;
312
+ ioctl_cmd.size = wLen;
313
+ ioctl_cmd.buf = buf;
314
+ ioctl_cmd.delay = 0;
315
+
316
+ ifr->ifr_data = (caddr_t)&ioctl_cmd;
317
+
318
+ if (ioctl(info->inet_sock, AX_PRIVATE, ifr) < 0) {
319
+ perror("ioctl");
320
+ free(buf);
321
+ return;
322
+ }
323
+
324
+ ret = sscanf(info->argv[2], "%02X:%02X:%02X:%02X:%02X:%02X",(unsigned int*)&MAC[0],
325
+ (unsigned int*)&MAC[1],
326
+ (unsigned int*)&MAC[2],
327
+ (unsigned int*)&MAC[3],
328
+ (unsigned int*)&MAC[4],
329
+ (unsigned int*)&MAC[5]);
330
+ if (6 != ret) {
331
+ printf("Invalid MAC address\n\n");
332
+ return;
333
+ }
334
+
335
+ if (*buf == 0x1500) {
336
+ printf("No eeprom exists!\n");
337
+ printf("Or you must burn the default value first!\n\n");
338
+ return;
339
+ }
340
+
341
+ *(((char*)buf) + 8) = (unsigned char)MAC[1];
342
+ *(((char*)buf) + 9) = (unsigned char)MAC[0];
343
+ *(((char*)buf) + 10) = (unsigned char)MAC[3];
344
+ *(((char*)buf) + 11) = (unsigned char)MAC[2];
345
+ *(((char*)buf) + 12) = (unsigned char)MAC[5];
346
+ *(((char*)buf) + 13) = (unsigned char)MAC[4];
347
+
348
+ ioctl_cmd.ioctl_cmd = info->ioctl_cmd;
349
+ ioctl_cmd.size = wLen;
350
+ ioctl_cmd.buf = buf;
351
+ ioctl_cmd.delay = 5;
352
+
353
+io:
354
+ ifr->ifr_data = (caddr_t)&ioctl_cmd;
355
+
356
+debug_func("chgmac_func", buf, wLen);
357
+
358
+ if (ioctl(info->inet_sock, AX_PRIVATE, ifr) < 0) {
359
+ perror("ioctl");
360
+ free(buf);
361
+ return;
362
+ }
363
+
364
+ else {
365
+ if (compare_file(info) && retried < 3) {
366
+ ioctl_cmd.delay += 5;
367
+ ioctl_cmd.ioctl_cmd = info->ioctl_cmd;
368
+ retried++;
369
+ goto io;
370
+ }
371
+ if (retried == 3) {
372
+ printf("Failure to write\n\n");
373
+ free(buf);
374
+ return;
375
+ }
376
+ }
377
+
378
+ printf("Write completely\n\n");
379
+ free(buf);
380
+ return;
381
+}
382
+
383
+/* EXPORTED SUBPROGRAM BODIES */
384
+int main(int argc, char **argv)
385
+{
386
+#if NET_INTERFACE == INTERFACE_SCAN
387
+ struct ifaddrs *addrs, *tmp;
388
+ unsigned char dev_exist;
389
+#endif
390
+ struct ifreq ifr;
391
+ struct ax_command_info info;
392
+ AX_IOCTL_COMMAND ioctl_cmd;
393
+ int inet_sock;
394
+ unsigned char i;
395
+
396
+ if (argc < 2) {
397
+ show_usage();
398
+ return 0;
399
+ }
400
+
401
+ inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
402
+
403
+#if NET_INTERFACE == INTERFACE_SCAN
404
+ /* Get Device */
405
+ getifaddrs(&addrs);
406
+ tmp = addrs;
407
+ dev_exist = 0;
408
+
409
+ while (tmp) {
410
+ memset (&ioctl_cmd, 0, sizeof (AX_IOCTL_COMMAND));
411
+ ioctl_cmd.ioctl_cmd = AX_SIGNATURE;
412
+ // get network interface name
413
+ sprintf (ifr.ifr_name, "%s", tmp->ifa_name);
414
+
415
+ ifr.ifr_data = (caddr_t)&ioctl_cmd;
416
+ tmp = tmp->ifa_next;
417
+
418
+
419
+ if (ioctl (inet_sock, AX_PRIVATE, &ifr) < 0) {
420
+ continue;
421
+ }
422
+
423
+ if (strncmp (ioctl_cmd.sig, AX88772B_DRV_NAME, strlen(AX88772B_DRV_NAME)) == 0 ) {
424
+ dev_exist = 1;
425
+ break;
426
+ }
427
+ }
428
+
429
+ freeifaddrs(addrs);
430
+
431
+ if (dev_exist == 0) {
432
+ printf ("\n%s\n",AX88772C_IOCTL_VERSION);
433
+ printf("No %s found\n\n", AX88772B_SIGNATURE);
434
+ return 0;
435
+ }
436
+#else
437
+ for (i = 0; i < 255; i++) {
438
+
439
+ memset (&ioctl_cmd, 0, sizeof (AX_IOCTL_COMMAND));
440
+ ioctl_cmd.ioctl_cmd = AX_SIGNATURE;
441
+
442
+ sprintf (ifr.ifr_name, "eth%d", i);
443
+ ifr.ifr_data = (caddr_t)&ioctl_cmd;
444
+
445
+ if (ioctl (inet_sock, AX_PRIVATE, &ifr) < 0) {
446
+ continue;
447
+ }
448
+
449
+ if (strncmp (ioctl_cmd.sig, AX88772B_DRV_NAME, strlen(AX88772B_DRV_NAME)) == 0 ) {
450
+ break;
451
+ }
452
+
453
+ }
454
+
455
+ if (i == 255) {
456
+ printf ("\n%s\n",AX88772C_IOCTL_VERSION);
457
+ printf ("No %s found\n\n", AX88772B_SIGNATURE);
458
+ return 0;
459
+ }
460
+#endif
461
+ for(i=0; command_list[i].cmd != NULL; i++)
462
+ {
463
+ if (strncmp(argv[1], command_list[i].cmd, strlen(command_list[i].cmd)) == 0 ) {
464
+ printf ("\n%s\n",AX88772C_IOCTL_VERSION);
465
+ info.help_ins = command_list[i].help_ins;
466
+ info.help_desc = command_list[i].help_desc;
467
+ info.ifr = &ifr;
468
+ info.argc = argc;
469
+ info.argv = argv;
470
+ info.inet_sock = inet_sock;
471
+ info.ioctl_cmd = command_list[i].ioctl_cmd;
472
+ (command_list[i].OptFunc)(&info);
473
+ return 0;
474
+ }
475
+ }
476
+
477
+ printf ("Wrong command\n\n");
478
+
479
+ return 0;
480
+}
481
+
kernel/drivers/net/usb/AX88772C_eeprom/ioctl.h
....@@ -0,0 +1,75 @@
1
+#ifndef ioctl_h
2
+#define ioctl_h
3
+
4
+/* INCLUDE FILE DECLARATIONS */
5
+#include "command.h"
6
+
7
+/* CHANGE NETWORK INTERFACE WAY */
8
+// DEFAULT_SCAN : scan "eth0" - "eth255"
9
+// INTERFACE_SCAN : scan all available network interfaces
10
+#define NET_INTERFACE INTERFACE_SCAN
11
+#define DEFAULT_SCAN 0x00
12
+#define INTERFACE_SCAN 0x01
13
+
14
+/* NAMING CONSTANT DECLARATIONS */
15
+struct ax_command_info {
16
+ int inet_sock;
17
+ struct ifreq *ifr;
18
+ int argc;
19
+ char **argv;
20
+ unsigned short ioctl_cmd;
21
+ const char *help_ins;
22
+ const char *help_desc;
23
+};
24
+
25
+const char help_str1[] =
26
+"./ioctl help [command]\n"
27
+" -- command description\n";
28
+const char help_str2[] =
29
+" [command] - Display usage of specified command\n";
30
+
31
+const char readeeprom_str1[] =
32
+"./ioctl reeprom [file] [size]\n"
33
+" -- AX88772B EEPROM read tool\n";
34
+const char readeeprom_str2[] =
35
+" [file] - Output file\n"
36
+" [size] - EEPROM SIZE in bytes\n";
37
+
38
+const char writeeeprom_str1[] =
39
+"./ioctl weeprom [file] [size]\n"
40
+" -- AX88772B EEPROM write tool\n";
41
+const char writeeeprom_str2[] =
42
+" [file] - Input file\n"
43
+" [size] - EEPROM SIZE in bytes\n";
44
+
45
+const char chgmac_str1[] =
46
+"./ioctl chgmac [mac_addr] [size]\n"
47
+" -- AX88772B EEPROM write tool (specify MAC address)\n";
48
+const char chgmac_str2[] =
49
+" [mac_addr]- MAC address (xx:xx:xx:xx:xx:xx)\n"
50
+" [size] - EEPROM SIZE in bytes\n";
51
+
52
+/* EXPORTED SUBPROGRAM SPECIFICATIONS */
53
+void help_func (struct ax_command_info *info);
54
+void readeeprom_func(struct ax_command_info *info);
55
+void writeeeprom_func(struct ax_command_info *info);
56
+void chgmac_func(struct ax_command_info *info);
57
+/* TYPE DECLARATIONS */
58
+
59
+typedef void (*MENU_FUNC)(struct ax_command_info *info);
60
+
61
+struct {
62
+ char *cmd;
63
+ unsigned short ioctl_cmd;
64
+ MENU_FUNC OptFunc;
65
+ const char *help_ins;
66
+ const char *help_desc;
67
+} command_list[] = {
68
+ {"help", AX_SIGNATURE, help_func, help_str1, help_str2},
69
+ {"reeprom", AX_READ_EEPROM, readeeprom_func, readeeprom_str1, readeeprom_str2},
70
+ {"weeprom", AX_WRITE_EEPROM, writeeeprom_func, writeeeprom_str1, writeeeprom_str2},
71
+ {"chgmac", AX_WRITE_EEPROM, chgmac_func, chgmac_str1, chgmac_str2},
72
+ {NULL},
73
+};
74
+
75
+#endif /* End of console_debug_h */
kernel/drivers/net/usb/AX88772C_eeprom/ioctl_readme
....@@ -0,0 +1,61 @@
1
+AX88772C/AX88772B/AX88772A/AX88760/AX88772/AX88178 Linux SROM tool.
2
+
3
+This tool can be used to read/write the EEPROM of AX88772C/AX88772B/AX88772A/AX88760/AX88772/AX88178.
4
+================
5
+Getting Start
6
+================
7
+
8
+1. Extract the compressed driver source file to your template directory by the
9
+ following command:
10
+
11
+ [root@localhost template]# tar -xf AX88772B_772A_760_772_178_Linux_EEPROM_Programming_Tool_Source_v1.x.0.tar.bz2
12
+
13
+2. Now, the driver source files should be extracted under the current directory.
14
+ Executing the following command to compile the driver:
15
+
16
+ [root@localhost template]# make
17
+
18
+3. If the compilation is well, the ioctl will be created under the current
19
+ directory.
20
+
21
+Note: The default way to find the interface is to scan the ASIX device using the ethx
22
+ (x: 0~255).It is defined in the file, ioctl.h.
23
+
24
+ (As follows)
25
+ ...
26
+ // DEFAULT_SCAN : scan "eth0" - "eth255"
27
+ // INTERFACE_SCAN : scan all available network interfaces
28
+ #define NET_INTERFACE DEFAULT_SCAN
29
+ #define DEFAULT_SCAN 0x00
30
+ #define INTERFACE_SCAN 0x01
31
+ ...
32
+
33
+ Adjust the contents of #define NET_INTERFACE to select the method you want.
34
+
35
+================
36
+Usage
37
+================
38
+
39
+1. If you want to read out values of the EEPROM to a file, go to the driver directory and
40
+ execute the following command:
41
+
42
+ [root@localhost driver_dir]# ./ioctl reeprom file_name eeprom_size
43
+
44
+2. If you want to write values of a file to the EEPROM, go to the driver directory and
45
+ execute the following command:
46
+
47
+ [root@localhost driver_dir]# ./ioctl weeprom file_name eeprom_size
48
+
49
+3. If you want to change the MAC address of a dongle, go to the driver directory and
50
+ execute the following command:
51
+
52
+ [root@localhost driver_dir]# ./ioctl chgmac mac_addr eeprom_size
53
+
54
+4. If you need more information about the instructions, go to the driver directory and
55
+ execute the following commands:
56
+
57
+ [root@localhost driver_dir]# ./ioctl reeprom help
58
+
59
+or
60
+
61
+ [root@localhost driver_dir]# ./ioctl weeprom help
kernel/drivers/net/usb/AX88772C_eeprom/readme
....@@ -0,0 +1,92 @@
1
+============================================================================
2
+ASIX AX88178 USB 2.0 Gigabit Ethernet Network Adapter
3
+ASIX AX88772 USB 2.0 Fast Ethernet Network Adapter
4
+ASIX AX88772A USB 2.0 Fast Ethernet Network Adapter
5
+ASIX AX88760 USB 2.0 MTT HUB and USB 2.0 to Fast Ethernet Combo Controller
6
+ASIX AX88772B USB 2.0 Fast Ethernet Network Adapter
7
+ASIX AX88772C USB 2.0 Fast Ethernet Network Adapter
8
+Driver Compilation & Configuration on the Linux
9
+============================================================================
10
+
11
+This driver has been verified on Linux kernel 2.6.14 and later.
12
+
13
+================
14
+Prerequisites
15
+================
16
+
17
+Prepare to build the driver, you need the Linux kernel sources installed on the
18
+build machine, and make sure that the version of the running kernel must match
19
+the installed kernel sources. If you don't have the kernel sources, you can get
20
+it from www.kernel.org or contact to your Linux distributor. If you don't know
21
+how to do, please refer to KERNEL-HOWTO.
22
+
23
+Note: Please make sure the kernel is built with one of the "Support for
24
+ Host-side, EHCI, OHCI, or UHCI" option support.
25
+
26
+
27
+===========================
28
+Conditional Compilation Flag
29
+===========================
30
+[AX_FORCE_BUFF_ALIGN]
31
+Description:
32
+ There are alignment issues of USB buffer in some USB host controllers.
33
+ Turn on this flag if the implementation of your USB host controller
34
+ cannot handle non-double word aligned buffer.
35
+ When turn on this flag, driver will fixup egress packet aligned on double
36
+ word boundary before deliver to USB host controller.
37
+Setting:
38
+ 1 -> Enable TX buffers forced on double word alignment.
39
+ 0 -> Disable TX buffers forced on double word alignment.
40
+Default:
41
+ 0
42
+
43
+
44
+================
45
+Getting Start
46
+================
47
+
48
+1. Extract the compressed driver source file to your template directory by the
49
+ following command:
50
+
51
+ [root@localhost template]# tar -xf DRIVER_SOURCE_PACKAGE.tar.bz2
52
+
53
+2. Now, the driver source files should be extracted under the current directory.
54
+ Executing the following command to compile the driver:
55
+
56
+ [root@localhost template]# make
57
+
58
+3. If the compilation is well, the asix.ko will be created under the current
59
+ directory.
60
+
61
+4. If you want to use modprobe command to mount the driver, executing the
62
+ following command to install the driver into your Linux:
63
+
64
+ [root@localhost template]# make install
65
+
66
+
67
+================
68
+Usage
69
+================
70
+
71
+1. If you want to load the driver manually, go to the driver directory and
72
+ execute the following commands:
73
+
74
+ [root@localhost template]# insmod asix.ko
75
+
76
+2. If you had installed the driver during driver compilation, then you can use
77
+ the following command to load the driver automatically.
78
+
79
+ [root@localhost anywhere]# modprobe asix
80
+
81
+If you want to unload the driver, just executing the following command:
82
+
83
+ [root@localhost anywhere]# rmmod asix
84
+
85
+================
86
+Special define
87
+================
88
+There is a RX_SKB_COPY preprocessor define in asix.h can solve rx_throttle problem
89
+in some version of 3.4 Linux kernel. Removing the comment before the define can enable
90
+this feature.
91
+
92
+
kernel/drivers/net/usb/Makefile
....@@ -41,3 +41,5 @@
4141 obj-$(CONFIG_USB_NET_CDC_MBIM) += cdc_mbim.o
4242 obj-$(CONFIG_USB_NET_CH9200) += ch9200.o
4343 obj-$(CONFIG_USB_NET_AQC111) += aqc111.o
44
+#obj-y += AX88772C_eeprom/
45
+obj-y += ax88772C/
kernel/drivers/net/usb/ax88772C/Makefile
....@@ -0,0 +1 @@
1
+obj-m += asix.o
kernel/drivers/net/usb/ax88772C/asix.c
....@@ -0,0 +1,4369 @@
1
+/*
2
+ * ASIX AX8817X based USB 2.0 Ethernet Devices
3
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
4
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
5
+ * Copyright (c) 2002-2003 TiVo Inc.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+/* debug messages, extra info */
23
+/* #define DEBUG */
24
+
25
+#include <linux/version.h>
26
+/* #include <linux/config.h> */
27
+#ifdef CONFIG_USB_DEBUG
28
+# define DEBUG
29
+#endif
30
+#include <linux/module.h>
31
+#include <linux/kmod.h>
32
+#include <linux/sched.h>
33
+#include <linux/init.h>
34
+#include <linux/netdevice.h>
35
+#include <linux/etherdevice.h>
36
+#include <linux/ethtool.h>
37
+#include <linux/workqueue.h>
38
+#include <linux/mii.h>
39
+#include <linux/usb.h>
40
+#include <linux/crc32.h>
41
+
42
+#include "axusbnet.c"
43
+#include "asix.h"
44
+
45
+static char version[] =
46
+KERN_INFO "ASIX USB Ethernet Adapter:v" DRIVER_VERSION
47
+ " http://www.asix.com.tw\n";
48
+
49
+/* configuration of maximum bulk in size */
50
+static int bsize = AX88772B_MAX_BULKIN_16K;
51
+module_param(bsize, int, 0);
52
+MODULE_PARM_DESC(bsize, "Maximum transfer size per bulk");
53
+
54
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
55
+static void ax88772b_link_reset(void *data);
56
+static void ax88772a_link_reset(void *data);
57
+static void ax88772_link_reset(void *data);
58
+#else
59
+static void ax88772b_link_reset(struct work_struct *work);
60
+static void ax88772a_link_reset(struct work_struct *work);
61
+static void ax88772_link_reset(struct work_struct *work);
62
+#endif
63
+static int ax88772a_phy_powerup(struct usbnet *dev);
64
+static void ax8817x_mdio_write_le(struct net_device *netdev, int phy_id,
65
+ int loc, int val);
66
+static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc);
67
+static int ax88772b_set_csums(struct usbnet *dev);
68
+static int ax88772b_external_phyinit(struct usbnet *dev);
69
+
70
+/* ASIX AX8817X based USB 2.0 Ethernet Devices */
71
+
72
+static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
73
+ u16 size, void *data)
74
+{
75
+ return usb_control_msg(
76
+ dev->udev,
77
+ usb_rcvctrlpipe(dev->udev, 0),
78
+ cmd,
79
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
80
+ value,
81
+ index,
82
+ data,
83
+ size,
84
+ USB_CTRL_GET_TIMEOUT);
85
+}
86
+
87
+static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
88
+ u16 size, void *data)
89
+{
90
+ return usb_control_msg(
91
+ dev->udev,
92
+ usb_sndctrlpipe(dev->udev, 0),
93
+ cmd,
94
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
95
+ value,
96
+ index,
97
+ data,
98
+ size,
99
+ USB_CTRL_SET_TIMEOUT);
100
+}
101
+
102
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
103
+static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
104
+#else
105
+static void ax8817x_async_cmd_callback(struct urb *urb)
106
+#endif
107
+{
108
+ struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
109
+
110
+ if (urb->status < 0)
111
+ printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
112
+ urb->status);
113
+
114
+ kfree(req);
115
+ usb_free_urb(urb);
116
+}
117
+
118
+static int ax8817x_set_mac_addr(struct net_device *net, void *p)
119
+{
120
+ struct usbnet *dev = netdev_priv(net);
121
+ struct sockaddr *addr = p;
122
+ int ret;
123
+
124
+ memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
125
+
126
+ /* Set the MAC address */
127
+ ret = ax8817x_write_cmd(dev, AX88772_CMD_WRITE_NODE_ID,
128
+ 0, 0, ETH_ALEN, net->dev_addr);
129
+ if (ret < 0)
130
+ return ret;
131
+
132
+ return 0;
133
+}
134
+
135
+static void ax88178_status(struct usbnet *dev, struct urb *urb)
136
+{
137
+ struct ax88172_int_data *event;
138
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
139
+ int link;
140
+
141
+ if (urb->actual_length < 8)
142
+ return;
143
+
144
+ if (ax178dataptr->EepromData == PHY_MODE_MAC_TO_MAC_GMII)
145
+ return;
146
+
147
+ event = urb->transfer_buffer;
148
+ link = event->link & 0x01;
149
+ if (netif_carrier_ok(dev->net) != link) {
150
+ if (link) {
151
+ netif_carrier_on(dev->net);
152
+ axusbnet_defer_kevent(dev, EVENT_LINK_RESET);
153
+ } else
154
+ netif_carrier_off(dev->net);
155
+ devwarn(dev, "ax88178 - Link status is: %d", link);
156
+ }
157
+}
158
+
159
+static void ax8817x_status(struct usbnet *dev, struct urb *urb)
160
+{
161
+ struct ax88172_int_data *event;
162
+ int link;
163
+
164
+ if (urb->actual_length < 8)
165
+ return;
166
+
167
+ event = urb->transfer_buffer;
168
+ link = event->link & 0x01;
169
+ if (netif_carrier_ok(dev->net) != link) {
170
+ if (link) {
171
+ netif_carrier_on(dev->net);
172
+ axusbnet_defer_kevent(dev, EVENT_LINK_RESET);
173
+ } else
174
+ netif_carrier_off(dev->net);
175
+ devwarn(dev, "ax8817x - Link status is: %d", link);
176
+ }
177
+}
178
+
179
+static void ax88772_status(struct usbnet *dev, struct urb *urb)
180
+{
181
+ struct ax88172_int_data *event;
182
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
183
+ int link;
184
+
185
+ if (urb->actual_length < 8)
186
+ return;
187
+
188
+ event = urb->transfer_buffer;
189
+ link = event->link & 0x01;
190
+
191
+ if (netif_carrier_ok(dev->net) != link) {
192
+ if (link) {
193
+ netif_carrier_on(dev->net);
194
+ ax772_data->Event = AX_SET_RX_CFG;
195
+ } else {
196
+ netif_carrier_off(dev->net);
197
+ if (ax772_data->Event == AX_NOP) {
198
+ ax772_data->Event = PHY_POWER_DOWN;
199
+ ax772_data->TickToExpire = 25;
200
+ }
201
+ }
202
+
203
+ devwarn(dev, "ax88772 - Link status is: %d", link);
204
+ }
205
+
206
+ if (ax772_data->Event)
207
+ queue_work(ax772_data->ax_work, &ax772_data->check_link);
208
+}
209
+
210
+static void ax88772a_status(struct usbnet *dev, struct urb *urb)
211
+{
212
+ struct ax88172_int_data *event;
213
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
214
+ int link;
215
+ int powsave = (ax772a_data->EepromData >> 14);
216
+
217
+ if (urb->actual_length < 8)
218
+ return;
219
+
220
+ event = urb->transfer_buffer;
221
+ link = event->link & 0x01;
222
+
223
+ if (netif_carrier_ok(dev->net) != link) {
224
+
225
+ if (link) {
226
+ netif_carrier_on(dev->net);
227
+ ax772a_data->Event = AX_SET_RX_CFG;
228
+ } else if ((powsave == 0x3) || (powsave == 0x1)) {
229
+ netif_carrier_off(dev->net);
230
+ if (ax772a_data->Event == AX_NOP) {
231
+ ax772a_data->Event = CHK_CABLE_EXIST;
232
+ ax772a_data->TickToExpire = 14;
233
+ }
234
+ } else {
235
+ netif_carrier_off(dev->net);
236
+ ax772a_data->Event = AX_NOP;
237
+ }
238
+
239
+ devwarn(dev, "ax88772a - Link status is: %d", link);
240
+ }
241
+
242
+ if (ax772a_data->Event)
243
+ queue_work(ax772a_data->ax_work, &ax772a_data->check_link);
244
+}
245
+
246
+static int ax88772b_stop(struct usbnet *dev)
247
+{
248
+ u16 *medium;
249
+
250
+ medium = kmalloc(2, GFP_ATOMIC);
251
+ if (medium) {
252
+ ax8817x_read_cmd(dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, medium);
253
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
254
+ (*medium & ~AX88772_MEDIUM_RX_ENABLE),
255
+ 0, 0, NULL);
256
+
257
+ kfree(medium);
258
+ return 0;
259
+ }
260
+ return -EINVAL;
261
+}
262
+
263
+static int ax88772b_reset(struct usbnet *dev)
264
+{
265
+ int ret;
266
+
267
+ /* Set the MAC address */
268
+ ret = ax8817x_write_cmd(dev, AX88772_CMD_WRITE_NODE_ID,
269
+ 0, 0, ETH_ALEN, dev->net->dev_addr);
270
+ if (ret < 0)
271
+ deverr(dev, "set MAC address failed: %d", ret);
272
+
273
+ /* stop MAC operation */
274
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, AX_RX_CTL_STOP,
275
+ 0, 0, NULL);
276
+ if (ret < 0)
277
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
278
+
279
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
280
+ AX88772_MEDIUM_DEFAULT, 0, 0,
281
+ NULL);
282
+ if (ret < 0)
283
+ deverr(dev, "Write medium mode register: %d", ret);
284
+
285
+ return ret;
286
+}
287
+
288
+static void ax88772b_status(struct usbnet *dev, struct urb *urb)
289
+{
290
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
291
+ struct ax88172_int_data *event;
292
+ int link;
293
+
294
+ if (urb->actual_length < 8)
295
+ return;
296
+
297
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
298
+ return;
299
+
300
+ event = urb->transfer_buffer;
301
+ if (ax772b_data->PhySelect == 0 &&
302
+ ax772b_data->OperationMode == OPERATION_MAC_MODE)
303
+ link = (event->link & AX_INT_SPLS_LINK) >> 1;
304
+ else
305
+ link = event->link & AX_INT_PPLS_LINK;
306
+
307
+ if (netif_carrier_ok(dev->net) != link) {
308
+ if (link) {
309
+ netif_carrier_on(dev->net);
310
+ ax772b_data->Event = AX_SET_RX_CFG;
311
+ } else {
312
+ netif_carrier_off(dev->net);
313
+ ax772b_data->time_to_chk = jiffies;
314
+ }
315
+ devwarn(dev, "ax88772b - Link status is: %d", link);
316
+ }
317
+
318
+ if (!link) {
319
+
320
+ int no_cable = (event->link & AX_INT_CABOFF_UNPLUG) ? 1 : 0;
321
+
322
+ if (no_cable) {
323
+ if ((ax772b_data->psc &
324
+ (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) &&
325
+ !ax772b_data->pw_enabled) {
326
+ /*
327
+ * AX88772B already entered power saving state
328
+ */
329
+ ax772b_data->pw_enabled = 1;
330
+ }
331
+ if (ax772b_data->psc & AX_SWRESET_AUTODETACH)
332
+ ax772b_data->Event = AX_CHK_AUTODETACH;
333
+
334
+ } else {
335
+ /* AX88772B resumed from power saving state */
336
+ if (ax772b_data->pw_enabled ||
337
+ (jiffies > (ax772b_data->time_to_chk +
338
+ AX88772B_WATCHDOG))) {
339
+ if (ax772b_data->pw_enabled)
340
+ ax772b_data->pw_enabled = 0;
341
+ ax772b_data->Event = PHY_POWER_UP;
342
+ ax772b_data->time_to_chk = jiffies;
343
+ }
344
+ }
345
+ }
346
+
347
+ if (ax772b_data->Event)
348
+ queue_work(ax772b_data->ax_work, &ax772b_data->check_link);
349
+}
350
+
351
+static void ax88772c_status(struct usbnet *dev, struct urb *urb)
352
+{
353
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
354
+ struct ax88172_int_data *event;
355
+ int link;
356
+
357
+ if (urb->actual_length < 8)
358
+ return;
359
+
360
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
361
+ return;
362
+
363
+ event = urb->transfer_buffer;
364
+ if (ax772b_data->PhySelect == 0 &&
365
+ ax772b_data->OperationMode == OPERATION_MAC_MODE)
366
+ link = (event->link & AX_INT_SPLS_LINK) >> 1;
367
+ else
368
+ link = event->link & AX_INT_PPLS_LINK;
369
+
370
+ if (netif_carrier_ok(dev->net) != link) {
371
+ if (link) {
372
+ netif_carrier_on(dev->net);
373
+ ax772b_data->Event = AX_SET_RX_CFG;
374
+ } else {
375
+ netif_carrier_off(dev->net);
376
+ ax772b_data->time_to_chk = jiffies;
377
+ }
378
+ devwarn(dev, "ax88772c - Link status is: %d", link);
379
+ }
380
+
381
+ if (!link) {
382
+
383
+ int no_cable = (event->link & AX_INT_CABOFF_UNPLUG) ? 1 : 0;
384
+
385
+ if (no_cable) {
386
+ if ((ax772b_data->psc &
387
+ (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) &&
388
+ !ax772b_data->pw_enabled) {
389
+ /*
390
+ * AX88772B already entered power saving state
391
+ */
392
+ ax772b_data->pw_enabled = 1;
393
+ }
394
+ if (ax772b_data->psc & AX_SWRESET_AUTODETACH)
395
+ ax772b_data->Event = AX_CHK_AUTODETACH;
396
+ } else {
397
+ /* AX88772B resumed from power saving state */
398
+ if (ax772b_data->pw_enabled ||
399
+ (jiffies > (ax772b_data->time_to_chk +
400
+ AX88772B_WATCHDOG))) {
401
+ if (ax772b_data->pw_enabled)
402
+ ax772b_data->pw_enabled = 0;
403
+ ax772b_data->Event = PHY_POWER_UP;
404
+ ax772b_data->time_to_chk = jiffies;
405
+ }
406
+ }
407
+ }
408
+
409
+ if (ax772b_data->Event)
410
+ queue_work(ax772b_data->ax_work, &ax772b_data->check_link);
411
+}
412
+
413
+void
414
+ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
415
+ u16 size, void *data)
416
+{
417
+ struct usb_ctrlrequest *req;
418
+ int status;
419
+ struct urb *urb;
420
+
421
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
422
+ if (urb == NULL) {
423
+ deverr(dev, "Error allocating URB in write_cmd_async!");
424
+ return;
425
+ }
426
+
427
+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
428
+ if (req == NULL) {
429
+ deverr(dev, "Failed to allocate memory for control request");
430
+ usb_free_urb(urb);
431
+ return;
432
+ }
433
+
434
+ req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
435
+ req->bRequest = cmd;
436
+ req->wValue = cpu_to_le16(value);
437
+ req->wIndex = cpu_to_le16(index);
438
+ req->wLength = cpu_to_le16(size);
439
+
440
+ usb_fill_control_urb(urb, dev->udev,
441
+ usb_sndctrlpipe(dev->udev, 0),
442
+ (void *)req, data, size,
443
+ ax8817x_async_cmd_callback, req);
444
+
445
+ status = usb_submit_urb(urb, GFP_ATOMIC);
446
+ if (status < 0) {
447
+ deverr(dev, "Error submitting the control message: status=%d",
448
+ status);
449
+ kfree(req);
450
+ usb_free_urb(urb);
451
+ }
452
+}
453
+
454
+static void ax8817x_set_multicast(struct net_device *net)
455
+{
456
+ struct usbnet *dev = netdev_priv(net);
457
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
458
+ u8 rx_ctl = AX_RX_CTL_START | AX_RX_CTL_AB;
459
+ int mc_count;
460
+
461
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
462
+ mc_count = net->mc_count;
463
+#else
464
+ mc_count = netdev_mc_count(net);
465
+#endif
466
+
467
+ if (net->flags & IFF_PROMISC) {
468
+ rx_ctl |= AX_RX_CTL_PRO;
469
+ } else if (net->flags & IFF_ALLMULTI
470
+ || mc_count > AX_MAX_MCAST) {
471
+ rx_ctl |= AX_RX_CTL_AMALL;
472
+ } else if (mc_count == 0) {
473
+ /* just broadcast and directed */
474
+ } else {
475
+ /* We use the 20 byte dev->data
476
+ * for our 8 byte filter buffer
477
+ * to avoid allocating memory that
478
+ * is tricky to free later */
479
+ u32 crc_bits;
480
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
481
+ struct dev_mc_list *mc_list = net->mc_list;
482
+ int i;
483
+
484
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
485
+
486
+ /* Build the multicast hash filter. */
487
+ for (i = 0; i < net->mc_count; i++) {
488
+ crc_bits =
489
+ ether_crc(ETH_ALEN,
490
+ mc_list->dmi_addr) >> 26;
491
+ data->multi_filter[crc_bits >> 3] |=
492
+ 1 << (crc_bits & 7);
493
+ mc_list = mc_list->next;
494
+ }
495
+#else
496
+ struct netdev_hw_addr *ha = NULL;
497
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
498
+ netdev_for_each_mc_addr(ha, net) {
499
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
500
+ data->multi_filter[crc_bits >> 3] |=
501
+ 1 << (crc_bits & 7);
502
+ }
503
+#endif
504
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
505
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
506
+
507
+ rx_ctl |= AX_RX_CTL_AM;
508
+ }
509
+
510
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
511
+}
512
+
513
+static void ax88178_set_multicast(struct net_device *net)
514
+{
515
+ struct usbnet *dev = netdev_priv(net);
516
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
517
+ u16 rx_ctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_MFB);
518
+ int mc_count;
519
+
520
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
521
+ mc_count = net->mc_count;
522
+#else
523
+ mc_count = netdev_mc_count(net);
524
+#endif
525
+
526
+ if (net->flags & IFF_PROMISC) {
527
+ rx_ctl |= AX_RX_CTL_PRO;
528
+ } else if (net->flags & IFF_ALLMULTI
529
+ || mc_count > AX_MAX_MCAST) {
530
+ rx_ctl |= AX_RX_CTL_AMALL;
531
+ } else if (mc_count == 0) {
532
+ /* just broadcast and directed */
533
+ } else {
534
+ /* We use the 20 byte dev->data
535
+ * for our 8 byte filter buffer
536
+ * to avoid allocating memory that
537
+ * is tricky to free later */
538
+ u32 crc_bits;
539
+
540
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
541
+ struct dev_mc_list *mc_list = net->mc_list;
542
+ int i;
543
+
544
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
545
+
546
+ /* Build the multicast hash filter. */
547
+ for (i = 0; i < net->mc_count; i++) {
548
+ crc_bits =
549
+ ether_crc(ETH_ALEN,
550
+ mc_list->dmi_addr) >> 26;
551
+ data->multi_filter[crc_bits >> 3] |=
552
+ 1 << (crc_bits & 7);
553
+ mc_list = mc_list->next;
554
+ }
555
+#else
556
+ struct netdev_hw_addr *ha = NULL;
557
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
558
+ netdev_for_each_mc_addr(ha, net) {
559
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
560
+ data->multi_filter[crc_bits >> 3] |=
561
+ 1 << (crc_bits & 7);
562
+ }
563
+#endif
564
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
565
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
566
+
567
+ rx_ctl |= AX_RX_CTL_AM;
568
+ }
569
+
570
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
571
+}
572
+
573
+static void ax88772b_set_multicast(struct net_device *net)
574
+{
575
+ struct usbnet *dev = netdev_priv(net);
576
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
577
+ u16 rx_ctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_HEADER_DEFAULT);
578
+ int mc_count;
579
+
580
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
581
+ mc_count = net->mc_count;
582
+#else
583
+ mc_count = netdev_mc_count(net);
584
+#endif
585
+
586
+ if (net->flags & IFF_PROMISC) {
587
+ rx_ctl |= AX_RX_CTL_PRO;
588
+ } else if (net->flags & IFF_ALLMULTI
589
+ || mc_count > AX_MAX_MCAST) {
590
+ rx_ctl |= AX_RX_CTL_AMALL;
591
+ } else if (mc_count == 0) {
592
+ /* just broadcast and directed */
593
+ } else {
594
+ /* We use the 20 byte dev->data
595
+ * for our 8 byte filter buffer
596
+ * to avoid allocating memory that
597
+ * is tricky to free later */
598
+ u32 crc_bits;
599
+
600
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
601
+ struct dev_mc_list *mc_list = net->mc_list;
602
+ int i;
603
+
604
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
605
+
606
+ /* Build the multicast hash filter. */
607
+ for (i = 0; i < net->mc_count; i++) {
608
+ crc_bits =
609
+ ether_crc(ETH_ALEN,
610
+ mc_list->dmi_addr) >> 26;
611
+ data->multi_filter[crc_bits >> 3] |=
612
+ 1 << (crc_bits & 7);
613
+ mc_list = mc_list->next;
614
+ }
615
+#else
616
+ struct netdev_hw_addr *ha = NULL;
617
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
618
+ netdev_for_each_mc_addr(ha, net) {
619
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
620
+ data->multi_filter[crc_bits >> 3] |=
621
+ 1 << (crc_bits & 7);
622
+ }
623
+#endif
624
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
625
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
626
+
627
+ rx_ctl |= AX_RX_CTL_AM;
628
+ }
629
+
630
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
631
+}
632
+
633
+static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
634
+{
635
+ struct usbnet *dev = netdev_priv(netdev);
636
+ u16 *res, ret;
637
+ u8* smsr;
638
+ int i = 0;
639
+
640
+ res = kmalloc(2, GFP_ATOMIC);
641
+ if (!res)
642
+ return 0;
643
+
644
+ do {
645
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
646
+
647
+ msleep(1);
648
+
649
+ smsr = (u8*) res;
650
+ ax8817x_read_cmd(dev, AX_CMD_READ_STATMNGSTS_REG, 0, 0, 1, smsr);
651
+ } while (!(*smsr & AX_HOST_EN) && (i++ < 30));
652
+
653
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, res);
654
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
655
+
656
+ ret = *res & 0xffff;
657
+ kfree(res);
658
+
659
+ return ret;
660
+}
661
+
662
+static int
663
+ax8817x_swmii_mdio_read(struct net_device *netdev, int phy_id, int loc)
664
+{
665
+ struct usbnet *dev = netdev_priv(netdev);
666
+ u16 *res;
667
+ u16 ret;
668
+
669
+ res = kmalloc(2, GFP_ATOMIC);
670
+ if (!res)
671
+ return 0;
672
+
673
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
674
+ (__u16)loc, 2, res);
675
+
676
+ ret = *res & 0xffff;
677
+ kfree(res);
678
+
679
+ return ret;
680
+}
681
+
682
+/* same as above, but converts resulting value to cpu byte order */
683
+static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
684
+{
685
+ return le16_to_cpu(ax8817x_mdio_read(netdev, phy_id, loc));
686
+}
687
+
688
+static int
689
+ax8817x_swmii_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
690
+{
691
+ return le16_to_cpu(ax8817x_swmii_mdio_read(netdev, phy_id, loc));
692
+}
693
+
694
+static void
695
+ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
696
+{
697
+ struct usbnet *dev = netdev_priv(netdev);
698
+ u16 *res;
699
+ u8* smsr;
700
+ int i = 0;
701
+
702
+ res = kmalloc(2, GFP_ATOMIC);
703
+ if (!res)
704
+ return;
705
+ smsr = (u8 *) res;
706
+
707
+ do {
708
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
709
+
710
+ msleep(1);
711
+
712
+ ax8817x_read_cmd(dev, AX_CMD_READ_STATMNGSTS_REG, 0, 0, 1, smsr);
713
+ } while (!(*smsr & AX_HOST_EN) && (i++ < 30));
714
+
715
+ *res = val;
716
+
717
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
718
+ (__u16)loc, 2, res);
719
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
720
+
721
+ kfree(res);
722
+}
723
+
724
+static void ax8817x_swmii_mdio_write(struct net_device *netdev, int phy_id,
725
+ int loc, int val)
726
+{
727
+ struct usbnet *dev = netdev_priv(netdev);
728
+ u16 *res;
729
+
730
+ res = kmalloc(2, GFP_ATOMIC);
731
+ if (!res)
732
+ return;
733
+ *res = val;
734
+
735
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
736
+ (__u16)loc, 2, res);
737
+
738
+ kfree(res);
739
+}
740
+
741
+static void
742
+ax88772b_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
743
+{
744
+ struct usbnet *dev = netdev_priv(netdev);
745
+ u16 *res;
746
+
747
+ res = kmalloc(2, GFP_ATOMIC);
748
+ if (!res)
749
+ return;
750
+ *res = val;
751
+
752
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
753
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
754
+ (__u16)loc, 2, res);
755
+
756
+ if (loc == MII_ADVERTISE) {
757
+ *res = cpu_to_le16(BMCR_ANENABLE | BMCR_ANRESTART);
758
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
759
+ (__u16)MII_BMCR, 2, res);
760
+ }
761
+
762
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
763
+
764
+ kfree(res);
765
+}
766
+
767
+/* same as above, but converts new value to le16 byte order before writing */
768
+static void
769
+ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
770
+{
771
+ ax8817x_mdio_write(netdev, phy_id, loc, cpu_to_le16(val));
772
+}
773
+
774
+static void ax8817x_swmii_mdio_write_le(struct net_device *netdev,
775
+ int phy_id, int loc, int val)
776
+{
777
+ ax8817x_swmii_mdio_write(netdev, phy_id, loc, cpu_to_le16(val));
778
+}
779
+
780
+static void
781
+ax88772b_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
782
+{
783
+ ax88772b_mdio_write(netdev, phy_id, loc, cpu_to_le16(val));
784
+}
785
+
786
+static int ax88772_suspend(struct usb_interface *intf,
787
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
788
+ pm_message_t message)
789
+#else
790
+ u32 message)
791
+#endif
792
+{
793
+ struct usbnet *dev = usb_get_intfdata(intf);
794
+ u16 *medium;
795
+
796
+ medium = kmalloc(2, GFP_ATOMIC);
797
+ if (!medium)
798
+ return axusbnet_suspend(intf, message);
799
+
800
+ ax8817x_read_cmd(dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, medium);
801
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
802
+ (*medium & ~AX88772_MEDIUM_RX_ENABLE), 0, 0, NULL);
803
+
804
+ kfree(medium);
805
+ return axusbnet_suspend(intf, message);
806
+}
807
+
808
+static int ax88772b_suspend(struct usb_interface *intf,
809
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
810
+ pm_message_t message)
811
+#else
812
+ u32 message)
813
+#endif
814
+{
815
+ struct usbnet *dev = usb_get_intfdata(intf);
816
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
817
+ u16 *tmp16;
818
+ u8 *opt;
819
+
820
+ tmp16 = kmalloc(2, GFP_ATOMIC);
821
+ if (!tmp16)
822
+ return axusbnet_suspend(intf, message);
823
+ opt = (u8 *)tmp16;
824
+#if 0
825
+ /* Read Wake-up Frame Array Register (Mask Wakeup Timer) */
826
+ ax8817x_read_cmd(dev, AX_CMD_READ_WKFARY, 0x11, 0, 4, &tmp32);
827
+ tmp32 &= 0xFFF0FFFF;
828
+ /* 8 second */
829
+ tmp32 |= 0x00020000;
830
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_WKFARY, 0x11, 0, 4, &tmp32);
831
+#endif
832
+ /* Preserve BMCR for restoring */
833
+ ax772b_data->presvd_phy_bmcr = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
834
+
835
+ /* Preserve Advertisement control reg for restoring */
836
+ ax772b_data->presvd_phy_advertise = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
837
+
838
+ ax8817x_read_cmd(dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, tmp16);
839
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
840
+ (*tmp16 & ~AX88772_MEDIUM_RX_ENABLE),
841
+ 0, 0, NULL);
842
+
843
+ ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, opt);
844
+ if (!(*opt & AX_MONITOR_LINK) && !(*opt & AX_MONITOR_MAGIC)) {
845
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
846
+ AX_SWRESET_IPRL | AX_SWRESET_IPPD,
847
+ 0, 0, NULL);
848
+
849
+ } else {
850
+
851
+ if (ax772b_data->psc & AX_SWRESET_WOLLP) {
852
+ *tmp16 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
853
+ MII_BMCR);
854
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id,
855
+ MII_BMCR, *tmp16 | BMCR_ANENABLE);
856
+
857
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
858
+ AX_SWRESET_IPRL | ax772b_data->psc,
859
+ 0, 0, NULL);
860
+ }
861
+
862
+ if (ax772b_data->psc &
863
+ (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) {
864
+ *opt |= AX_MONITOR_LINK;
865
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, *opt,
866
+ 0, 0, NULL);
867
+ }
868
+ }
869
+
870
+ dev->reg_monitor = *opt;
871
+
872
+ kfree(tmp16);
873
+ return axusbnet_suspend(intf, message);
874
+}
875
+
876
+static int ax88772_resume(struct usb_interface *intf)
877
+{
878
+ struct usbnet *dev = usb_get_intfdata(intf);
879
+
880
+ netif_carrier_off(dev->net);
881
+
882
+ return axusbnet_resume(intf);
883
+}
884
+
885
+static int ax88772b_resume(struct usb_interface *intf)
886
+{
887
+ struct usbnet *dev = usb_get_intfdata(intf);
888
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
889
+
890
+ if (ax772b_data->psc & AX_SWRESET_WOLLP) {
891
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
892
+ AX_SWRESET_IPRL | (ax772b_data->psc & 0x7FFF),
893
+ 0, 0, NULL);
894
+ }
895
+
896
+ if (ax772b_data->psc & (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1))
897
+ ax88772a_phy_powerup(dev);
898
+
899
+ netif_carrier_off(dev->net);
900
+
901
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
902
+ netif_carrier_on(dev->net);
903
+
904
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, dev->reg_monitor,
905
+ 0, 0, NULL);
906
+
907
+ return axusbnet_resume(intf);
908
+}
909
+
910
+static int ax88172_link_reset(struct usbnet *dev)
911
+{
912
+ u16 lpa;
913
+ u16 adv;
914
+ u16 res;
915
+ u8 mode;
916
+
917
+ mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
918
+ lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
919
+ adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
920
+ res = mii_nway_result(lpa|adv);
921
+ if (res & LPA_DUPLEX)
922
+ mode |= AX_MEDIUM_FULL_DUPLEX;
923
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
924
+
925
+ return 0;
926
+}
927
+
928
+static void
929
+ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
930
+{
931
+ struct usbnet *dev = netdev_priv(net);
932
+ u8 *opt;
933
+
934
+ wolinfo->supported = 0;
935
+ wolinfo->wolopts = 0;
936
+
937
+ opt = kmalloc(1, GFP_KERNEL);
938
+ if (!opt)
939
+ return;
940
+
941
+ if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, opt) < 0) {
942
+ kfree(opt);
943
+ return;
944
+ }
945
+
946
+ wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
947
+
948
+ if (*opt & AX_MONITOR_LINK)
949
+ wolinfo->wolopts |= WAKE_PHY;
950
+ if (*opt & AX_MONITOR_MAGIC)
951
+ wolinfo->wolopts |= WAKE_MAGIC;
952
+
953
+ kfree(opt);
954
+}
955
+
956
+static int
957
+ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
958
+{
959
+ struct usbnet *dev = netdev_priv(net);
960
+ u8 opt;
961
+
962
+ opt = 0;
963
+ if (wolinfo->wolopts & WAKE_PHY)
964
+ opt |= AX_MONITOR_LINK;
965
+ if (wolinfo->wolopts & WAKE_MAGIC)
966
+ opt |= AX_MONITOR_MAGIC;
967
+
968
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, opt, 0, 0, NULL);
969
+
970
+ return 0;
971
+}
972
+
973
+static int ax8817x_get_eeprom_len(struct net_device *net)
974
+{
975
+ return AX_EEPROM_LEN;
976
+}
977
+
978
+static int ax8817x_get_eeprom(struct net_device *net,
979
+ struct ethtool_eeprom *eeprom, u8 *data)
980
+{
981
+ struct usbnet *dev = netdev_priv(net);
982
+ u16 *ebuf = (u16 *)data;
983
+ int i;
984
+
985
+ /* Crude hack to ensure that we don't overwrite memory
986
+ * if an odd length is supplied
987
+ */
988
+ if (eeprom->len % 2)
989
+ return -EINVAL;
990
+
991
+ eeprom->magic = AX_EEPROM_MAGIC;
992
+
993
+ /* ax8817x returns 2 bytes from eeprom on read */
994
+ for (i = 0; i < eeprom->len / 2; i++) {
995
+ if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
996
+ eeprom->offset + i, 0, 2,
997
+ &ebuf[i]) < 0)
998
+ return -EINVAL;
999
+ }
1000
+ return 0;
1001
+}
1002
+
1003
+static void ax8817x_get_drvinfo(struct net_device *net,
1004
+ struct ethtool_drvinfo *info)
1005
+{
1006
+ /* Inherit standard device info */
1007
+ axusbnet_get_drvinfo(net, info);
1008
+ info->eedump_len = 0x3e;
1009
+}
1010
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1011
+static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
1012
+{
1013
+ struct usbnet *dev = netdev_priv(net);
1014
+ return mii_ethtool_gset(&dev->mii, cmd);
1015
+}
1016
+
1017
+static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
1018
+{
1019
+ struct usbnet *dev = netdev_priv(net);
1020
+ return mii_ethtool_sset(&dev->mii, cmd);
1021
+}
1022
+#else
1023
+static int ax8817x_get_link_ksettings(struct net_device *net,
1024
+ struct ethtool_link_ksettings *cmd)
1025
+{
1026
+ struct usbnet *dev = netdev_priv(net);
1027
+
1028
+ if (!dev->mii.mdio_read)
1029
+ return -EOPNOTSUPP;
1030
+
1031
+ mii_ethtool_get_link_ksettings(&dev->mii, cmd);
1032
+
1033
+ return 0;
1034
+}
1035
+
1036
+static int ax8817x_set_link_ksettings(struct net_device *net,
1037
+ const struct ethtool_link_ksettings *cmd)
1038
+{
1039
+ struct usbnet *dev = netdev_priv(net);
1040
+
1041
+ if (!dev->mii.mdio_write)
1042
+ return -EOPNOTSUPP;
1043
+
1044
+ return mii_ethtool_set_link_ksettings(&dev->mii, cmd);
1045
+}
1046
+#endif
1047
+/* We need to override some ethtool_ops so we require our
1048
+ own structure so we don't interfere with other usbnet
1049
+ devices that may be connected at the same time. */
1050
+static struct ethtool_ops ax8817x_ethtool_ops = {
1051
+ .get_drvinfo = ax8817x_get_drvinfo,
1052
+ .get_link = ethtool_op_get_link,
1053
+ .get_msglevel = axusbnet_get_msglevel,
1054
+ .set_msglevel = axusbnet_set_msglevel,
1055
+ .get_wol = ax8817x_get_wol,
1056
+ .set_wol = ax8817x_set_wol,
1057
+ .get_eeprom_len = ax8817x_get_eeprom_len,
1058
+ .get_eeprom = ax8817x_get_eeprom,
1059
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1060
+ .get_settings = ax8817x_get_settings,
1061
+ .set_settings = ax8817x_set_settings,
1062
+#else
1063
+ .get_link_ksettings = ax8817x_get_link_ksettings,
1064
+ .set_link_ksettings = ax8817x_set_link_ksettings,
1065
+#endif
1066
+};
1067
+
1068
+static int ax8817x_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
1069
+{
1070
+ struct usbnet *dev = netdev_priv(net);
1071
+
1072
+ return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
1073
+}
1074
+
1075
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1076
+static const struct net_device_ops ax88x72_netdev_ops = {
1077
+ .ndo_open = axusbnet_open,
1078
+ .ndo_stop = axusbnet_stop,
1079
+ .ndo_start_xmit = axusbnet_start_xmit,
1080
+ .ndo_tx_timeout = axusbnet_tx_timeout,
1081
+ .ndo_change_mtu = axusbnet_change_mtu,
1082
+ .ndo_get_stats = axusbnet_get_stats,
1083
+ .ndo_do_ioctl = ax8817x_ioctl,
1084
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
1085
+ .ndo_validate_addr = eth_validate_addr,
1086
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 2, 0)
1087
+ .ndo_set_multicast_list = ax8817x_set_multicast,
1088
+#else
1089
+ .ndo_set_rx_mode = ax8817x_set_multicast,
1090
+#endif
1091
+};
1092
+#endif
1093
+
1094
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1095
+static const struct net_device_ops ax88178_netdev_ops = {
1096
+ .ndo_open = axusbnet_open,
1097
+ .ndo_stop = axusbnet_stop,
1098
+ .ndo_start_xmit = axusbnet_start_xmit,
1099
+ .ndo_tx_timeout = axusbnet_tx_timeout,
1100
+ .ndo_change_mtu = axusbnet_change_mtu,
1101
+ .ndo_get_stats = axusbnet_get_stats,
1102
+ .ndo_do_ioctl = ax8817x_ioctl,
1103
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
1104
+ .ndo_validate_addr = eth_validate_addr,
1105
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 2, 0)
1106
+ .ndo_set_multicast_list = ax88178_set_multicast,
1107
+#else
1108
+ .ndo_set_rx_mode = ax88178_set_multicast,
1109
+#endif
1110
+};
1111
+#endif
1112
+
1113
+static int access_eeprom_mac(struct usbnet *dev, u8 *buf, u8 offset, bool wflag)
1114
+{
1115
+ int ret = 0, i;
1116
+ u16* tmp = (u16*)buf;
1117
+
1118
+ if (wflag) {
1119
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_EN,
1120
+ 0, 0, 0, NULL);
1121
+ if (ret < 0)
1122
+ return ret;
1123
+
1124
+ mdelay(15);
1125
+ }
1126
+
1127
+ for (i = 0; i < (ETH_ALEN >> 1); i++) {
1128
+ if (wflag) {
1129
+ u16 wd = cpu_to_le16(*(tmp + i));
1130
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM, offset + i,
1131
+ wd, 0, NULL);
1132
+ if (ret < 0)
1133
+ break;
1134
+
1135
+ mdelay(15);
1136
+ }
1137
+ else {
1138
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
1139
+ offset + i, 0, 2, tmp + i);
1140
+ if (ret < 0)
1141
+ break;
1142
+ }
1143
+ }
1144
+
1145
+ if (!wflag) {
1146
+ if (ret < 0) {
1147
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
1148
+ netdev_dbg(dev->net, "Failed to read MAC address from EEPROM: %d\n", ret);
1149
+ #else
1150
+ devdbg(dev, "Failed to read MAC address from EEPROM: %d\n", ret);
1151
+ #endif
1152
+ return ret;
1153
+ }
1154
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
1155
+ }
1156
+ else {
1157
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_DIS,
1158
+ 0, 0, 0, NULL);
1159
+ if (ret < 0)
1160
+ return ret;
1161
+
1162
+ /* reload eeprom data */
1163
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
1164
+ AXGPIOS_RSE, 0, 0, NULL);
1165
+ if (ret < 0)
1166
+ return ret;
1167
+ }
1168
+
1169
+ return 0;
1170
+}
1171
+
1172
+static int ax8817x_check_ether_addr(struct usbnet *dev)
1173
+{
1174
+ unsigned char *tmp = (unsigned char*)dev->net->dev_addr;
1175
+ u8 default_mac[6] = {0, 0x0e, 0xc6, 0x87, 0x72, 0x01};
1176
+
1177
+ if (((*((u8*)tmp) == 0) && (*((u8*)tmp + 1) == 0) && (*((u8*)tmp + 2) == 0)) ||
1178
+ !is_valid_ether_addr((u8*)tmp) ||
1179
+ !memcmp(dev->net->dev_addr, default_mac, ETH_ALEN)) {
1180
+ printk("Found invalid EEPROM MAC address value ");
1181
+ printk("%02X-%02X-%02X-%02X-%02X-%02X\n", *((u8*)tmp + 0),
1182
+ *((u8*)tmp + 1),
1183
+ *((u8*)tmp + 2),
1184
+ *((u8*)tmp + 3),
1185
+ *((u8*)tmp + 4),
1186
+ *((u8*)tmp + 5));
1187
+
1188
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1189
+ eth_hw_addr_random(dev->net);
1190
+#else
1191
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
1192
+ dev->net->addr_assign_type |= NET_ADDR_RANDOM;
1193
+#endif
1194
+ random_ether_addr(dev->net->dev_addr);
1195
+#endif
1196
+ *tmp = 0;
1197
+ *(tmp + 1) = 0x0E;
1198
+ *(tmp + 2) = 0xC6;
1199
+ *(tmp + 3) = 0x8F;
1200
+
1201
+ return -EADDRNOTAVAIL;
1202
+ }
1203
+ return 0;
1204
+}
1205
+
1206
+static int ax8817x_get_mac(struct usbnet *dev, u8* buf)
1207
+{
1208
+ int ret, i;
1209
+
1210
+
1211
+ ret = access_eeprom_mac(dev, buf, 0x04, 0);
1212
+ if (ret < 0)
1213
+ goto out;
1214
+
1215
+ if (ax8817x_check_ether_addr(dev)) {
1216
+ ret = access_eeprom_mac(dev, dev->net->dev_addr, 0x04, 1);
1217
+ if (ret < 0) {
1218
+ deverr(dev, "Failed to write MAC to EEPROM: %d", ret);
1219
+ goto out;
1220
+ }
1221
+
1222
+ msleep(5);
1223
+
1224
+ ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
1225
+ 0, 0, ETH_ALEN, buf);
1226
+ if (ret < 0) {
1227
+ deverr(dev, "Failed to read MAC address: %d", ret);
1228
+ goto out;
1229
+ }
1230
+
1231
+ for (i = 0; i < ETH_ALEN; i++)
1232
+ if (*(dev->net->dev_addr + i) != *((u8*)buf + i)) {
1233
+ devwarn(dev, "Found invalid EEPROM part or non-EEPROM");
1234
+ break;
1235
+ }
1236
+ }
1237
+
1238
+ memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
1239
+
1240
+ /* Set the MAC address */
1241
+ ax8817x_write_cmd (dev, AX88772_CMD_WRITE_NODE_ID, 0, 0,
1242
+ ETH_ALEN, dev->net->dev_addr);
1243
+
1244
+ if (ret < 0) {
1245
+ deverr(dev, "Failed to write MAC address: %d", ret);
1246
+ goto out;
1247
+ }
1248
+
1249
+ return 0;
1250
+out:
1251
+ return ret;
1252
+}
1253
+
1254
+static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
1255
+{
1256
+ int ret = 0;
1257
+ void *buf;
1258
+ int i;
1259
+ unsigned long gpio_bits = dev->driver_info->data;
1260
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
1261
+
1262
+ axusbnet_get_endpoints(dev, intf);
1263
+
1264
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
1265
+ if (!buf) {
1266
+ ret = -ENOMEM;
1267
+ goto out1;
1268
+ }
1269
+
1270
+ /* Toggle the GPIOs in a manufacturer/model specific way */
1271
+ for (i = 2; i >= 0; i--) {
1272
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
1273
+ (gpio_bits >> (i * 8)) & 0xff,
1274
+ 0, 0, NULL);
1275
+ if (ret < 0)
1276
+ goto out2;
1277
+
1278
+ msleep(5);
1279
+ }
1280
+
1281
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, NULL);
1282
+ if (ret < 0) {
1283
+ deverr(dev, "send AX_CMD_WRITE_RX_CTL failed: %d", ret);
1284
+ goto out2;
1285
+ }
1286
+
1287
+ /* Get the MAC address */
1288
+ memset(buf, 0, ETH_ALEN);
1289
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf);
1290
+ if (ret < 0) {
1291
+ deverr(dev, "read AX_CMD_READ_NODE_ID failed: %d", ret);
1292
+ goto out2;
1293
+ }
1294
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
1295
+
1296
+ /* Get the PHY id */
1297
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
1298
+ if (ret < 0) {
1299
+ deverr(dev, "error on read AX_CMD_READ_PHY_ID: %02x", ret);
1300
+ goto out2;
1301
+ } else if (ret < 2) {
1302
+ /* this should always return 2 bytes */
1303
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
1304
+ ret);
1305
+ ret = -EIO;
1306
+ goto out2;
1307
+ }
1308
+
1309
+ /* Initialize MII structure */
1310
+ dev->mii.dev = dev->net;
1311
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
1312
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
1313
+ dev->mii.phy_id_mask = 0x3f;
1314
+ dev->mii.reg_num_mask = 0x1f;
1315
+ dev->mii.phy_id = *((u8 *)buf + 1);
1316
+
1317
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1318
+ dev->net->do_ioctl = ax8817x_ioctl;
1319
+ dev->net->set_multicast_list = ax8817x_set_multicast;
1320
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
1321
+#else
1322
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
1323
+#endif
1324
+
1325
+ dev->net->ethtool_ops = &ax8817x_ethtool_ops;
1326
+
1327
+ /* Register suspend and resume functions */
1328
+ data->suspend = axusbnet_suspend;
1329
+ data->resume = axusbnet_resume;
1330
+
1331
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
1332
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
1333
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
1334
+ mii_nway_restart(&dev->mii);
1335
+
1336
+ printk(version);
1337
+
1338
+ return 0;
1339
+out2:
1340
+ kfree(buf);
1341
+out1:
1342
+ return ret;
1343
+}
1344
+
1345
+static struct ethtool_ops ax88772_ethtool_ops = {
1346
+ .get_drvinfo = ax8817x_get_drvinfo,
1347
+ .get_link = ethtool_op_get_link,
1348
+ .get_msglevel = axusbnet_get_msglevel,
1349
+ .set_msglevel = axusbnet_set_msglevel,
1350
+ .get_wol = ax8817x_get_wol,
1351
+ .set_wol = ax8817x_set_wol,
1352
+ .get_eeprom_len = ax8817x_get_eeprom_len,
1353
+ .get_eeprom = ax8817x_get_eeprom,
1354
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1355
+ .get_settings = ax8817x_get_settings,
1356
+ .set_settings = ax8817x_set_settings,
1357
+#else
1358
+ .get_link_ksettings = ax8817x_get_link_ksettings,
1359
+ .set_link_ksettings = ax8817x_set_link_ksettings,
1360
+#endif
1361
+};
1362
+
1363
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
1364
+{
1365
+ int ret;
1366
+ void *buf;
1367
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
1368
+ struct ax88772_data *ax772_data = NULL;
1369
+
1370
+ axusbnet_get_endpoints(dev, intf);
1371
+
1372
+ buf = kmalloc(6, GFP_KERNEL);
1373
+ if (!buf) {
1374
+ deverr(dev, "Cannot allocate memory for buffer");
1375
+ ret = -ENOMEM;
1376
+ goto out1;
1377
+ }
1378
+
1379
+ ax772_data = kmalloc(sizeof(*ax772_data), GFP_KERNEL);
1380
+ if (!ax772_data) {
1381
+ deverr(dev, "Cannot allocate memory for AX88772 data");
1382
+ kfree(buf);
1383
+ return -ENOMEM;
1384
+ }
1385
+
1386
+ memset(ax772_data, 0, sizeof(*ax772_data));
1387
+ dev->priv = ax772_data;
1388
+
1389
+ ax772_data->ax_work = create_singlethread_workqueue("ax88772");
1390
+ if (!ax772_data->ax_work) {
1391
+ kfree(ax772_data);
1392
+ kfree(buf);
1393
+ return -ENOMEM;
1394
+ }
1395
+
1396
+ ax772_data->dev = dev;
1397
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
1398
+ INIT_WORK(&ax772_data->check_link, ax88772_link_reset, dev);
1399
+#else
1400
+ INIT_WORK(&ax772_data->check_link, ax88772_link_reset);
1401
+#endif
1402
+
1403
+ /* reload eeprom data */
1404
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, 0x00B0, 0, 0, NULL);
1405
+ if (ret < 0)
1406
+ goto out2;
1407
+
1408
+ msleep(5);
1409
+
1410
+ /* Initialize MII structure */
1411
+ dev->mii.dev = dev->net;
1412
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
1413
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
1414
+ dev->mii.phy_id_mask = 0xff;
1415
+ dev->mii.reg_num_mask = 0xff;
1416
+
1417
+ /* Get the PHY id */
1418
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
1419
+ if (ret < 0) {
1420
+ deverr(dev, "Error reading PHY ID: %02x", ret);
1421
+ goto out2;
1422
+ } else if (ret < 2) {
1423
+ /* this should always return 2 bytes */
1424
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
1425
+ ret);
1426
+ ret = -EIO;
1427
+ goto out2;
1428
+ }
1429
+ dev->mii.phy_id = *((u8 *)buf + 1);
1430
+
1431
+ if (dev->mii.phy_id == 0x10) {
1432
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
1433
+ 0x0001, 0, 0, NULL);
1434
+ if (ret < 0) {
1435
+ deverr(dev, "Select PHY #1 failed: %d", ret);
1436
+ goto out2;
1437
+ }
1438
+
1439
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
1440
+ 0, 0, NULL);
1441
+ if (ret < 0) {
1442
+ deverr(dev, "Failed to power down PHY: %d", ret);
1443
+ goto out2;
1444
+ }
1445
+
1446
+ msleep(150);
1447
+
1448
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
1449
+ 0, 0, NULL);
1450
+ if (ret < 0) {
1451
+ deverr(dev, "Failed to perform software reset: %d",
1452
+ ret);
1453
+ goto out2;
1454
+ }
1455
+
1456
+ msleep(150);
1457
+
1458
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1459
+ AX_SWRESET_IPRL | AX_SWRESET_PRL,
1460
+ 0, 0, NULL);
1461
+ if (ret < 0) {
1462
+ deverr(dev,
1463
+ "Failed to set PHY reset control: %d", ret);
1464
+ goto out2;
1465
+ }
1466
+ } else {
1467
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
1468
+ 0x0000, 0, 0, NULL);
1469
+ if (ret < 0) {
1470
+ deverr(dev, "Select PHY #1 failed: %d", ret);
1471
+ goto out2;
1472
+ }
1473
+
1474
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1475
+ AX_SWRESET_IPPD | AX_SWRESET_PRL,
1476
+ 0, 0, NULL);
1477
+ if (ret < 0) {
1478
+ deverr(dev, "Failed to power down internal PHY: %d",
1479
+ ret);
1480
+ goto out2;
1481
+ }
1482
+ }
1483
+
1484
+ msleep(150);
1485
+
1486
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
1487
+ 0x0000, 0, 0, NULL);
1488
+ if (ret < 0) {
1489
+ deverr(dev, "Failed to reset RX_CTL: %d", ret);
1490
+ goto out2;
1491
+ }
1492
+
1493
+ /* Get the MAC address */
1494
+ memset(buf, 0, ETH_ALEN);
1495
+ ret = ax8817x_get_mac(dev, buf);
1496
+ if (ret < 0) {
1497
+ deverr(dev, "Get HW address failed: %d", ret);
1498
+ goto out2;
1499
+ }
1500
+
1501
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
1502
+ if (ret < 0) {
1503
+ deverr(dev, "Enabling software MII failed: %d", ret);
1504
+ goto out2;
1505
+ }
1506
+
1507
+ if (dev->mii.phy_id == 0x10) {
1508
+ ret = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 2);
1509
+ if (ret != 0x003b) {
1510
+ deverr(dev, "Read PHY register 2 must be 0x3b00: %d",
1511
+ ret);
1512
+ goto out2;
1513
+ }
1514
+
1515
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL,
1516
+ 0, 0, NULL);
1517
+ if (ret < 0) {
1518
+ deverr(dev, "Set external PHY reset pin level: %d",
1519
+ ret);
1520
+ goto out2;
1521
+ }
1522
+ msleep(150);
1523
+
1524
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1525
+ AX_SWRESET_IPRL | AX_SWRESET_PRL,
1526
+ 0, 0, NULL);
1527
+ if (ret < 0) {
1528
+ deverr(dev,
1529
+ "Set Internal/External PHY reset control: %d",
1530
+ ret);
1531
+ goto out2;
1532
+ }
1533
+ msleep(150);
1534
+ }
1535
+
1536
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1537
+ dev->net->do_ioctl = ax8817x_ioctl;
1538
+ dev->net->set_multicast_list = ax8817x_set_multicast;
1539
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
1540
+#else
1541
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
1542
+#endif
1543
+
1544
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
1545
+
1546
+ /* Register suspend and resume functions */
1547
+ data->suspend = ax88772_suspend;
1548
+ data->resume = ax88772_resume;
1549
+
1550
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
1551
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
1552
+ ADVERTISE_ALL | ADVERTISE_CSMA);
1553
+
1554
+ mii_nway_restart(&dev->mii);
1555
+ ax772_data->autoneg_start = jiffies;
1556
+ ax772_data->Event = WAIT_AUTONEG_COMPLETE;
1557
+
1558
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 0, 0, 0, NULL);
1559
+ if (ret < 0) {
1560
+ deverr(dev, "Write medium mode register: %d", ret);
1561
+ goto out2;
1562
+ }
1563
+
1564
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
1565
+ AX88772_IPG0_DEFAULT |
1566
+ (AX88772_IPG1_DEFAULT << 8),
1567
+ AX88772_IPG2_DEFAULT, 0, NULL);
1568
+ if (ret < 0) {
1569
+ deverr(dev, "Write IPG,IPG1,IPG2 failed: %d", ret);
1570
+ goto out2;
1571
+ }
1572
+
1573
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
1574
+ if (ret < 0) {
1575
+ deverr(dev, "Failed to set hardware MII: %02x", ret);
1576
+ goto out2;
1577
+ }
1578
+
1579
+ /* Set RX_CTL to default values with 2k buffer, and enable cactus */
1580
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0, NULL);
1581
+ if (ret < 0) {
1582
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
1583
+ goto out2;
1584
+ }
1585
+
1586
+ /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
1587
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
1588
+ /* hard_mtu is still the default - the device does not support
1589
+ jumbo eth frames */
1590
+ dev->rx_urb_size = 2048;
1591
+ }
1592
+
1593
+ kfree(buf);
1594
+ printk(version);
1595
+ return 0;
1596
+
1597
+out2:
1598
+ destroy_workqueue(ax772_data->ax_work);
1599
+ kfree(ax772_data);
1600
+ kfree(buf);
1601
+out1:
1602
+ return ret;
1603
+}
1604
+
1605
+static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
1606
+{
1607
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
1608
+
1609
+ if (ax772_data) {
1610
+ flush_workqueue(ax772_data->ax_work);
1611
+ destroy_workqueue(ax772_data->ax_work);
1612
+
1613
+ /* stop MAC operation */
1614
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, AX_RX_CTL_STOP,
1615
+ 0, 0, NULL);
1616
+
1617
+ /* Power down PHY */
1618
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
1619
+ 0, 0, NULL);
1620
+
1621
+ kfree(ax772_data);
1622
+ }
1623
+}
1624
+
1625
+static int ax88772a_phy_powerup(struct usbnet *dev)
1626
+{
1627
+ int ret;
1628
+ /* set the embedded Ethernet PHY in power-down state */
1629
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1630
+ AX_SWRESET_IPPD | AX_SWRESET_IPRL, 0, 0, NULL);
1631
+ if (ret < 0) {
1632
+ deverr(dev, "Failed to power down PHY: %d", ret);
1633
+ return ret;
1634
+ }
1635
+
1636
+ msleep(10);
1637
+
1638
+ /* set the embedded Ethernet PHY in power-up state */
1639
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL,
1640
+ 0, 0, NULL);
1641
+ if (ret < 0) {
1642
+ deverr(dev, "Failed to reset PHY: %d", ret);
1643
+ return ret;
1644
+ }
1645
+
1646
+ msleep(600);
1647
+
1648
+ /* set the embedded Ethernet PHY in reset state */
1649
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
1650
+ 0, 0, NULL);
1651
+ if (ret < 0) {
1652
+ deverr(dev, "Failed to power up PHY: %d", ret);
1653
+ return ret;
1654
+ }
1655
+
1656
+ /* set the embedded Ethernet PHY in power-up state */
1657
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL,
1658
+ 0, 0, NULL);
1659
+ if (ret < 0) {
1660
+ deverr(dev, "Failed to reset PHY: %d", ret);
1661
+ return ret;
1662
+ }
1663
+
1664
+ return 0;
1665
+}
1666
+
1667
+static int ax88772a_bind(struct usbnet *dev, struct usb_interface *intf)
1668
+{
1669
+ int ret = -EIO;
1670
+ void *buf;
1671
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
1672
+ struct ax88772a_data *ax772a_data = NULL;
1673
+
1674
+ printk(version);
1675
+
1676
+ axusbnet_get_endpoints(dev, intf);
1677
+
1678
+ buf = kmalloc(6, GFP_KERNEL);
1679
+ if (!buf) {
1680
+ deverr(dev, "Cannot allocate memory for buffer");
1681
+ ret = -ENOMEM;
1682
+ goto out1;
1683
+ }
1684
+
1685
+ ax772a_data = kmalloc(sizeof(*ax772a_data), GFP_KERNEL);
1686
+ if (!ax772a_data) {
1687
+ deverr(dev, "Cannot allocate memory for AX88772A data");
1688
+ kfree(buf);
1689
+ return -ENOMEM;
1690
+ }
1691
+ memset(ax772a_data, 0, sizeof(*ax772a_data));
1692
+ dev->priv = ax772a_data;
1693
+
1694
+ ax772a_data->ax_work = create_singlethread_workqueue("ax88772a");
1695
+ if (!ax772a_data->ax_work) {
1696
+ kfree(ax772a_data);
1697
+ kfree(buf);
1698
+ return -ENOMEM;
1699
+ }
1700
+
1701
+ ax772a_data->dev = dev;
1702
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
1703
+ INIT_WORK(&ax772a_data->check_link, ax88772a_link_reset, dev);
1704
+#else
1705
+ INIT_WORK(&ax772a_data->check_link, ax88772a_link_reset);
1706
+#endif
1707
+
1708
+ /* Get the EEPROM data*/
1709
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2,
1710
+ (void *)&ax772a_data->EepromData);
1711
+ if (ret < 0) {
1712
+ deverr(dev, "read SROM address 17h failed: %d", ret);
1713
+ goto out2;
1714
+ }
1715
+ le16_to_cpus(&ax772a_data->EepromData);
1716
+ /* End of get EEPROM data */
1717
+
1718
+ /* reload eeprom data */
1719
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
1720
+ AXGPIOS_RSE, 0, 0, NULL);
1721
+ if (ret < 0)
1722
+ goto out2;
1723
+
1724
+ msleep(5);
1725
+
1726
+ /* Initialize MII structure */
1727
+ dev->mii.dev = dev->net;
1728
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
1729
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
1730
+ dev->mii.phy_id_mask = 0xff;
1731
+ dev->mii.reg_num_mask = 0xff;
1732
+
1733
+ /* Get the PHY id */
1734
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
1735
+ if (ret < 0) {
1736
+ deverr(dev, "Error reading PHY ID: %02x", ret);
1737
+ goto out2;
1738
+ } else if (ret < 2) {
1739
+ /* this should always return 2 bytes */
1740
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
1741
+ ret);
1742
+ goto out2;
1743
+ }
1744
+ dev->mii.phy_id = *((u8 *)buf + 1);
1745
+
1746
+ if (dev->mii.phy_id != 0x10) {
1747
+ deverr(dev, "Got wrong PHY ID: %02x", dev->mii.phy_id);
1748
+ goto out2;
1749
+ }
1750
+
1751
+ /* select the embedded 10/100 Ethernet PHY */
1752
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
1753
+ AX_PHYSEL_SSEN | AX_PHYSEL_PSEL | AX_PHYSEL_SSMII,
1754
+ 0, 0, NULL);
1755
+ if (ret < 0) {
1756
+ deverr(dev, "Select PHY #1 failed: %d", ret);
1757
+ goto out2;
1758
+ }
1759
+
1760
+ ret = ax88772a_phy_powerup(dev);
1761
+ if (ret < 0)
1762
+ goto out2;
1763
+
1764
+ /* stop MAC operation */
1765
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, AX_RX_CTL_STOP,
1766
+ 0, 0, NULL);
1767
+ if (ret < 0) {
1768
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
1769
+ goto out2;
1770
+ }
1771
+
1772
+ /* Get the MAC address */
1773
+ memset(buf, 0, ETH_ALEN);
1774
+ ret = ax8817x_get_mac(dev, buf);
1775
+ if (ret < 0) {
1776
+ deverr(dev, "Get HW address failed: %d", ret);
1777
+ goto out2;
1778
+ }
1779
+
1780
+ /* make sure the driver can enable sw mii operation */
1781
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
1782
+ if (ret < 0) {
1783
+ deverr(dev, "Enabling software MII failed: %d", ret);
1784
+ goto out2;
1785
+ }
1786
+
1787
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1788
+ dev->net->do_ioctl = ax8817x_ioctl;
1789
+ dev->net->set_multicast_list = ax8817x_set_multicast;
1790
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
1791
+#else
1792
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
1793
+#endif
1794
+
1795
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
1796
+
1797
+ /* Register suspend and resume functions */
1798
+ data->suspend = ax88772_suspend;
1799
+ data->resume = ax88772_resume;
1800
+
1801
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
1802
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
1803
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
1804
+
1805
+ mii_nway_restart(&dev->mii);
1806
+ ax772a_data->autoneg_start = jiffies;
1807
+ ax772a_data->Event = WAIT_AUTONEG_COMPLETE;
1808
+
1809
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
1810
+ 0, 0, 0, NULL);
1811
+ if (ret < 0) {
1812
+ deverr(dev, "Write medium mode register: %d", ret);
1813
+ goto out2;
1814
+ }
1815
+
1816
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
1817
+ AX88772A_IPG0_DEFAULT | AX88772A_IPG1_DEFAULT << 8,
1818
+ AX88772A_IPG2_DEFAULT, 0, NULL);
1819
+ if (ret < 0) {
1820
+ deverr(dev, "Write IPG,IPG1,IPG2 failed: %d", ret);
1821
+ goto out2;
1822
+ }
1823
+
1824
+ memset(buf, 0, 4);
1825
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_IPG012, 0, 0, 3, buf);
1826
+ *((u8 *)buf + 3) = 0x00;
1827
+ if (ret < 0) {
1828
+ deverr(dev, "Failed to read IPG,IPG1,IPG2 failed: %d", ret);
1829
+ goto out2;
1830
+ } else {
1831
+ __u32 tmp32 = *((u32*)buf);
1832
+ le32_to_cpus(&tmp32);
1833
+ if (tmp32 != (AX88772A_IPG2_DEFAULT << 16 |
1834
+ AX88772A_IPG1_DEFAULT << 8 | AX88772A_IPG0_DEFAULT)) {
1835
+ printk("Non-authentic ASIX product\nASIX does not support it\n");
1836
+ ret = -ENODEV;
1837
+ goto out2;
1838
+ }
1839
+ }
1840
+
1841
+ /* Set RX_CTL to default values with 2k buffer, and enable cactus */
1842
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
1843
+ (AX_RX_CTL_START | AX_RX_CTL_AB),
1844
+ 0, 0, NULL);
1845
+ if (ret < 0) {
1846
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
1847
+ goto out2;
1848
+ }
1849
+
1850
+ /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
1851
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
1852
+ /* hard_mtu is still the default - the device does not support
1853
+ jumbo eth frames */
1854
+ dev->rx_urb_size = 2048;
1855
+ }
1856
+
1857
+ kfree(buf);
1858
+
1859
+ return ret;
1860
+out2:
1861
+ destroy_workqueue(ax772a_data->ax_work);
1862
+ kfree(ax772a_data);
1863
+ kfree(buf);
1864
+out1:
1865
+ return ret;
1866
+}
1867
+
1868
+static void ax88772a_unbind(struct usbnet *dev, struct usb_interface *intf)
1869
+{
1870
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
1871
+
1872
+ if (ax772a_data) {
1873
+
1874
+ flush_workqueue(ax772a_data->ax_work);
1875
+ destroy_workqueue(ax772a_data->ax_work);
1876
+
1877
+ /* stop MAC operation */
1878
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
1879
+ AX_RX_CTL_STOP, 0, 0, NULL);
1880
+
1881
+ /* Power down PHY */
1882
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
1883
+ AX_SWRESET_IPPD, 0, 0, NULL);
1884
+
1885
+ kfree(ax772a_data);
1886
+ }
1887
+}
1888
+
1889
+static int ax88772b_set_csums(struct usbnet *dev)
1890
+{
1891
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
1892
+ u16 checksum;
1893
+
1894
+ if (ax772b_data->checksum & AX_RX_CHECKSUM)
1895
+ checksum = AX_RXCOE_DEF_CSUM;
1896
+ else
1897
+ checksum = 0;
1898
+
1899
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RXCOE_CTL,
1900
+ checksum, 0, 0, NULL);
1901
+
1902
+ if (ax772b_data->checksum & AX_TX_CHECKSUM)
1903
+ checksum = AX_TXCOE_DEF_CSUM;
1904
+ else
1905
+ checksum = 0;
1906
+
1907
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_TXCOE_CTL,
1908
+ checksum, 0, 0, NULL);
1909
+
1910
+ return 0;
1911
+}
1912
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
1913
+static u32 ax88772b_get_tx_csum(struct net_device *netdev)
1914
+{
1915
+ struct usbnet *dev = netdev_priv(netdev);
1916
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
1917
+
1918
+ return ax772b_data->checksum & AX_TX_CHECKSUM;
1919
+}
1920
+
1921
+static u32 ax88772b_get_rx_csum(struct net_device *netdev)
1922
+{
1923
+ struct usbnet *dev = netdev_priv(netdev);
1924
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
1925
+
1926
+ return ax772b_data->checksum & AX_RX_CHECKSUM;
1927
+}
1928
+
1929
+static int ax88772b_set_rx_csum(struct net_device *netdev, u32 val)
1930
+{
1931
+ struct usbnet *dev = netdev_priv(netdev);
1932
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
1933
+
1934
+ if (val)
1935
+ ax772b_data->checksum |= AX_RX_CHECKSUM;
1936
+ else
1937
+ ax772b_data->checksum &= ~AX_RX_CHECKSUM;
1938
+
1939
+ return ax88772b_set_csums(dev);
1940
+}
1941
+
1942
+static int ax88772b_set_tx_csum(struct net_device *netdev, u32 val)
1943
+{
1944
+ struct usbnet *dev = netdev_priv(netdev);
1945
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
1946
+
1947
+ if (val)
1948
+ ax772b_data->checksum |= AX_TX_CHECKSUM;
1949
+ else
1950
+ ax772b_data->checksum &= ~AX_TX_CHECKSUM;
1951
+
1952
+ ethtool_op_set_tx_csum(netdev, val);
1953
+
1954
+ return ax88772b_set_csums(dev);
1955
+}
1956
+#endif
1957
+static struct ethtool_ops ax88772b_ethtool_ops = {
1958
+ .get_drvinfo = ax8817x_get_drvinfo,
1959
+ .get_link = ethtool_op_get_link,
1960
+ .get_msglevel = axusbnet_get_msglevel,
1961
+ .set_msglevel = axusbnet_set_msglevel,
1962
+ .get_wol = ax8817x_get_wol,
1963
+ .set_wol = ax8817x_set_wol,
1964
+ .get_eeprom_len = ax8817x_get_eeprom_len,
1965
+ .get_eeprom = ax8817x_get_eeprom,
1966
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1967
+ .get_settings = ax8817x_get_settings,
1968
+ .set_settings = ax8817x_set_settings,
1969
+#else
1970
+ .get_link_ksettings = ax8817x_get_link_ksettings,
1971
+ .set_link_ksettings = ax8817x_set_link_ksettings,
1972
+#endif
1973
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
1974
+ .set_tx_csum = ax88772b_set_tx_csum,
1975
+ .get_tx_csum = ax88772b_get_tx_csum,
1976
+ .get_rx_csum = ax88772b_get_rx_csum,
1977
+ .set_rx_csum = ax88772b_set_rx_csum,
1978
+#endif
1979
+};
1980
+
1981
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1982
+static const struct net_device_ops ax88772b_netdev_ops = {
1983
+ .ndo_open = axusbnet_open,
1984
+ .ndo_stop = axusbnet_stop,
1985
+ .ndo_start_xmit = axusbnet_start_xmit,
1986
+ .ndo_tx_timeout = axusbnet_tx_timeout,
1987
+ .ndo_change_mtu = axusbnet_change_mtu,
1988
+ .ndo_do_ioctl = ax8817x_ioctl,
1989
+ .ndo_get_stats = axusbnet_get_stats,
1990
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
1991
+ .ndo_validate_addr = eth_validate_addr,
1992
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 2, 0)
1993
+ .ndo_set_multicast_list = ax88772b_set_multicast,
1994
+#else
1995
+ .ndo_set_rx_mode = ax88772b_set_multicast,
1996
+#endif
1997
+};
1998
+#endif
1999
+
2000
+static int ax88772b_bind(struct usbnet *dev, struct usb_interface *intf)
2001
+{
2002
+ int ret;
2003
+ void *buf;
2004
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
2005
+ struct ax88772b_data *ax772b_data;
2006
+ u16 *tmp16;
2007
+ u8 *tmp8;
2008
+ u8 tempphyselect;
2009
+ bool internalphy;
2010
+
2011
+ printk(version);
2012
+ axusbnet_get_endpoints(dev, intf);
2013
+ buf = kmalloc(6, GFP_KERNEL);
2014
+ if (!buf) {
2015
+ deverr(dev, "Cannot allocate memory for buffer");
2016
+ return -ENOMEM;
2017
+ }
2018
+ tmp16 = (u16 *)buf;
2019
+ ax772b_data = kmalloc(sizeof(*ax772b_data), GFP_KERNEL);
2020
+ if (!ax772b_data) {
2021
+ deverr(dev, "Cannot allocate memory for AX88772B data");
2022
+ kfree(buf);
2023
+ return -ENOMEM;
2024
+ }
2025
+ memset(ax772b_data, 0, sizeof(*ax772b_data));
2026
+ dev->priv = ax772b_data;
2027
+ ax772b_data->ax_work = create_singlethread_workqueue("ax88772b");
2028
+ if (!ax772b_data->ax_work) {
2029
+ kfree(buf);
2030
+ kfree(ax772b_data);
2031
+ return -ENOMEM;
2032
+ }
2033
+
2034
+ ax772b_data->dev = dev;
2035
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
2036
+ INIT_WORK(&ax772b_data->check_link, ax88772b_link_reset, dev);
2037
+#else
2038
+ INIT_WORK(&ax772b_data->check_link, ax88772b_link_reset);
2039
+#endif
2040
+
2041
+ tmp8 = (u8 *)buf;
2042
+ ret = ax8817x_read_cmd(dev, AX_CMD_SW_PHY_STATUS,
2043
+ 0, 0, 1, tmp8);
2044
+
2045
+ if (ret < 0) {
2046
+ deverr(dev,
2047
+ "read SW interface selection status register failed: %d\n",
2048
+ ret);
2049
+ goto err_out;
2050
+ }
2051
+ tempphyselect = *tmp8;
2052
+ tempphyselect &= 0x0C;
2053
+
2054
+ if (tempphyselect == AX_PHYSEL_SSRMII) {
2055
+ internalphy = false;
2056
+ ax772b_data->OperationMode = OPERATION_MAC_MODE;
2057
+ ax772b_data->PhySelect = 0x00;
2058
+ } else if (tempphyselect == AX_PHYSEL_SSRRMII) {
2059
+ internalphy = true;
2060
+ ax772b_data->OperationMode = OPERATION_PHY_MODE;
2061
+ ax772b_data->PhySelect = 0x00;
2062
+ } else if (tempphyselect == AX_PHYSEL_SSMII) {
2063
+ internalphy = true;
2064
+ ax772b_data->OperationMode = OPERATION_MAC_MODE;
2065
+ ax772b_data->PhySelect = 0x01;
2066
+ } else {
2067
+ deverr(dev, "Unknown MII type\n");
2068
+ goto err_out;
2069
+ }
2070
+
2071
+ /* reload eeprom data */
2072
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_RSE,
2073
+ 0, 0, NULL);
2074
+ if (ret < 0) {
2075
+ deverr(dev, "Failed to enable GPIO function: %d", ret);
2076
+ goto err_out;
2077
+ }
2078
+ msleep(5);
2079
+
2080
+ /* Get the EEPROM data*/
2081
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 0x18, 0, 2,
2082
+ (void *)tmp16);
2083
+ if (ret < 0) {
2084
+ deverr(dev, "read SROM address 18h failed: %d", ret);
2085
+ goto err_out;
2086
+ }
2087
+ le16_to_cpus(tmp16);
2088
+ ax772b_data->psc = *tmp16 & 0xFF00;
2089
+ /* End of get EEPROM data */
2090
+
2091
+ /* Get the MAC address */
2092
+ memset(buf, 0, ETH_ALEN);
2093
+ ret = ax8817x_get_mac(dev, buf);
2094
+ if (ret < 0) {
2095
+ deverr(dev, "Get HW address failed: %d", ret);
2096
+ goto err_out;
2097
+ }
2098
+
2099
+ /* Initialize MII structure */
2100
+ dev->mii.dev = dev->net;
2101
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
2102
+ dev->mii.mdio_write = ax88772b_mdio_write_le;
2103
+ dev->mii.phy_id_mask = 0xff;
2104
+ dev->mii.reg_num_mask = 0xff;
2105
+
2106
+ /* Get the PHY id */
2107
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
2108
+ if (ret < 0) {
2109
+ deverr(dev, "Error reading PHY ID: %02x", ret);
2110
+ goto err_out;
2111
+ } else if (ret < 2) {
2112
+ /* this should always return 2 bytes */
2113
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
2114
+ ret);
2115
+ ret = -EIO;
2116
+ goto err_out;
2117
+ }
2118
+
2119
+ if (internalphy)
2120
+ dev->mii.phy_id = *((u8 *)buf + 1);
2121
+ else
2122
+ dev->mii.phy_id = *((u8 *)buf);
2123
+
2124
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
2125
+ ax772b_data->PhySelect, 0, 0, NULL);
2126
+ if (ret < 0) {
2127
+ deverr(dev, "Select PHY #1 failed: %d", ret);
2128
+ goto err_out;
2129
+ }
2130
+
2131
+#if 0
2132
+ /* select the embedded 10/100 Ethernet PHY */
2133
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
2134
+ AX_PHYSEL_SSEN | AX_PHYSEL_PSEL | AX_PHYSEL_SSMII,
2135
+ 0, 0, NULL);
2136
+ if (ret < 0) {
2137
+ deverr(dev, "Select PHY #1 failed: %d", ret);
2138
+ goto err_out;
2139
+ }
2140
+
2141
+ if (dev->mii.phy_id != 0x10) {
2142
+ deverr(dev, "Got wrong PHY ID: %02x", dev->mii.phy_id);
2143
+ ret = -EIO;
2144
+ goto err_out;
2145
+ }
2146
+#endif
2147
+ ret = ax88772a_phy_powerup(dev);
2148
+ if (ret < 0)
2149
+ goto err_out;
2150
+
2151
+ /* stop MAC operation */
2152
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
2153
+ AX_RX_CTL_STOP, 0, 0, NULL);
2154
+ if (ret < 0) {
2155
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2156
+ goto err_out;
2157
+ }
2158
+
2159
+ /* make sure the driver can enable sw mii operation */
2160
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
2161
+ if (ret < 0) {
2162
+ deverr(dev, "Enabling software MII failed: %d", ret);
2163
+ goto err_out;
2164
+ }
2165
+
2166
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
2167
+ dev->net->do_ioctl = ax8817x_ioctl;
2168
+ dev->net->set_multicast_list = ax88772b_set_multicast;
2169
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
2170
+#else
2171
+ dev->net->netdev_ops = &ax88772b_netdev_ops;
2172
+#endif
2173
+
2174
+ dev->net->ethtool_ops = &ax88772b_ethtool_ops;
2175
+
2176
+ /* Register suspend and resume functions */
2177
+ data->suspend = ax88772b_suspend;
2178
+ data->resume = ax88772b_resume;
2179
+
2180
+ if ((ax772b_data->OperationMode == OPERATION_MAC_MODE) &&
2181
+ (ax772b_data->PhySelect == 0x00)) {
2182
+ if (ax88772b_external_phyinit(dev) != 0x00) {
2183
+ deverr(dev, "Failed to initial the external phy");
2184
+ goto err_out;
2185
+ }
2186
+ }
2187
+
2188
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
2189
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id
2190
+ , MII_BMCR, 0x3900);
2191
+
2192
+ if (dev->mii.phy_id != 0x10)
2193
+ ax8817x_mdio_write_le(dev->net, 0x10, MII_BMCR, 0x3900);
2194
+
2195
+ if (dev->mii.phy_id == 0x10 && ax772b_data->OperationMode
2196
+ != OPERATION_PHY_MODE) {
2197
+
2198
+ *tmp16 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
2199
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, 0x12,
2200
+ ((*tmp16 & 0xFF9F) | 0x0040));
2201
+ }
2202
+
2203
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
2204
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
2205
+
2206
+ mii_nway_restart(&dev->mii);
2207
+
2208
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
2209
+ 0, 0, 0, NULL);
2210
+ if (ret < 0) {
2211
+ deverr(dev, "Failed to write medium mode: %d", ret);
2212
+ goto err_out;
2213
+ }
2214
+
2215
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
2216
+ AX88772A_IPG0_DEFAULT | AX88772A_IPG1_DEFAULT << 8,
2217
+ AX88772A_IPG2_DEFAULT, 0, NULL);
2218
+ if (ret < 0) {
2219
+ deverr(dev, "Failed to write interframe gap: %d", ret);
2220
+ goto err_out;
2221
+ }
2222
+
2223
+ memset(buf, 0, 4);
2224
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_IPG012, 0, 0, 3, buf);
2225
+ *((u8 *)buf + 3) = 0x00;
2226
+ if (ret < 0) {
2227
+ deverr(dev, "Failed to read IPG,IPG1,IPG2 failed: %d", ret);
2228
+ goto err_out;
2229
+ } else {
2230
+ __u32 tmp32 = *((u32*)buf);
2231
+ le32_to_cpus(&tmp32);
2232
+ if (tmp32 != (AX88772A_IPG2_DEFAULT << 16 |
2233
+ AX88772A_IPG1_DEFAULT << 8 | AX88772A_IPG0_DEFAULT)) {
2234
+ printk("Non-authentic ASIX product\nASIX does not support it\n");
2235
+ ret = -ENODEV;
2236
+ goto err_out;
2237
+ }
2238
+ }
2239
+
2240
+ dev->net->features |= NETIF_F_IP_CSUM;
2241
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
2242
+ dev->net->features |= NETIF_F_IPV6_CSUM;
2243
+#endif
2244
+
2245
+ ax772b_data->checksum = AX_RX_CHECKSUM | AX_TX_CHECKSUM;
2246
+ ret = ax88772b_set_csums(dev);
2247
+ if (ret < 0) {
2248
+ deverr(dev, "Write RX_COE/TX_COE failed: %d", ret);
2249
+ goto err_out;
2250
+ }
2251
+
2252
+ dev->rx_size = bsize & 0x07;
2253
+ if (dev->udev->speed == USB_SPEED_HIGH) {
2254
+
2255
+ ret = ax8817x_write_cmd(dev, 0x2A,
2256
+ AX88772B_BULKIN_SIZE[dev->rx_size].byte_cnt,
2257
+ AX88772B_BULKIN_SIZE[dev->rx_size].threshold,
2258
+ 0, NULL);
2259
+ if (ret < 0) {
2260
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2261
+ goto err_out;
2262
+ }
2263
+
2264
+ dev->rx_urb_size = AX88772B_BULKIN_SIZE[dev->rx_size].size;
2265
+ } else {
2266
+ ret = ax8817x_write_cmd(dev, 0x2A,
2267
+ 0x8000, 0x8001, 0, NULL);
2268
+ if (ret < 0) {
2269
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2270
+ goto err_out;
2271
+ }
2272
+ dev->rx_urb_size = 2048;
2273
+ }
2274
+
2275
+ /* Configure RX header type */
2276
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
2277
+ (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_HEADER_DEFAULT),
2278
+ 0, 0, NULL);
2279
+ if (ret < 0) {
2280
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
2281
+ goto err_out;
2282
+ }
2283
+
2284
+ /* Overwrite power saving configuration from eeprom */
2285
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL |
2286
+ (ax772b_data->psc & 0x7FFF), 0, 0, NULL);
2287
+
2288
+ if (ret < 0) {
2289
+ deverr(dev, "Failed to configure PHY power saving: %d", ret);
2290
+ goto err_out;
2291
+ }
2292
+
2293
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
2294
+ netif_carrier_on(dev->net);
2295
+
2296
+ kfree(buf);
2297
+
2298
+ return ret;
2299
+err_out:
2300
+ destroy_workqueue(ax772b_data->ax_work);
2301
+ kfree(buf);
2302
+ kfree(ax772b_data);
2303
+ return ret;
2304
+}
2305
+
2306
+static int ax88772b_external_phyinit(struct usbnet *dev) {
2307
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2308
+ u16 phyid1, phyid2;
2309
+
2310
+ phyid1 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x02);
2311
+ phyid2 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x03);
2312
+ ax772b_data->ext_phy_oui = EXTPHY_ID_MASK_OUI(phyid1, phyid2);
2313
+ ax772b_data->ext_phy_model = EXTPHY_ID_MASK_MODEL(phyid2);
2314
+
2315
+ if (ax772b_data->ext_phy_oui == EXTPHY_BROADCOM_OUI) {
2316
+ if(ax772b_data->ext_phy_model == EXTPHY_BCM89811_MODEL) {
2317
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x0, 0x8000);
2318
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2319
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2320
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2321
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2322
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2323
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2324
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1F, 0x0c00);
2325
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1E, 0x030A);
2326
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1F, 0x3440);
2327
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1E, 0x0166);
2328
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1F, 0x0020);
2329
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x012D);
2330
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x9B52);
2331
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x012E);
2332
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0xA04D);
2333
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0123);
2334
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x00c0);
2335
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0154);
2336
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x81C4);
2337
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0811);
2338
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0000);
2339
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x01D3);
2340
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0064);
2341
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x01C1);
2342
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0xA5F7);
2343
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0028);
2344
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0400);
2345
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x001D);
2346
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x3411);
2347
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0820);
2348
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0401);
2349
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x002F);
2350
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0xF167);
2351
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1e, 0x0045);
2352
+ ax88772b_mdio_write_le(dev->net, dev->mii.phy_id, 0x1f, 0x0500);
2353
+ return 0;
2354
+ }
2355
+ }
2356
+
2357
+ return 0;
2358
+}
2359
+
2360
+static void ax88772b_unbind(struct usbnet *dev, struct usb_interface *intf)
2361
+{
2362
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
2363
+
2364
+ if (ax772b_data) {
2365
+
2366
+ flush_workqueue(ax772b_data->ax_work);
2367
+ destroy_workqueue(ax772b_data->ax_work);
2368
+
2369
+ /* stop MAC operation */
2370
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
2371
+ AX_RX_CTL_STOP, 0, 0, NULL);
2372
+
2373
+ /* Power down PHY */
2374
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
2375
+ AX_SWRESET_IPPD, 0, 0, NULL);
2376
+
2377
+ kfree(ax772b_data);
2378
+ }
2379
+}
2380
+
2381
+static int
2382
+ax88178_media_check(struct usbnet *dev, struct ax88178_data *ax178dataptr)
2383
+{
2384
+ int fullduplex, i = 0;
2385
+ u16 tempshort = 0;
2386
+ u16 media;
2387
+ u16 advertise, lpa, result, stat1000, _lpa, _stat1000, delay = 5 * HZ;
2388
+ unsigned long jtimeout;
2389
+
2390
+ jtimeout = jiffies + delay;
2391
+ do {
2392
+ _lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
2393
+ _stat1000 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
2394
+ MII_STAT1000);
2395
+
2396
+ lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
2397
+ stat1000 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
2398
+ MII_STAT1000);
2399
+
2400
+ if (time_after(jiffies, jtimeout))
2401
+ break;
2402
+
2403
+ } while ((_lpa != lpa) || (_stat1000 != stat1000) || i++ < 3);
2404
+
2405
+ advertise = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
2406
+ MII_ADVERTISE);
2407
+ result = advertise & lpa;
2408
+
2409
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2410
+ (ax178dataptr->LedMode == 1)) {
2411
+ tempshort = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
2412
+ MARVELL_MANUAL_LED) & 0xfc0f;
2413
+ }
2414
+
2415
+ fullduplex = 1;
2416
+ if (stat1000 & LPA_1000FULL) {
2417
+ media = MEDIUM_GIGA_MODE | MEDIUM_FULL_DUPLEX_MODE |
2418
+ MEDIUM_ENABLE_125MHZ | MEDIUM_ENABLE_RECEIVE;
2419
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2420
+ (ax178dataptr->LedMode == 1))
2421
+ tempshort |= 0x3e0;
2422
+ } else if (result & LPA_100FULL) {
2423
+ media = MEDIUM_FULL_DUPLEX_MODE | MEDIUM_ENABLE_RECEIVE |
2424
+ MEDIUM_MII_100M_MODE;
2425
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2426
+ (ax178dataptr->LedMode == 1))
2427
+ tempshort |= 0x3b0;
2428
+ } else if (result & LPA_100HALF) {
2429
+ fullduplex = 0;
2430
+ media = MEDIUM_ENABLE_RECEIVE | MEDIUM_MII_100M_MODE;
2431
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2432
+ (ax178dataptr->LedMode == 1))
2433
+ tempshort |= 0x3b0;
2434
+ } else if (result & LPA_10FULL) {
2435
+ media = MEDIUM_FULL_DUPLEX_MODE | MEDIUM_ENABLE_RECEIVE;
2436
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2437
+ (ax178dataptr->LedMode == 1))
2438
+ tempshort |= 0x2f0;
2439
+ } else {
2440
+ media = MEDIUM_ENABLE_RECEIVE;
2441
+ fullduplex = 0;
2442
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2443
+ (ax178dataptr->LedMode == 1))
2444
+ tempshort |= 0x02f0;
2445
+ }
2446
+
2447
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
2448
+ (ax178dataptr->LedMode == 1)) {
2449
+ ax8817x_mdio_write_le(dev->net,
2450
+ dev->mii.phy_id, MARVELL_MANUAL_LED, tempshort);
2451
+ }
2452
+
2453
+ media |= 0x0004;
2454
+ if (ax178dataptr->UseRgmii)
2455
+ media |= 0x0008;
2456
+ if (fullduplex) {
2457
+ media |= 0x0020; /* ebable tx flow control as default; */
2458
+ media |= 0x0010; /* ebable rx flow control as default; */
2459
+ }
2460
+
2461
+ return media;
2462
+}
2463
+
2464
+static void Vitess_8601_Init(struct usbnet *dev, int state)
2465
+{
2466
+ u16 reg;
2467
+
2468
+ switch (state) {
2469
+ case 0: /* tx, rx clock skew */
2470
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 31, 1);
2471
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 28, 0);
2472
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 31, 0);
2473
+ break;
2474
+
2475
+ case 1:
2476
+ ax8817x_swmii_mdio_write_le(dev->net,
2477
+ dev->mii.phy_id, 31, 0x52B5);
2478
+ ax8817x_swmii_mdio_write_le(dev->net,
2479
+ dev->mii.phy_id, 18, 0x009E);
2480
+ ax8817x_swmii_mdio_write_le(dev->net,
2481
+ dev->mii.phy_id, 17, 0xDD39);
2482
+ ax8817x_swmii_mdio_write_le(dev->net,
2483
+ dev->mii.phy_id, 16, 0x87AA);
2484
+
2485
+ ax8817x_swmii_mdio_write_le(dev->net,
2486
+ dev->mii.phy_id, 16, 0xA7B4);
2487
+
2488
+ ax8817x_swmii_mdio_write_le(dev->net,
2489
+ dev->mii.phy_id, 18,
2490
+ ax8817x_swmii_mdio_read_le(dev->net,
2491
+ dev->mii.phy_id, 18));
2492
+
2493
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2494
+ dev->mii.phy_id, 17) & ~0x003f) | 0x003c;
2495
+ ax8817x_swmii_mdio_write_le(dev->net,
2496
+ dev->mii.phy_id, 17, reg);
2497
+ ax8817x_swmii_mdio_write_le(dev->net,
2498
+ dev->mii.phy_id, 16, 0x87B4);
2499
+
2500
+ ax8817x_swmii_mdio_write_le(dev->net,
2501
+ dev->mii.phy_id, 16, 0xa794);
2502
+
2503
+ ax8817x_swmii_mdio_write_le(dev->net,
2504
+ dev->mii.phy_id, 18,
2505
+ ax8817x_swmii_mdio_read_le(dev->net,
2506
+ dev->mii.phy_id, 18));
2507
+
2508
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2509
+ dev->mii.phy_id, 17) & ~0x003f) | 0x003e;
2510
+ ax8817x_swmii_mdio_write_le(dev->net,
2511
+ dev->mii.phy_id, 17, reg);
2512
+ ax8817x_swmii_mdio_write_le(dev->net,
2513
+ dev->mii.phy_id, 16, 0x8794);
2514
+
2515
+ ax8817x_swmii_mdio_write_le(dev->net,
2516
+ dev->mii.phy_id, 18, 0x00f7);
2517
+ ax8817x_swmii_mdio_write_le(dev->net,
2518
+ dev->mii.phy_id, 17, 0xbe36);
2519
+ ax8817x_swmii_mdio_write_le(dev->net,
2520
+ dev->mii.phy_id, 16, 0x879e);
2521
+
2522
+ ax8817x_swmii_mdio_write_le(dev->net,
2523
+ dev->mii.phy_id, 16, 0xa7a0);
2524
+
2525
+ ax8817x_swmii_mdio_write_le(dev->net,
2526
+ dev->mii.phy_id, 18,
2527
+ ax8817x_swmii_mdio_read_le(dev->net,
2528
+ dev->mii.phy_id, 18));
2529
+
2530
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2531
+ dev->mii.phy_id, 17) & ~0x003f) | 0x0034;
2532
+ ax8817x_swmii_mdio_write_le(dev->net,
2533
+ dev->mii.phy_id, 17, reg);
2534
+ ax8817x_swmii_mdio_write_le(dev->net,
2535
+ dev->mii.phy_id, 16, 0x87a0);
2536
+
2537
+ ax8817x_swmii_mdio_write_le(dev->net,
2538
+ dev->mii.phy_id, 18, 0x003c);
2539
+ ax8817x_swmii_mdio_write_le(dev->net,
2540
+ dev->mii.phy_id, 17, 0xf3cf);
2541
+ ax8817x_swmii_mdio_write_le(dev->net,
2542
+ dev->mii.phy_id, 16, 0x87a2);
2543
+
2544
+ ax8817x_swmii_mdio_write_le(dev->net,
2545
+ dev->mii.phy_id, 18, 0x003c);
2546
+ ax8817x_swmii_mdio_write_le(dev->net,
2547
+ dev->mii.phy_id, 17, 0xf3cf);
2548
+ ax8817x_swmii_mdio_write_le(dev->net,
2549
+ dev->mii.phy_id, 16, 0x87a4);
2550
+
2551
+ ax8817x_swmii_mdio_write_le(dev->net,
2552
+ dev->mii.phy_id, 18, 0x003c);
2553
+ ax8817x_swmii_mdio_write_le(dev->net,
2554
+ dev->mii.phy_id, 17, 0xd287);
2555
+ ax8817x_swmii_mdio_write_le(dev->net,
2556
+ dev->mii.phy_id, 16, 0x87a6);
2557
+
2558
+ ax8817x_swmii_mdio_write_le(dev->net,
2559
+ dev->mii.phy_id, 16, 0xa7a8);
2560
+
2561
+ ax8817x_swmii_mdio_write_le(dev->net,
2562
+ dev->mii.phy_id, 18,
2563
+ ax8817x_swmii_mdio_read_le(dev->net,
2564
+ dev->mii.phy_id, 18));
2565
+
2566
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2567
+ dev->mii.phy_id, 17) & ~0x0fff) | 0x0125;
2568
+ ax8817x_swmii_mdio_write_le(dev->net,
2569
+ dev->mii.phy_id, 17, reg);
2570
+ ax8817x_swmii_mdio_write_le(dev->net,
2571
+ dev->mii.phy_id, 16, 0x87a8);
2572
+
2573
+ /* Enable Smart Pre-emphasis */
2574
+ ax8817x_swmii_mdio_write_le(dev->net,
2575
+ dev->mii.phy_id, 16, 0xa7fa);
2576
+
2577
+ ax8817x_swmii_mdio_write_le(dev->net,
2578
+ dev->mii.phy_id, 18,
2579
+ ax8817x_swmii_mdio_read_le(dev->net,
2580
+ dev->mii.phy_id, 18));
2581
+
2582
+ reg = (ax8817x_swmii_mdio_read_le(dev->net,
2583
+ dev->mii.phy_id, 17) & ~0x0008) | 0x0008;
2584
+
2585
+ ax8817x_swmii_mdio_write_le(dev->net,
2586
+ dev->mii.phy_id, 17, reg);
2587
+ ax8817x_swmii_mdio_write_le(dev->net,
2588
+ dev->mii.phy_id, 16, 0x87fa);
2589
+
2590
+ ax8817x_swmii_mdio_write_le(dev->net,
2591
+ dev->mii.phy_id, 31, 0);
2592
+
2593
+ break;
2594
+ }
2595
+}
2596
+
2597
+static void
2598
+marvell_88E1510_magic_init(struct usbnet *dev)
2599
+{
2600
+ ax8817x_swmii_mdio_write_le(dev->net,
2601
+ dev->mii.phy_id, 22, 0xff);
2602
+ ax8817x_swmii_mdio_write_le(dev->net,
2603
+ dev->mii.phy_id, 17, 0x214b);
2604
+ ax8817x_swmii_mdio_write_le(dev->net,
2605
+ dev->mii.phy_id, 16, 0x2144);
2606
+ ax8817x_swmii_mdio_write_le(dev->net,
2607
+ dev->mii.phy_id, 17, 0x0c28);
2608
+ ax8817x_swmii_mdio_write_le(dev->net,
2609
+ dev->mii.phy_id, 16, 0x2146);
2610
+ ax8817x_swmii_mdio_write_le(dev->net,
2611
+ dev->mii.phy_id, 17, 0xb233);
2612
+ ax8817x_swmii_mdio_write_le(dev->net,
2613
+ dev->mii.phy_id, 16, 0x214d);
2614
+ ax8817x_swmii_mdio_write_le(dev->net,
2615
+ dev->mii.phy_id, 17, 0xcc0c);
2616
+ ax8817x_swmii_mdio_write_le(dev->net,
2617
+ dev->mii.phy_id, 16, 0x2159);
2618
+ ax8817x_swmii_mdio_write_le(dev->net,
2619
+ dev->mii.phy_id, 22, 0x00fb);
2620
+ ax8817x_swmii_mdio_write_le(dev->net,
2621
+ dev->mii.phy_id, 7, 0xc00d);
2622
+ ax8817x_swmii_mdio_write_le(dev->net,
2623
+ dev->mii.phy_id, 22, 0);
2624
+}
2625
+
2626
+static int
2627
+ax88178_phy_init(struct usbnet *dev, struct ax88178_data *ax178dataptr)
2628
+{
2629
+ int i;
2630
+ u16 phyanar, phyauxctrl, phyctrl, tempshort, phyid1;
2631
+ u16 phyreg = 0;
2632
+
2633
+ /* Disable MII operation of AX88178 Hardware */
2634
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
2635
+
2636
+
2637
+ /* Read SROM - MiiPhy Address (ID) */
2638
+ ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, &dev->mii.phy_id);
2639
+ le32_to_cpus(&dev->mii.phy_id);
2640
+
2641
+ /* Initialize MII structure */
2642
+ dev->mii.phy_id >>= 8;
2643
+ dev->mii.phy_id &= PHY_ID_MASK;
2644
+ dev->mii.dev = dev->net;
2645
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
2646
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
2647
+ dev->mii.phy_id_mask = 0x3f;
2648
+ dev->mii.reg_num_mask = 0x1f;
2649
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 11)
2650
+ dev->mii.supports_gmii = 1;
2651
+#endif
2652
+
2653
+ if (ax178dataptr->PhyMode == PHY_MODE_MAC_TO_MAC_GMII) {
2654
+ ax178dataptr->UseRgmii = 0;
2655
+ ax178dataptr->MediaLink = MEDIUM_GIGA_MODE |
2656
+ MEDIUM_FULL_DUPLEX_MODE |
2657
+ MEDIUM_ENABLE_125MHZ |
2658
+ MEDIUM_ENABLE_RECEIVE |
2659
+ MEDIUM_ENABLE_RX_FLOWCTRL |
2660
+ MEDIUM_ENABLE_TX_FLOWCTRL;
2661
+ goto SKIPPHYSETTING;
2662
+ }
2663
+
2664
+ /* test read phy register 2 */
2665
+ if (!ax178dataptr->UseGpio0) {
2666
+ i = 1000;
2667
+ while (i--) {
2668
+ phyid1 = ax8817x_swmii_mdio_read_le(dev->net,
2669
+ dev->mii.phy_id, GMII_PHY_OUI);
2670
+ if ((phyid1 == 0x000f) || (phyid1 == 0x0141) ||
2671
+ (phyid1 == 0x0282) || (phyid1 == 0x004d) ||
2672
+ (phyid1 == 0x0243) || (phyid1 == 0x001C) ||
2673
+ (phyid1 == 0x0007))
2674
+ break;
2675
+ msleep(5);
2676
+ }
2677
+ if (i < 0)
2678
+ return -EIO;
2679
+ }
2680
+
2681
+ ax178dataptr->UseRgmii = 0;
2682
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
2683
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
2684
+ dev->mii.phy_id, 27);
2685
+ if (!(phyreg & 4) && !(ax178dataptr->LedMode & 0x10)) {
2686
+ ax178dataptr->UseRgmii = 1;
2687
+ ax8817x_swmii_mdio_write_le(dev->net,
2688
+ dev->mii.phy_id, 20, 0x82);
2689
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2690
+ } else if (ax178dataptr->LedMode & 0x10) {
2691
+
2692
+ ax178dataptr->UseRgmii = 1;
2693
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2694
+ marvell_88E1510_magic_init(dev);
2695
+
2696
+ ax8817x_swmii_mdio_write_le(dev->net,
2697
+ dev->mii.phy_id, 22, 2);
2698
+
2699
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
2700
+ dev->mii.phy_id, 21);
2701
+
2702
+ ax8817x_swmii_mdio_write_le(dev->net,
2703
+ dev->mii.phy_id, 21, phyreg | 0x30);
2704
+
2705
+ ax8817x_swmii_mdio_write_le(dev->net,
2706
+ dev->mii.phy_id, 22, 0);
2707
+ }
2708
+ } else if ((ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) ||
2709
+ (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0_GMII)) {
2710
+ if (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) {
2711
+ ax178dataptr->UseRgmii = 1;
2712
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2713
+ }
2714
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V1) {
2715
+ /* not Cameo */
2716
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode) {
2717
+ ax178dataptr->UseRgmii = 1;
2718
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2719
+ }
2720
+
2721
+ for (i = 0; i < (sizeof(CICADA_FAMILY_HWINIT) /
2722
+ sizeof(CICADA_FAMILY_HWINIT[0])); i++) {
2723
+ ax8817x_swmii_mdio_write_le(dev->net,
2724
+ dev->mii.phy_id,
2725
+ CICADA_FAMILY_HWINIT[i].offset,
2726
+ CICADA_FAMILY_HWINIT[i].value);
2727
+ }
2728
+
2729
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2) {
2730
+ /* not Cameo */
2731
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode) {
2732
+ ax178dataptr->UseRgmii = 1;
2733
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2734
+ }
2735
+
2736
+ for (i = 0; i < (sizeof(CICADA_V2_HWINIT) /
2737
+ sizeof(CICADA_V2_HWINIT[0])); i++) {
2738
+ ax8817x_swmii_mdio_write_le(dev->net,
2739
+ dev->mii.phy_id, CICADA_V2_HWINIT[i].offset,
2740
+ CICADA_V2_HWINIT[i].value);
2741
+ }
2742
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX) {
2743
+ /* not Cameo */
2744
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode) {
2745
+ ax178dataptr->UseRgmii = 1;
2746
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2747
+ }
2748
+
2749
+ for (i = 0; i < (sizeof(CICADA_V2_HWINIT) /
2750
+ sizeof(CICADA_V2_HWINIT[0])); i++) {
2751
+ ax8817x_swmii_mdio_write_le(dev->net,
2752
+ dev->mii.phy_id, CICADA_V2_HWINIT[i].offset,
2753
+ CICADA_V2_HWINIT[i].value);
2754
+ }
2755
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211CL) {
2756
+ ax178dataptr->UseRgmii = 1;
2757
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2758
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211BN) {
2759
+ ax178dataptr->UseRgmii = 1;
2760
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2761
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8251CL) {
2762
+ ax178dataptr->UseRgmii = 1;
2763
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2764
+ } else if (ax178dataptr->PhyMode == PHY_MODE_VSC8601) {
2765
+ ax178dataptr->UseRgmii = 1;
2766
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
2767
+ /* Vitess_8601_Init (dev, 0); */
2768
+ }
2769
+
2770
+ if (ax178dataptr->PhyMode != PHY_MODE_ATTANSIC_V0) {
2771
+ /* software reset */
2772
+ ax8817x_swmii_mdio_write_le(
2773
+ dev->net, dev->mii.phy_id, GMII_PHY_CONTROL,
2774
+ ax8817x_swmii_mdio_read_le(
2775
+ dev->net, dev->mii.phy_id, GMII_PHY_CONTROL)
2776
+ | GMII_CONTROL_RESET);
2777
+ msleep(1);
2778
+ }
2779
+
2780
+ if ((ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) ||
2781
+ (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0_GMII)) {
2782
+ if (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) {
2783
+ i = 1000;
2784
+ while (i--) {
2785
+ ax8817x_swmii_mdio_write_le(dev->net,
2786
+ dev->mii.phy_id, 21, 0x1001);
2787
+
2788
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
2789
+ dev->mii.phy_id, 21);
2790
+ if ((phyreg & 0xf00f) == 0x1001)
2791
+ break;
2792
+ }
2793
+ if (i < 0)
2794
+ return -EIO;
2795
+ }
2796
+
2797
+ if (ax178dataptr->LedMode == 4) {
2798
+ ax8817x_swmii_mdio_write_le(dev->net,
2799
+ dev->mii.phy_id, 28, 0x7417);
2800
+ } else if (ax178dataptr->LedMode == 9) {
2801
+ ax8817x_swmii_mdio_write_le(dev->net,
2802
+ dev->mii.phy_id, 28, 0x7a10);
2803
+ } else if (ax178dataptr->LedMode == 10) {
2804
+ ax8817x_swmii_mdio_write_le(dev->net,
2805
+ dev->mii.phy_id, 28, 0x7a13);
2806
+ }
2807
+
2808
+ for (i = 0; i < (sizeof(AGERE_FAMILY_HWINIT) /
2809
+ sizeof(AGERE_FAMILY_HWINIT[0])); i++) {
2810
+ ax8817x_swmii_mdio_write_le(dev->net,
2811
+ dev->mii.phy_id, AGERE_FAMILY_HWINIT[i].offset,
2812
+ AGERE_FAMILY_HWINIT[i].value);
2813
+ }
2814
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211CL) {
2815
+
2816
+ ax8817x_swmii_mdio_write_le(dev->net,
2817
+ dev->mii.phy_id, 0x1f, 0x0005);
2818
+ ax8817x_swmii_mdio_write_le(dev->net,
2819
+ dev->mii.phy_id, 0x0c, 0);
2820
+
2821
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 0x01,
2822
+ (ax8817x_swmii_mdio_read_le(dev->net,
2823
+ dev->mii.phy_id, 0x01) | 0x0080));
2824
+ ax8817x_swmii_mdio_write_le(dev->net,
2825
+ dev->mii.phy_id, 0x1f, 0);
2826
+
2827
+ if (ax178dataptr->LedMode == 12) {
2828
+ ax8817x_swmii_mdio_write_le(dev->net,
2829
+ dev->mii.phy_id, 0x1f, 0x0002);
2830
+ ax8817x_swmii_mdio_write_le(dev->net,
2831
+ dev->mii.phy_id, 0x1a, 0x00cb);
2832
+ ax8817x_swmii_mdio_write_le(dev->net,
2833
+ dev->mii.phy_id, 0x1f, 0);
2834
+ }
2835
+ } else if (ax178dataptr->PhyMode == PHY_MODE_VSC8601) {
2836
+ Vitess_8601_Init(dev, 1);
2837
+ }
2838
+
2839
+ /* read phy register 0 */
2840
+ phyctrl = ax8817x_swmii_mdio_read_le(dev->net,
2841
+ dev->mii.phy_id, GMII_PHY_CONTROL);
2842
+ tempshort = phyctrl;
2843
+ phyctrl &= ~(GMII_CONTROL_POWER_DOWN | GMII_CONTROL_ISOLATE);
2844
+ if (phyctrl != tempshort) {
2845
+ ax8817x_swmii_mdio_write_le(dev->net,
2846
+ dev->mii.phy_id, GMII_PHY_CONTROL, phyctrl);
2847
+ }
2848
+
2849
+ /* LED */
2850
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
2851
+ if (ax178dataptr->LedMode == 1) {
2852
+
2853
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
2854
+ dev->mii.phy_id, 24) & 0xf8ff) | (1 + 0x100);
2855
+ ax8817x_swmii_mdio_write_le(dev->net,
2856
+ dev->mii.phy_id, 24, phyreg);
2857
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
2858
+ dev->mii.phy_id, 25) & 0xfc0f;
2859
+ } else if (ax178dataptr->LedMode == 2) {
2860
+
2861
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
2862
+ dev->mii.phy_id, 24) & 0xf886) |
2863
+ (1 + 0x10 + 0x300);
2864
+ ax8817x_swmii_mdio_write_le(dev->net,
2865
+ dev->mii.phy_id, 24, phyreg);
2866
+ } else if (ax178dataptr->LedMode == 5) {
2867
+
2868
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
2869
+ dev->mii.phy_id, 24) & 0xf8be) |
2870
+ (1 + 0x40 + 0x300);
2871
+ ax8817x_swmii_mdio_write_le(dev->net,
2872
+ dev->mii.phy_id, 24, phyreg);
2873
+ } else if (ax178dataptr->LedMode == 7) {
2874
+
2875
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
2876
+ dev->mii.phy_id, 24) & 0xf8ff) |
2877
+ (1 + 0x100);
2878
+ ax8817x_swmii_mdio_write_le(dev->net,
2879
+ dev->mii.phy_id, 24, phyreg);
2880
+
2881
+ } else if (ax178dataptr->LedMode == 8) {
2882
+
2883
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
2884
+ dev->mii.phy_id, 24) & 0xf8be) |
2885
+ (1 + 0x40 + 0x100);
2886
+ ax8817x_swmii_mdio_write_le(dev->net,
2887
+ dev->mii.phy_id, 24, phyreg);
2888
+
2889
+ } else if (ax178dataptr->LedMode == 11) {
2890
+
2891
+ phyreg = ax8817x_swmii_mdio_read_le(dev->net,
2892
+ dev->mii.phy_id, 24) & 0x4106;
2893
+ ax8817x_swmii_mdio_write_le(dev->net,
2894
+ dev->mii.phy_id, 24, phyreg);
2895
+ } else if (ax178dataptr->LedMode == 0x10) {
2896
+ /* MARVEL 88e1510 use default led setting */
2897
+ }
2898
+
2899
+ } else if ((ax178dataptr->PhyMode == PHY_MODE_CICADA_V1) ||
2900
+ (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2) ||
2901
+ (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX)) {
2902
+
2903
+ if (ax178dataptr->LedMode == 3) {
2904
+
2905
+ phyreg = (ax8817x_swmii_mdio_read_le(dev->net,
2906
+ dev->mii.phy_id, 27) & 0xFCFF) | 0x0100;
2907
+ ax8817x_swmii_mdio_write_le(dev->net,
2908
+ dev->mii.phy_id, 27, phyreg);
2909
+ }
2910
+
2911
+ }
2912
+
2913
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
2914
+ if (ax178dataptr->LedMode == 1)
2915
+ phyreg |= 0x3f0;
2916
+ }
2917
+
2918
+ phyanar = 1 | (GMII_ANAR_PAUSE | GMII_ANAR_100TXFD | GMII_ANAR_100TX |
2919
+ GMII_ANAR_10TFD | GMII_ANAR_10T | GMII_ANAR_ASYM_PAUSE);
2920
+
2921
+ phyauxctrl = GMII_1000_AUX_CTRL_FD_CAPABLE;
2922
+
2923
+ ax8817x_swmii_mdio_write_le(dev->net,
2924
+ dev->mii.phy_id, GMII_PHY_ANAR, phyanar);
2925
+ ax8817x_swmii_mdio_write_le(dev->net,
2926
+ dev->mii.phy_id, GMII_PHY_1000BT_CONTROL, phyauxctrl);
2927
+
2928
+ if (ax178dataptr->PhyMode == PHY_MODE_VSC8601) {
2929
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
2930
+ 31, 0x52B5);
2931
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
2932
+ 16, 0xA7F8);
2933
+
2934
+ tempshort = ax8817x_swmii_mdio_read_le(dev->net,
2935
+ dev->mii.phy_id, 17) & (~0x0018);
2936
+
2937
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
2938
+ 17, tempshort);
2939
+
2940
+ tempshort = ax8817x_swmii_mdio_read_le(dev->net,
2941
+ dev->mii.phy_id, 18);
2942
+
2943
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id, 18,
2944
+ tempshort);
2945
+
2946
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
2947
+ 16, 0x87F8);
2948
+ ax8817x_swmii_mdio_write_le(dev->net, dev->mii.phy_id,
2949
+ 31, 0);
2950
+ }
2951
+
2952
+ if (ax178dataptr->PhyMode == PHY_MODE_ATTANSIC_V0) {
2953
+ ax8817x_swmii_mdio_write_le(dev->net,
2954
+ dev->mii.phy_id, GMII_PHY_CONTROL, 0x9000);
2955
+
2956
+ } else {
2957
+ phyctrl &= ~GMII_CONTROL_LOOPBACK;
2958
+ phyctrl |= (GMII_CONTROL_ENABLE_AUTO | GMII_CONTROL_START_AUTO);
2959
+
2960
+ ax8817x_swmii_mdio_write_le(dev->net,
2961
+ dev->mii.phy_id, GMII_PHY_CONTROL, phyctrl);
2962
+ }
2963
+
2964
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
2965
+ if (ax178dataptr->LedMode == 1)
2966
+ ax8817x_swmii_mdio_write_le(dev->net,
2967
+ dev->mii.phy_id, 25, phyreg);
2968
+ }
2969
+
2970
+SKIPPHYSETTING:
2971
+
2972
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
2973
+ ax178dataptr->MediaLink, 0, 0, NULL);
2974
+
2975
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
2976
+ AX88772_IPG0_DEFAULT | (AX88772_IPG1_DEFAULT << 8),
2977
+ AX88772_IPG2_DEFAULT, 0, NULL);
2978
+
2979
+ msleep(1);
2980
+
2981
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
2982
+
2983
+ return 0;
2984
+}
2985
+
2986
+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
2987
+{
2988
+ int ret;
2989
+ void *buf;
2990
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
2991
+ struct ax88178_data *ax178dataptr = NULL;
2992
+
2993
+ axusbnet_get_endpoints(dev, intf);
2994
+
2995
+ buf = kmalloc(6, GFP_KERNEL);
2996
+ if (!buf) {
2997
+ deverr(dev, "Cannot allocate memory for buffer");
2998
+ return -ENOMEM;
2999
+ }
3000
+
3001
+ /* allocate 178 data */
3002
+ ax178dataptr = kmalloc(sizeof(*ax178dataptr), GFP_KERNEL);
3003
+ if (!ax178dataptr) {
3004
+ deverr(dev, "Cannot allocate memory for AX88178 data");
3005
+ ret = -ENOMEM;
3006
+ goto error_out;
3007
+ }
3008
+ memset(ax178dataptr, 0, sizeof(struct ax88178_data));
3009
+ dev->priv = ax178dataptr;
3010
+ /* end of allocate 178 data */
3011
+
3012
+ /* Get the EEPROM data*/
3013
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2,
3014
+ (void *)(&ax178dataptr->EepromData));
3015
+ if (ret < 0) {
3016
+ deverr(dev, "read SROM address 17h failed: %d", ret);
3017
+ goto error_out;
3018
+ }
3019
+ le16_to_cpus(&ax178dataptr->EepromData);
3020
+ /* End of get EEPROM data */
3021
+
3022
+ if (ax178dataptr->EepromData == 0xffff) {
3023
+ ax178dataptr->PhyMode = PHY_MODE_MARVELL;
3024
+ ax178dataptr->LedMode = 0;
3025
+ ax178dataptr->UseGpio0 = 1; /* True */
3026
+ } else {
3027
+ ax178dataptr->PhyMode = (u8)(ax178dataptr->EepromData &
3028
+ EEPROMMASK);
3029
+ ax178dataptr->LedMode = (u8)(ax178dataptr->EepromData >> 8);
3030
+
3031
+ /* for buffalo new (use gpio2) */
3032
+ if (ax178dataptr->LedMode == 6)
3033
+ ax178dataptr->LedMode = 1;
3034
+ else if (ax178dataptr->LedMode == 1)
3035
+ ax178dataptr->BuffaloOld = 1;
3036
+
3037
+
3038
+ if (ax178dataptr->EepromData & 0x80)
3039
+ ax178dataptr->UseGpio0 = 0; /* MARVEL se and other */
3040
+ else
3041
+ ax178dataptr->UseGpio0 = 1; /* cameo */
3042
+ }
3043
+
3044
+ if (ax178dataptr->UseGpio0) {
3045
+
3046
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
3047
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3048
+ AXGPIOS_GPO0EN | AXGPIOS_RSE,
3049
+ 0, 0, NULL);
3050
+ if (ret < 0) {
3051
+ deverr(dev, "write GPIO failed: %d", ret);
3052
+ goto error_out;
3053
+ }
3054
+
3055
+ msleep(25);
3056
+
3057
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3058
+ (AXGPIOS_GPO2 | AXGPIOS_GPO2EN |
3059
+ AXGPIOS_GPO0EN), 0, 0, NULL);
3060
+ if (ret < 0) {
3061
+ deverr(dev, "write GPIO failed: %d", ret);
3062
+ goto error_out;
3063
+ }
3064
+
3065
+ msleep(15);
3066
+
3067
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3068
+ AXGPIOS_GPO2EN | AXGPIOS_GPO0EN,
3069
+ 0, 0, NULL);
3070
+ if (ret < 0) {
3071
+ deverr(dev, "write GPIO failed: %d", ret);
3072
+ goto error_out;
3073
+ }
3074
+
3075
+ msleep(245);
3076
+
3077
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3078
+ (AXGPIOS_GPO2 | AXGPIOS_GPO2EN |
3079
+ AXGPIOS_GPO0EN), 0, 0, NULL);
3080
+ if (ret < 0) {
3081
+ deverr(dev, "write GPIO failed: %d", ret);
3082
+ goto error_out;
3083
+ }
3084
+
3085
+ } else { /* vitesse */
3086
+
3087
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3088
+ (AXGPIOS_RSE | AXGPIOS_GPO0EN |
3089
+ AXGPIOS_GPO0), 0, 0, NULL);
3090
+ if (ret < 0) {
3091
+ deverr(dev, "write GPIO failed: %d", ret);
3092
+ goto error_out;
3093
+ }
3094
+
3095
+ msleep(25);
3096
+
3097
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3098
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
3099
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
3100
+ 0, 0, NULL);
3101
+ if (ret < 0) {
3102
+ deverr(dev, "write GPIO failed: %d", ret);
3103
+ goto error_out;
3104
+ }
3105
+
3106
+ msleep(25);
3107
+
3108
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3109
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
3110
+ AXGPIOS_GPO2EN), 0, 0, NULL);
3111
+ if (ret < 0) {
3112
+ deverr(dev, "write GPIO failed: %d", ret);
3113
+ goto error_out;
3114
+ }
3115
+
3116
+ msleep(245);
3117
+
3118
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3119
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
3120
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
3121
+ 0, 0, NULL);
3122
+ if (ret < 0) {
3123
+ deverr(dev, "write GPIO failed: %d", ret);
3124
+ goto error_out;
3125
+ }
3126
+ }
3127
+ } else { /* use gpio1 */
3128
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3129
+ (AXGPIOS_GPO1 | AXGPIOS_GPO1EN |
3130
+ AXGPIOS_RSE), 0, 0, NULL);
3131
+ if (ret < 0) {
3132
+ deverr(dev, "write GPIO failed: %d", ret);
3133
+ goto error_out;
3134
+ }
3135
+
3136
+ if (ax178dataptr->BuffaloOld) {
3137
+ msleep(350);
3138
+
3139
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3140
+ AXGPIOS_GPO1EN, 0, 0, NULL);
3141
+ if (ret < 0) {
3142
+ deverr(dev, "write GPIO failed: %d", ret);
3143
+ goto error_out;
3144
+ }
3145
+
3146
+ msleep(350);
3147
+
3148
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3149
+ AXGPIOS_GPO1EN | AXGPIOS_GPO1,
3150
+ 0, 0, NULL);
3151
+ if (ret < 0) {
3152
+ deverr(dev, "write GPIO failed: %d", ret);
3153
+ goto error_out;
3154
+ }
3155
+ } else {
3156
+ msleep(25);
3157
+
3158
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3159
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
3160
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
3161
+ 0, 0, NULL);
3162
+ if (ret < 0) {
3163
+ deverr(dev, "write GPIO failed: %d", ret);
3164
+ goto error_out;
3165
+ }
3166
+
3167
+ msleep(25);
3168
+
3169
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3170
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
3171
+ AXGPIOS_GPO2EN), 0, 0, NULL);
3172
+ if (ret < 0) {
3173
+ deverr(dev, "write GPIO failed: %d", ret);
3174
+ goto error_out;
3175
+ }
3176
+
3177
+ msleep(245);
3178
+
3179
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
3180
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
3181
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
3182
+ 0, 0, NULL);
3183
+ if (ret < 0) {
3184
+ deverr(dev, "write GPIO failed: %d", ret);
3185
+ goto error_out;
3186
+ }
3187
+ }
3188
+ }
3189
+
3190
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL);
3191
+ if (ret < 0) {
3192
+ deverr(dev, "Select PHY failed: %d", ret);
3193
+ goto error_out;
3194
+ }
3195
+
3196
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD |
3197
+ AX_SWRESET_PRL, 0, 0, NULL);
3198
+ if (ret < 0) {
3199
+ deverr(dev, "Issue sw reset failed: %d", ret);
3200
+ goto error_out;
3201
+ }
3202
+
3203
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0, 0, 0, NULL);
3204
+ if (ret < 0) {
3205
+ deverr(dev, "Issue rx ctrl failed: %d", ret);
3206
+ goto error_out;
3207
+ }
3208
+
3209
+ /* Get the MAC address */
3210
+ memset(buf, 0, ETH_ALEN);
3211
+ ax8817x_get_mac(dev, buf);
3212
+ if (ret < 0)
3213
+ goto error_out;
3214
+ /* End of get MAC address */
3215
+
3216
+ ret = ax88178_phy_init(dev, ax178dataptr);
3217
+ if (ret < 0)
3218
+ goto error_out;
3219
+
3220
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
3221
+ dev->net->do_ioctl = ax8817x_ioctl;
3222
+ dev->net->set_multicast_list = ax88178_set_multicast;
3223
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
3224
+#else
3225
+ dev->net->netdev_ops = &ax88178_netdev_ops;
3226
+#endif
3227
+ dev->net->ethtool_ops = &ax8817x_ethtool_ops;
3228
+
3229
+ /* Register suspend and resume functions */
3230
+ data->suspend = ax88772_suspend;
3231
+ data->resume = ax88772_resume;
3232
+
3233
+ if (dev->driver_info->flags & FLAG_FRAMING_AX)
3234
+ dev->rx_urb_size = 16384;
3235
+
3236
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, (AX_RX_CTL_MFB |
3237
+ AX_RX_CTL_START | AX_RX_CTL_AB), 0, 0, NULL);
3238
+ if (ret < 0) {
3239
+ deverr(dev, "write RX ctrl reg failed: %d", ret);
3240
+ goto error_out;
3241
+ }
3242
+
3243
+ kfree(buf);
3244
+ printk(version);
3245
+ return ret;
3246
+
3247
+error_out:
3248
+ kfree(ax178dataptr);
3249
+ kfree(buf);
3250
+ return ret;
3251
+}
3252
+
3253
+static void ax88178_unbind(struct usbnet *dev, struct usb_interface *intf)
3254
+{
3255
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
3256
+
3257
+ if (ax178dataptr) {
3258
+
3259
+ /* stop MAC operation */
3260
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
3261
+ AX_RX_CTL_STOP, 0, 0, NULL);
3262
+
3263
+ kfree(ax178dataptr);
3264
+ }
3265
+}
3266
+
3267
+static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
3268
+{
3269
+ u8 *head;
3270
+ u32 header;
3271
+ char *packet;
3272
+ struct sk_buff *ax_skb = NULL;
3273
+ u16 size;
3274
+
3275
+ head = (u8 *) skb->data;
3276
+ memcpy(&header, head, sizeof(header));
3277
+ le32_to_cpus(&header);
3278
+ packet = head + sizeof(header);
3279
+
3280
+ skb_pull(skb, 4);
3281
+
3282
+ while (skb->len > 0) {
3283
+ if ((short)(header & 0x00007ff) !=
3284
+ ~((short)(((header & 0xffff0000) | 0xf8000000) >> 16))) {
3285
+ deverr(dev, "header length data is error 0x%08x, %d\n",
3286
+ header, skb->len);
3287
+ }
3288
+ /* get the packet length */
3289
+ size = (u16) (header & 0x00007ff);
3290
+
3291
+ if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
3292
+
3293
+ /* Make sure ip header is aligned on 32-bit boundary */
3294
+ if (!((unsigned long)skb->data & 0x02)) {
3295
+ memmove(skb->data - 2, skb->data, size);
3296
+ skb->data -= 2;
3297
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3298
+ skb->tail = skb->data + size;
3299
+#else
3300
+ skb_set_tail_pointer(skb, size);
3301
+#endif
3302
+ }
3303
+ skb->truesize = size + sizeof(struct sk_buff);
3304
+ skb->len = size;
3305
+
3306
+ return 2;
3307
+ }
3308
+
3309
+ if (size > ETH_FRAME_LEN) {
3310
+ deverr(dev, "invalid rx length %d", size);
3311
+ return 0;
3312
+ }
3313
+#ifndef RX_SKB_COPY
3314
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
3315
+#else
3316
+ ax_skb = alloc_skb(size + NET_IP_ALIGN, GFP_ATOMIC);
3317
+ skb_reserve(ax_skb, NET_IP_ALIGN);
3318
+#endif
3319
+ if (ax_skb) {
3320
+#ifndef RX_SKB_COPY
3321
+ /* Make sure ip header is aligned on 32-bit boundary */
3322
+ if (!((unsigned long)packet & 0x02)) {
3323
+ memmove(packet - 2, packet, size);
3324
+ packet -= 2;
3325
+ }
3326
+ ax_skb->data = packet;
3327
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3328
+ ax_skb->tail = packet + size;
3329
+#else
3330
+ skb_set_tail_pointer(ax_skb, size);
3331
+#endif
3332
+
3333
+#else
3334
+ skb_put(ax_skb, size);
3335
+ memcpy(ax_skb->data, packet , size);
3336
+#endif
3337
+ ax_skb->truesize = size + sizeof(struct sk_buff);
3338
+ axusbnet_skb_return(dev, ax_skb);
3339
+
3340
+ } else {
3341
+ return 0;
3342
+ }
3343
+
3344
+ skb_pull(skb, (size + 1) & 0xfffe);
3345
+
3346
+ if (skb->len == 0)
3347
+ break;
3348
+
3349
+ head = (u8 *) skb->data;
3350
+ memcpy(&header, head, sizeof(header));
3351
+ le32_to_cpus(&header);
3352
+ packet = head + sizeof(header);
3353
+ skb_pull(skb, 4);
3354
+ }
3355
+
3356
+ if (skb->len < 0) {
3357
+ deverr(dev, "invalid rx length %d", skb->len);
3358
+ return 0;
3359
+ }
3360
+ return 1;
3361
+}
3362
+
3363
+static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
3364
+ gfp_t flags)
3365
+{
3366
+ int padlen = ((skb->len + 4) % 512) ? 0 : 4;
3367
+ u32 packet_len;
3368
+ u32 padbytes = 0xffff0000;
3369
+
3370
+#if (!AX_FORCE_BUFF_ALIGN)
3371
+ int headroom = skb_headroom(skb);
3372
+ int tailroom = skb_tailroom(skb);
3373
+
3374
+ if ((!skb_cloned(skb))
3375
+ && ((headroom + tailroom) >= (4 + padlen))) {
3376
+ if ((headroom < 4) || (tailroom < padlen)) {
3377
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
3378
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3379
+ skb->tail = skb->data + skb->len;
3380
+#else
3381
+ skb_set_tail_pointer(skb, skb->len);
3382
+#endif
3383
+ }
3384
+ } else
3385
+#endif
3386
+ {
3387
+ struct sk_buff *skb2;
3388
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
3389
+ dev_kfree_skb_any(skb);
3390
+ skb = skb2;
3391
+ if (!skb)
3392
+ return NULL;
3393
+ }
3394
+
3395
+ skb_push(skb, 4);
3396
+ packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
3397
+ cpu_to_le32s(&packet_len);
3398
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3399
+ memcpy(skb->data, &packet_len, sizeof(packet_len));
3400
+#else
3401
+ skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
3402
+#endif
3403
+
3404
+ if ((skb->len % 512) == 0) {
3405
+ cpu_to_le32s(&padbytes);
3406
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3407
+ memcpy(skb->tail, &padbytes, sizeof(padbytes));
3408
+#else
3409
+ memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
3410
+#endif
3411
+ skb_put(skb, sizeof(padbytes));
3412
+ }
3413
+ return skb;
3414
+}
3415
+
3416
+static void
3417
+ax88772b_rx_checksum(struct sk_buff *skb, struct ax88772b_rx_header *rx_hdr)
3418
+{
3419
+ skb->ip_summed = CHECKSUM_NONE;
3420
+
3421
+ /* checksum error bit is set */
3422
+ if (rx_hdr->l3_csum_err || rx_hdr->l4_csum_err)
3423
+ return;
3424
+
3425
+ /* It must be a TCP or UDP packet with a valid checksum */
3426
+ if ((rx_hdr->l4_type == AX_RXHDR_L4_TYPE_TCP) ||
3427
+ (rx_hdr->l4_type == AX_RXHDR_L4_TYPE_UDP)) {
3428
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
3429
+ }
3430
+}
3431
+
3432
+static int ax88772b_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
3433
+{
3434
+ struct ax88772b_rx_header rx_hdr;
3435
+ struct sk_buff *ax_skb = NULL;
3436
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
3437
+
3438
+ while (skb->len > 0) {
3439
+
3440
+ le16_to_cpus((u16 *)skb->data);
3441
+ le16_to_cpus(((u16 *)skb->data) + 1);
3442
+
3443
+ memcpy(&rx_hdr, skb->data, sizeof(struct ax88772b_rx_header));
3444
+
3445
+ if ((short)rx_hdr.len != (~((short)rx_hdr.len_bar) & 0x7FF))
3446
+ return 0;
3447
+
3448
+ if (rx_hdr.len > (ETH_FRAME_LEN + 4)) {
3449
+ deverr(dev, "invalid rx length %d", rx_hdr.len);
3450
+ return 0;
3451
+ }
3452
+
3453
+ if (skb->len - ((rx_hdr.len +
3454
+ sizeof(struct ax88772b_rx_header) + 3) &
3455
+ 0xfffc) == 0) {
3456
+ skb_pull(skb, sizeof(struct ax88772b_rx_header));
3457
+ skb->len = rx_hdr.len;
3458
+
3459
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3460
+ skb->tail = skb->data + rx_hdr.len;
3461
+#else
3462
+ skb_set_tail_pointer(skb, rx_hdr.len);
3463
+#endif
3464
+ skb->truesize = rx_hdr.len + sizeof(struct sk_buff);
3465
+
3466
+ if (ax772b_data->checksum & AX_RX_CHECKSUM)
3467
+ ax88772b_rx_checksum(skb, &rx_hdr);
3468
+
3469
+ return 2;
3470
+ }
3471
+#ifndef RX_SKB_COPY
3472
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
3473
+#else
3474
+ ax_skb = alloc_skb(rx_hdr.len + NET_IP_ALIGN, GFP_ATOMIC);
3475
+ skb_reserve(ax_skb, NET_IP_ALIGN);
3476
+#endif
3477
+ if (ax_skb) {
3478
+#ifndef RX_SKB_COPY
3479
+ ax_skb->len = rx_hdr.len;
3480
+ ax_skb->data = skb->data +
3481
+ sizeof(struct ax88772b_rx_header);
3482
+
3483
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3484
+ ax_skb->tail = ax_skb->data + rx_hdr.len;
3485
+#else
3486
+ skb_set_tail_pointer(ax_skb, rx_hdr.len);
3487
+#endif
3488
+
3489
+#else
3490
+ skb_put(ax_skb, rx_hdr.len);
3491
+ memcpy(ax_skb->data, skb->data + sizeof(struct ax88772b_rx_header), rx_hdr.len);
3492
+#endif
3493
+
3494
+ ax_skb->truesize = rx_hdr.len + sizeof(struct sk_buff);
3495
+
3496
+ if (ax772b_data->checksum & AX_RX_CHECKSUM)
3497
+ ax88772b_rx_checksum(ax_skb, &rx_hdr);
3498
+
3499
+ axusbnet_skb_return(dev, ax_skb);
3500
+
3501
+ } else {
3502
+ return 0;
3503
+ }
3504
+
3505
+ skb_pull(skb, ((rx_hdr.len +
3506
+ sizeof(struct ax88772b_rx_header) + 3)
3507
+ & 0xfffc));
3508
+ }
3509
+
3510
+ if (skb->len < 0) {
3511
+ deverr(dev, "invalid rx length %d", skb->len);
3512
+ return 0;
3513
+ }
3514
+ return 1;
3515
+}
3516
+
3517
+static struct sk_buff *
3518
+ax88772b_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
3519
+{
3520
+ int padlen = ((skb->len + 4) % 512) ? 0 : 4;
3521
+ u32 packet_len;
3522
+ u32 padbytes = 0xffff0000;
3523
+
3524
+#if (!AX_FORCE_BUFF_ALIGN)
3525
+ int headroom = skb_headroom(skb);
3526
+ int tailroom = skb_tailroom(skb);
3527
+
3528
+ if ((!skb_cloned(skb))
3529
+ && ((headroom + tailroom) >= (4 + padlen))) {
3530
+ if ((headroom < 4) || (tailroom < padlen)) {
3531
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
3532
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3533
+ skb->tail = skb->data + skb->len;
3534
+#else
3535
+ skb_set_tail_pointer(skb, skb->len);
3536
+#endif
3537
+ }
3538
+ } else
3539
+#endif
3540
+ {
3541
+ struct sk_buff *skb2;
3542
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
3543
+ dev_kfree_skb_any(skb);
3544
+ skb = skb2;
3545
+ if (!skb)
3546
+ return NULL;
3547
+ }
3548
+
3549
+ skb_push(skb, 4);
3550
+ packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
3551
+
3552
+ cpu_to_le32s(&packet_len);
3553
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3554
+ memcpy(skb->data, &packet_len, sizeof(packet_len));
3555
+#else
3556
+ skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
3557
+#endif
3558
+
3559
+ if ((skb->len % 512) == 0) {
3560
+ cpu_to_le32s(&padbytes);
3561
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
3562
+ memcpy(skb->tail, &padbytes, sizeof(padbytes));
3563
+#else
3564
+ memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
3565
+#endif
3566
+ skb_put(skb, sizeof(padbytes));
3567
+ }
3568
+
3569
+ return skb;
3570
+}
3571
+
3572
+static const u8 chkcntsel[6][3] = {
3573
+ {12, 23, 31},
3574
+ {12, 31, 23},
3575
+ {23, 31, 12},
3576
+ {23, 12, 31},
3577
+ {31, 12, 23},
3578
+ {31, 23, 12}
3579
+};
3580
+
3581
+static void ax88772_save_bmcr_anar(struct usbnet *dev)
3582
+{
3583
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
3584
+
3585
+ if (ax772_data) {
3586
+ /* Preserve BMCR for restoring */
3587
+ ax772_data->presvd_phy_bmcr =
3588
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
3589
+
3590
+ /* Preserve Advertisement control reg for restoring */
3591
+ ax772_data->presvd_phy_advertise =
3592
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
3593
+ }
3594
+}
3595
+
3596
+static void ax88772_restore_bmcr_anar(struct usbnet *dev)
3597
+{
3598
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
3599
+
3600
+ if (ax772_data && ax772_data->presvd_phy_advertise && ax772_data->presvd_phy_bmcr) {
3601
+ /* Restore Advertisement control reg */
3602
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
3603
+ ax772_data->presvd_phy_advertise);
3604
+ /* Restore BMCR */
3605
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR,
3606
+ ax772_data->presvd_phy_bmcr);
3607
+ ax772_data->presvd_phy_advertise = 0;
3608
+ ax772_data->presvd_phy_bmcr = 0;
3609
+ }
3610
+}
3611
+
3612
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
3613
+static void ax88772_link_reset(void *data)
3614
+{
3615
+ struct usbnet *dev = (struct usbnet *)data;
3616
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
3617
+#else
3618
+static void ax88772_link_reset(struct work_struct *work)
3619
+{
3620
+ struct ax88772_data *ax772_data = container_of(work,
3621
+ struct ax88772_data,
3622
+ check_link);
3623
+ struct usbnet *dev = ax772_data->dev;
3624
+#endif
3625
+ if (ax772_data->Event == AX_SET_RX_CFG) {
3626
+ u16 bmcr;
3627
+ u16 mode;
3628
+
3629
+ ax772_data->Event = AX_NOP;
3630
+
3631
+ mode = AX88772_MEDIUM_DEFAULT;
3632
+
3633
+ bmcr = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
3634
+ MII_BMCR);
3635
+ if (!(bmcr & BMCR_FULLDPLX))
3636
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
3637
+ if (!(bmcr & BMCR_SPEED100))
3638
+ mode &= ~AX88772_MEDIUM_100MB;
3639
+
3640
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
3641
+ mode, 0, 0, NULL);
3642
+ return;
3643
+ }
3644
+
3645
+ switch (ax772_data->Event) {
3646
+ case WAIT_AUTONEG_COMPLETE:
3647
+ if (jiffies > (ax772_data->autoneg_start + 5 * HZ)) {
3648
+ ax772_data->Event = PHY_POWER_DOWN;
3649
+ ax772_data->TickToExpire = 23;
3650
+ }
3651
+ break;
3652
+ case PHY_POWER_DOWN:
3653
+ if (ax772_data->TickToExpire == 23) {
3654
+ ax88772_save_bmcr_anar(dev);
3655
+ /* Set Phy Power Down */
3656
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
3657
+ 0, 0, NULL);
3658
+ --ax772_data->TickToExpire;
3659
+ } else if (--ax772_data->TickToExpire == 0) {
3660
+ /* Set Phy Power Up */
3661
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3662
+ AX_SWRESET_IPRL, 0, 0, NULL);
3663
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3664
+ AX_SWRESET_IPPD | AX_SWRESET_IPRL, 0, 0, NULL);
3665
+ msleep(10);
3666
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3667
+ AX_SWRESET_IPRL, 0, 0, NULL);
3668
+ msleep(60);
3669
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3670
+ AX_SWRESET_CLEAR, 0, 0, NULL);
3671
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3672
+ AX_SWRESET_IPRL, 0, 0, NULL);
3673
+
3674
+ if (ax772_data->presvd_phy_advertise && ax772_data->presvd_phy_bmcr) {
3675
+ ax88772_restore_bmcr_anar(dev);
3676
+
3677
+ } else {
3678
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id,
3679
+ MII_ADVERTISE,
3680
+ ADVERTISE_ALL | ADVERTISE_CSMA |
3681
+ ADVERTISE_PAUSE_CAP);
3682
+ mii_nway_restart(&dev->mii);
3683
+ }
3684
+
3685
+ ax772_data->Event = PHY_POWER_UP;
3686
+ ax772_data->TickToExpire = 47;
3687
+ }
3688
+ break;
3689
+ case PHY_POWER_UP:
3690
+ if (--ax772_data->TickToExpire == 0) {
3691
+ ax772_data->Event = PHY_POWER_DOWN;
3692
+ ax772_data->TickToExpire = 23;
3693
+ }
3694
+ break;
3695
+ default:
3696
+ break;
3697
+ }
3698
+ return;
3699
+}
3700
+
3701
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
3702
+static void ax88772a_link_reset(void *data)
3703
+{
3704
+ struct usbnet *dev = (struct usbnet *)data;
3705
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
3706
+#else
3707
+static void ax88772a_link_reset(struct work_struct *work)
3708
+{
3709
+ struct ax88772a_data *ax772a_data = container_of(work,
3710
+ struct ax88772a_data,
3711
+ check_link);
3712
+ struct usbnet *dev = ax772a_data->dev;
3713
+#endif
3714
+ int powsave = (ax772a_data->EepromData >> 14);
3715
+ u16 phy_reg;
3716
+
3717
+ if (ax772a_data->Event == AX_SET_RX_CFG) {
3718
+ u16 bmcr;
3719
+ u16 mode;
3720
+
3721
+ ax772a_data->Event = AX_NOP;
3722
+
3723
+ mode = AX88772_MEDIUM_DEFAULT;
3724
+
3725
+ bmcr = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id,
3726
+ MII_BMCR);
3727
+ if (!(bmcr & BMCR_FULLDPLX))
3728
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
3729
+ if (!(bmcr & BMCR_SPEED100))
3730
+ mode &= ~AX88772_MEDIUM_100MB;
3731
+
3732
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode,
3733
+ 0, 0, NULL);
3734
+
3735
+ if (ax772a_data->presvd_phy_advertise && ax772a_data->presvd_phy_bmcr) {
3736
+
3737
+ /* Restore Advertisement control reg */
3738
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
3739
+ ax772a_data->presvd_phy_advertise);
3740
+ /* Restore BMCR */
3741
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR,
3742
+ ax772a_data->presvd_phy_bmcr);
3743
+ ax772a_data->presvd_phy_advertise = 0;
3744
+ ax772a_data->presvd_phy_bmcr = 0;
3745
+ }
3746
+
3747
+ return;
3748
+ }
3749
+
3750
+ switch (ax772a_data->Event) {
3751
+ case WAIT_AUTONEG_COMPLETE:
3752
+ if (jiffies > (ax772a_data->autoneg_start + 5 * HZ)) {
3753
+ ax772a_data->Event = CHK_CABLE_EXIST;
3754
+ ax772a_data->TickToExpire = 14;
3755
+ }
3756
+ break;
3757
+ case CHK_CABLE_EXIST:
3758
+ phy_reg = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
3759
+ if ((phy_reg != 0x8012) && (phy_reg != 0x8013)) {
3760
+ ax8817x_mdio_write_le(dev->net,
3761
+ dev->mii.phy_id, 0x16, 0x4040);
3762
+ mii_nway_restart(&dev->mii);
3763
+ ax772a_data->Event = CHK_CABLE_STATUS;
3764
+ ax772a_data->TickToExpire = 31;
3765
+ } else if (--ax772a_data->TickToExpire == 0) {
3766
+ mii_nway_restart(&dev->mii);
3767
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
3768
+ if (powsave == 0x03) {
3769
+ ax772a_data->TickToExpire = 47;
3770
+ } else if (powsave == 0x01) {
3771
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
3772
+ ax772a_data->DlySel = 0;
3773
+ ax772a_data->TickToExpire =
3774
+ chkcntsel[ax772a_data->DlyIndex][ax772a_data->DlySel];
3775
+ }
3776
+ }
3777
+ break;
3778
+ case CHK_CABLE_EXIST_AGAIN:
3779
+ /* if cable disconnected */
3780
+ phy_reg = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
3781
+ if ((phy_reg != 0x8012) && (phy_reg != 0x8013)) {
3782
+ mii_nway_restart(&dev->mii);
3783
+ ax772a_data->Event = CHK_CABLE_STATUS;
3784
+ ax772a_data->TickToExpire = 31;
3785
+ } else if (--ax772a_data->TickToExpire == 0) {
3786
+ if (!ax772a_data->presvd_phy_advertise && !ax772a_data->presvd_phy_bmcr) {
3787
+ /* Preserve BMCR for restoring */
3788
+ ax772a_data->presvd_phy_bmcr =
3789
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
3790
+
3791
+ /* Preserve Advertisement control reg for restoring */
3792
+ ax772a_data->presvd_phy_advertise =
3793
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
3794
+ }
3795
+
3796
+
3797
+ /* Power down PHY */
3798
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3799
+ AX_SWRESET_IPPD,
3800
+ 0, 0, NULL);
3801
+ ax772a_data->Event = PHY_POWER_DOWN;
3802
+ if (powsave == 0x03)
3803
+ ax772a_data->TickToExpire = 23;
3804
+ else if (powsave == 0x01)
3805
+ ax772a_data->TickToExpire = 31;
3806
+ }
3807
+ break;
3808
+ case PHY_POWER_DOWN:
3809
+ if (--ax772a_data->TickToExpire == 0)
3810
+ ax772a_data->Event = PHY_POWER_UP;
3811
+ break;
3812
+ case CHK_CABLE_STATUS:
3813
+ if (--ax772a_data->TickToExpire == 0) {
3814
+ ax8817x_mdio_write_le(dev->net,
3815
+ dev->mii.phy_id, 0x16, 0x4040);
3816
+ mii_nway_restart(&dev->mii);
3817
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
3818
+ if (powsave == 0x03) {
3819
+ ax772a_data->TickToExpire = 47;
3820
+ } else if (powsave == 0x01) {
3821
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
3822
+ ax772a_data->DlySel = 0;
3823
+ ax772a_data->TickToExpire =
3824
+ chkcntsel[ax772a_data->DlyIndex][ax772a_data->DlySel];
3825
+ }
3826
+ }
3827
+ break;
3828
+ case PHY_POWER_UP:
3829
+
3830
+ if (!ax772a_data->presvd_phy_advertise && !ax772a_data->presvd_phy_bmcr) {
3831
+ /* Preserve BMCR for restoring */
3832
+ ax772a_data->presvd_phy_bmcr =
3833
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
3834
+
3835
+ /* Preserve Advertisement control reg for restoring */
3836
+ ax772a_data->presvd_phy_advertise =
3837
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
3838
+ }
3839
+
3840
+ ax88772a_phy_powerup(dev);
3841
+
3842
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
3843
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
3844
+
3845
+ mii_nway_restart(&dev->mii);
3846
+
3847
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
3848
+
3849
+ if (powsave == 0x03) {
3850
+ ax772a_data->TickToExpire = 47;
3851
+ } else if (powsave == 0x01) {
3852
+ if (++ax772a_data->DlySel >= 3) {
3853
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
3854
+ ax772a_data->DlySel = 0;
3855
+ }
3856
+ ax772a_data->TickToExpire =
3857
+ chkcntsel[ax772a_data->DlyIndex][ax772a_data->DlySel];
3858
+ }
3859
+ break;
3860
+ default:
3861
+ break;
3862
+ }
3863
+
3864
+ return;
3865
+}
3866
+
3867
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
3868
+static void ax88772b_link_reset(void *data)
3869
+{
3870
+ struct usbnet *dev = (struct usbnet *)data;
3871
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
3872
+#else
3873
+static void ax88772b_link_reset(struct work_struct *work)
3874
+{
3875
+ struct ax88772b_data *ax772b_data = container_of(work,
3876
+ struct ax88772b_data,
3877
+ check_link);
3878
+ struct usbnet *dev = ax772b_data->dev;
3879
+#endif
3880
+
3881
+ switch (ax772b_data->Event) {
3882
+
3883
+ case AX_SET_RX_CFG:
3884
+ {
3885
+ u16 bmcr = ax8817x_mdio_read_le(dev->net,
3886
+ dev->mii.phy_id, MII_BMCR);
3887
+ u16 mode = AX88772_MEDIUM_DEFAULT;
3888
+
3889
+ if (!(bmcr & BMCR_FULLDPLX))
3890
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
3891
+ if (!(bmcr & BMCR_SPEED100))
3892
+ mode &= ~AX88772_MEDIUM_100MB;
3893
+
3894
+ if (ax772b_data->ext_phy_oui == EXTPHY_BROADCOM_OUI) {
3895
+ if(ax772b_data->ext_phy_model == EXTPHY_BCM89811_MODEL) {
3896
+ mode = AX88772_MEDIUM_DEFAULT;
3897
+ }
3898
+ }
3899
+
3900
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode,
3901
+ 0, 0, NULL);
3902
+ break;
3903
+ }
3904
+ case PHY_POWER_UP:
3905
+ {
3906
+ u16 tmp16;
3907
+
3908
+ if (!ax772b_data->presvd_phy_advertise && !ax772b_data->presvd_phy_bmcr) {
3909
+ /* Preserve BMCR for restoring */
3910
+ ax772b_data->presvd_phy_bmcr =
3911
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_BMCR);
3912
+
3913
+ /* Preserve Advertisement control reg for restoring */
3914
+ ax772b_data->presvd_phy_advertise =
3915
+ ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
3916
+ }
3917
+
3918
+ ax88772a_phy_powerup(dev);
3919
+ tmp16 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
3920
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, 0x12,
3921
+ ((tmp16 & 0xFF9F) | 0x0040));
3922
+
3923
+ /* Restore Advertisement control reg */
3924
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
3925
+ ax772b_data->presvd_phy_advertise);
3926
+ /* Restore BMCR */
3927
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR,
3928
+ ax772b_data->presvd_phy_bmcr);
3929
+ ax772b_data->presvd_phy_advertise = 0;
3930
+ ax772b_data->presvd_phy_bmcr = 0;
3931
+
3932
+ break;
3933
+ }
3934
+
3935
+ case AX_CHK_AUTODETACH:
3936
+ {
3937
+ int ret;
3938
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
3939
+ AX_SWRESET_IPRL |
3940
+ (ax772b_data->psc & 0x7FFF),
3941
+ 0, 0, NULL);
3942
+ if (ret < 0) {
3943
+ deverr(dev, "Failed to configure PHY power saving: %d",
3944
+ ret);
3945
+ }
3946
+
3947
+ break;
3948
+ }
3949
+ default:
3950
+ break;
3951
+ }
3952
+
3953
+ ax772b_data->Event = AX_NOP;
3954
+
3955
+ return;
3956
+}
3957
+
3958
+static int ax88178_set_media(struct usbnet *dev)
3959
+{
3960
+ int ret;
3961
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
3962
+ int media;
3963
+
3964
+ media = ax88178_media_check(dev, ax178dataptr);
3965
+ if (media < 0)
3966
+ return media;
3967
+
3968
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, media, 0,
3969
+ 0, NULL);
3970
+ if (ret < 0) {
3971
+ deverr(dev, "write mode medium reg failed: %d", ret);
3972
+ return ret;
3973
+ }
3974
+
3975
+ return 0;
3976
+}
3977
+
3978
+static int ax88178_link_reset(struct usbnet *dev)
3979
+{
3980
+ return ax88178_set_media(dev);
3981
+}
3982
+
3983
+static int ax_suspend(struct usb_interface *intf,
3984
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
3985
+ pm_message_t message)
3986
+#else
3987
+ u32 message)
3988
+#endif
3989
+{
3990
+ struct usbnet *dev = usb_get_intfdata(intf);
3991
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
3992
+
3993
+ return data->suspend(intf, message);
3994
+}
3995
+
3996
+static int ax_resume(struct usb_interface *intf)
3997
+{
3998
+ struct usbnet *dev = usb_get_intfdata(intf);
3999
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
4000
+
4001
+ return data->resume(intf);
4002
+}
4003
+
4004
+static const struct driver_info ax88178_info = {
4005
+ .description = "",
4006
+// .description = "ASIX AX88178 USB 2.0 Ethernet",
4007
+ .bind = ax88178_bind,
4008
+ .unbind = ax88178_unbind,
4009
+ .status = ax88178_status,
4010
+ .link_reset = ax88178_link_reset,
4011
+ .reset = ax88178_link_reset,
4012
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4013
+ .stop = ax88772b_stop,
4014
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4015
+#else
4016
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4017
+#endif
4018
+ .rx_fixup = ax88772_rx_fixup,
4019
+ .tx_fixup = ax88772_tx_fixup,
4020
+};
4021
+
4022
+static const struct driver_info belkin178_info = {
4023
+ .description = "Belkin Gigabit USB 2.0 Network Adapter",
4024
+ .bind = ax88178_bind,
4025
+ .unbind = ax88178_unbind,
4026
+ .status = ax88178_status,
4027
+ .link_reset = ax88178_link_reset,
4028
+ .reset = ax88178_link_reset,
4029
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4030
+ .stop = ax88772b_stop,
4031
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4032
+#else
4033
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4034
+#endif
4035
+ .rx_fixup = ax88772_rx_fixup,
4036
+ .tx_fixup = ax88772_tx_fixup,
4037
+};
4038
+
4039
+static const struct driver_info ax8817x_info = {
4040
+ .description = "",
4041
+// .description = "ASIX AX8817x USB 2.0 Ethernet",
4042
+ .bind = ax8817x_bind,
4043
+ .status = ax8817x_status,
4044
+ .link_reset = ax88172_link_reset,
4045
+ .reset = ax88172_link_reset,
4046
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4047
+ .stop = ax88772b_stop,
4048
+ .flags = FLAG_ETHER | FLAG_AVOID_UNLINK_URBS,
4049
+#else
4050
+ .flags = FLAG_ETHER,
4051
+#endif
4052
+};
4053
+
4054
+static const struct driver_info dlink_dub_e100_info = {
4055
+ .description = "DLink DUB-E100 USB Ethernet",
4056
+ .bind = ax8817x_bind,
4057
+ .status = ax8817x_status,
4058
+ .link_reset = ax88172_link_reset,
4059
+ .reset = ax88172_link_reset,
4060
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4061
+ .stop = ax88772b_stop,
4062
+ .flags = FLAG_ETHER | FLAG_AVOID_UNLINK_URBS,
4063
+#else
4064
+ .flags = FLAG_ETHER,
4065
+#endif
4066
+};
4067
+
4068
+static const struct driver_info netgear_fa120_info = {
4069
+ .description = "Netgear FA-120 USB Ethernet",
4070
+ .bind = ax8817x_bind,
4071
+ .status = ax8817x_status,
4072
+ .link_reset = ax88172_link_reset,
4073
+ .reset = ax88172_link_reset,
4074
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4075
+ .stop = ax88772b_stop,
4076
+ .flags = FLAG_ETHER | FLAG_AVOID_UNLINK_URBS,
4077
+#else
4078
+ .flags = FLAG_ETHER,
4079
+#endif
4080
+};
4081
+
4082
+static const struct driver_info hawking_uf200_info = {
4083
+ .description = "Hawking UF200 USB Ethernet",
4084
+ .bind = ax8817x_bind,
4085
+ .status = ax8817x_status,
4086
+ .link_reset = ax88172_link_reset,
4087
+ .reset = ax88172_link_reset,
4088
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4089
+ .stop = ax88772b_stop,
4090
+ .flags = FLAG_ETHER | FLAG_AVOID_UNLINK_URBS,
4091
+#else
4092
+ .flags = FLAG_ETHER,
4093
+#endif
4094
+};
4095
+
4096
+static const struct driver_info ax88772_info = {
4097
+ .description = "",
4098
+// .description = "ASIX AX88772 USB 2.0 Ethernet",
4099
+ .bind = ax88772_bind,
4100
+ .unbind = ax88772_unbind,
4101
+ .status = ax88772_status,
4102
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4103
+ .stop = ax88772b_stop,
4104
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4105
+#else
4106
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4107
+#endif
4108
+ .rx_fixup = ax88772_rx_fixup,
4109
+ .tx_fixup = ax88772_tx_fixup,
4110
+ .reset = ax88772b_reset,
4111
+};
4112
+
4113
+static const struct driver_info dlink_dub_e100b_info = {
4114
+ .description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
4115
+ .bind = ax88772_bind,
4116
+ .unbind = ax88772_unbind,
4117
+ .status = ax88772_status,
4118
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4119
+ .stop = ax88772b_stop,
4120
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4121
+#else
4122
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4123
+#endif
4124
+ .rx_fixup = ax88772_rx_fixup,
4125
+ .tx_fixup = ax88772_tx_fixup,
4126
+ .reset = ax88772b_reset,
4127
+};
4128
+
4129
+static const struct driver_info dlink_dub_e100_772b_info = {
4130
+ .description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
4131
+ .bind = ax88772b_bind,
4132
+ .unbind = ax88772b_unbind,
4133
+ .status = ax88772b_status,
4134
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4135
+ .stop = ax88772b_stop,
4136
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT | FLAG_AVOID_UNLINK_URBS,
4137
+#else
4138
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
4139
+#endif
4140
+ .rx_fixup = ax88772b_rx_fixup,
4141
+ .tx_fixup = ax88772b_tx_fixup,
4142
+ .reset = ax88772b_reset,
4143
+};
4144
+
4145
+static const struct driver_info dlink_dub_e100_772c_info = {
4146
+ .description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
4147
+ .bind = ax88772b_bind,
4148
+ .unbind = ax88772b_unbind,
4149
+ .status = ax88772b_status,
4150
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4151
+ .stop = ax88772b_stop,
4152
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT | FLAG_AVOID_UNLINK_URBS,
4153
+#else
4154
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
4155
+#endif
4156
+ .rx_fixup = ax88772b_rx_fixup,
4157
+ .tx_fixup = ax88772b_tx_fixup,
4158
+ .reset = ax88772b_reset,
4159
+};
4160
+
4161
+static const struct driver_info ax88772a_info = {
4162
+ .description = "",
4163
+// .description = "ASIX AX88772A USB 2.0 Ethernet",
4164
+ .bind = ax88772a_bind,
4165
+ .unbind = ax88772a_unbind,
4166
+ .status = ax88772a_status,
4167
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4168
+ .stop = ax88772b_stop,
4169
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS,
4170
+#else
4171
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
4172
+#endif
4173
+ .rx_fixup = ax88772_rx_fixup,
4174
+ .tx_fixup = ax88772_tx_fixup,
4175
+ .reset = ax88772b_reset,
4176
+};
4177
+
4178
+static const struct driver_info ax88772b_info = {
4179
+ .description = "",
4180
+// .description = "ASIX AX88772B USB 2.0 Ethernet",
4181
+ .bind = ax88772b_bind,
4182
+ .unbind = ax88772b_unbind,
4183
+ .status = ax88772b_status,
4184
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4185
+ .stop = ax88772b_stop,
4186
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT | FLAG_AVOID_UNLINK_URBS,
4187
+#else
4188
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
4189
+#endif
4190
+ .rx_fixup = ax88772b_rx_fixup,
4191
+ .tx_fixup = ax88772b_tx_fixup,
4192
+ .reset = ax88772b_reset,
4193
+};
4194
+
4195
+static const struct driver_info ax88772c_info = {
4196
+ .description = "",
4197
+// .description = "ASIX AX88772C USB 2.0 Ethernet",
4198
+ .bind = ax88772b_bind,
4199
+ .unbind = ax88772b_unbind,
4200
+ .status = ax88772c_status,
4201
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
4202
+ .stop = ax88772b_stop,
4203
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT | FLAG_AVOID_UNLINK_URBS,
4204
+#else
4205
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
4206
+#endif
4207
+ .rx_fixup = ax88772b_rx_fixup,
4208
+ .tx_fixup = ax88772b_tx_fixup,
4209
+ .reset = ax88772b_reset,
4210
+};
4211
+
4212
+static const struct usb_device_id products[] = {
4213
+{
4214
+ /* 88178 */
4215
+ USB_DEVICE(0x0b95, 0x1780),
4216
+ .driver_info = (unsigned long) &ax88178_info,
4217
+}, {
4218
+ /* 88178 for billianton linksys */
4219
+ USB_DEVICE(0x077b, 0x2226),
4220
+ .driver_info = (unsigned long) &ax88178_info,
4221
+}, {
4222
+ /* ABOCOM for linksys */
4223
+ USB_DEVICE(0x1737, 0x0039),
4224
+ .driver_info = (unsigned long) &ax88178_info,
4225
+}, {
4226
+ /* ABOCOM for pci */
4227
+ USB_DEVICE(0x14ea, 0xab11),
4228
+ .driver_info = (unsigned long) &ax88178_info,
4229
+}, {
4230
+ /* Belkin */
4231
+ USB_DEVICE(0x050d, 0x5055),
4232
+ .driver_info = (unsigned long) &belkin178_info,
4233
+}, {
4234
+ /* Linksys USB200M */
4235
+ USB_DEVICE(0x077b, 0x2226),
4236
+ .driver_info = (unsigned long) &ax8817x_info,
4237
+}, {
4238
+ /* Netgear FA120 */
4239
+ USB_DEVICE(0x0846, 0x1040),
4240
+ .driver_info = (unsigned long) &netgear_fa120_info,
4241
+}, {
4242
+ /* DLink DUB-E100 */
4243
+ USB_DEVICE(0x2001, 0x1a00),
4244
+ .driver_info = (unsigned long) &dlink_dub_e100_info,
4245
+}, {
4246
+ /* DLink DUB-E100B */
4247
+ USB_DEVICE(0x2001, 0x3c05),
4248
+ .driver_info = (unsigned long) &dlink_dub_e100b_info,
4249
+}, {
4250
+ /* DLink DUB-E100B */
4251
+ USB_DEVICE(0x07d1, 0x3c05),
4252
+ .driver_info = (unsigned long) &dlink_dub_e100b_info,
4253
+}, {
4254
+ /* DLink DUB-E100 (AX88772B)*/
4255
+ USB_DEVICE_VER(0x2001, 0x1a02, 0, 1),
4256
+ .driver_info = (unsigned long) &dlink_dub_e100_772b_info,
4257
+}, {
4258
+ /* DLink DUB-E100 (AX88772C)*/
4259
+ USB_DEVICE_VER(0x2001, 0x1a02, 0, 2),
4260
+ .driver_info = (unsigned long) &dlink_dub_e100_772c_info,
4261
+}, {
4262
+ /* Intellinet, ST Lab USB Ethernet */
4263
+ USB_DEVICE(0x0b95, 0x1720),
4264
+ .driver_info = (unsigned long) &ax8817x_info,
4265
+}, {
4266
+ /* Hawking UF200, TrendNet TU2-ET100 */
4267
+ USB_DEVICE(0x07b8, 0x420a),
4268
+ .driver_info = (unsigned long) &hawking_uf200_info,
4269
+}, {
4270
+ /* Billionton Systems, USB2AR */
4271
+ USB_DEVICE(0x08dd, 0x90ff),
4272
+ .driver_info = (unsigned long) &ax8817x_info,
4273
+}, {
4274
+ /* ATEN UC210T */
4275
+ USB_DEVICE(0x0557, 0x2009),
4276
+ .driver_info = (unsigned long) &ax8817x_info,
4277
+}, {
4278
+ /* Buffalo LUA-U2-KTX */
4279
+ USB_DEVICE(0x0411, 0x003d),
4280
+ .driver_info = (unsigned long) &ax8817x_info,
4281
+}, {
4282
+ /* Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter" */
4283
+ USB_DEVICE(0x6189, 0x182d),
4284
+ .driver_info = (unsigned long) &ax8817x_info,
4285
+}, {
4286
+ /* corega FEther USB2-TX */
4287
+ USB_DEVICE(0x07aa, 0x0017),
4288
+ .driver_info = (unsigned long) &ax8817x_info,
4289
+}, {
4290
+ /* Surecom EP-1427X-2 */
4291
+ USB_DEVICE(0x1189, 0x0893),
4292
+ .driver_info = (unsigned long) &ax8817x_info,
4293
+}, {
4294
+ /* goodway corp usb gwusb2e */
4295
+ USB_DEVICE(0x1631, 0x6200),
4296
+ .driver_info = (unsigned long) &ax8817x_info,
4297
+}, {
4298
+ /* ASIX AX88772 10/100 */
4299
+ USB_DEVICE(0x0b95, 0x7720),
4300
+ .driver_info = (unsigned long) &ax88772_info,
4301
+}, {
4302
+ /* ASIX AX88772 10/100 */
4303
+ USB_DEVICE(0x125E, 0x180D),
4304
+ .driver_info = (unsigned long) &ax88772_info,
4305
+}, {
4306
+ /* ASIX AX88772A 10/100 */
4307
+ USB_DEVICE(0x0b95, 0x772A),
4308
+ .driver_info = (unsigned long) &ax88772a_info,
4309
+}, {
4310
+ /* ASIX AX88772A 10/100 */
4311
+ USB_DEVICE(0x0db0, 0xA877),
4312
+ .driver_info = (unsigned long) &ax88772a_info,
4313
+}, {
4314
+ /* ASIX AX88772A 10/100 */
4315
+ USB_DEVICE(0x0421, 0x772A),
4316
+ .driver_info = (unsigned long) &ax88772a_info,
4317
+}, {
4318
+ /* Linksys 200M */
4319
+ USB_DEVICE(0x13B1, 0x0018),
4320
+ .driver_info = (unsigned long) &ax88772a_info,
4321
+}, {
4322
+ USB_DEVICE(0x05ac, 0x1402),
4323
+ .driver_info = (unsigned long) &ax88772a_info,
4324
+}, {
4325
+ /* ASIX AX88772B 10/100 */
4326
+ USB_DEVICE_VER(0x0b95, 0x772B, 0, 1),
4327
+ .driver_info = (unsigned long) &ax88772b_info,
4328
+}, {
4329
+ /* Asus AX88772B 10/100 */
4330
+ USB_DEVICE_VER(0x0b95, 0x7e2b, 0, 1),
4331
+ .driver_info = (unsigned long) &ax88772b_info,
4332
+}, {
4333
+ /* Lenovo AX88772B 10/100 */
4334
+ USB_DEVICE_VER(0x17ef, 0x7203, 0, 1),
4335
+ .driver_info = (unsigned long) &ax88772b_info,
4336
+},{
4337
+ /* ASIX AX88772B ver.2 10/100 */
4338
+ USB_DEVICE_VER(0x0b95, 0x772B, 0, 2),
4339
+ .driver_info = (unsigned long) &ax88772c_info,
4340
+},
4341
+ { }, /* END */
4342
+};
4343
+MODULE_DEVICE_TABLE(usb, products);
4344
+
4345
+static struct usb_driver asix_driver = {
4346
+ /* .owner = THIS_MODULE, */
4347
+ .name = "asix",
4348
+ .id_table = products,
4349
+ .probe = axusbnet_probe,
4350
+ .suspend = ax_suspend,
4351
+ .resume = ax_resume,
4352
+ .disconnect = axusbnet_disconnect,
4353
+};
4354
+
4355
+static int __init asix_init(void)
4356
+{
4357
+ return usb_register(&asix_driver);
4358
+}
4359
+module_init(asix_init);
4360
+
4361
+static void __exit asix_exit(void)
4362
+{
4363
+ usb_deregister(&asix_driver);
4364
+}
4365
+module_exit(asix_exit);
4366
+
4367
+MODULE_AUTHOR(DRIVER_AUTHOR);
4368
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
4369
+MODULE_LICENSE(DRIVER_LICENSE);
kernel/drivers/net/usb/ax88772C/asix.h
....@@ -0,0 +1,575 @@
1
+#ifndef __LINUX_USBNET_ASIX_H
2
+#define __LINUX_USBNET_ASIX_H
3
+
4
+/*
5
+ * Turn on this flag if the implementation of your USB host controller
6
+ * cannot handle non-double word aligned buffer.
7
+ * When turn on this flag, driver will fixup egress packet aligned on double
8
+ * word boundary before deliver to USB host controller. And will Disable the
9
+ * function "skb_reserve (skb, NET_IP_ALIGN)" to retain the buffer aligned on
10
+ * double word alignment for ingress packets.
11
+ */
12
+#define AX_FORCE_BUFF_ALIGN 0
13
+
14
+//#define RX_SKB_COPY
15
+
16
+#define AX_MONITOR_MODE 0x01
17
+#define AX_MONITOR_LINK 0x02
18
+#define AX_MONITOR_MAGIC 0x04
19
+#define AX_MONITOR_HSFS 0x10
20
+
21
+/* AX88172 Medium Status Register values */
22
+#define AX_MEDIUM_FULL_DUPLEX 0x02
23
+#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
24
+#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
25
+#define AX_MCAST_FILTER_SIZE 8
26
+#define AX_MAX_MCAST 64
27
+
28
+#define AX_EEPROM_LEN 0x40
29
+
30
+#define AX_SWRESET_CLEAR 0x00
31
+#define AX_SWRESET_RR 0x01
32
+#define AX_SWRESET_RT 0x02
33
+#define AX_SWRESET_PRTE 0x04
34
+#define AX_SWRESET_PRL 0x08
35
+#define AX_SWRESET_BZ 0x10
36
+#define AX_SWRESET_IPRL 0x20
37
+#define AX_SWRESET_IPPD 0x40
38
+#define AX_SWRESET_IPOSC 0x0080
39
+#define AX_SWRESET_IPPSL_0 0x0100
40
+#define AX_SWRESET_IPPSL_1 0x0200
41
+#define AX_SWRESET_IPCOPS 0x0400
42
+#define AX_SWRESET_IPCOPSC 0x0800
43
+#define AX_SWRESET_AUTODETACH 0x1000
44
+#define AX_SWRESET_WOLLP 0x8000
45
+
46
+#define AX88772_IPG0_DEFAULT 0x15
47
+#define AX88772_IPG1_DEFAULT 0x0c
48
+#define AX88772_IPG2_DEFAULT 0x0E
49
+
50
+#define AX88772A_IPG0_DEFAULT 0x15
51
+#define AX88772A_IPG1_DEFAULT 0x16
52
+#define AX88772A_IPG2_DEFAULT 0x1A
53
+
54
+#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
55
+#define AX88772_MEDIUM_RESERVED 0x0004
56
+#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
57
+#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
58
+#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
59
+#define AX88772_MEDIUM_RX_ENABLE 0x0100
60
+#define AX88772_MEDIUM_100MB 0x0200
61
+#define AX88772_MEDIUM_DEFAULT \
62
+ (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
63
+ AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
64
+ AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE)
65
+
66
+#define AX_CMD_SET_SW_MII 0x06
67
+#define AX_CMD_READ_MII_REG 0x07
68
+#define AX_CMD_WRITE_MII_REG 0x08
69
+#define AX_CMD_READ_STATMNGSTS_REG 0x09
70
+ #define AX_HOST_EN 0x01
71
+
72
+#define AX_CMD_SET_HW_MII 0x0a
73
+#define AX_CMD_READ_EEPROM 0x0b
74
+#define AX_CMD_WRITE_EEPROM 0x0c
75
+#define AX_CMD_WRITE_EEPROM_EN 0x0d
76
+#define AX_CMD_WRITE_EEPROM_DIS 0x0e
77
+#define AX_CMD_WRITE_RX_CTL 0x10
78
+#define AX_CMD_READ_IPG012 0x11
79
+#define AX_CMD_WRITE_IPG0 0x12
80
+#define AX_CMD_WRITE_IPG1 0x13
81
+#define AX_CMD_WRITE_IPG2 0x14
82
+#define AX_CMD_WRITE_MULTI_FILTER 0x16
83
+#define AX_CMD_READ_NODE_ID 0x17
84
+#define AX_CMD_READ_PHY_ID 0x19
85
+#define AX_CMD_READ_MEDIUM_MODE 0x1a
86
+#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
87
+#define AX_CMD_READ_MONITOR_MODE 0x1c
88
+#define AX_CMD_WRITE_MONITOR_MODE 0x1d
89
+#define AX_CMD_WRITE_GPIOS 0x1f
90
+#define AX_CMD_SW_RESET 0x20
91
+#define AX_CMD_SW_PHY_STATUS 0x21
92
+#define AX_CMD_SW_PHY_SELECT 0x22
93
+ #define AX_PHYSEL_PSEL (1 << 0)
94
+ #define AX_PHYSEL_ASEL (1 << 1)
95
+ #define AX_PHYSEL_SSMII (0 << 2)
96
+ #define AX_PHYSEL_SSRMII (1 << 2)
97
+ #define AX_PHYSEL_SSRRMII (3 << 2)
98
+ #define AX_PHYSEL_SSEN (1 << 4)
99
+#define AX88772_CMD_READ_NODE_ID 0x13
100
+#define AX88772_CMD_WRITE_NODE_ID 0x14
101
+#define AX_CMD_READ_WKFARY 0x23
102
+#define AX_CMD_WRITE_WKFARY 0x24
103
+#define AX_CMD_READ_RXCOE_CTL 0x2b
104
+#define AX_CMD_WRITE_RXCOE_CTL 0x2c
105
+#define AX_CMD_READ_TXCOE_CTL 0x2d
106
+#define AX_CMD_WRITE_TXCOE_CTL 0x2e
107
+
108
+#define REG_LENGTH 2
109
+#define PHY_ID_MASK 0x1f
110
+
111
+#define AX_RXCOE_IPCE 0x0001
112
+#define AX_RXCOE_IPVE 0x0002
113
+#define AX_RXCOE_V6VE 0x0004
114
+#define AX_RXCOE_TCPE 0x0008
115
+#define AX_RXCOE_UDPE 0x0010
116
+#define AX_RXCOE_ICMP 0x0020
117
+#define AX_RXCOE_IGMP 0x0040
118
+#define AX_RXCOE_ICV6 0x0080
119
+#define AX_RXCOE_TCPV6 0x0100
120
+#define AX_RXCOE_UDPV6 0x0200
121
+#define AX_RXCOE_ICMV6 0x0400
122
+#define AX_RXCOE_IGMV6 0x0800
123
+#define AX_RXCOE_ICV6V6 0x1000
124
+#define AX_RXCOE_FOPC 0x8000
125
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
126
+#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
127
+ AX_RXCOE_V6VE | AX_RXCOE_TCPE | \
128
+ AX_RXCOE_UDPE | AX_RXCOE_ICV6 | \
129
+ AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6)
130
+#else
131
+#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
132
+ AX_RXCOE_TCPE | AX_RXCOE_UDPE)
133
+#endif
134
+
135
+#define AX_RXCOE_64TE 0x0100
136
+#define AX_RXCOE_PPPOE 0x0200
137
+#define AX_RXCOE_RPCE 0x8000
138
+
139
+#define AX_TXCOE_IP 0x0001
140
+#define AX_TXCOE_TCP 0x0002
141
+#define AX_TXCOE_UDP 0x0004
142
+#define AX_TXCOE_ICMP 0x0008
143
+#define AX_TXCOE_IGMP 0x0010
144
+#define AX_TXCOE_ICV6 0x0020
145
+
146
+#define AX_TXCOE_TCPV6 0x0100
147
+#define AX_TXCOE_UDPV6 0x0200
148
+#define AX_TXCOE_ICMV6 0x0400
149
+#define AX_TXCOE_IGMV6 0x0800
150
+#define AX_TXCOE_ICV6V6 0x1000
151
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
152
+#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \
153
+ AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6)
154
+#else
155
+#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP)
156
+#endif
157
+
158
+#define AX_TXCOE_64TE 0x0001
159
+#define AX_TXCOE_PPPE 0x0002
160
+
161
+#define AX88772B_MAX_BULKIN_2K 0
162
+#define AX88772B_MAX_BULKIN_4K 1
163
+#define AX88772B_MAX_BULKIN_6K 2
164
+#define AX88772B_MAX_BULKIN_8K 3
165
+#define AX88772B_MAX_BULKIN_16K 4
166
+#define AX88772B_MAX_BULKIN_20K 5
167
+#define AX88772B_MAX_BULKIN_24K 6
168
+#define AX88772B_MAX_BULKIN_32K 7
169
+struct {unsigned short size, byte_cnt, threshold; } AX88772B_BULKIN_SIZE[] = {
170
+ /* 2k */
171
+ {2048, 0x8000, 0x8001},
172
+ /* 4k */
173
+ {4096, 0x8100, 0x8147},
174
+ /* 6k */
175
+ {6144, 0x8200, 0x81EB},
176
+ /* 8k */
177
+ {8192, 0x8300, 0x83D7},
178
+ /* 16 */
179
+ {16384, 0x8400, 0x851E},
180
+ /* 20k */
181
+ {20480, 0x8500, 0x8666},
182
+ /* 24k */
183
+ {24576, 0x8600, 0x87AE},
184
+ /* 32k */
185
+ {32768, 0x8700, 0x8A3D},
186
+};
187
+
188
+
189
+#define AX_RX_CTL_RH1M 0x0100 /* Enable RX-Header mode 0 */
190
+#define AX_RX_CTL_RH2M 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */
191
+#define AX_RX_CTL_RH3M 0x0400 /* checksum value in rx header 3 */
192
+#define AX_RX_HEADER_DEFAULT (AX_RX_CTL_RH1M | AX_RX_CTL_RH2M)
193
+
194
+#define AX_RX_CTL_MFB 0x0300 /* Maximum Frame size 16384bytes */
195
+#define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */
196
+#define AX_RX_CTL_AP 0x0020 /* Accept physcial address from Multicast array */
197
+#define AX_RX_CTL_AM 0x0010
198
+#define AX_RX_CTL_AB 0x0008 /* Accetp Brocadcast frames*/
199
+#define AX_RX_CTL_SEP 0x0004 /* Save error packets */
200
+#define AX_RX_CTL_AMALL 0x0002 /* Accetp all multicast frames */
201
+#define AX_RX_CTL_PRO 0x0001 /* Promiscuous Mode */
202
+#define AX_RX_CTL_STOP 0x0000 /* Stop MAC */
203
+
204
+#define AX_MONITOR_MODE 0x01
205
+#define AX_MONITOR_LINK 0x02
206
+#define AX_MONITOR_MAGIC 0x04
207
+#define AX_MONITOR_HSFS 0x10
208
+
209
+#define AX_MCAST_FILTER_SIZE 8
210
+#define AX_MAX_MCAST 64
211
+#define AX_INTERRUPT_BUFSIZE 8
212
+
213
+#define AX_EEPROM_LEN 0x40
214
+#define AX_EEPROM_MAGIC 0xdeadbeef
215
+#define EEPROMMASK 0x7f
216
+
217
+/* GPIO REGISTER */
218
+#define AXGPIOS_GPO0EN 0X01 /* 1 << 0 */
219
+#define AXGPIOS_GPO0 0X02 /* 1 << 1 */
220
+#define AXGPIOS_GPO1EN 0X04 /* 1 << 2 */
221
+#define AXGPIOS_GPO1 0X08 /* 1 << 3 */
222
+#define AXGPIOS_GPO2EN 0X10 /* 1 << 4 */
223
+#define AXGPIOS_GPO2 0X20 /* 1 << 5 */
224
+#define AXGPIOS_RSE 0X80 /* 1 << 7 */
225
+
226
+/* TX-header format */
227
+#define AX_TX_HDR_CPHI 0x4000
228
+#define AX_TX_HDR_DICF 0x8000
229
+
230
+/* GMII register definitions */
231
+#define GMII_PHY_CONTROL 0x00 /* control reg */
232
+#define GMII_PHY_STATUS 0x01 /* status reg */
233
+#define GMII_PHY_OUI 0x02 /* most of the OUI bits */
234
+#define GMII_PHY_MODEL 0x03 /* model/rev bits, and rest of OUI */
235
+#define GMII_PHY_ANAR 0x04 /* AN advertisement reg */
236
+#define GMII_PHY_ANLPAR 0x05 /* AN Link Partner */
237
+#define GMII_PHY_ANER 0x06 /* AN expansion reg */
238
+#define GMII_PHY_1000BT_CONTROL 0x09 /* control reg for 1000BT */
239
+#define GMII_PHY_1000BT_STATUS 0x0A /* status reg for 1000BT */
240
+
241
+/* Bit definitions: GMII Control */
242
+#define GMII_CONTROL_RESET 0x8000 /* reset bit in control reg */
243
+#define GMII_CONTROL_LOOPBACK 0x4000 /* loopback bit in control reg */
244
+#define GMII_CONTROL_10MB 0x0000 /* 10 Mbit */
245
+#define GMII_CONTROL_100MB 0x2000 /* 100Mbit */
246
+#define GMII_CONTROL_1000MB 0x0040 /* 1000Mbit */
247
+#define GMII_CONTROL_SPEED_BITS 0x2040 /* speed bit mask */
248
+#define GMII_CONTROL_ENABLE_AUTO 0x1000 /* autonegotiate enable */
249
+#define GMII_CONTROL_POWER_DOWN 0x0800
250
+#define GMII_CONTROL_ISOLATE 0x0400 /* islolate bit */
251
+#define GMII_CONTROL_START_AUTO 0x0200 /* restart autonegotiate */
252
+#define GMII_CONTROL_FULL_DUPLEX 0x0100
253
+
254
+/* Bit definitions: GMII Status */
255
+#define GMII_STATUS_100MB_MASK 0xE000 /* any of these indicate 100 Mbit */
256
+#define GMII_STATUS_10MB_MASK 0x1800 /* either of these indicate 10 Mbit */
257
+#define GMII_STATUS_AUTO_DONE 0x0020 /* auto negotiation complete */
258
+#define GMII_STATUS_AUTO 0x0008 /* auto negotiation is available */
259
+#define GMII_STATUS_LINK_UP 0x0004 /* link status bit */
260
+#define GMII_STATUS_EXTENDED 0x0001 /* extended regs exist */
261
+#define GMII_STATUS_100T4 0x8000 /* capable of 100BT4 */
262
+#define GMII_STATUS_100TXFD 0x4000 /* capable of 100BTX full duplex */
263
+#define GMII_STATUS_100TX 0x2000 /* capable of 100BTX */
264
+#define GMII_STATUS_10TFD 0x1000 /* capable of 10BT full duplex */
265
+#define GMII_STATUS_10T 0x0800 /* capable of 10BT */
266
+
267
+/* Bit definitions: Auto-Negotiation Advertisement */
268
+#define GMII_ANAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
269
+#define GMII_ANAR_PAUSE 0x0400 /* support pause packets */
270
+#define GMII_ANAR_100T4 0x0200 /* support 100BT4 */
271
+#define GMII_ANAR_100TXFD 0x0100 /* support 100BTX full duplex */
272
+#define GMII_ANAR_100TX 0x0080 /* support 100BTX half duplex */
273
+#define GMII_ANAR_10TFD 0x0040 /* support 10BT full duplex */
274
+#define GMII_ANAR_10T 0x0020 /* support 10BT half duplex */
275
+#define GMII_SELECTOR_FIELD 0x001F /* selector field. */
276
+
277
+/* Bit definitions: Auto-Negotiation Link Partner Ability */
278
+#define GMII_ANLPAR_100T4 0x0200 /* support 100BT4 */
279
+#define GMII_ANLPAR_100TXFD 0x0100 /* support 100BTX full duplex */
280
+#define GMII_ANLPAR_100TX 0x0080 /* support 100BTX half duplex */
281
+#define GMII_ANLPAR_10TFD 0x0040 /* support 10BT full duplex */
282
+#define GMII_ANLPAR_10T 0x0020 /* support 10BT half duplex */
283
+#define GMII_ANLPAR_PAUSE 0x0400 /* support pause packets */
284
+#define GMII_ANLPAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
285
+#define GMII_ANLPAR_ACK 0x4000 /* means LCB was successfully rx'd */
286
+#define GMII_SELECTOR_8023 0x0001;
287
+
288
+/* Bit definitions: 1000BaseT AUX Control */
289
+#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000
290
+#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 /* full duplex capable */
291
+#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 /* half duplex capable */
292
+
293
+/* Bit definitions: 1000BaseT AUX Status */
294
+#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 /* full duplex capable */
295
+#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 /* half duplex capable */
296
+
297
+/* Cicada MII Registers */
298
+#define GMII_AUX_CTRL_STATUS 0x1C
299
+#define GMII_AUX_ANEG_CPLT 0x8000
300
+#define GMII_AUX_FDX 0x0020
301
+#define GMII_AUX_SPEED_1000 0x0010
302
+#define GMII_AUX_SPEED_100 0x0008
303
+
304
+#ifndef ADVERTISE_PAUSE_CAP
305
+#define ADVERTISE_PAUSE_CAP 0x0400
306
+#endif
307
+
308
+#ifndef MII_STAT1000
309
+#define MII_STAT1000 0x000A
310
+#endif
311
+
312
+#ifndef LPA_1000FULL
313
+#define LPA_1000FULL 0x0800
314
+#endif
315
+
316
+/* medium mode register */
317
+#define MEDIUM_GIGA_MODE 0x0001
318
+#define MEDIUM_FULL_DUPLEX_MODE 0x0002
319
+#define MEDIUM_TX_ABORT_MODE 0x0004
320
+#define MEDIUM_ENABLE_125MHZ 0x0008
321
+#define MEDIUM_ENABLE_RX_FLOWCTRL 0x0010
322
+#define MEDIUM_ENABLE_TX_FLOWCTRL 0x0020
323
+#define MEDIUM_ENABLE_JUMBO_FRAME 0x0040
324
+#define MEDIUM_CHECK_PAUSE_FRAME_MODE 0x0080
325
+#define MEDIUM_ENABLE_RECEIVE 0x0100
326
+#define MEDIUM_MII_100M_MODE 0x0200
327
+#define MEDIUM_ENABLE_JAM_PATTERN 0x0400
328
+#define MEDIUM_ENABLE_STOP_BACKPRESSURE 0x0800
329
+#define MEDIUM_ENABLE_SUPPER_MAC_SUPPORT 0x1000
330
+
331
+/* PHY mode */
332
+#define PHY_MODE_MARVELL 0
333
+#define PHY_MODE_CICADA_FAMILY 1
334
+#define PHY_MODE_CICADA_V1 1
335
+#define PHY_MODE_AGERE_FAMILY 2
336
+#define PHY_MODE_AGERE_V0 2
337
+#define PHY_MODE_CICADA_V2 5
338
+#define PHY_MODE_AGERE_V0_GMII 6
339
+#define PHY_MODE_CICADA_V2_ASIX 9
340
+#define PHY_MODE_VSC8601 10
341
+#define PHY_MODE_RTL8211CL 12
342
+#define PHY_MODE_RTL8211BN 13
343
+#define PHY_MODE_RTL8251CL 14
344
+#define PHY_MODE_ATTANSIC_V0 0x40
345
+#define PHY_MODE_ATTANSIC_FAMILY 0x40
346
+#define PHY_MODE_MAC_TO_MAC_GMII 0x7C
347
+
348
+/* */
349
+#define LED_MODE_MARVELL 0
350
+#define LED_MODE_CAMEO 1
351
+
352
+#define MARVELL_LED_CTRL 0x18
353
+#define MARVELL_MANUAL_LED 0x19
354
+
355
+#define PHY_IDENTIFIER 0x0002
356
+#define PHY_AGERE_IDENTIFIER 0x0282
357
+#define PHY_CICADA_IDENTIFIER 0x000f
358
+#define PHY_MARVELL_IDENTIFIER 0x0141
359
+
360
+#define PHY_MARVELL_STATUS 0x001b
361
+#define MARVELL_STATUS_HWCFG 0x0004 /* SGMII without clock */
362
+
363
+#define PHY_MARVELL_CTRL 0x0014
364
+#define MARVELL_CTRL_RXDELAY 0x0080
365
+#define MARVELL_CTRL_TXDELAY 0x0002
366
+
367
+#define PHY_CICADA_EXTPAGE 0x001f
368
+#define CICADA_EXTPAGE_EN 0x0001
369
+#define CICADA_EXTPAGE_DIS 0x0000
370
+
371
+/* External ethernet phy */
372
+#define EXTPHY_ID_MASK_OUI(phyid1, phyid2) ((phyid1 << 6) | ((phyid2 & 0xFC00) >> 10))
373
+#define EXTPHY_ID_MASK_MODEL(phyid2) ((phyid2 & 0x3F0) >> 4)
374
+
375
+#define EXTPHY_BROADCOM_OUI 0x2B8094
376
+#define EXTPHY_BCM89811_MODEL 0x02
377
+
378
+struct {unsigned short value, offset; } CICADA_FAMILY_HWINIT[] = {
379
+ {0x0001, 0x001f}, {0x1c25, 0x0017}, {0x2a30, 0x001f}, {0x234c, 0x0010},
380
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa7fa, 0x0000},
381
+ {0x0012, 0x0002}, {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f},
382
+ {0xafac, 0x0000}, {0x000d, 0x0002}, {0x001c, 0x0001}, {0x8fac, 0x0000},
383
+ {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x2a30, 0x001f}, {0x0400, 0x0014},
384
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa760, 0x0000},
385
+ {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000}, {0x52b5, 0x001f},
386
+ {0xa760, 0x0000}, {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000},
387
+ {0x52b5, 0x001f}, {0xafae, 0x0000}, {0x0004, 0x0002}, {0x0671, 0x0001},
388
+ {0x8fae, 0x0000}, {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x0000, 0x001f},
389
+};
390
+
391
+struct {unsigned short value, offset; } CICADA_V2_HWINIT[] = {
392
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x000f, 0x0002},
393
+ {0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
394
+ {0x0000, 0x001f},
395
+};
396
+
397
+struct {unsigned short value, offset; } CICADA_V2_ASIX_HWINIT[] = {
398
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x0012, 0x0002},
399
+ {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f}, {0x000f, 0x0002},
400
+ {0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
401
+ {0x0000, 0x001f},
402
+};
403
+
404
+struct {unsigned short value, offset; } AGERE_FAMILY_HWINIT[] = {
405
+ {0x0800, 0x0000}, {0x0007, 0x0012}, {0x8805, 0x0010}, {0xb03e, 0x0011},
406
+ {0x8808, 0x0010}, {0xe110, 0x0011}, {0x8806, 0x0010}, {0xb03e, 0x0011},
407
+ {0x8807, 0x0010}, {0xff00, 0x0011}, {0x880e, 0x0010}, {0xb4d3, 0x0011},
408
+ {0x880f, 0x0010}, {0xb4d3, 0x0011}, {0x8810, 0x0010}, {0xb4d3, 0x0011},
409
+ {0x8817, 0x0010}, {0x1c00, 0x0011}, {0x300d, 0x0010}, {0x0001, 0x0011},
410
+ {0x0002, 0x0012},
411
+};
412
+
413
+struct ax88178_data {
414
+ u16 EepromData;
415
+ u16 MediaLink;
416
+ int UseGpio0;
417
+ int UseRgmii;
418
+ u8 PhyMode;
419
+ u8 LedMode;
420
+ u8 BuffaloOld;
421
+};
422
+
423
+enum watchdog_state {
424
+ AX_NOP = 0,
425
+ CHK_LINK, /* Routine A */
426
+ CHK_CABLE_EXIST, /* Called by A */
427
+ CHK_CABLE_EXIST_AGAIN, /* Routine B */
428
+ PHY_POWER_UP, /* Called by B */
429
+ PHY_POWER_UP_BH,
430
+ PHY_POWER_DOWN,
431
+ CHK_CABLE_STATUS, /* Routine C */
432
+ WAIT_AUTONEG_COMPLETE,
433
+ AX_SET_RX_CFG,
434
+ AX_CHK_AUTODETACH,
435
+};
436
+
437
+struct ax88772b_data {
438
+ struct usbnet *dev;
439
+ struct workqueue_struct *ax_work;
440
+ struct work_struct check_link;
441
+ unsigned long time_to_chk;
442
+ u16 psc;
443
+ u8 pw_enabled;
444
+ u8 Event;
445
+ u8 checksum;
446
+ u8 PhySelect:1;
447
+ u8 OperationMode:1;
448
+ u16 presvd_phy_advertise;
449
+ u16 presvd_phy_bmcr;
450
+
451
+ u32 ext_phy_oui;
452
+ u8 ext_phy_model;
453
+};
454
+
455
+/* define for MAC or PHY mode */
456
+#define OPERATION_MAC_MODE 0
457
+#define OPERATION_PHY_MODE 1
458
+
459
+struct ax88772a_data {
460
+ struct usbnet *dev;
461
+ struct workqueue_struct *ax_work;
462
+ struct work_struct check_link;
463
+ unsigned long autoneg_start;
464
+#define AX88772B_WATCHDOG (6 * HZ)
465
+ u8 Event;
466
+ u8 TickToExpire;
467
+ u8 DlyIndex;
468
+ u8 DlySel;
469
+ u16 EepromData;
470
+ u16 presvd_phy_advertise;
471
+ u16 presvd_phy_bmcr;
472
+};
473
+
474
+struct ax88772_data {
475
+ struct usbnet *dev;
476
+ struct workqueue_struct *ax_work;
477
+ struct work_struct check_link;
478
+ unsigned long autoneg_start;
479
+ u8 Event;
480
+ u8 TickToExpire;
481
+ u16 presvd_phy_advertise;
482
+ u16 presvd_phy_bmcr;
483
+};
484
+
485
+#define AX_RX_CHECKSUM 1
486
+#define AX_TX_CHECKSUM 2
487
+
488
+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
489
+struct ax8817x_data {
490
+ u8 multi_filter[AX_MCAST_FILTER_SIZE];
491
+ int (*resume) (struct usb_interface *intf);
492
+ int (*suspend) (struct usb_interface *intf,
493
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
494
+ pm_message_t message);
495
+#else
496
+ u32 message);
497
+#endif
498
+};
499
+
500
+struct ax88172_int_data {
501
+ u16 res1;
502
+#define AX_INT_PPLS_LINK (1 << 0)
503
+#define AX_INT_SPLS_LINK (1 << 1)
504
+#define AX_INT_CABOFF_UNPLUG (1 << 7)
505
+ u8 link;
506
+ u16 res2;
507
+ u8 status;
508
+ u16 res3;
509
+} __attribute__ ((packed));
510
+
511
+#define AX_RXHDR_L4_ERR (1 << 8)
512
+#define AX_RXHDR_L3_ERR (1 << 9)
513
+
514
+#define AX_RXHDR_L4_TYPE_UDP 1
515
+#define AX_RXHDR_L4_TYPE_ICMP 2
516
+#define AX_RXHDR_L4_TYPE_IGMP 3
517
+#define AX_RXHDR_L4_TYPE_TCP 4
518
+#define AX_RXHDR_L4_TYPE_TCMPV6 5
519
+#define AX_RXHDR_L4_TYPE_MASK 7
520
+
521
+#define AX_RXHDR_L3_TYPE_IP 1
522
+#define AX_RXHDR_L3_TYPE_IPV6 2
523
+
524
+struct ax88772b_rx_header {
525
+#if defined(__LITTLE_ENDIAN_BITFIELD)
526
+ u16 len:11,
527
+ res1:1,
528
+ crc:1,
529
+ mii:1,
530
+ runt:1,
531
+ mc_bc:1;
532
+
533
+ u16 len_bar:11,
534
+ res2:5;
535
+
536
+ u8 vlan_ind:3,
537
+ vlan_tag_striped:1,
538
+ pri:3,
539
+ res3:1;
540
+
541
+ u8 l4_csum_err:1,
542
+ l3_csum_err:1,
543
+ l4_type:3,
544
+ l3_type:2,
545
+ ce:1;
546
+#elif defined(__BIG_ENDIAN_BITFIELD)
547
+ u16 mc_bc:1,
548
+ runt:1,
549
+ mii:1,
550
+ crc:1,
551
+ res1:1,
552
+ len:11;
553
+
554
+ u16 res2:5,
555
+ len_bar:11;
556
+
557
+ u8 res3:1,
558
+ pri:3,
559
+ vlan_tag_striped:1,
560
+ vlan_ind:3;
561
+
562
+ u8 ce:1,
563
+ l3_type:2,
564
+ l4_type:3,
565
+ l3_csum_err:1,
566
+ l4_csum_err:1;
567
+#else
568
+#error "Please fix <asm/byteorder.h>"
569
+#endif
570
+
571
+} __attribute__ ((packed));
572
+
573
+
574
+#endif /* __LINUX_USBNET_ASIX_H */
575
+
kernel/drivers/net/usb/ax88772C/axusbnet.c
....@@ -0,0 +1,1488 @@
1
+/*
2
+ * USB Network driver infrastructure
3
+ * Copyright (C) 2000-2005 by David Brownell
4
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ */
20
+
21
+/*
22
+ * This is a generic "USB networking" framework that works with several
23
+ * kinds of full and high speed networking devices: host-to-host cables,
24
+ * smart usb peripherals, and actual Ethernet adapters.
25
+ *
26
+ * These devices usually differ in terms of control protocols (if they
27
+ * even have one!) and sometimes they define new framing to wrap or batch
28
+ * Ethernet packets. Otherwise, they talk to USB pretty much the same,
29
+ * so interface (un)binding, endpoint I/O queues, fault handling, and other
30
+ * issues can usefully be addressed by this framework.
31
+ */
32
+
33
+/* error path messages, extra info */
34
+#define DEBUG
35
+/* more; success messages */
36
+/* #define VERBOSE */
37
+
38
+#include <linux/module.h>
39
+#include <linux/init.h>
40
+#include <linux/netdevice.h>
41
+#include <linux/etherdevice.h>
42
+#include <linux/ctype.h>
43
+#include <linux/ethtool.h>
44
+#include <linux/workqueue.h>
45
+#include <linux/mii.h>
46
+#include <linux/usb.h>
47
+/*#include <linux/usb/usbnet.h>*/
48
+
49
+#include "asix.h"
50
+#include "axusbnet.h"
51
+
52
+#define DRIVER_VERSION "4.24.0"
53
+#define DRIVER_AUTHOR "David Hollis"
54
+#define DRIVER_DESCRIPTION "ASIX AX88772C_772B_772A_760_772_178 USB 2.0 \
55
+Ethernet Devices"
56
+#define DRIVER_LICENSE "GPL"
57
+
58
+static void axusbnet_unlink_rx_urbs(struct usbnet *);
59
+
60
+static void
61
+ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
62
+ u16 size, void *data);
63
+
64
+/*-------------------------------------------------------------------------*/
65
+
66
+/*
67
+ * Nineteen USB 1.1 max size bulk transactions per frame (ms), max.
68
+ * Several dozen bytes of IPv4 data can fit in two such transactions.
69
+ * One maximum size Ethernet packet takes twenty four of them.
70
+ * For high speed, each frame comfortably fits almost 36 max size
71
+ * Ethernet packets (so queues should be bigger).
72
+ *
73
+ * REVISIT qlens should be members of 'struct usbnet'; the goal is to
74
+ * let the USB host controller be busy for 5msec or more before an irq
75
+ * is required, under load. Jumbograms change the equation.
76
+ */
77
+#define RX_MAX_QUEUE_MEMORY (60 * 1518)
78
+#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
79
+ (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4)
80
+#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
81
+ (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4)
82
+
83
+/* reawaken network queue this soon after stopping; else watchdog barks */
84
+/* #define TX_TIMEOUT_JIFFIES (5 * HZ) */
85
+#define TX_TIMEOUT_JIFFIES (30 * HZ)
86
+
87
+/* throttle rx/tx briefly after some faults, so khubd might disconnect() */
88
+/* us (it polls at HZ/4 usually) before we report too many false errors. */
89
+#define THROTTLE_JIFFIES (HZ / 8)
90
+
91
+/* between wakeups */
92
+#define UNLINK_TIMEOUT_MS 3
93
+
94
+/*-------------------------------------------------------------------------*/
95
+
96
+static const char driver_name[] = "axusbnet";
97
+
98
+/* use ethtool to change the level for any given device */
99
+static int msg_level = -1;
100
+module_param(msg_level, int, 0);
101
+MODULE_PARM_DESC(msg_level, "Override default message level");
102
+
103
+/*-------------------------------------------------------------------------*/
104
+
105
+/* handles CDC Ethernet and many other network "bulk data" interfaces */
106
+static
107
+int axusbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
108
+{
109
+ int tmp;
110
+ struct usb_host_interface *alt = NULL;
111
+ struct usb_host_endpoint *in = NULL, *out = NULL;
112
+ struct usb_host_endpoint *status = NULL;
113
+
114
+ for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
115
+ unsigned ep;
116
+
117
+ in = out = status = NULL;
118
+ alt = intf->altsetting + tmp;
119
+
120
+ /* take the first altsetting with in-bulk + out-bulk;
121
+ * remember any status endpoint, just in case;
122
+ * ignore other endpoints and altsetttings.
123
+ */
124
+ for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
125
+ struct usb_host_endpoint *e;
126
+ int intr = 0;
127
+
128
+ e = alt->endpoint + ep;
129
+ switch (e->desc.bmAttributes) {
130
+ case USB_ENDPOINT_XFER_INT:
131
+ if (!(e->desc.bEndpointAddress & USB_DIR_IN))
132
+ continue;
133
+ intr = 1;
134
+ /* FALLTHROUGH */
135
+ case USB_ENDPOINT_XFER_BULK:
136
+ break;
137
+ default:
138
+ continue;
139
+ }
140
+ if (e->desc.bEndpointAddress & USB_DIR_IN) {
141
+ if (!intr && !in) {
142
+ in = e;
143
+ } else if (intr && !status) {
144
+ status = e;
145
+ }
146
+ } else {
147
+ if (!out) {
148
+ out = e;
149
+ }
150
+ }
151
+ }
152
+ if (in && out)
153
+ break;
154
+ }
155
+ if (!alt || !in || !out)
156
+ return -EINVAL;
157
+
158
+ if (alt->desc.bAlternateSetting != 0
159
+ || !(dev->driver_info->flags & FLAG_NO_SETINT)) {
160
+ tmp = usb_set_interface(dev->udev, alt->desc.bInterfaceNumber,
161
+ alt->desc.bAlternateSetting);
162
+ if (tmp < 0)
163
+ return tmp;
164
+ }
165
+
166
+ dev->in = usb_rcvbulkpipe(dev->udev,
167
+ in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
168
+ dev->out = usb_sndbulkpipe(dev->udev,
169
+ out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
170
+ dev->status = status;
171
+ return 0;
172
+}
173
+
174
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
175
+static void intr_complete(struct urb *urb, struct pt_regs *regs);
176
+#else
177
+static void intr_complete(struct urb *urb);
178
+#endif
179
+
180
+static int init_status(struct usbnet *dev, struct usb_interface *intf)
181
+{
182
+ char *buf = NULL;
183
+ unsigned pipe = 0;
184
+ unsigned maxp;
185
+ unsigned period;
186
+
187
+ if (!dev->driver_info->status)
188
+ return 0;
189
+
190
+ pipe = usb_rcvintpipe(dev->udev,
191
+ dev->status->desc.bEndpointAddress
192
+ & USB_ENDPOINT_NUMBER_MASK);
193
+ maxp = usb_maxpacket(dev->udev, pipe, 0);
194
+
195
+ /* avoid 1 msec chatter: min 8 msec poll rate */
196
+ period = max((int) dev->status->desc.bInterval,
197
+ (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
198
+
199
+ buf = kmalloc(maxp, GFP_KERNEL);
200
+ if (buf) {
201
+ dev->interrupt = usb_alloc_urb(0, GFP_KERNEL);
202
+ if (!dev->interrupt) {
203
+ kfree(buf);
204
+ return -ENOMEM;
205
+ } else {
206
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
207
+ dev->interrupt->transfer_flags |= URB_ASYNC_UNLINK;
208
+#endif
209
+ usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
210
+ buf, maxp, intr_complete, dev, period);
211
+ devdbg(dev,
212
+ "status ep%din, %d bytes period %d",
213
+ usb_pipeendpoint(pipe), maxp, period);
214
+ }
215
+ }
216
+ return 0;
217
+}
218
+
219
+/* Passes this packet up the stack, updating its accounting.
220
+ * Some link protocols batch packets, so their rx_fixup paths
221
+ * can return clones as well as just modify the original skb.
222
+ */
223
+static
224
+void axusbnet_skb_return(struct usbnet *dev, struct sk_buff *skb)
225
+{
226
+ int status;
227
+
228
+ skb->dev = dev->net;
229
+ skb->protocol = eth_type_trans(skb, dev->net);
230
+ dev->stats.rx_packets++;
231
+ dev->stats.rx_bytes += skb->len;
232
+
233
+ if (netif_msg_rx_status(dev))
234
+ devdbg(dev, "< rx, len %zu, type 0x%x",
235
+ skb->len + sizeof(struct ethhdr), skb->protocol);
236
+ memset(skb->cb, 0, sizeof(struct skb_data));
237
+ status = netif_rx(skb);
238
+ if (status != NET_RX_SUCCESS && netif_msg_rx_err(dev))
239
+ devdbg(dev, "netif_rx status %d", status);
240
+}
241
+
242
+/*-------------------------------------------------------------------------
243
+ *
244
+ * Network Device Driver (peer link to "Host Device", from USB host)
245
+ *
246
+ *-------------------------------------------------------------------------*/
247
+
248
+static
249
+int axusbnet_change_mtu(struct net_device *net, int new_mtu)
250
+{
251
+ struct usbnet *dev = netdev_priv(net);
252
+ int ll_mtu = new_mtu + net->hard_header_len;
253
+ int old_hard_mtu = dev->hard_mtu;
254
+ int old_rx_urb_size = dev->rx_urb_size;
255
+
256
+ if (new_mtu <= 0)
257
+ return -EINVAL;
258
+ /* no second zero-length packet read wanted after mtu-sized packets */
259
+ if ((ll_mtu % dev->maxpacket) == 0)
260
+ return -EDOM;
261
+ net->mtu = new_mtu;
262
+
263
+ dev->hard_mtu = net->mtu + net->hard_header_len;
264
+ if (dev->rx_urb_size == old_hard_mtu) {
265
+ dev->rx_urb_size = dev->hard_mtu;
266
+ if (dev->rx_urb_size > old_rx_urb_size)
267
+ axusbnet_unlink_rx_urbs(dev);
268
+ }
269
+
270
+ return 0;
271
+}
272
+
273
+static struct net_device_stats *axusbnet_get_stats(struct net_device *net)
274
+{
275
+ struct usbnet *dev = netdev_priv(net);
276
+ return &dev->stats;
277
+}
278
+
279
+/*-------------------------------------------------------------------------*/
280
+
281
+/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
282
+ * completion callbacks. 2.5 should have fixed those bugs...
283
+ */
284
+
285
+static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
286
+ struct sk_buff_head *list, enum skb_state state)
287
+{
288
+ unsigned long flags;
289
+ enum skb_state old_state;
290
+ struct skb_data *entry = (struct skb_data *) skb->cb;
291
+
292
+ spin_lock_irqsave(&list->lock, flags);
293
+ old_state = entry->state;
294
+ entry->state = state;
295
+ __skb_unlink(skb, list);
296
+
297
+ /* defer_bh() is never called with list == &dev->done.
298
+ * spin_lock_nested() tells lockdep that it is OK to take
299
+ * dev->done.lock here with list->lock held.
300
+ */
301
+ spin_lock_nested(&dev->done.lock, SINGLE_DEPTH_NESTING);
302
+
303
+ __skb_queue_tail(&dev->done, skb);
304
+ if (dev->done.qlen == 1)
305
+ tasklet_schedule(&dev->bh);
306
+
307
+ spin_unlock(&dev->done.lock);
308
+ spin_unlock_irqrestore(&list->lock, flags);
309
+
310
+ return old_state;
311
+}
312
+
313
+/* some work can't be done in tasklets, so we use keventd
314
+ *
315
+ * NOTE: annoying asymmetry: if it's active, schedule_work() fails,
316
+ * but tasklet_schedule() doesn't. hope the failure is rare.
317
+ */
318
+static
319
+void axusbnet_defer_kevent(struct usbnet *dev, int work)
320
+{
321
+ set_bit(work, &dev->flags);
322
+ if (!schedule_work(&dev->kevent))
323
+ deverr(dev, "kevent %d may have been dropped", work);
324
+ else
325
+ devdbg(dev, "kevent %d scheduled", work);
326
+}
327
+
328
+/*-------------------------------------------------------------------------*/
329
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
330
+static void rx_complete(struct urb *urb, struct pt_regs *regs);
331
+#else
332
+static void rx_complete(struct urb *urb);
333
+#endif
334
+
335
+static void rx_submit(struct usbnet *dev, struct urb *urb, gfp_t flags)
336
+{
337
+ struct sk_buff *skb;
338
+ struct skb_data *entry;
339
+ int retval = 0;
340
+ unsigned long lockflags;
341
+ size_t size = dev->rx_urb_size;
342
+ struct driver_info *info = dev->driver_info;
343
+ u8 align;
344
+
345
+ /* prevent rx skb allocation when error ratio is high */
346
+ if (test_bit(EVENT_RX_KILL, &dev->flags)) {
347
+ usb_free_urb(urb);
348
+ return;
349
+ }
350
+
351
+#if (AX_FORCE_BUFF_ALIGN)
352
+ align = 0;
353
+#else
354
+ if (!(info->flags & FLAG_HW_IP_ALIGNMENT))
355
+ align = NET_IP_ALIGN;
356
+ else
357
+ align = 0;
358
+#endif
359
+ skb = alloc_skb(size + align, flags);
360
+ if (skb == NULL) {
361
+
362
+ if (netif_msg_rx_err(dev))
363
+ devdbg(dev, "no rx skb");
364
+
365
+ if ((dev->rx_urb_size > 2048) && dev->rx_size) {
366
+ dev->rx_size--;
367
+ dev->rx_urb_size =
368
+ AX88772B_BULKIN_SIZE[dev->rx_size].size;
369
+
370
+ ax8817x_write_cmd_async(dev, 0x2A,
371
+ AX88772B_BULKIN_SIZE[dev->rx_size].byte_cnt,
372
+ AX88772B_BULKIN_SIZE[dev->rx_size].threshold,
373
+ 0, NULL);
374
+ }
375
+
376
+ if (!(dev->flags & EVENT_RX_MEMORY))
377
+ axusbnet_defer_kevent(dev, EVENT_RX_MEMORY);
378
+ usb_free_urb(urb);
379
+ return;
380
+ }
381
+
382
+ if (align)
383
+ skb_reserve(skb, NET_IP_ALIGN);
384
+
385
+ entry = (struct skb_data *) skb->cb;
386
+ entry->urb = urb;
387
+ entry->dev = dev;
388
+ entry->state = rx_start;
389
+ entry->length = 0;
390
+
391
+ usb_fill_bulk_urb(urb, dev->udev, dev->in, skb->data,
392
+ size, rx_complete, skb);
393
+
394
+ spin_lock_irqsave(&dev->rxq.lock, lockflags);
395
+
396
+ if (netif_running(dev->net)
397
+ && netif_device_present(dev->net)
398
+ && !test_bit(EVENT_RX_HALT, &dev->flags)) {
399
+ switch (retval = usb_submit_urb(urb, GFP_ATOMIC)) {
400
+ case -EPIPE:
401
+ axusbnet_defer_kevent(dev, EVENT_RX_HALT);
402
+ break;
403
+ case -ENOMEM:
404
+ axusbnet_defer_kevent(dev, EVENT_RX_MEMORY);
405
+ break;
406
+ case -ENODEV:
407
+ if (netif_msg_ifdown(dev))
408
+ devdbg(dev, "device gone");
409
+ netif_device_detach(dev->net);
410
+ break;
411
+ default:
412
+ if (netif_msg_rx_err(dev))
413
+ devdbg(dev, "rx submit, %d", retval);
414
+ tasklet_schedule(&dev->bh);
415
+ break;
416
+ case 0:
417
+ __skb_queue_tail(&dev->rxq, skb);
418
+ }
419
+ } else {
420
+ if (netif_msg_ifdown(dev))
421
+ devdbg(dev, "rx: stopped");
422
+ retval = -ENOLINK;
423
+ }
424
+ spin_unlock_irqrestore(&dev->rxq.lock, lockflags);
425
+ if (retval) {
426
+ dev_kfree_skb_any(skb);
427
+ usb_free_urb(urb);
428
+ }
429
+}
430
+
431
+
432
+/*-------------------------------------------------------------------------*/
433
+
434
+static inline void rx_process(struct usbnet *dev, struct sk_buff *skb)
435
+{
436
+ if (dev->driver_info->rx_fixup
437
+ && !dev->driver_info->rx_fixup(dev, skb))
438
+ goto error;
439
+ /* else network stack removes extra byte if we forced a short packet */
440
+
441
+ if (skb->len)
442
+ axusbnet_skb_return(dev, skb);
443
+ else {
444
+ if (netif_msg_rx_err(dev))
445
+ devdbg(dev, "drop");
446
+error:
447
+ dev->stats.rx_errors++;
448
+ skb_queue_tail(&dev->done, skb);
449
+ }
450
+}
451
+
452
+/*-------------------------------------------------------------------------*/
453
+
454
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
455
+static void rx_complete(struct urb *urb, struct pt_regs *regs)
456
+#else
457
+static void rx_complete(struct urb *urb)
458
+#endif
459
+{
460
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
461
+ struct skb_data *entry = (struct skb_data *) skb->cb;
462
+ struct usbnet *dev = entry->dev;
463
+ int urb_status = urb->status;
464
+ enum skb_state state;
465
+
466
+ skb_put(skb, urb->actual_length);
467
+ state = rx_done;
468
+ entry->urb = NULL;
469
+
470
+ switch (urb_status) {
471
+ /* success */
472
+ case 0:
473
+ if (skb->len < dev->net->hard_header_len) {
474
+ entry->state = rx_cleanup;
475
+ dev->stats.rx_errors++;
476
+ dev->stats.rx_length_errors++;
477
+ if (netif_msg_rx_err(dev))
478
+ devdbg(dev, "rx length %d", skb->len);
479
+ }
480
+ break;
481
+
482
+ /* stalls need manual reset. this is rare ... except that
483
+ * when going through USB 2.0 TTs, unplug appears this way.
484
+ * we avoid the highspeed version of the ETIMEDOUT/EILSEQ
485
+ * storm, recovering as needed.
486
+ */
487
+ case -EPIPE:
488
+ dev->stats.rx_errors++;
489
+ axusbnet_defer_kevent(dev, EVENT_RX_HALT);
490
+ /* FALLTHROUGH */
491
+
492
+ /* software-driven interface shutdown */
493
+ case -ECONNRESET: /* async unlink */
494
+ case -ESHUTDOWN: /* hardware gone */
495
+ if (netif_msg_ifdown(dev))
496
+ devdbg(dev, "rx shutdown, code %d", urb_status);
497
+ goto block;
498
+
499
+ /* we get controller i/o faults during khubd disconnect() delays.
500
+ * throttle down resubmits, to avoid log floods; just temporarily,
501
+ * so we still recover when the fault isn't a khubd delay.
502
+ */
503
+ case -EPROTO:
504
+ case -ETIME:
505
+ case -EILSEQ:
506
+ dev->stats.rx_errors++;
507
+ if (!timer_pending(&dev->delay)) {
508
+ mod_timer(&dev->delay, jiffies + THROTTLE_JIFFIES);
509
+ if (netif_msg_link(dev))
510
+ devdbg(dev, "rx throttle %d", urb_status);
511
+ }
512
+block:
513
+ state = rx_cleanup;
514
+ entry->urb = urb;
515
+ urb = NULL;
516
+ break;
517
+
518
+ /* data overrun ... flush fifo? */
519
+ case -EOVERFLOW:
520
+ dev->stats.rx_over_errors++;
521
+ /* FALLTHROUGH */
522
+
523
+ default:
524
+ state = rx_cleanup;
525
+ dev->stats.rx_errors++;
526
+ if (netif_msg_rx_err(dev))
527
+ devdbg(dev, "rx status %d", urb_status);
528
+ break;
529
+ }
530
+
531
+ /* stop rx if packet error rate is high */
532
+ if (++dev->pkt_cnt > 30) {
533
+ dev->pkt_cnt = 0;
534
+ dev->pkt_err = 0;
535
+ } else {
536
+ if (state == rx_cleanup)
537
+ dev->pkt_err++;
538
+ if (dev->pkt_err > 20)
539
+ set_bit(EVENT_RX_KILL, &dev->flags);
540
+ }
541
+
542
+ state = defer_bh(dev, skb, &dev->rxq, state);
543
+
544
+ if (urb) {
545
+ if (netif_running(dev->net) &&
546
+ !test_bit(EVENT_RX_HALT, &dev->flags) &&
547
+ state != unlink_start) {
548
+ rx_submit(dev, urb, GFP_ATOMIC);
549
+ return;
550
+ }
551
+ usb_free_urb(urb);
552
+ }
553
+ if (netif_msg_rx_err(dev))
554
+ devdbg(dev, "no read resubmitted");
555
+}
556
+
557
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
558
+static void intr_complete(struct urb *urb, struct pt_regs *regs)
559
+#else
560
+static void intr_complete(struct urb *urb)
561
+#endif
562
+{
563
+ struct usbnet *dev = urb->context;
564
+ int status = urb->status;
565
+
566
+ switch (status) {
567
+ /* success */
568
+ case 0:
569
+ dev->driver_info->status(dev, urb);
570
+ break;
571
+
572
+ /* software-driven interface shutdown */
573
+ case -ENOENT: /* urb killed */
574
+ case -ESHUTDOWN: /* hardware gone */
575
+ if (netif_msg_ifdown(dev))
576
+ devdbg(dev, "intr shutdown, code %d", status);
577
+ return;
578
+
579
+ /* NOTE: not throttling like RX/TX, since this endpoint
580
+ * already polls infrequently
581
+ */
582
+ default:
583
+ devdbg(dev, "intr status %d", status);
584
+ break;
585
+ }
586
+
587
+ if (!netif_running(dev->net))
588
+ return;
589
+
590
+ memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
591
+ status = usb_submit_urb(urb, GFP_ATOMIC);
592
+ if (status != 0 && netif_msg_timer(dev))
593
+ deverr(dev, "intr resubmit --> %d", status);
594
+}
595
+
596
+/*-------------------------------------------------------------------------*/
597
+
598
+/* unlink pending rx/tx; completion handlers do all other cleanup */
599
+
600
+static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
601
+{
602
+ unsigned long flags;
603
+ struct sk_buff *skb = NULL;
604
+ int count = 0;
605
+
606
+ spin_lock_irqsave (&q->lock, flags);
607
+ while (!skb_queue_empty(q)) {
608
+ struct skb_data *entry;
609
+ struct urb *urb;
610
+ int retval;
611
+
612
+ skb_queue_walk(q, skb) {
613
+ entry = (struct skb_data *) skb->cb;
614
+ if (entry->state != unlink_start)
615
+ goto found;
616
+ }
617
+ break;
618
+found:
619
+ entry->state = unlink_start;
620
+ urb = entry->urb;
621
+
622
+ /*
623
+ * Get reference count of the URB to avoid it to be
624
+ * freed during usb_unlink_urb, which may trigger
625
+ * use-after-free problem inside usb_unlink_urb since
626
+ * usb_unlink_urb is always racing with .complete
627
+ * handler(include defer_bh).
628
+ */
629
+ usb_get_urb(urb);
630
+ spin_unlock_irqrestore(&q->lock, flags);
631
+ // during some PM-driven resume scenarios,
632
+ // these (async) unlinks complete immediately
633
+ retval = usb_unlink_urb (urb);
634
+ if (retval != -EINPROGRESS && retval != 0)
635
+ printk(DEBUG "unlink urb err, %d\n", retval);
636
+ else
637
+ count++;
638
+ usb_put_urb(urb);
639
+ spin_lock_irqsave(&q->lock, flags);
640
+ }
641
+ spin_unlock_irqrestore (&q->lock, flags);
642
+
643
+ return count;
644
+}
645
+
646
+/* Flush all pending rx urbs */
647
+/* minidrivers may need to do this when the MTU changes */
648
+
649
+static
650
+void axusbnet_unlink_rx_urbs(struct usbnet *dev)
651
+{
652
+ if (netif_running(dev->net)) {
653
+ (void) unlink_urbs(dev, &dev->rxq);
654
+ tasklet_schedule(&dev->bh);
655
+ }
656
+}
657
+
658
+/*-------------------------------------------------------------------------*/
659
+
660
+/* precondition: never called in_interrupt */
661
+
662
+static
663
+int axusbnet_stop(struct net_device *net)
664
+{
665
+ struct usbnet *dev = netdev_priv(net);
666
+ struct driver_info *info = dev->driver_info;
667
+
668
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)
669
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
670
+#else
671
+ DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
672
+#endif
673
+ DECLARE_WAITQUEUE(wait, current);
674
+
675
+ netif_stop_queue(net);
676
+
677
+ if (netif_msg_ifdown(dev))
678
+ devinfo(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
679
+ dev->stats.rx_packets, dev->stats.tx_packets,
680
+ dev->stats.rx_errors, dev->stats.tx_errors);
681
+
682
+ /* allow minidriver to stop correctly (wireless devices to turn off
683
+ * radio etc) */
684
+ if (info->stop) {
685
+ int retval;
686
+ retval = info->stop(dev);
687
+ if (retval < 0 && netif_msg_ifdown(dev))
688
+ devinfo(dev,
689
+ "stop fail (%d) usbnet usb-%s-%s, %s",
690
+ retval,
691
+ dev->udev->bus->bus_name, dev->udev->devpath,
692
+ info->description);
693
+ }
694
+
695
+ if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
696
+ int temp;
697
+ /* ensure there are no more active urbs */
698
+ add_wait_queue(&unlink_wakeup, &wait);
699
+ dev->wait = &unlink_wakeup;
700
+ temp = unlink_urbs(dev, &dev->txq) +
701
+ unlink_urbs(dev, &dev->rxq);
702
+
703
+ /* maybe wait for deletions to finish. */
704
+ while (!skb_queue_empty(&dev->rxq)
705
+ && !skb_queue_empty(&dev->txq)
706
+ && !skb_queue_empty(&dev->done)) {
707
+ msleep(UNLINK_TIMEOUT_MS);
708
+ if (netif_msg_ifdown(dev))
709
+ devdbg(dev, "waited for %d urb completions",
710
+ temp);
711
+ }
712
+ dev->wait = NULL;
713
+ remove_wait_queue(&unlink_wakeup, &wait);
714
+ }
715
+
716
+ usb_kill_urb(dev->interrupt);
717
+
718
+ /* deferred work (task, timer, softirq) must also stop.
719
+ * can't flush_scheduled_work() until we drop rtnl (later),
720
+ * else workers could deadlock; so make workers a NOP.
721
+ */
722
+ dev->flags = 0;
723
+ del_timer_sync(&dev->delay);
724
+ tasklet_kill(&dev->bh);
725
+
726
+ return 0;
727
+}
728
+
729
+/*-------------------------------------------------------------------------*/
730
+
731
+/* posts reads, and enables write queuing */
732
+
733
+/* precondition: never called in_interrupt */
734
+
735
+static
736
+int axusbnet_open(struct net_device *net)
737
+{
738
+ struct usbnet *dev = netdev_priv(net);
739
+ int retval = 0;
740
+ struct driver_info *info = dev->driver_info;
741
+
742
+ /* put into "known safe" state */
743
+ if (info->reset) {
744
+ retval = info->reset(dev);
745
+ if (retval < 0) {
746
+ if (netif_msg_ifup(dev))
747
+ devinfo(dev,
748
+ "open reset fail (%d) usbnet usb-%s-%s, %s",
749
+ retval,
750
+ dev->udev->bus->bus_name,
751
+ dev->udev->devpath,
752
+ info->description);
753
+ goto done;
754
+ }
755
+ }
756
+
757
+ /* insist peer be connected */
758
+ if (info->check_connect) {
759
+ retval = info->check_connect(dev);
760
+ if (retval < 0) {
761
+ if (netif_msg_ifup(dev))
762
+ devdbg(dev, "can't open; %d", retval);
763
+ goto done;
764
+ }
765
+ }
766
+
767
+ /* start any status interrupt transfer */
768
+ if (dev->interrupt) {
769
+ retval = usb_submit_urb(dev->interrupt, GFP_KERNEL);
770
+ if (retval < 0) {
771
+ if (netif_msg_ifup(dev))
772
+ deverr(dev, "intr submit %d", retval);
773
+ goto done;
774
+ }
775
+ }
776
+
777
+ /* reset rx error state */
778
+ dev->pkt_cnt = 0;
779
+ dev->pkt_err = 0;
780
+ clear_bit(EVENT_RX_KILL, &dev->flags);
781
+
782
+ netif_start_queue(net);
783
+ if (netif_msg_ifup(dev)) {
784
+ char *framing;
785
+
786
+ if (dev->driver_info->flags & FLAG_FRAMING_NC)
787
+ framing = "NetChip";
788
+ else if (dev->driver_info->flags & FLAG_FRAMING_GL)
789
+ framing = "GeneSys";
790
+ else if (dev->driver_info->flags & FLAG_FRAMING_Z)
791
+ framing = "Zaurus";
792
+ else if (dev->driver_info->flags & FLAG_FRAMING_RN)
793
+ framing = "RNDIS";
794
+ else if (dev->driver_info->flags & FLAG_FRAMING_AX)
795
+ framing = "ASIX";
796
+ else
797
+ framing = "simple";
798
+
799
+ devinfo(dev, "open: enable queueing (rx %d, tx %d) mtu %d %s framing",
800
+ (int)RX_QLEN(dev), (int)TX_QLEN(dev), dev->net->mtu,
801
+ framing);
802
+ }
803
+
804
+ /* delay posting reads until we're fully open */
805
+ tasklet_schedule(&dev->bh);
806
+ return retval;
807
+done:
808
+ return retval;
809
+}
810
+
811
+/*-------------------------------------------------------------------------*/
812
+
813
+/* ethtool methods; minidrivers may need to add some more, but
814
+ * they'll probably want to use this base set.
815
+ */
816
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
817
+static
818
+int axusbnet_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
819
+{
820
+ struct usbnet *dev = netdev_priv(net);
821
+
822
+ if (!dev->mii.mdio_read)
823
+ return -EOPNOTSUPP;
824
+
825
+ return mii_ethtool_gset(&dev->mii, cmd);
826
+}
827
+
828
+static
829
+int axusbnet_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
830
+{
831
+ struct usbnet *dev = netdev_priv(net);
832
+ int retval;
833
+
834
+ if (!dev->mii.mdio_write)
835
+ return -EOPNOTSUPP;
836
+
837
+ retval = mii_ethtool_sset(&dev->mii, cmd);
838
+
839
+ /* link speed/duplex might have changed */
840
+ if (dev->driver_info->link_reset)
841
+ dev->driver_info->link_reset(dev);
842
+
843
+ return retval;
844
+
845
+}
846
+#endif
847
+static
848
+u32 axusbnet_get_link(struct net_device *net)
849
+{
850
+ struct usbnet *dev = netdev_priv(net);
851
+
852
+ /* If a check_connect is defined, return its result */
853
+ if (dev->driver_info->check_connect)
854
+ return dev->driver_info->check_connect(dev) == 0;
855
+
856
+ /* if the device has mii operations, use those */
857
+ if (dev->mii.mdio_read)
858
+ return mii_link_ok(&dev->mii);
859
+
860
+ /* Otherwise, dtrt for drivers calling netif_carrier_{on,off} */
861
+ return ethtool_op_get_link(net);
862
+}
863
+
864
+static
865
+int axusbnet_nway_reset(struct net_device *net)
866
+{
867
+ struct usbnet *dev = netdev_priv(net);
868
+
869
+ if (!dev->mii.mdio_write)
870
+ return -EOPNOTSUPP;
871
+
872
+ return mii_nway_restart(&dev->mii);
873
+}
874
+
875
+static
876
+void axusbnet_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
877
+{
878
+ struct usbnet *dev = netdev_priv(net);
879
+
880
+ strncpy(info->driver, dev->driver_name, sizeof(info->driver));
881
+ strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
882
+ strncpy(info->fw_version, dev->driver_info->description,
883
+ sizeof(info->fw_version));
884
+ usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info));
885
+}
886
+
887
+static
888
+u32 axusbnet_get_msglevel(struct net_device *net)
889
+{
890
+ struct usbnet *dev = netdev_priv(net);
891
+
892
+ return dev->msg_enable;
893
+}
894
+
895
+static
896
+void axusbnet_set_msglevel(struct net_device *net, u32 level)
897
+{
898
+ struct usbnet *dev = netdev_priv(net);
899
+
900
+ dev->msg_enable = level;
901
+}
902
+
903
+/* drivers may override default ethtool_ops in their bind() routine */
904
+static struct ethtool_ops axusbnet_ethtool_ops = {
905
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
906
+ .get_settings = axusbnet_get_settings,
907
+ .set_settings = axusbnet_set_settings,
908
+#endif
909
+ .get_link = axusbnet_get_link,
910
+ .nway_reset = axusbnet_nway_reset,
911
+ .get_drvinfo = axusbnet_get_drvinfo,
912
+ .get_msglevel = axusbnet_get_msglevel,
913
+ .set_msglevel = axusbnet_set_msglevel,
914
+};
915
+
916
+/*-------------------------------------------------------------------------*/
917
+
918
+/* work that cannot be done in interrupt context uses keventd.
919
+ *
920
+ * NOTE: with 2.5 we could do more of this using completion callbacks,
921
+ * especially now that control transfers can be queued.
922
+ */
923
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
924
+static void kevent(void *data)
925
+{
926
+ struct usbnet *dev = (struct usbnet *)data;
927
+#else
928
+static void kevent(struct work_struct *work)
929
+{
930
+ struct usbnet *dev =
931
+ container_of(work, struct usbnet, kevent);
932
+#endif
933
+ int status;
934
+
935
+ /* usb_clear_halt() needs a thread context */
936
+ if (test_bit(EVENT_TX_HALT, &dev->flags)) {
937
+
938
+ unlink_urbs(dev, &dev->txq);
939
+ status = usb_clear_halt(dev->udev, dev->out);
940
+ if (status < 0
941
+ && status != -EPIPE
942
+ && status != -ESHUTDOWN) {
943
+ if (netif_msg_tx_err(dev))
944
+ deverr(dev, "can't clear tx halt, status %d",
945
+ status);
946
+ } else {
947
+ clear_bit(EVENT_TX_HALT, &dev->flags);
948
+ if (status != -ESHUTDOWN)
949
+ netif_wake_queue(dev->net);
950
+ }
951
+ }
952
+ if (test_bit(EVENT_RX_HALT, &dev->flags)) {
953
+
954
+ unlink_urbs(dev, &dev->rxq);
955
+ status = usb_clear_halt(dev->udev, dev->in);
956
+ if (status < 0
957
+ && status != -EPIPE
958
+ && status != -ESHUTDOWN) {
959
+ if (netif_msg_rx_err(dev))
960
+ deverr(dev, "can't clear rx halt, status %d",
961
+ status);
962
+ } else {
963
+ clear_bit(EVENT_RX_HALT, &dev->flags);
964
+ tasklet_schedule(&dev->bh);
965
+ }
966
+ }
967
+
968
+ /* tasklet could resubmit itself forever if memory is tight */
969
+ if (test_bit(EVENT_RX_MEMORY, &dev->flags)) {
970
+ struct urb *urb = NULL;
971
+
972
+ if (netif_running(dev->net))
973
+ urb = usb_alloc_urb(0, GFP_KERNEL);
974
+ else
975
+ clear_bit(EVENT_RX_MEMORY, &dev->flags);
976
+ if (urb != NULL) {
977
+ clear_bit(EVENT_RX_MEMORY, &dev->flags);
978
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
979
+ urb->transfer_flags |= URB_ASYNC_UNLINK;
980
+#endif
981
+ rx_submit(dev, urb, GFP_KERNEL);
982
+ tasklet_schedule(&dev->bh);
983
+ }
984
+ }
985
+
986
+ if (test_bit(EVENT_LINK_RESET, &dev->flags)) {
987
+ struct driver_info *info = dev->driver_info;
988
+
989
+ clear_bit(EVENT_LINK_RESET, &dev->flags);
990
+ if (info->link_reset) {
991
+ int retval;
992
+ retval = info->link_reset(dev);
993
+ if (retval < 0) {
994
+ devinfo(dev,
995
+ "link reset failed (%d) usbnet usb-%s-%s, %s",
996
+ retval,
997
+ dev->udev->bus->bus_name,
998
+ dev->udev->devpath,
999
+ info->description);
1000
+ }
1001
+ }
1002
+ }
1003
+
1004
+ if (dev->flags)
1005
+ devdbg(dev, "kevent done, flags = 0x%lx", dev->flags);
1006
+}
1007
+
1008
+/*-------------------------------------------------------------------------*/
1009
+
1010
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
1011
+static void tx_complete(struct urb *urb, struct pt_regs *regs)
1012
+#else
1013
+static void tx_complete(struct urb *urb)
1014
+#endif
1015
+{
1016
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
1017
+ struct skb_data *entry = (struct skb_data *) skb->cb;
1018
+ struct usbnet *dev = entry->dev;
1019
+
1020
+ if (urb->status == 0) {
1021
+ dev->stats.tx_packets++;
1022
+ dev->stats.tx_bytes += entry->length;
1023
+ } else {
1024
+ dev->stats.tx_errors++;
1025
+
1026
+ switch (urb->status) {
1027
+ case -EPIPE:
1028
+ axusbnet_defer_kevent(dev, EVENT_TX_HALT);
1029
+ break;
1030
+
1031
+ /* software-driven interface shutdown */
1032
+ case -ECONNRESET: /* async unlink */
1033
+ case -ESHUTDOWN: /* hardware gone */
1034
+ break;
1035
+
1036
+ /* like rx, tx gets controller i/o faults during khubd delays */
1037
+ /* and so it uses the same throttling mechanism. */
1038
+ case -EPROTO:
1039
+ case -ETIME:
1040
+ case -EILSEQ:
1041
+ if (!timer_pending(&dev->delay)) {
1042
+ mod_timer(&dev->delay,
1043
+ jiffies + THROTTLE_JIFFIES);
1044
+ if (netif_msg_link(dev))
1045
+ devdbg(dev, "tx throttle %d",
1046
+ urb->status);
1047
+ }
1048
+ netif_stop_queue(dev->net);
1049
+ break;
1050
+ default:
1051
+ if (netif_msg_tx_err(dev))
1052
+ devdbg(dev, "tx err %d", entry->urb->status);
1053
+ break;
1054
+ }
1055
+ }
1056
+
1057
+ urb->dev = NULL;
1058
+ entry->state = tx_done;
1059
+ (void) defer_bh(dev, skb, &dev->txq, tx_done);
1060
+}
1061
+
1062
+/*-------------------------------------------------------------------------*/
1063
+
1064
+static
1065
+void axusbnet_tx_timeout(struct net_device *net)
1066
+{
1067
+ struct usbnet *dev = netdev_priv(net);
1068
+ struct driver_info *info = dev->driver_info;
1069
+
1070
+ if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
1071
+ unlink_urbs(dev, &dev->txq);
1072
+ }
1073
+ tasklet_schedule(&dev->bh);
1074
+
1075
+ /* FIXME: device recovery -- reset? */
1076
+}
1077
+
1078
+/*-------------------------------------------------------------------------*/
1079
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
1080
+static int
1081
+#else
1082
+static netdev_tx_t
1083
+#endif
1084
+axusbnet_start_xmit(struct sk_buff *skb, struct net_device *net)
1085
+{
1086
+ struct usbnet *dev = netdev_priv(net);
1087
+ int length;
1088
+ struct urb *urb = NULL;
1089
+ struct skb_data *entry;
1090
+ struct driver_info *info = dev->driver_info;
1091
+ unsigned long flags;
1092
+ int retval;
1093
+
1094
+ /* some devices want funky USB-level framing, for */
1095
+ /* win32 driver (usually) and/or hardware quirks */
1096
+ if (info->tx_fixup) {
1097
+ skb = info->tx_fixup(dev, skb, GFP_ATOMIC);
1098
+ if (!skb) {
1099
+ if (netif_msg_tx_err(dev))
1100
+ devdbg(dev, "can't tx_fixup skb");
1101
+ goto drop;
1102
+ }
1103
+ }
1104
+ length = skb->len;
1105
+
1106
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
1107
+ if (!urb) {
1108
+ if (netif_msg_tx_err(dev))
1109
+ devdbg(dev, "no urb");
1110
+ goto drop;
1111
+ }
1112
+
1113
+ entry = (struct skb_data *) skb->cb;
1114
+ entry->urb = urb;
1115
+ entry->dev = dev;
1116
+ entry->state = tx_start;
1117
+ entry->length = length;
1118
+
1119
+ usb_fill_bulk_urb(urb, dev->udev, dev->out, skb->data,
1120
+ skb->len, tx_complete, skb);
1121
+
1122
+ /* don't assume the hardware handles USB_ZERO_PACKET
1123
+ * NOTE: strictly conforming cdc-ether devices should expect
1124
+ * the ZLP here, but ignore the one-byte packet.
1125
+ */
1126
+ if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
1127
+ urb->transfer_buffer_length++;
1128
+ if (skb_tailroom(skb)) {
1129
+ skb->data[skb->len] = 0;
1130
+ __skb_put(skb, 1);
1131
+ }
1132
+ }
1133
+
1134
+ spin_lock_irqsave(&dev->txq.lock, flags);
1135
+
1136
+ switch ((retval = usb_submit_urb(urb, GFP_ATOMIC))) {
1137
+ case -EPIPE:
1138
+ netif_stop_queue(net);
1139
+ axusbnet_defer_kevent(dev, EVENT_TX_HALT);
1140
+ break;
1141
+ default:
1142
+ if (netif_msg_tx_err(dev))
1143
+ devdbg(dev, "tx: submit urb err %d", retval);
1144
+ break;
1145
+ case 0:
1146
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
1147
+ net->trans_start = jiffies;
1148
+#else
1149
+ netif_trans_update(net);
1150
+#endif
1151
+ __skb_queue_tail(&dev->txq, skb);
1152
+ if (dev->txq.qlen >= TX_QLEN(dev))
1153
+ netif_stop_queue(net);
1154
+ }
1155
+ spin_unlock_irqrestore(&dev->txq.lock, flags);
1156
+
1157
+ if (retval) {
1158
+ if (netif_msg_tx_err(dev))
1159
+ devdbg(dev, "drop, code %d", retval);
1160
+drop:
1161
+ dev->stats.tx_dropped++;
1162
+ if (skb)
1163
+ dev_kfree_skb_any(skb);
1164
+ usb_free_urb(urb);
1165
+ } else if (netif_msg_tx_queued(dev)) {
1166
+ devdbg(dev, "> tx, len %d, type 0x%x",
1167
+ length, skb->protocol);
1168
+ }
1169
+ return NETDEV_TX_OK;
1170
+}
1171
+
1172
+/*-------------------------------------------------------------------------*/
1173
+
1174
+/* tasklet (work deferred from completions, in_irq) or timer */
1175
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
1176
+static void axusbnet_bh(unsigned long param)
1177
+#else
1178
+static void axusbnet_bh (struct timer_list *t)
1179
+#endif
1180
+{
1181
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
1182
+ struct usbnet *dev = (struct usbnet *) param;
1183
+#else
1184
+ struct usbnet *dev = from_timer(dev, t, delay);
1185
+#endif
1186
+ struct sk_buff *skb;
1187
+ struct skb_data *entry = NULL;
1188
+
1189
+ while ((skb = skb_dequeue(&dev->done))) {
1190
+ entry = (struct skb_data *) skb->cb;
1191
+ switch (entry->state) {
1192
+ case rx_done:
1193
+ entry->state = rx_cleanup;
1194
+ rx_process(dev, skb);
1195
+ continue;
1196
+ case tx_done:
1197
+ case rx_cleanup:
1198
+ usb_free_urb(entry->urb);
1199
+ dev_kfree_skb(skb);
1200
+ continue;
1201
+ default:
1202
+ devdbg(dev, "bogus skb state %d", entry->state);
1203
+ }
1204
+ }
1205
+
1206
+ /* restart RX again after disabling due to high error rate */
1207
+ clear_bit(EVENT_RX_KILL, &dev->flags);
1208
+
1209
+ /* waiting for all pending urbs to complete? */
1210
+ if (dev->wait) {
1211
+ if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0)
1212
+ wake_up(dev->wait);
1213
+
1214
+ /* or are we maybe short a few urbs? */
1215
+ } else if (netif_running(dev->net)
1216
+ && netif_device_present(dev->net)
1217
+ && !timer_pending(&dev->delay)
1218
+ && !test_bit(EVENT_RX_HALT, &dev->flags)) {
1219
+ int temp = dev->rxq.qlen;
1220
+ int qlen = RX_QLEN(dev);
1221
+
1222
+ if (temp < qlen) {
1223
+ struct urb *urb = NULL;
1224
+ int i;
1225
+
1226
+ /* don't refill the queue all at once */
1227
+ for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
1228
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
1229
+ if (urb != NULL) {
1230
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
1231
+ urb->transfer_flags |= URB_ASYNC_UNLINK;
1232
+#endif
1233
+ rx_submit(dev, urb, GFP_ATOMIC);
1234
+ }
1235
+ }
1236
+ if (temp != dev->rxq.qlen && netif_msg_link(dev))
1237
+ devdbg(dev, "rxqlen %d --> %d",
1238
+ temp, dev->rxq.qlen);
1239
+ if (dev->rxq.qlen < qlen)
1240
+ tasklet_schedule(&dev->bh);
1241
+ }
1242
+ if (dev->txq.qlen < TX_QLEN(dev))
1243
+ netif_wake_queue(dev->net);
1244
+ }
1245
+}
1246
+
1247
+
1248
+/*-------------------------------------------------------------------------
1249
+ *
1250
+ * USB Device Driver support
1251
+ *
1252
+ *-------------------------------------------------------------------------*/
1253
+
1254
+/* precondition: never called in_interrupt */
1255
+
1256
+static
1257
+void axusbnet_disconnect(struct usb_interface *intf)
1258
+{
1259
+ struct usbnet *dev;
1260
+ struct usb_device *xdev;
1261
+ struct net_device *net;
1262
+
1263
+ dev = usb_get_intfdata(intf);
1264
+ usb_set_intfdata(intf, NULL);
1265
+ if (!dev)
1266
+ return;
1267
+
1268
+ xdev = interface_to_usbdev(intf);
1269
+
1270
+ if (netif_msg_probe(dev))
1271
+ devinfo(dev, "unregister '%s' usb-%s-%s, %s",
1272
+ intf->dev.driver->name,
1273
+ xdev->bus->bus_name, xdev->devpath,
1274
+ dev->driver_info->description);
1275
+
1276
+ net = dev->net;
1277
+ unregister_netdev(net);
1278
+
1279
+ /* we don't hold rtnl here ... */
1280
+ flush_scheduled_work();
1281
+
1282
+ if (dev->driver_info->unbind)
1283
+ dev->driver_info->unbind(dev, intf);
1284
+
1285
+ free_netdev(net);
1286
+ usb_put_dev(xdev);
1287
+}
1288
+
1289
+/*-------------------------------------------------------------------------*/
1290
+
1291
+/* precondition: never called in_interrupt */
1292
+
1293
+static int
1294
+axusbnet_probe(struct usb_interface *udev, const struct usb_device_id *prod)
1295
+{
1296
+ struct usbnet *dev;
1297
+ struct net_device *net;
1298
+ struct usb_host_interface *interface;
1299
+ struct driver_info *info;
1300
+ struct usb_device *xdev;
1301
+ int status;
1302
+ const char *name;
1303
+
1304
+ name = udev->dev.driver->name;
1305
+ info = (struct driver_info *) prod->driver_info;
1306
+ if (!info) {
1307
+ printk(KERN_ERR "blacklisted by %s\n", name);
1308
+ return -ENODEV;
1309
+ }
1310
+ xdev = interface_to_usbdev(udev);
1311
+ interface = udev->cur_altsetting;
1312
+
1313
+ usb_get_dev(xdev);
1314
+
1315
+ status = -ENOMEM;
1316
+
1317
+ /* set up our own records */
1318
+ net = alloc_etherdev(sizeof(*dev));
1319
+ if (!net) {
1320
+ printk(KERN_ERR "can't kmalloc dev");
1321
+ goto out;
1322
+ }
1323
+
1324
+ dev = netdev_priv(net);
1325
+ dev->udev = xdev;
1326
+ dev->intf = udev;
1327
+ dev->driver_info = info;
1328
+ dev->driver_name = name;
1329
+ dev->msg_enable = netif_msg_init(msg_level, NETIF_MSG_DRV |
1330
+ NETIF_MSG_PROBE | NETIF_MSG_LINK);
1331
+ skb_queue_head_init(&dev->rxq);
1332
+ skb_queue_head_init(&dev->txq);
1333
+ skb_queue_head_init(&dev->done);
1334
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
1335
+ dev->bh.func = axusbnet_bh;
1336
+ dev->bh.data = (unsigned long) dev;
1337
+#else
1338
+ dev->bh.func = (void (*)(unsigned long))axusbnet_bh;
1339
+ dev->bh.data = (unsigned long)&dev->delay;
1340
+#endif
1341
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
1342
+ INIT_WORK(&dev->kevent, kevent, dev);
1343
+#else
1344
+ INIT_WORK(&dev->kevent, kevent);
1345
+#endif
1346
+
1347
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
1348
+ dev->delay.function = axusbnet_bh;
1349
+ dev->delay.data = (unsigned long) dev;
1350
+ init_timer(&dev->delay);
1351
+#else
1352
+ timer_setup(&dev->delay, axusbnet_bh, 0);
1353
+#endif
1354
+ /* mutex_init(&dev->phy_mutex); */
1355
+
1356
+ dev->net = net;
1357
+
1358
+ /* rx and tx sides can use different message sizes;
1359
+ * bind() should set rx_urb_size in that case.
1360
+ */
1361
+ dev->hard_mtu = net->mtu + net->hard_header_len;
1362
+
1363
+#if 0
1364
+ /* dma_supported() is deeply broken on almost all architectures */
1365
+ /* possible with some EHCI controllers */
1366
+ if (dma_supported(&udev->dev, DMA_BIT_MASK(64)))
1367
+ net->features |= NETIF_F_HIGHDMA;
1368
+#endif
1369
+
1370
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1371
+ net->open = axusbnet_open,
1372
+ net->stop = axusbnet_stop,
1373
+ net->hard_start_xmit = axusbnet_start_xmit,
1374
+ net->tx_timeout = axusbnet_tx_timeout,
1375
+ net->get_stats = axusbnet_get_stats;
1376
+#endif
1377
+
1378
+ net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
1379
+ net->ethtool_ops = &axusbnet_ethtool_ops;
1380
+
1381
+ /* allow device-specific bind/init procedures */
1382
+ /* NOTE net->name still not usable ... */
1383
+ status = info->bind(dev, udev);
1384
+ if (status < 0) {
1385
+ deverr(dev, "Binding device failed: %d", status);
1386
+ goto out1;
1387
+ }
1388
+
1389
+ /* maybe the remote can't receive an Ethernet MTU */
1390
+ if (net->mtu > (dev->hard_mtu - net->hard_header_len))
1391
+ net->mtu = dev->hard_mtu - net->hard_header_len;
1392
+
1393
+ status = init_status(dev, udev);
1394
+ if (status < 0)
1395
+ goto out3;
1396
+
1397
+ if (!dev->rx_urb_size)
1398
+ dev->rx_urb_size = dev->hard_mtu;
1399
+ dev->maxpacket = usb_maxpacket(dev->udev, dev->out, 1);
1400
+
1401
+ SET_NETDEV_DEV(net, &udev->dev);
1402
+ status = register_netdev(net);
1403
+ if (status) {
1404
+ deverr(dev, "net device registration failed: %d", status);
1405
+ goto out3;
1406
+ }
1407
+
1408
+ if (netif_msg_probe(dev))
1409
+ devinfo(dev, "register '%s' at usb-%s-%s, %s, %pM",
1410
+ udev->dev.driver->name,
1411
+ xdev->bus->bus_name, xdev->devpath,
1412
+ dev->driver_info->description,
1413
+ net->dev_addr);
1414
+
1415
+ /* ok, it's ready to go. */
1416
+ usb_set_intfdata(udev, dev);
1417
+
1418
+ /* start as if the link is up */
1419
+ netif_device_attach(net);
1420
+
1421
+ return 0;
1422
+
1423
+out3:
1424
+ if (info->unbind)
1425
+ info->unbind(dev, udev);
1426
+out1:
1427
+ free_netdev(net);
1428
+out:
1429
+ usb_put_dev(xdev);
1430
+ return status;
1431
+}
1432
+
1433
+/*-------------------------------------------------------------------------*/
1434
+
1435
+/*
1436
+ * suspend the whole driver as soon as the first interface is suspended
1437
+ * resume only when the last interface is resumed
1438
+ */
1439
+
1440
+static int axusbnet_suspend(struct usb_interface *intf,
1441
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
1442
+pm_message_t message)
1443
+#else
1444
+u32 message)
1445
+#endif
1446
+{
1447
+ struct usbnet *dev = usb_get_intfdata(intf);
1448
+
1449
+ if (!dev->suspend_count++) {
1450
+ /*
1451
+ * accelerate emptying of the rx and queues, to avoid
1452
+ * having everything error out.
1453
+ */
1454
+ netif_device_detach(dev->net);
1455
+ (void) unlink_urbs(dev, &dev->rxq);
1456
+ (void) unlink_urbs(dev, &dev->txq);
1457
+ usb_kill_urb(dev->interrupt);
1458
+ /*
1459
+ * reattach so runtime management can use and
1460
+ * wake the device
1461
+ */
1462
+ netif_device_attach(dev->net);
1463
+ }
1464
+ return 0;
1465
+}
1466
+
1467
+static int
1468
+axusbnet_resume(struct usb_interface *intf)
1469
+{
1470
+ struct usbnet *dev = usb_get_intfdata(intf);
1471
+ int retval = 0;
1472
+
1473
+ if (!--dev->suspend_count)
1474
+ tasklet_schedule(&dev->bh);
1475
+
1476
+ retval = init_status(dev, intf);
1477
+ if (retval < 0)
1478
+ return retval;
1479
+
1480
+ if (dev->interrupt) {
1481
+ retval = usb_submit_urb(dev->interrupt, GFP_KERNEL);
1482
+ if (retval < 0 && netif_msg_ifup(dev))
1483
+ deverr(dev, "intr submit %d", retval);
1484
+ }
1485
+
1486
+ return retval;
1487
+}
1488
+
kernel/drivers/net/usb/ax88772C/axusbnet.h
....@@ -0,0 +1,212 @@
1
+/*
2
+ * USB Networking Link Interface
3
+ *
4
+ * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net>
5
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+#ifndef __LINUX_USB_USBNET_H
23
+#define __LINUX_USB_USBNET_H
24
+
25
+#ifndef gfp_t
26
+#define gfp_t int
27
+#endif
28
+
29
+/* interface from usbnet core to each USB networking link we handle */
30
+struct usbnet {
31
+ /* housekeeping */
32
+ struct usb_device *udev;
33
+ struct usb_interface *intf;
34
+ struct driver_info *driver_info;
35
+ const char *driver_name;
36
+ void *driver_priv;
37
+ wait_queue_head_t *wait;
38
+ /* struct mutex phy_mutex; */
39
+ unsigned char suspend_count;
40
+ unsigned char pkt_cnt, pkt_err;
41
+
42
+ /* i/o info: pipes etc */
43
+ unsigned in, out;
44
+ struct usb_host_endpoint *status;
45
+ unsigned maxpacket;
46
+ struct timer_list delay;
47
+
48
+ /* protocol/interface state */
49
+ struct net_device *net;
50
+ struct net_device_stats stats;
51
+ int msg_enable;
52
+ unsigned long data[5];
53
+ u32 xid;
54
+ u32 hard_mtu; /* count any extra framing */
55
+ size_t rx_urb_size; /* size for rx urbs */
56
+ struct mii_if_info mii;
57
+
58
+ /* various kinds of pending driver work */
59
+ struct sk_buff_head rxq;
60
+ struct sk_buff_head txq;
61
+ struct sk_buff_head done;
62
+ struct sk_buff_head rxq_pause;
63
+ struct urb *interrupt;
64
+ struct tasklet_struct bh;
65
+
66
+ struct work_struct kevent;
67
+ unsigned long flags;
68
+# define EVENT_TX_HALT 0
69
+# define EVENT_RX_HALT 1
70
+# define EVENT_RX_MEMORY 2
71
+# define EVENT_STS_SPLIT 3
72
+# define EVENT_LINK_RESET 4
73
+# define EVENT_RX_PAUSED 5
74
+# define EVENT_RX_KILL 10
75
+
76
+ void *priv; /* point to minidriver private data */
77
+ unsigned char rx_size;
78
+ unsigned char reg_monitor;
79
+};
80
+
81
+static inline struct usb_driver *driver_of(struct usb_interface *intf)
82
+{
83
+ return to_usb_driver(intf->dev.driver);
84
+}
85
+
86
+/* interface from the device/framing level "minidriver" to core */
87
+struct driver_info {
88
+ char *description;
89
+
90
+ int flags;
91
+/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */
92
+#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
93
+#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
94
+#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */
95
+#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */
96
+
97
+#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
98
+#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
99
+
100
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
101
+#define FLAG_WLAN 0x0080 /* use "wlan%d" names */
102
+#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
103
+#define FLAG_SEND_ZLP 0x0200 /* hw requires ZLPs are sent */
104
+#define FLAG_HW_IP_ALIGNMENT 0x0400 /* AX88772B support hardware IP alignment */
105
+
106
+
107
+ /* init device ... can sleep, or cause probe() failure */
108
+ int (*bind)(struct usbnet *, struct usb_interface *);
109
+
110
+ /* cleanup device ... can sleep, but can't fail */
111
+ void (*unbind)(struct usbnet *, struct usb_interface *);
112
+
113
+ /* reset device ... can sleep */
114
+ int (*reset)(struct usbnet *);
115
+
116
+ /* stop device ... can sleep */
117
+ int (*stop)(struct usbnet *);
118
+
119
+ /* see if peer is connected ... can sleep */
120
+ int (*check_connect)(struct usbnet *);
121
+
122
+ /* for status polling */
123
+ void (*status)(struct usbnet *, struct urb *);
124
+
125
+ /* link reset handling, called from defer_kevent */
126
+ int (*link_reset)(struct usbnet *);
127
+
128
+ /* fixup rx packet (strip framing) */
129
+ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
130
+
131
+ /* fixup tx packet (add framing) */
132
+ struct sk_buff *(*tx_fixup)(struct usbnet *dev,
133
+ struct sk_buff *skb, gfp_t flags);
134
+
135
+ /* early initialization code, can sleep. This is for minidrivers
136
+ * having 'subminidrivers' that need to do extra initialization
137
+ * right after minidriver have initialized hardware. */
138
+ int (*early_init)(struct usbnet *dev);
139
+
140
+ /* called by minidriver when receiving indication */
141
+ void (*indication)(struct usbnet *dev, void *ind, int indlen);
142
+
143
+ /* for new devices, use the descriptor-reading code instead */
144
+ int in; /* rx endpoint */
145
+ int out; /* tx endpoint */
146
+
147
+ unsigned long data; /* Misc driver specific data */
148
+};
149
+
150
+/* Drivers that reuse some of the standard USB CDC infrastructure
151
+ * (notably, using multiple interfaces according to the CDC
152
+ * union descriptor) get some helper code.
153
+ */
154
+struct cdc_state {
155
+ struct usb_cdc_header_desc *header;
156
+ struct usb_cdc_union_desc *u;
157
+ struct usb_cdc_ether_desc *ether;
158
+ struct usb_interface *control;
159
+ struct usb_interface *data;
160
+};
161
+
162
+/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
163
+#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
164
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
165
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
166
+ |USB_CDC_PACKET_TYPE_DIRECTED)
167
+
168
+
169
+/* we record the state for each of our queued skbs */
170
+enum skb_state {
171
+ illegal = 0,
172
+ tx_start, tx_done,
173
+ rx_start, rx_done, rx_cleanup,
174
+ unlink_start
175
+};
176
+
177
+struct skb_data { /* skb->cb is one of these */
178
+ struct urb *urb;
179
+ struct usbnet *dev;
180
+ enum skb_state state;
181
+ size_t length;
182
+};
183
+
184
+#ifndef skb_queue_walk_safe
185
+#define skb_queue_walk_safe(queue, skb, tmp) \
186
+ for (skb = (queue)->next, tmp = skb->next; \
187
+ skb != (struct sk_buff *)(queue); \
188
+ skb = tmp, tmp = skb->next)
189
+#endif
190
+
191
+/* messaging support includes the interface name, so it must not be
192
+ * used before it has one ... notably, in minidriver bind() calls.
193
+ */
194
+#ifdef DEBUG
195
+#define devdbg(usbnet, fmt, arg...) \
196
+ printk("%s: " fmt "\n" , (usbnet)->net->name , ## arg)
197
+#else
198
+#define devdbg(usbnet, fmt, arg...) \
199
+ ({ if (0) printk("%s: " fmt "\n" , (usbnet)->net->name , \
200
+ ## arg); 0; })
201
+#endif
202
+
203
+#define deverr(usbnet, fmt, arg...) \
204
+ printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
205
+#define devwarn(usbnet, fmt, arg...) \
206
+ printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
207
+
208
+#define devinfo(usbnet, fmt, arg...) \
209
+ printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
210
+
211
+
212
+#endif /* __LINUX_USB_USBNET_H */
kernel/drivers/net/usb/ax88772C/readme
....@@ -0,0 +1,92 @@
1
+============================================================================
2
+ASIX AX88178 USB 2.0 Gigabit Ethernet Network Adapter
3
+ASIX AX88772 USB 2.0 Fast Ethernet Network Adapter
4
+ASIX AX88772A USB 2.0 Fast Ethernet Network Adapter
5
+ASIX AX88760 USB 2.0 MTT HUB and USB 2.0 to Fast Ethernet Combo Controller
6
+ASIX AX88772B USB 2.0 Fast Ethernet Network Adapter
7
+ASIX AX88772C USB 2.0 Fast Ethernet Network Adapter
8
+Driver Compilation & Configuration on the Linux
9
+============================================================================
10
+
11
+This driver has been verified on Linux kernel 2.6.14 and later.
12
+
13
+================
14
+Prerequisites
15
+================
16
+
17
+Prepare to build the driver, you need the Linux kernel sources installed on the
18
+build machine, and make sure that the version of the running kernel must match
19
+the installed kernel sources. If you don't have the kernel sources, you can get
20
+it from www.kernel.org or contact to your Linux distributor. If you don't know
21
+how to do, please refer to KERNEL-HOWTO.
22
+
23
+Note: Please make sure the kernel is built with one of the "Support for
24
+ Host-side, EHCI, OHCI, or UHCI" option support.
25
+
26
+
27
+===========================
28
+Conditional Compilation Flag
29
+===========================
30
+[AX_FORCE_BUFF_ALIGN]
31
+Description:
32
+ There are alignment issues of USB buffer in some USB host controllers.
33
+ Turn on this flag if the implementation of your USB host controller
34
+ cannot handle non-double word aligned buffer.
35
+ When turn on this flag, driver will fixup egress packet aligned on double
36
+ word boundary before deliver to USB host controller.
37
+Setting:
38
+ 1 -> Enable TX buffers forced on double word alignment.
39
+ 0 -> Disable TX buffers forced on double word alignment.
40
+Default:
41
+ 0
42
+
43
+
44
+================
45
+Getting Start
46
+================
47
+
48
+1. Extract the compressed driver source file to your template directory by the
49
+ following command:
50
+
51
+ [root@localhost template]# tar -xf DRIVER_SOURCE_PACKAGE.tar.bz2
52
+
53
+2. Now, the driver source files should be extracted under the current directory.
54
+ Executing the following command to compile the driver:
55
+
56
+ [root@localhost template]# make
57
+
58
+3. If the compilation is well, the asix.ko will be created under the current
59
+ directory.
60
+
61
+4. If you want to use modprobe command to mount the driver, executing the
62
+ following command to install the driver into your Linux:
63
+
64
+ [root@localhost template]# make install
65
+
66
+
67
+================
68
+Usage
69
+================
70
+
71
+1. If you want to load the driver manually, go to the driver directory and
72
+ execute the following commands:
73
+
74
+ [root@localhost template]# insmod asix.ko
75
+
76
+2. If you had installed the driver during driver compilation, then you can use
77
+ the following command to load the driver automatically.
78
+
79
+ [root@localhost anywhere]# modprobe asix
80
+
81
+If you want to unload the driver, just executing the following command:
82
+
83
+ [root@localhost anywhere]# rmmod asix
84
+
85
+================
86
+Special define
87
+================
88
+There is a RX_SKB_COPY preprocessor define in asix.h can solve rx_throttle problem
89
+in some version of 3.4 Linux kernel. Removing the comment before the define can enable
90
+this feature.
91
+
92
+