MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / net / ks8695 / ks8695_main.c
blob50184a05858b460cc2f462cd202409ec2857f80d
1 /*
2 Copyright (c) 2002-2003, Micrel Semiconductor
4 Written 2002 by LIQUN RUAN
6 This software may be used and distributed according to the terms of
7 the GNU General Public License (GPL), incorporated herein by reference.
8 Drivers based on or derived from this code fall under the GPL and must
9 retain the authorship, copyright and license notice. This file is not
10 a complete program and may only be used when the entire operating
11 system is licensed under the GPL.
13 The author may be reached as liqun.ruan@micrel.com
14 Micrel Semiconductor
15 1931 Fortune Dr.
16 San Jose, CA 95131
18 This driver is for Micrel's KS8695/KS8695P SOHO Router Chipset as ethernet driver.
20 Support and updates available at
21 www.micrel.com/ks8695/ not ready yet!!!
24 #define __KS8695_MAIN__
25 #include <linux/mii.h>
26 #include "ks8695_drv.h"
27 #include "ks8695_ioctrl.h"
28 #include "ks8695_cache.h"
29 #include <asm-arm/unaligned.h>
31 #ifdef CONFIG_LEDMAN
32 #include <linux/ledman.h>
33 #endif
35 /* define which external ports do what... */
36 #if defined(CONFIG_MACH_CM4008) || defined(CONFIG_MACH_CM41xx) || \
37 defined(CONFIG_MACH_LITE300) || defined(CONFIG_MACH_SE4200)
38 #define LANPORT 0
39 #define WANPORT 1
40 #define HPNAPORT 2
41 #else
42 #define WANPORT 0
43 #define LANPORT 1
44 #define HPNAPORT 2
45 #endif
47 #undef USE_TX_UNAVAIL
48 #undef USE_RX_UNAVAIL
49 #undef PACKET_DUMP
51 /* process recevied packet in task ReceiveProcessTask().*/
52 //RLQ, defined in Makfile
53 //#define RX_TASK
54 //#define TX_TASK
56 /* process recevied packet in ISR.*/
57 #undef HANDLE_RXPACKET_BY_INTERRUPT
58 #ifdef HANDLE_RXPACKET_BY_INTERRUPT
59 #undef RX_TASK
60 #undef TX_TASK
61 #endif
63 #define USE_FIQ
65 static int offset = 2; /* shift 2 bytes so that IP header can align to dword boundary */
67 /* update dcache by ourself only if no PCI subsystem is used */
68 #define KS8695_MAX_INTLOOP 1
69 #define WATCHDOG_TICK 3
71 #ifndef CONFIG_ARCH_KS8695P
72 #ifdef KS8695X
73 char ks8695_driver_name[] = "ks8695X SOHO Router 10/100T Ethernet Dirver";
74 char ks8695_driver_string[]="Micrel KS8695X Ethernet Network Driver";
75 #else
76 char ks8695_driver_name[] = "ks8695 SOHO Router 10/100T Ethernet Dirver";
77 char ks8695_driver_string[]="Micrel KS8695 Ethernet Network Driver";
78 #endif /*KS8695X*/
79 #else
80 char ks8695_driver_name[] = "ks8695P SOHO Router 10/100T Ethernet Dirver";
81 char ks8695_driver_string[]="Micrel KS8695P Ethernet Network Driver";
82 #endif //CONFIG_ARCH_KS8695P
83 char ks8695_driver_version[] = "1.0.0.20";
84 char ks8695_copyright[] = "Copyright (c) 2002-2004 Micrel Semiconductor Corp.";
86 PADAPTER_STRUCT ks8695_adapter_list = NULL;
88 #if defined(CONFIG_MACH_CM4002) || defined(CONFIG_MACH_CM4008) || \
89 defined(CONFIG_MACH_CM41xx)
90 #define KS8695_MAX_NIC 1 /* Only 1 LAN port used */
91 #elif !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
92 #define KS8695_MAX_NIC 3 /* 0 for WAN, 1 for LAN and 2 for HPHA */
93 #else
94 #define KS8695_MAX_NIC 2 /* 0 for WAN and 1 for LAN, KS8695X doesn't have HPNA port either */
95 #endif //CONFIG_ARCH_KS8695P
97 #define STAT_NET(x) (Adapter->net_stats.x)
99 static struct pci_dev pci_dev_mimic[KS8695_MAX_NIC];
100 static int pci_dev_index = 0; /* max dev probe allowed */
102 #define KS8695_OPTION_INIT { [0 ... KS8695_MAX_NIC - 1] = OPTION_UNSET }
104 static int TxDescriptors[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
105 static int RxDescriptors[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
106 static int Speed[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
107 static int Duplex[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
108 static int FlowControl[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
109 static int RxChecksum[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
110 static int TxChecksum[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
111 static int TxPBL[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
112 static int RxPBL[KS8695_MAX_NIC] = KS8695_OPTION_INIT;
113 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
114 static int HPNA = OPTION_UNSET;
115 #endif
116 #ifdef __KS8695_CACHE_H
117 static int PowerSaving = 0; /* default is off */
118 static int ICacheLockdown = 0; /* default is off */
119 static int RoundRobin = 1; /* default Icache is roundrobin */
120 #endif
122 /* For mii-tool support */
123 static struct mii_regs mii_regs_lan[] = {
124 { {KS8695_SWITCH_PORT1, }, {KS8695_SWITCH_AUTO0, 16}, {KS8695_LAN12_POWERMAGR, 16} },
125 { {KS8695_SWITCH_PORT2, }, {KS8695_SWITCH_AUTO0, 0}, {KS8695_LAN12_POWERMAGR, 0} },
126 { {KS8695_SWITCH_PORT3, }, {KS8695_SWITCH_AUTO1, 16}, {KS8695_LAN34_POWERMAGR, 16} },
127 { {KS8695_SWITCH_PORT4, }, {KS8695_SWITCH_AUTO1, 0}, {KS8695_LAN34_POWERMAGR, 0} }
129 static struct mii_regs mii_regs_wan[] = {
130 { {KS8695_WAN_CONTROL, }, {KS8695_WAN_CONTROL, 16}, {KS8695_WAN_CONTROL, 16} }
132 static int skipcmd = 0;
133 static uint16_t ctype = SW_PHY_DEFAULT;
135 #ifndef CONFIG_ARCH_KS8695P
136 #ifdef KS8695X
137 MODULE_AUTHOR("Micrel Semiconductor, <liqun.ruan@micrel.com>");
138 MODULE_DESCRIPTION("Micrel KS8695X SOHO Router Ethernet Network Driver");
139 #else
140 /* for historical reason */
141 MODULE_AUTHOR("Micrel Kendin Operations, <lruan@kendin.com>");
142 MODULE_DESCRIPTION("Micrel Kendin KS8695 SOHO Router Ethernet Network Driver");
143 #endif
144 #else
145 MODULE_AUTHOR("Micrel Semiconductor, <liqun.ruan@micrel.com>");
146 MODULE_DESCRIPTION("Micrel KS8695P SOHO Router Ethernet Network Driver");
147 #endif
148 #ifdef ARM_LINUX
149 MODULE_LICENSE("GPL");
150 #endif
152 module_param_array(TxDescriptors, int, NULL, 0);
153 module_param_array(RxDescriptors, int, NULL, 0);
154 module_param_array(Speed, int, NULL, 0);
155 module_param_array(Duplex, int, NULL, 0);
156 module_param_array(FlowControl, int, NULL, 0);
157 module_param_array(RxChecksum, int, NULL, 0);
158 module_param_array(TxChecksum, int, NULL, 0);
159 module_param_array(TxPBL, int, NULL, 0);
160 module_param_array(RxPBL, int, NULL, 0);
161 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
162 module_param(HPNA, int, 0);
163 #endif
164 module_param(PowerSaving, int, 0);
165 module_param(ICacheLockdown, int, 0);
166 module_param(RoundRobin, int, 0);
168 EXPORT_SYMBOL(ks8695_init_module);
169 EXPORT_SYMBOL(ks8695_exit_module);
170 EXPORT_SYMBOL(ks8695_probe);
171 EXPORT_SYMBOL(ks8695_remove);
172 EXPORT_SYMBOL(ks8695_open);
173 EXPORT_SYMBOL(ks8695_close);
174 EXPORT_SYMBOL(ks8695_xmit_frame);
175 EXPORT_SYMBOL(ks8695_isr);
176 EXPORT_SYMBOL(ks8695_isr_link);
177 EXPORT_SYMBOL(ks8695_set_multi);
178 EXPORT_SYMBOL(ks8695_change_mtu);
179 EXPORT_SYMBOL(ks8695_set_mac);
180 EXPORT_SYMBOL(ks8695_get_stats);
181 EXPORT_SYMBOL(ks8695_watchdog);
182 EXPORT_SYMBOL(ks8695_ioctl);
184 /* for I-cache lockdown or FIQ purpose */
185 EXPORT_SYMBOL(ks8695_isre);
187 int ks8695_module_probe(void);
188 EXPORT_SYMBOL(ks8695_module_probe);
190 /*********************************************************************
191 * Fast timer poll support
192 *********************************************************************/
194 #if defined(CONFIG_FAST_TIMER)
195 #define FAST_POLL 1
196 #include <linux/fast_timer.h>
197 static void ks8695_fast_poll(void *arg);
198 static int ks8695_poll_ready;
199 #endif
201 /*********************************************************************
202 * Local Function Prototypes
203 *********************************************************************/
204 static void CheckConfigurations(PADAPTER_STRUCT Adapter);
205 static int SoftwareInit(PADAPTER_STRUCT Adapter);
206 static int HardwareInit(PADAPTER_STRUCT Adapter);
207 static int AllocateTxDescriptors(PADAPTER_STRUCT Adapter);
208 static int AllocateRxDescriptors(PADAPTER_STRUCT Adapter);
209 static void FreeTxDescriptors(PADAPTER_STRUCT Adapter);
210 static void FreeRxDescriptors(PADAPTER_STRUCT Adapter);
211 static void UpdateStatsCounters(PADAPTER_STRUCT Adapter);
212 #if 0
213 static int ProcessTxInterrupts(PADAPTER_STRUCT Adapter);
214 static int ProcessRxInterrupts(PADAPTER_STRUCT Adapter);
215 #endif
216 static void ReceiveBufferFill(uintptr_t data);
217 static void CleanTxRing(PADAPTER_STRUCT Adapter);
218 static void CleanRxRing(PADAPTER_STRUCT Adapter);
219 static void InitTxRing(PADAPTER_STRUCT Adapter);
220 static void InitRxRing(PADAPTER_STRUCT Adapter);
221 /*static void ReceiveBufferFillEx(PADAPTER_STRUCT Adapter);*/
222 #ifdef __KS8695_CACHE_H
223 static int ks8695_icache_lock2(void *icache_start, void *icache_end);
224 #endif
226 #ifdef RX_TASK
227 static void ReceiveProcessTask(uintptr_t data);
228 #endif
229 #ifdef TX_TASK
230 static void TransmitProcessTask(uintptr_t data);
231 #endif
234 * ResetDma
235 * This function is use to reset DMA in case Tx DMA was sucked due to
236 * heavy traffic condition.
238 * Argument(s)
239 * Adapter pointer to ADAPTER_STRUCT structure.
241 * Return(s)
242 * 0 if success
243 * negative value if failed
245 static __inline void ResetDma(PADAPTER_STRUCT Adapter)
247 struct net_device *netdev;
248 /*BOOLEAN bTxStarted, bRxStarted;*/
249 UINT uRxReg;
251 #ifdef DEBUG_THIS
252 if (DMA_LAN == DI.usDMAId) {
253 DRV_INFO("%s: LAN", __FUNCTION__);
254 } else if (DMA_WAN == DI.usDMAId) {
255 DRV_INFO("%s: WAN", __FUNCTION__);
256 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
257 } else {
258 DRV_INFO("%s: HPNA", __FUNCTION__);
259 #endif
261 #endif
263 if (!test_bit(KS8695_BOARD_OPEN, &Adapter->flags)) {
264 DRV_INFO("%s: driver not opened yet", __FUNCTION__);
265 return;
268 netdev = Adapter->netdev;
270 #ifdef RX_TASK
271 tasklet_disable(&DI.rx_tasklet);
272 #endif
273 #ifdef TX_TASK
274 tasklet_disable(&DI.tx_tasklet);
275 #endif
276 netif_stop_queue(netdev);
278 macStopAll(Adapter);
280 CleanRxRing(Adapter);
281 InitRxRing(Adapter);
282 CleanTxRing(Adapter);
283 InitTxRing(Adapter);
285 ks8695_ChipInit(Adapter, FALSE);
287 KS8695_WRITE_REG(KS8695_INT_STATUS, DI.uIntMask);
289 /* read RX mode register */
290 uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
291 if (netdev->flags & IFF_PROMISC) {
292 uRxReg |= DMA_PROMISCUOUS;
294 if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) {
295 uRxReg |= DMA_MULTICAST;
297 uRxReg |= DMA_BROADCAST;
299 /* write RX mode register */
300 KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg);
302 KS8695_WRITE_REG(REG_RXBASE + DI.nOffset, cpu_to_le32(DI.RxDescDMA));
303 KS8695_WRITE_REG(REG_TXBASE + DI.nOffset, cpu_to_le32(DI.TxDescDMA));
304 macEnableInterrupt(Adapter, TRUE);
306 #ifdef RX_TASK
307 tasklet_enable( &DI.rx_tasklet );
308 if (DI.rx_scheduled) {
309 tasklet_hi_schedule(&DI.rx_tasklet);
311 #endif
312 #ifdef TX_TASK
313 tasklet_enable( &DI.tx_tasklet );
314 if (DI.tx_scheduled) {
315 tasklet_hi_schedule(&DI.tx_tasklet);
317 #endif
318 netif_start_queue(netdev);
320 /*if (bRxStarted)*/
321 macStartRx(Adapter, TRUE);
322 /*if (bTxStarted)*/
323 macStartTx(Adapter, TRUE);
327 * ks8695_dump_packet
328 * This function is use to dump given packet for debugging.
330 * Argument(s)
331 * Adapter pointer to ADAPTER_STRUCT structure.
332 * data pointer to the beginning of the packet to dump
333 * len length of the packet
334 * flag debug flag
336 * Return(s)
337 * NONE.
339 #ifndef PING_READY
340 static __inline void ks8695_dump_packet(PADAPTER_STRUCT Adapter, unsigned char *data, int len, UINT flag)
342 /* we may need to have locking mechamism to use this function, since Rx call it within INT context
343 and Tx call it in normal context */
345 if (flag && len >= 18) {
346 if (flag & DEBUG_PACKET_LEN) {
347 printk("Pkt Len=%d\n", len);
349 if (flag & DEBUG_PACKET_CONTENT) {
350 int j = 0, k;
352 do {
353 printk("\n %08x ", (int)(data+j));
354 for (k = 0; (k < 16 && len); k++, data++, len--) {
355 printk("%02x ", *data);
357 j += 16;
358 } while (len > 0);
359 printk("\n");
363 #endif
365 #ifdef PING_READY
366 static __inline void ks8695_dump_packet(PADAPTER_STRUCT Adapter, unsigned char *data, int len, UINT flag)
368 /* we may need to have locking mechamism to use this function, since Rx call it within INT context
369 and Tx call it in normal context */
371 DRV_INFO("%s", __FUNCTION__);
373 if (flag && len >= 18) {
374 if (flag & DEBUG_PACKET_LEN) {
375 printk("Pkt Len=%d\n", len);
377 if (flag & DEBUG_PACKET_HEADER) {
378 printk("DA=%02x:%02x:%02x:%02x:%02x:%02x\n",
379 *data, *(data + 1), *(data + 2), *(data + 3), *(data + 4), *(data + 5));
380 printk("SA=%02x:%02x:%02x:%02x:%02x:%02x\n",
381 *(data + 6), *(data + 7), *(data + 8), *(data + 9), *(data + 10), *(data + 11));
382 printk("Type=%04x (%d)\n", ntohs(*(unsigned short *)(data + 12)), ntohs(*(unsigned short *)(data + 12)));
384 if (flag & DEBUG_PACKET_CONTENT) {
385 int j = 0, k;
387 /* skip DA/SA/TYPE, ETH_HLEN is defined in if_ether.h under include/linux dir */
388 data += ETH_HLEN;
389 /*len -= (ETH_HLEN + ETH_CRC_LENGTH);*/
390 len -= ETH_HLEN;
391 do {
392 printk("\n %04d ", j);
393 for (k = 0; (k < 16 && len); k++, data++, len--) {
394 printk("%02x ", *data);
396 j += 16;
397 } while (len > 0);
398 /* last dump crc field */
399 /*printk("\nCRC=%04x\n", ntohl(*(unsigned int *)data));*/
403 #endif
407 * ks8695_relink
408 * This function is use to setup link in case some dynamic configuration
409 * is applied via ifconfig! if driver is opened!
411 * Argument(s)
412 * Adapter pointer to ADAPTER_STRUCT structure.
414 * Return(s)
415 * NONE.
417 static void ks8695_relink(PADAPTER_STRUCT Adapter)
419 if (test_bit(KS8695_BOARD_OPEN, &Adapter->flags)) {
420 /* reset the flag even if it is auto nego is in progress
421 to make sure we don't miss it!!! */
422 if (DMA_LAN != DI.usDMAId) {
423 swDetectPhyConnection(Adapter, 0);
425 else {
426 int i;
428 for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
429 swDetectPhyConnection(Adapter, i);
436 * ks8695_report_carrier
437 * This function is use to report carrier status to net device
439 * Argument(s)
440 * netdev pointer to net_device structure.
441 * carrier carrier status (0 off, non zero on)
443 * Return(s)
444 * NONE.
446 static void ks8695_report_carrier(struct net_device *netdev, int carrier)
448 #ifdef DEBUG_THIS
449 DRV_INFO("%s", __FUNCTION__);
450 #endif
452 /* if link is on */
453 if (carrier) {
454 netif_carrier_on(netdev);
455 netif_carrier_ok(netdev);
457 else {
458 netif_carrier_off(netdev);
462 static void ks8695_tx_timeout(struct net_device *netdev)
464 printk("%s(%d): ks8695_tx_timeout()\n", __FILE__, __LINE__);
468 * ks8695_module_probe
469 * This function is used to simulate pci's probe function.
471 * Argument(s)
472 * NONE.
474 * Return(s)
475 * 0 if success
476 * negative value if failed
478 int ks8695_module_probe(void)
480 #if 0
481 spinlock_t eth_lock = SPIN_LOCK_UNLOCKED;
482 unsigned long flags;
483 #endif
484 int nRet;
485 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
486 int nHPHA = 0;
487 #endif
489 #ifdef DEBUG_THIS
490 DRV_INFO("%s", __FUNCTION__);
491 #endif
493 #ifdef __KS8695_CACHE_H
494 if (RoundRobin) {
495 ks8695_icache_change_policy(RoundRobin);
497 if (ICacheLockdown)
498 ks8695_icache_lock2(ks8695_isr, ks8695_isre);
499 #endif
501 if (pci_dev_index >= KS8695_MAX_NIC)
502 return -EINVAL;
504 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
505 /* if user enabled HPNA */
506 if (HPNA != OPTION_UNSET) {
507 nHPHA = HPNA ? 1 : 0;
509 #endif
511 #ifdef __KS8695_CACHE_H
512 /* if allow power saving, default no power saving (wait for interrupt) */
513 if (PowerSaving) {
514 ks8695_enable_power_saving(PowerSaving);
516 #endif
518 nRet = 0;
519 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
520 /* default WAN and LAN, plus HPNA if enabled by the user */
521 for (pci_dev_index = 0; pci_dev_index < (2 + nHPHA); pci_dev_index++) {
522 #else
523 /* KS8695P and KS8695X has only WAN and LAN */
524 for (pci_dev_index = 0; pci_dev_index < KS8695_MAX_NIC; pci_dev_index++) {
525 #endif
526 if (0 == pci_dev_index) {
527 //strcpy(pci_dev_mimic[pci_dev_index].name, "WAN Port");
528 pci_dev_mimic[pci_dev_index].irq = 29;
530 else if (1 == pci_dev_index) {
531 //strcpy(pci_dev_mimic[pci_dev_index].name, "LAN Port");
532 pci_dev_mimic[pci_dev_index].irq = 22;
534 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
535 else {
536 //strcpy(pci_dev_mimic[pci_dev_index].name, "HPNA Port");
537 pci_dev_mimic[pci_dev_index].irq = 14;
539 #endif
540 #ifdef DEBUG_THIS
541 DRV_INFO("%s: set ks8695_probe(%d)", __FUNCTION__, pci_dev_index);
542 #endif
543 #if 0
544 /* We MUST not have interrupts off when calling through this */
545 spin_lock_irqsave(&eth_lock, flags);
546 #endif
547 /* we don't use pci id field, so set it to NULL */
548 nRet = ks8695_probe(&pci_dev_mimic[pci_dev_index], NULL);
549 #if 0
550 spin_unlock_irqrestore(&eth_lock, flags);
551 #endif
552 /* if error happened */
553 if (nRet) {
554 DRV_ERR("%s: ks8695_probe(%d) failed, error code = 0x%08x", __FUNCTION__, pci_dev_index, nRet);
555 break;
559 return nRet;
563 * hook_irqs
564 * This function is used to hook irqs associated to given DMA type
566 * Argument(s)
567 * netdev pointer to netdev structure.
568 * req request or free interrupts
570 * Return(s)
571 * 0 if success
572 * negative value if failed
574 static int hook_irqs(struct net_device *netdev, int req)
576 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
577 #ifndef FAST_POLL
578 int i;
579 #endif
581 switch (DI.usDMAId) {
582 default:
583 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
584 case DMA_HPNA:
585 #endif
586 case DMA_LAN:
587 break;
589 case DMA_WAN:
590 if (DI.uLinkIntMask & INT_WAN_LINK) {
591 if (req) {
592 #ifndef USE_FIQ
593 if (request_irq(31, ks8695_isr_link, SA_SHIRQ, "WAN eth", netdev)) {
594 #else
595 if (request_irq(31, ks8695_isr_link, SA_SHIRQ | SA_INTERRUPT, "WAN eth", netdev)) {
596 #endif
597 return -EBUSY;
600 else {
601 free_irq(31, netdev);
604 break;
607 #ifdef FAST_POLL
608 if (req)
609 fast_timer_add(ks8695_fast_poll, netdev);
610 else
611 fast_timer_remove(ks8695_fast_poll, netdev);
612 #else
613 /* each DMA has 6 interrupt bits associated, except WAN which has one extra, INT_WAN_LINK */
614 for (i = 0; i < 6; i++) {
615 if (DI.uIntMask & (1L << (DI.uIntShift + i))) {
616 if (req) {
617 #ifndef USE_FIQ
618 if (request_irq(i + DI.uIntShift, &ks8695_isr, SA_SHIRQ, "LAN eth", netdev)) {
619 #else
620 if (request_irq(i + DI.uIntShift, &ks8695_isr, SA_SHIRQ | SA_INTERRUPT, "LAN eth", netdev)) {
621 #endif
622 return -EBUSY;
625 else {
626 free_irq(i + DI.uIntShift, netdev);
630 #endif /* FAST_POLL */
632 return 0;
636 * Determine MAC addresses for ethernet ports.
638 #if defined(CONFIG_MACH_CM4002) || defined(CONFIG_MACH_CM4008) || \
639 defined(CONFIG_MACH_CM41xx)
640 #define MAC_OFFSET 0x1c000
641 #define MAC_DEFAULT 0x00, 0x13, 0xc6, 0x00, 0x00, 0x00
642 #elif defined(CONFIG_MACH_LITE300) || defined(CONFIG_MACH_SE4200)
643 #define MAC_OFFSET 0x0c000
644 #define MAC_DEFAULT 0x00, 0xd0, 0xcf, 0x00, 0x00, 0x00
645 #endif
647 #ifdef MAC_OFFSET
649 * Ideally we want to use the MAC addresses stored in flash.
650 * But we do some sanity checks in case they are not present
651 * first.
653 void ks8695_getmac(unsigned char *dst, int index)
655 unsigned char dm[] = { MAC_DEFAULT };
656 unsigned char *src, *mp, *ep;
657 int i;
659 /* Construct a default MAC address just in case */
660 dm[ETH_LENGTH_OF_ADDRESS-1] = index;
661 src = &dm[0];
663 ep = ioremap(0x02000000, 0x20000);
664 if (ep) {
665 /* Check if flash MAC is valid */
666 mp = ep + MAC_OFFSET + (index * ETH_LENGTH_OF_ADDRESS);
667 for (i = 0; (i < ETH_LENGTH_OF_ADDRESS); i++) {
668 if ((mp[i] != 0) && (mp[i] != 0xff)) {
669 src = mp;
670 break;
675 memcpy(dst, src, ETH_LENGTH_OF_ADDRESS);
677 if (ep)
678 iounmap(ep);
680 #else
681 void ks8695_getmac(unsigned char *dst, int index)
683 static char macs[] = {
684 0x00, 0x10, 0xa1, 0x00, 0x10, 0x01,
686 memcpy(dst, macs, ETH_LENGTH_OF_ADDRESS);
687 macs[ETH_LENGTH_OF_ADDRESS-1]++;
689 #endif
692 * ks8695_init_module
693 * This function is the first routine called when the driver is loaded.
695 * Argument(s)
696 * NONE.
698 * Return(s)
699 * 0 if success
700 * negative value if failed
702 int ks8695_init_module(void)
704 int nRet;
706 /* Print the driver ID string and copyright notice */
707 DRV_INFO(" %s, version %s, %s",
708 ks8695_driver_string, ks8695_driver_version, ks8695_copyright);
710 #ifdef DEBUG_THIS
711 DRV_INFO(" IO Address=0x%x", KS8695_IO_VIRT));
712 #endif
714 nRet = ks8695_module_probe();
716 return nRet;
719 module_init(ks8695_init_module);
722 * ks8695_exit_module
723 * This function is called just before the driver is removed from memory.
725 * Argument(s)
726 * NONE.
728 * Return(s)
729 * NONE.
731 void ks8695_exit_module(void)
733 #ifdef DEBUG_THIS
734 DRV_INFO("%s: pci_dev_index=%d", __FUNCTION__, pci_dev_index);
735 #endif
738 int i;
740 #ifdef __KS8695_CACHE_H
741 if (ICacheLockdown)
742 ks8695_icache_unlock();
743 #endif
744 for (i = pci_dev_index; i > 0; i--) {
745 ks8695_remove(&pci_dev_mimic[i - 1]);
747 pci_dev_index = 0;
751 module_exit(ks8695_exit_module);
754 * ks8695_probe
755 * This function initializes an adapter identified by a pci_dev
756 * structure. Note that KS8695 eval board doesn't have PCI bus at all,
757 * but the driver uses that since it was derived from a PCI based driver
758 * originally.
760 * Argument(s)
761 * pdev pointer to PCI device information struct
762 * ent pointer to PCI device ID structure (ks8695_pci_table)
764 * Return(s)
765 * 0 if success
766 * negative value if failed
768 int ks8695_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
770 struct net_device *netdev = NULL;
771 PADAPTER_STRUCT Adapter;
772 static int cards_found = 0;
773 int nRet;
775 /* Register a new network interface and allocate private data
776 structure (ADAPTER_STRUCT) */
777 netdev = alloc_etherdev(sizeof(ADAPTER_STRUCT));
778 if (NULL == netdev) {
779 DRV_ERR("alloc_etherdev failed");
780 return -ENOMEM;
783 Adapter = (PADAPTER_STRUCT) netdev_priv(netdev);
784 /*memset(Adapter, 0, sizeof(ADAPTER_STRUCT));*/
785 Adapter->netdev = netdev;
786 Adapter->pdev = pdev;
788 /* chain the ADAPTER_STRUCT into the list */
789 if (ks8695_adapter_list)
790 ks8695_adapter_list->prev = Adapter;
791 Adapter->next = ks8695_adapter_list;
792 ks8695_adapter_list = Adapter;
794 /* simply tell the network interface we are using this irq, but the driver
795 use more for each DMA, look for /proc/interrupts for details */
796 netdev->irq = pdev->irq;
798 Adapter->stDMAInfo.nBaseAddr = KS8695_IO_VIRT;
799 netdev->mem_start = KS8695_IO_VIRT;
800 netdev->mem_end = netdev->mem_start + 0xffff;
802 /* #ifdef DEBUG_THIS */
803 DRV_INFO("VA = 0x%08x, PA=0x%08x", Adapter->stDMAInfo.nBaseAddr, KS8695_IO_BASE);
804 /* #endif */
806 /* set up function pointers to driver entry points */
807 netdev->open = &ks8695_open;
808 netdev->stop = &ks8695_close;
809 netdev->hard_start_xmit = &ks8695_xmit_frame;
810 netdev->get_stats = &ks8695_get_stats;
811 netdev->set_multicast_list = &ks8695_set_multi;
812 netdev->set_mac_address = &ks8695_set_mac;
813 netdev->change_mtu = &ks8695_change_mtu;
814 netdev->do_ioctl = &ks8695_ioctl;
815 netdev->tx_timeout = &ks8695_tx_timeout;
816 netdev->watchdog_timeo = 10*HZ;
817 if (DI.bTxChecksum)
818 netdev->features |= NETIF_F_HW_CSUM;
820 #ifdef CONFIG_ARCH_KS8695P
821 Adapter->rev = (KS8695_READ_REG(KS8695_REVISION_ID) >> 0x4) & 0xf;
822 #else
823 #ifdef KS8695X
824 Adapter->rev = (KS8695_READ_REG(KS8695_REVISION_ID) >> 0x4) & 0xf;
825 #else
826 Adapter->rev = 0;
827 #endif /*KS8695X*/
828 #endif
830 /* the card will tell which driver it will be */
831 Adapter->bd_number = cards_found;
833 if (WANPORT == cards_found) {
834 /* for WAN */
835 DI.usDMAId = DMA_WAN;
836 DI.nOffset = DMA_WAN;
837 DI.uIntMask = INT_WAN_MASK;
838 DI.uLinkIntMask = INT_WAN_LINK;
840 #ifndef USE_RX_UNAVAIL
841 /* clear Rx buf unavail bit */
842 DI.uIntMask &= ~BIT(27);
843 #endif
845 #ifndef USE_TX_UNAVAIL
846 /* clear Tx buf unavail bit */
847 DI.uIntMask &= ~BIT(28);
848 #endif
849 /* DMA's stop bit is a little bit different compared with KS9020, so disable them first */
850 DI.uIntMask &= ~BIT(26);
851 DI.uIntMask &= ~BIT(25);
852 DI.uIntShift = 25;
854 /* set default mac address for WAN */
855 ks8695_getmac(DI.stMacStation, cards_found);
857 } else if (LANPORT == cards_found) {
858 /* for LAN */
859 DI.usDMAId = DMA_LAN;
860 DI.nOffset = DMA_LAN;
861 DI.uIntMask = INT_LAN_MASK;
863 #ifndef USE_RX_UNAVAIL
864 /* clear Rx buf unavail bit */
865 DI.uIntMask &= ~BIT(14);
866 #endif
868 #ifndef USE_TX_UNAVAIL
869 /* clear Tx buf unavail bit */
870 DI.uIntMask &= ~BIT(15);
871 #endif
872 DI.uIntMask &= ~BIT(13);
873 DI.uIntMask &= ~BIT(12);
874 DI.uIntShift = 12;
876 ks8695_getmac(DI.stMacStation, cards_found);
878 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
879 } else if (HPNAPORT == cards_found) {
880 /* for HPNA */
881 DI.usDMAId = DMA_HPNA;
882 DI.nOffset = DMA_HPNA;
883 DI.uIntMask = INT_HPNA_MASK;
884 #ifdef RX_TASK
885 /* clear Rx buf unavail bit */
886 DI.uIntMask &= ~BIT(20);
887 #endif
888 #ifndef USE_TX_UNAVAIL
889 /* clear Tx buf unavail bit */
890 /* if use Tx coalescing, don't disable Tx Complete bit */
891 DI.uIntMask &= ~BIT(21);
892 #else
893 /* clear Tx Completed bit */
894 DI.uIntMask &= ~BIT(23);
895 #endif
896 DI.uIntMask &= ~BIT(19);
897 DI.uIntMask &= ~BIT(18);
899 DI.uIntShift = 18;
900 ks8695_getmac(DI.stMacStation, cards_found);
901 #endif
902 } else {
903 DRV_ERR("%s: card id out of range (%d)", __FUNCTION__, cards_found);
904 return -ENODEV;
907 nRet = SoftwareInit(Adapter);
908 if (nRet) {
909 DRV_ERR("%s: SoftwareInit failed", __FUNCTION__);
910 ks8695_remove(pdev);
911 return nRet;
913 CheckConfigurations(Adapter);
915 /* reset spinlock */
916 DI.lock = SPIN_LOCK_UNLOCKED;
917 DI.lock_refill = SPIN_LOCK_UNLOCKED;
919 /* finally, we get around to setting up the hardware */
920 if (HardwareInit(Adapter) < 0) {
921 DRV_ERR("%s: HardwareInit failed", __FUNCTION__);
922 ks8695_remove(pdev);
923 return -ENODEV;
925 cards_found++;
927 #if defined(CONFIG_MACH_LITE300)
928 /* set LED 0 for link/activities */
929 swSetLED(Adapter, FALSE, LED_LINK_ACTIVITY);
930 #else
931 /* set LED 0 for speed */
932 swSetLED(Adapter, FALSE, LED_SPEED);
933 #endif
934 /* set LED 1 for link/activities */
935 swSetLED(Adapter, TRUE, LED_LINK_ACTIVITY);
937 if ((nRet = register_netdev(netdev))) {
938 return -EIO;
941 return 0;
945 * ks8695_remove
946 * This function is called by the PCI subsystem to alert the driver
947 * that it should release a PCI device. It is called to clean up from
948 * a failure in ks8695_probe.
950 * Argument(s)
951 * pdev pointer to PCI device information struct
953 * Return(s)
954 * NONE.
956 void ks8695_remove(struct pci_dev *pdev)
958 struct net_device *netdev;
959 PADAPTER_STRUCT Adapter;
961 #ifdef DEBUG_THIS
962 DRV_INFO("%s", __FUNCTION__);
963 #endif
965 /* find the Adapter struct that matches this PCI device */
966 for (Adapter = ks8695_adapter_list; Adapter != NULL; Adapter = Adapter->next) {
967 if (Adapter->pdev == pdev)
968 break;
970 /* if no match is found */
971 if (Adapter == NULL)
972 return;
974 #ifdef DEBUG_THIS
975 DRV_INFO("%s: match found, bd_num = %d", __FUNCTION__, Adapter->bd_number);
976 #endif
978 netdev = Adapter->netdev;
980 if (test_bit(KS8695_BOARD_OPEN, &Adapter->flags))
981 ks8695_close(netdev);
983 /* remove from the adapter list */
984 if (ks8695_adapter_list == Adapter)
985 ks8695_adapter_list = Adapter->next;
986 if (Adapter->next != NULL)
987 Adapter->next->prev = Adapter->prev;
988 if (Adapter->prev != NULL)
989 Adapter->prev->next = Adapter->next;
991 /* free the net_device _and_ ADAPTER_STRUCT memory */
992 unregister_netdev(netdev);
993 kfree(netdev);
997 * CheckConfigurations
998 * This function checks all command line paramters for valid user
999 * input. If an invalid value is given, or if no user specified
1000 * value exists, a default value is used.
1002 * Argument(s)
1003 * Adapter pointer to ADAPTER_STRUCT structure.
1005 * Return(s)
1006 * NONE.
1008 static void CheckConfigurations(PADAPTER_STRUCT Adapter)
1010 int board = Adapter->bd_number, i;
1012 #ifdef DEBUG_THIS
1013 DRV_INFO("%s (board number = %d)", __FUNCTION__, board);
1014 #endif
1016 /* Transmit Descriptor Count */
1017 if (TxDescriptors[board] == OPTION_UNSET) {
1018 DI.nTxDescTotal = TXDESC_DEFAULT; /* 256 | 128 | 64(d) */
1019 } else if ((TxDescriptors[board] > TXDESC_MAX) &&
1020 (TxDescriptors[board] < TXDESC_MIN)) {
1021 DRV_WARN("Invalid TxDescriptor specified (%d), using default %d",
1022 TxDescriptors[board], TXDESC_DEFAULT);
1023 DI.nTxDescTotal = TXDESC_DEFAULT;
1024 } else {
1025 DRV_INFO("User specified TxDescriptors %d is used", TxDescriptors[board]);
1026 DI.nTxDescTotal = TxDescriptors[board];
1028 /* Tx coalescing, currently can only be used if buffer unavailable bit is set */
1029 DI.nTransmitCoalescing = (DI.nTxDescTotal >> 3);
1031 /* Receive Descriptor Count */
1032 if (RxDescriptors[board] == OPTION_UNSET) {
1033 DI.nRxDescTotal = RXDESC_DEFAULT; /* 256(d) | 128 | 64 */
1034 } else if ((RxDescriptors[board] > RXDESC_MAX) ||
1035 (RxDescriptors[board] < RXDESC_MIN)) {
1036 DRV_WARN("Invalid RxDescriptor specified (%d), using default %d",
1037 RxDescriptors[board], RXDESC_DEFAULT);
1038 } else {
1039 DRV_INFO("User specified RxDescriptors %d is used", RxDescriptors[board]);
1040 DI.nRxDescTotal = RxDescriptors[board];
1043 /* Receive Checksum Offload Enable */
1044 if (RxChecksum[board] == OPTION_UNSET) {
1045 DI.bRxChecksum = RXCHECKSUM_DEFAULT; /* enabled */
1046 } else if ((RxChecksum[board] != OPTION_ENABLED) && (RxChecksum[board] != OPTION_DISABLED)) {
1047 DRV_INFO("Invalid RxChecksum specified (%i), using default of %i",
1048 RxChecksum[board], RXCHECKSUM_DEFAULT);
1049 DI.bRxChecksum = RXCHECKSUM_DEFAULT;
1050 } else {
1051 DRV_INFO("Receive Checksum Offload %s",
1052 RxChecksum[board] == OPTION_ENABLED ? "Enabled" : "Disabled");
1053 DI.bRxChecksum = RxChecksum[board];
1056 /* Transmit Checksum Offload Enable configuration */
1057 if (OPTION_UNSET == TxChecksum[board]) {
1058 DI.bTxChecksum = TXCHECKSUM_DEFAULT; /* disabled */
1059 } else if ((OPTION_ENABLED != TxChecksum[board]) && (OPTION_DISABLED != TxChecksum[board])) {
1060 DRV_INFO("Invalid TxChecksum specified (%i), using default of %i",
1061 TxChecksum[board], TXCHECKSUM_DEFAULT);
1062 DI.bTxChecksum = TXCHECKSUM_DEFAULT;
1063 } else {
1064 DRV_INFO("Transmit Checksum Offload specified %s",
1065 TxChecksum[board] == OPTION_ENABLED ? "Enabled" : "Disabled");
1066 DI.bTxChecksum = TxChecksum[board];
1069 /* Flow Control */
1070 if (FlowControl[board] == OPTION_UNSET) {
1071 DI.bRxFlowCtrl = FLOWCONTROL_DEFAULT; /* enabled */
1072 } else if ((OPTION_ENABLED != FlowControl[board]) && (OPTION_DISABLED != FlowControl[board])) {
1073 DRV_INFO("Invalid FlowControl specified (%i), using default %i",
1074 FlowControl[board], FLOWCONTROL_DEFAULT);
1075 DI.bRxFlowCtrl = FLOWCONTROL_DEFAULT;
1076 } else {
1077 DRV_INFO("Flow Control %s", FlowControl[board] == OPTION_ENABLED ?
1078 "Enabled" : "Disabled");
1079 DI.bRxFlowCtrl = FlowControl[board];
1081 /* currently Tx control flow shares the setting of Rx control flow */
1082 DI.bTxFlowCtrl = DI.bRxFlowCtrl;
1084 /* Perform PHY PowerDown Reset instead of soft reset, the Option function can
1085 be overwritten by user later */
1086 DI.bPowerDownReset = TRUE;
1088 /* Programmable Burst Length */
1089 if (OPTION_UNSET == TxPBL[board]) {
1090 DI.byTxPBL = PBL_DEFAULT; /* FIFO size */
1091 } else if ((0 != TxPBL[board]) && (1 != TxPBL[board]) && (2 != TxPBL[board]) && (4 != TxPBL[board]) &&
1092 (8 != TxPBL[board]) && (16 != TxPBL[board]) && (32 != TxPBL[board])) {
1093 DRV_INFO("Invalid TX Programmable Burst Length specified (%i), using default of %i",
1094 TxPBL[board], PBL_DEFAULT);
1095 DI.byTxPBL = PBL_DEFAULT;
1096 } else {
1097 DRV_INFO("Programmable Burst Length specified %d bytes", TxPBL[board]);
1098 DI.byTxPBL = TxPBL[board];
1101 if (OPTION_UNSET == RxPBL[board]) {
1102 DI.byRxPBL = PBL_DEFAULT; /* FIFO size */
1103 } else if ((0 != TxPBL[board]) && (1 != RxPBL[board]) && (2 != RxPBL[board]) && (4 != RxPBL[board]) &&
1104 (8 != RxPBL[board]) && (16 != RxPBL[board]) && (32 != RxPBL[board])) {
1105 DRV_INFO("Invalid TX Programmable Burst Length specified (%i), using default of %i",
1106 RxPBL[board], PBL_DEFAULT);
1107 DI.byRxPBL = PBL_DEFAULT;
1108 } else {
1109 DRV_INFO("Programmable Burst Length specified %d bytes", RxPBL[board]);
1110 DI.byRxPBL = RxPBL[board];
1113 /* User speed and/or duplex options */
1114 if (Duplex[board] == OPTION_UNSET && Speed[board] == OPTION_UNSET) {
1115 DI.usCType[0] = SW_PHY_DEFAULT;
1117 else {
1118 switch (Speed[board]) {
1119 case 10:
1120 if (Duplex[board])
1121 DI.usCType[0] = SW_PHY_10BASE_T_FD; /* 10Base-TX Full Duplex */
1122 else {
1123 /* don't advertise flow control in half duplex case */
1124 if (DMA_WAN == DI.usDMAId) {
1125 DI.bRxFlowCtrl = FALSE;
1126 DI.bTxFlowCtrl = FALSE;
1128 DI.usCType[0] = SW_PHY_10BASE_T; /* 10Base-T Half Duplex */
1130 break;
1132 case 100:
1133 default:
1134 if (Duplex[board])
1135 DI.usCType[0] = SW_PHY_100BASE_TX_FD; /* 100Base-TX Full Duplex */
1136 else {
1137 /* don't advertise flow control in half duplex case */
1138 if (DMA_WAN == DI.usDMAId) {
1139 DI.bRxFlowCtrl = FALSE;
1140 DI.bTxFlowCtrl = FALSE;
1142 DI.usCType[0] = SW_PHY_100BASE_TX; /* 100Base-TX Half Duplex */
1144 break;
1148 if (DMA_LAN == DI.usDMAId) {
1149 /*TEMP, currently assume all other ports share same configuration with
1150 first one, will add more options for LAN ports later */
1151 for (i = 1; i < SW_MAX_LAN_PORTS; i++) {
1152 DI.usCType[i] = DI.usCType[0];
1155 /* initialize some variables which do not have user configurable options */
1156 for (i = 0; i <= SW_MAX_LAN_PORTS; i++) {
1157 DPI[i].byCrossTalkMask = 0x1f;
1158 DPI[i].bySpanningTree = SW_SPANNINGTREE_ALL;
1159 DPI[i].byDisableSpanningTreeLearn = FALSE;
1162 /* set default as direct mode for port 5, so no lookup table is checking */
1163 DI.bRxDirectMode = FALSE;
1164 DI.bTxRreTagMode = FALSE;
1166 DI.bPort5FlowCtrl = DI.bRxFlowCtrl;
1167 DI.bPortsFlowCtrl = DI.bRxFlowCtrl;
1172 * SoftwareInit
1173 * This function initializes the Adapter private data structure.
1175 * Argument(s)
1176 * Adapter pointer to ADAPTER_STRUCT structure
1178 * Return(s)
1179 * 0 if success
1180 * negative value if failed
1182 static int SoftwareInit(PADAPTER_STRUCT Adapter)
1184 struct net_device *netdev = Adapter->netdev;
1186 /* Initial Receive Buffer Length */
1187 if ((netdev->mtu + ENET_HEADER_SIZE + ETH_CRC_LENGTH) <= BUFFER_1568) {
1188 DI.uRxBufferLen = BUFFER_1568; /* 0x620 */
1190 else {
1191 DI.uRxBufferLen = BUFFER_2048; /* 0x800 */
1194 /* please update link status within watchdog routine */
1195 DI.bLinkChanged[0] = TRUE;
1196 if (DMA_LAN == DI.usDMAId) { /* if LAN driver, 3 more ports */
1197 DI.bLinkChanged[1] = TRUE;
1198 DI.bLinkChanged[2] = TRUE;
1199 DI.bLinkChanged[3] = TRUE;
1202 return 0;
1206 * HardwareInit
1207 * This function initializes the hardware to a configuration as specified by the
1208 * Adapter structure, including mac I/F, switch engine, IRQ and others.
1210 * Argument(s)
1211 * Adapter pointer to ADAPTER_STRUCT structure
1213 * Return(s)
1214 * 0 if success
1215 * negative value if failed
1217 static int HardwareInit(PADAPTER_STRUCT Adapter)
1219 #ifdef DEBUG_THIS
1220 DRV_INFO("%s", __FUNCTION__);
1221 #endif
1223 /* note that chip reset should only take once
1224 if three driver instances are used for WAN, LAN and HPNA respectively for KS8695
1225 For KS8695P only two driver instances are used (WAN and LAN) */
1226 if (!ks8695_ChipInit(Adapter, TRUE)) {
1227 DRV_ERR("Hardware Initialization Failed");
1228 return -1;
1231 return 0;
1235 * ks8695_open
1236 * This function is called when a network interface is made
1237 * active by the system (IFF_UP). At this point all resources needed
1238 * for transmit and receive operations are allocated, the interrupt
1239 * handler is registered with the OS, the watchdog timer is started,
1240 * and the stack is notified when the interface is ready.
1242 * Argument(s)
1243 * netdev pointer to net_device struct
1245 * Return(s)
1246 * 0 if success
1247 * negative value if failed
1249 int ks8695_open(struct net_device *netdev)
1251 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
1253 #ifdef DEBUG_THIS
1254 DRV_INFO("%s", __FUNCTION__);
1255 #endif
1257 /* prevent multiple opens on same driver instance */
1258 if (test_and_set_bit(KS8695_BOARD_OPEN, &Adapter->flags)) {
1259 return -EBUSY;
1261 #ifdef FAST_POLL
1262 ks8695_poll_ready = 0;
1263 #endif
1265 /* stop Tx/Rx and disable interrupt */
1266 macStopAll(Adapter);
1267 if (DMA_LAN == DI.usDMAId) {
1268 swEnableSwitch(Adapter, FALSE);
1271 if (HardwareInit(Adapter) < 0) {
1272 clear_bit(KS8695_BOARD_OPEN, &Adapter->flags);
1273 return -EBUSY;
1276 /* allocate transmit descriptors */
1277 if (AllocateTxDescriptors(Adapter) != 0) {
1278 clear_bit(KS8695_BOARD_OPEN, &Adapter->flags);
1279 return -ENOMEM;
1281 /* set base address for Tx DMA */
1282 KS8695_WRITE_REG(REG_TXBASE + DI.nOffset, cpu_to_le32(DI.TxDescDMA));
1283 macStartTx(Adapter, TRUE);
1285 /* allocate receive descriptors and buffers */
1286 if (AllocateRxDescriptors(Adapter) != 0) {
1287 FreeTxDescriptors(Adapter);
1288 clear_bit(KS8695_BOARD_OPEN, &Adapter->flags);
1289 return -ENOMEM;
1291 /* set base address for Rx DMA */
1292 KS8695_WRITE_REG(REG_RXBASE + DI.nOffset, cpu_to_le32(DI.RxDescDMA));
1293 macStartRx(Adapter, TRUE);
1295 /* hook the interrupt */
1296 if (hook_irqs(netdev, TRUE)) {
1297 DRV_ERR("%s: hook_irqs failed", __FUNCTION__);
1298 clear_bit(KS8695_BOARD_OPEN, &Adapter->flags);
1299 FreeTxDescriptors(Adapter);
1300 FreeRxDescriptors(Adapter);
1301 return -EBUSY;
1304 /* fill Rx ring with sk_buffs */
1305 ReceiveBufferFill((unsigned long)Adapter);
1307 #ifdef RX_TASK
1308 /* if use task based rx process, initialize it */
1309 /* Initialize the tasklet again may crash the kernel. */
1310 if ( DI.rx_tasklet.func == ReceiveProcessTask ) {
1311 tasklet_enable( &DI.rx_tasklet );
1313 else
1314 tasklet_init(&DI.rx_tasklet, ReceiveProcessTask, (unsigned long)Adapter);
1315 #endif
1316 #ifdef TX_TASK
1317 /* if use task based tx process, initialize it */
1318 /* Initialize the tasklet again may crash the kernel. */
1319 if ( DI.tx_tasklet.func == TransmitProcessTask ) {
1320 tasklet_enable( &DI.tx_tasklet );
1322 else
1323 tasklet_init(&DI.tx_tasklet, TransmitProcessTask, (unsigned long)Adapter);
1324 #endif
1326 /* Set the watchdog timer for 2 seconds */
1327 init_timer(&Adapter->timer_id);
1329 Adapter->timer_id.function = &ks8695_watchdog;
1330 Adapter->timer_id.data = (unsigned long) netdev;
1331 mod_timer(&Adapter->timer_id, (jiffies + WATCHDOG_TICK * HZ));
1333 /* stats accumulated while down are dropped
1334 * this does not clear the running total */
1335 swResetSNMPInfo(Adapter);
1337 if (DMA_LAN == DI.usDMAId) {
1338 swEnableSwitch(Adapter, TRUE);
1340 macEnableInterrupt(Adapter, TRUE);
1342 /* clear tbusy bit */
1343 netif_start_queue(netdev);
1345 #ifdef FAST_POLL
1346 ks8695_poll_ready++;
1347 #endif
1348 return 0;
1352 * ks8695_close
1353 * This function is called when an interface is de-activated by the network
1354 * module (IFF_DOWN).
1356 * Argument(s)
1357 * netdev pointer to net_device struct
1359 * Return(s)
1360 * 0 if success
1361 * negative value if failed
1363 int ks8695_close(struct net_device *netdev)
1365 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
1367 #ifdef DEBUG_THIS
1368 DRV_INFO("%s", __FUNCTION__);
1369 #endif
1371 if (!test_bit(KS8695_BOARD_OPEN, &Adapter->flags))
1372 return 0;
1374 /* stop all */
1375 macStopAll(Adapter);
1376 if (DMA_LAN == DI.usDMAId) {
1377 swEnableSwitch(Adapter, FALSE);
1380 netif_stop_queue(netdev);
1381 hook_irqs(netdev, FALSE);
1382 del_timer(&Adapter->timer_id);
1384 #ifdef RX_TASK
1385 tasklet_disable(&DI.rx_tasklet);
1386 DI.rx_scheduled = FALSE;
1387 #endif
1388 #ifdef TX_TASK
1389 tasklet_disable(&DI.tx_tasklet);
1390 DI.tx_scheduled = FALSE;
1391 #endif
1392 FreeTxDescriptors(Adapter);
1393 FreeRxDescriptors(Adapter);
1395 clear_bit(KS8695_BOARD_OPEN, &Adapter->flags);
1397 return 0;
1401 * InitTxRing
1402 * This function is used to initialize Tx descriptor ring.
1404 * Argument(s)
1405 * Adapter pointer to ADAPTER_STRUCT struct
1407 * Return(s)
1408 * NONE
1410 void InitTxRing(PADAPTER_STRUCT Adapter)
1412 int i;
1413 TXDESC *pTxDesc = DI.pTxDescriptors;
1414 UINT32 uPA = DI.TxDescDMA;
1416 for (i = 0; i < DI.nTxDescTotal - 1; i++, pTxDesc++) {
1417 uPA += sizeof(TXDESC); /* pointer to next Tx Descriptor */
1418 pTxDesc->TxDMANextPtr = cpu_to_le32(uPA);
1420 /* last descriptor should point back to the beginning */
1421 pTxDesc->TxDMANextPtr = cpu_to_le32(DI.TxDescDMA);
1422 pTxDesc->TxFrameControl |= cpu_to_le32(TFC_TER);
1427 * KS8695's internal ethernet driver doesn't use PCI bus at all. As a resumt
1428 * call these set of functions instead
1430 static void *consistent_alloc_ex(int gfp, size_t size, dma_addr_t *dma_handle)
1432 struct page *page, *end, *free;
1433 unsigned long order;
1434 void *ret, *virt;
1436 if (in_interrupt())
1437 BUG();
1439 size = PAGE_ALIGN(size);
1440 order = get_order(size);
1442 page = alloc_pages(gfp, order);
1443 if (!page)
1444 goto no_page;
1447 * We could do with a page_to_phys here
1449 virt = page_address(page);
1450 *dma_handle = virt_to_phys(virt);
1451 ret = __ioremap(virt_to_phys(virt), size, 0);
1452 if (!ret)
1453 goto no_remap;
1456 * free wasted pages. We skip the first page since we know
1457 * that it will have count = 1 and won't require freeing.
1458 * We also mark the pages in use as reserved so that
1459 * remap_page_range works.
1461 page = virt_to_page(virt);
1462 free = page + (size >> PAGE_SHIFT);
1463 end = page + (1 << order);
1465 for (; page < end; page++) {
1466 if (page >= free)
1467 __free_page(page);
1468 else
1469 SetPageReserved(page);
1471 return ret;
1473 no_remap:
1474 __free_pages(page, order);
1475 no_page:
1476 return NULL;
1480 * free a page as defined by the above mapping. We expressly forbid
1481 * calling this from interrupt context.
1483 static void consistent_free_ex(void *vaddr, size_t size, dma_addr_t handle)
1485 struct page *page, *end;
1486 void *virt;
1488 if (in_interrupt())
1489 BUG();
1491 virt = phys_to_virt(handle);
1494 * More messing around with the MM internals. This is
1495 * sick, but then so is remap_page_range().
1497 size = PAGE_ALIGN(size);
1498 page = virt_to_page(virt);
1499 end = page + (size >> PAGE_SHIFT);
1501 for (; page < end; page++)
1502 ClearPageReserved(page);
1504 __iounmap(vaddr);
1508 * AllocateTxDescriptors
1509 * This function is used to allocate Tx descriptors, including allocate memory,
1510 * alignment adjustment, variable initialization and so on.
1512 * Argument(s)
1513 * Adapter pointer to ADAPTER_STRUCT struct
1515 * Return(s)
1516 * 0 if success
1517 * negative value if failed
1519 static int AllocateTxDescriptors(PADAPTER_STRUCT Adapter)
1521 int size;
1523 #ifdef DEBUG_THIS
1524 DRV_INFO("%s", __FUNCTION__);
1525 #endif
1527 /* allocate data buffers for transmission */
1528 size = sizeof(struct ks8695_buffer) * DI.nTxDescTotal;
1529 DI.pTxSkb = kmalloc(size, GFP_KERNEL);
1530 if (DI.pTxSkb == NULL) {
1531 return -ENOMEM;
1533 memset(DI.pTxSkb, 0, size);
1535 /* round up to nearest 4K */
1536 size = KS8695_ROUNDUP(DI.nTxDescTotal * sizeof(TXDESC) + DESC_ALIGNMENT, BUFFER_4K);
1537 DI.pTxDescriptors = consistent_alloc_ex(GFP_KERNEL | GFP_DMA, size, &DI.TxDescDMA);
1538 if (NULL == DI.pTxDescriptors) {
1539 kfree(DI.pTxSkb);
1540 DI.pTxSkb = NULL;
1541 return -ENOMEM;
1544 #ifdef DEBUG_THIS
1545 DRV_INFO("TXDESC> DataBuf=0x%08x, Descriptor=0x%08x, PA=0x%08x", (UINT)DI.pTxSkb, (UINT)DI.pTxDescriptors, (UINT)DI.TxDescDMA);
1546 #endif
1547 memset(DI.pTxDescriptors, 0, size);
1549 atomic_set(&DI.nTxDescAvail, DI.nTxDescTotal);
1550 DI.nTxDescNextAvail = 0;
1551 DI.nTxDescUsed = 0;
1552 DI.nTransmitCount = 0;
1553 DI.nTxProcessedCount = 0;
1554 DI.bTxNoResource = 0;
1556 InitTxRing(Adapter);
1558 return 0;
1562 * InitRxRing
1563 * This function is used to initialize Rx descriptor ring.
1565 * Argument(s)
1566 * Adapter pointer to ADAPTER_STRUCT struct
1568 * Return(s)
1569 * NONE
1571 void InitRxRing(PADAPTER_STRUCT Adapter)
1573 int i;
1574 RXDESC *pRxDesc = DI.pRxDescriptors;
1575 UINT32 uPA = DI.RxDescDMA;
1577 for (i = 0; i < DI.nRxDescTotal - 1; i++, pRxDesc++) {
1578 uPA += sizeof(RXDESC); /* pointer to next Rx Descriptor */
1579 pRxDesc->RxDMANextPtr = cpu_to_le32(uPA);
1581 /* last descriptor should point back to the beginning */
1582 pRxDesc->RxDMANextPtr = cpu_to_le32(DI.RxDescDMA);
1583 pRxDesc->RxDMAFragLen &= cpu_to_le32(~RFC_RBS_MASK);
1587 * AllocateRxDescriptors
1588 * This function is used to setup Rx descriptors, including allocate memory, receive SKBs
1589 * alignment adjustment, variable initialization and so on.
1591 * Argument(s)
1592 * Adapter pointer to ADAPTER_STRUCT struct
1594 * Return(s)
1595 * 0 if success
1596 * negative value if failed
1598 static int AllocateRxDescriptors(PADAPTER_STRUCT Adapter)
1600 int size;
1602 #ifdef DEBUG_THIS
1603 DRV_INFO("%s", __FUNCTION__);
1604 #endif
1606 size = sizeof(struct ks8695_buffer) * DI.nRxDescTotal;
1607 DI.pRxSkb = kmalloc(size, GFP_KERNEL);
1608 if (DI.pRxSkb == NULL) {
1609 return -ENOMEM;
1611 memset(DI.pRxSkb, 0, size);
1613 /* Round up to nearest 4K */
1614 size = KS8695_ROUNDUP(DI.nRxDescTotal * sizeof(RXDESC) + DESC_ALIGNMENT, BUFFER_4K);
1615 DI.pRxDescriptors = consistent_alloc_ex(GFP_KERNEL | GFP_DMA, size, &DI.RxDescDMA);
1616 if (NULL == DI.pRxDescriptors) {
1617 kfree(DI.pRxSkb);
1618 DI.pRxSkb = NULL;
1619 return -ENOMEM;
1622 #ifdef DEBUG_THIS
1623 DRV_INFO("RXDESC> DataBuf=0x%08x, Descriptor=0x%08x, PA=0x%08x",
1624 (UINT)DI.pRxSkb, (UINT)DI.pRxDescriptors, (UINT)DI.RxDescDMA);
1625 #endif
1627 memset(DI.pRxDescriptors, 0, size);
1629 DI.nRxDescNextAvail = 0;
1630 atomic_set(&DI.RxDescEmpty, DI.nRxDescTotal);
1631 DI.nRxDescNextToFill = 0;
1633 InitRxRing(Adapter);
1635 return 0;
1639 * FreeTxDescriptors
1640 * This function is used to free Tx resources.
1642 * Argument(s)
1643 * Adapter pointer to ADAPTER_STRUCT struct
1645 * Return(s)
1646 * NONE.
1648 static void FreeTxDescriptors(PADAPTER_STRUCT Adapter)
1650 int size;
1652 #ifdef DEBUG_THIS
1653 DRV_INFO("%s", __FUNCTION__);
1654 #endif
1656 CleanTxRing(Adapter);
1658 kfree(DI.pTxSkb);
1659 DI.pTxSkb = NULL;
1661 size = KS8695_ROUNDUP(DI.nTxDescTotal * sizeof(TXDESC) + DESC_ALIGNMENT, BUFFER_4K);
1662 consistent_free_ex((void *)DI.pTxDescriptors, size, DI.TxDescDMA);
1663 DI.pTxDescriptors = NULL;
1664 DI.TxDescDMA = 0;
1668 * CleanTxRing
1669 * This function is used to go through Tx descriptor list and clean up any pending resources.
1671 * Argument(s)
1672 * Adapter pointer to ADAPTER_STRUCT struct
1674 * Return(s)
1675 * NONE.
1677 static void CleanTxRing(PADAPTER_STRUCT Adapter)
1679 unsigned long size;
1680 TXDESC *pTxDesc = DI.pTxDescriptors;
1681 int i;
1683 /* free pending sk_buffs if any */
1684 for (i = 0; i < DI.nTxDescTotal; i++, pTxDesc++) {
1685 if (NULL != DI.pTxSkb[i].skb) {
1686 dev_kfree_skb(DI.pTxSkb[i].skb);
1687 DI.pTxSkb[i].skb = NULL;
1689 /* reset corresponding Tx Descriptor structure as well */
1690 pTxDesc->TxDMAFragAddr = 0;
1691 pTxDesc->TxOwnBit = 0;
1692 pTxDesc->TxFrameControl = 0;
1695 DI.nTransmitCount = 0;
1696 DI.nTxProcessedCount = 0;
1698 size = sizeof(struct ks8695_buffer) * DI.nTxDescTotal;
1699 memset(DI.pTxSkb, 0, size);
1701 size = KS8695_ROUNDUP(DI.nTxDescTotal * sizeof(TXDESC) + DESC_ALIGNMENT, BUFFER_4K);
1702 memset(DI.pTxDescriptors, 0, size);
1703 atomic_set(&DI.nTxDescAvail, DI.nTxDescTotal);
1704 DI.nTxDescNextAvail = 0;
1705 DI.nTxDescUsed = 0;
1707 /* for safety!!! */
1708 KS8695_WRITE_REG(REG_TXBASE + DI.nOffset, 0);
1712 * FreeRxDescriptors
1713 * This function is used to free Rx resources.
1715 * Argument(s)
1716 * Adapter pointer to ADAPTER_STRUCT struct
1718 * Return(s)
1719 * NONE.
1721 static void FreeRxDescriptors(PADAPTER_STRUCT Adapter)
1723 int size;
1725 #ifdef DEBUG_THIS
1726 DRV_INFO("%s", __FUNCTION__);
1727 #endif
1729 #if 0
1730 #ifdef RX_TASK
1731 tasklet_disable(&DI.rx_tasklet);
1732 DI.rx_scheduled = FALSE;
1733 #endif
1734 #ifdef TX_TASK
1735 tasklet_disable(&DI.tx_tasklet);
1736 DI.tx_scheduled = FALSE;
1737 #endif
1738 #endif
1740 CleanRxRing(Adapter);
1742 kfree(DI.pRxSkb);
1743 DI.pRxSkb = NULL;
1745 size = KS8695_ROUNDUP(DI.nRxDescTotal * sizeof(RXDESC) + DESC_ALIGNMENT, BUFFER_4K);
1746 consistent_free_ex((void *)DI.pRxDescriptors, size, DI.RxDescDMA);
1747 DI.pRxDescriptors = NULL;
1748 DI.RxDescDMA = 0;
1752 * CleanRxRing
1753 * This function is used to go through Rx descriptor list and clean up any pending resources.
1755 * Argument(s)
1756 * Adapter pointer to ADAPTER_STRUCT struct
1758 * Return(s)
1759 * NONE.
1761 static void CleanRxRing(PADAPTER_STRUCT Adapter)
1763 unsigned long size;
1764 RXDESC *pRxDesc = DI.pRxDescriptors;
1765 int i;
1767 /* Free pending sk_buffs if any */
1768 for (i = 0; i < DI.nRxDescTotal; i++, pRxDesc++) {
1769 if (DI.pRxSkb[i].skb != NULL) {
1770 dev_kfree_skb(DI.pRxSkb[i].skb);
1771 DI.pRxSkb[i].skb = NULL;
1773 /* reset corresponding Rx Descriptor structure as well */
1774 pRxDesc->RxFrameControl &= cpu_to_le32(~(RFC_FRAMECTRL_MASK | DESC_OWN_BIT));
1775 pRxDesc->RxDMAFragLen = 0;
1776 pRxDesc->RxDMAFragAddr = 0;
1780 size = sizeof(struct ks8695_buffer) * DI.nRxDescTotal;
1781 memset(DI.pRxSkb, 0, size);
1783 size = KS8695_ROUNDUP(DI.nRxDescTotal * sizeof(RXDESC) + DESC_ALIGNMENT, BUFFER_4K);
1784 memset(DI.pRxDescriptors, 0, size);
1785 atomic_set(&DI.RxDescEmpty, DI.nRxDescTotal);
1786 DI.nRxDescNextAvail = 0;
1787 DI.nRxDescNextToFill = 0;
1789 /* for safety!!! */
1790 KS8695_WRITE_REG(REG_RXBASE + DI.nOffset, 0);
1794 * ks8695_set_multi
1795 * This function is used to set Multicast and Promiscuous mode. It is
1796 * called whenever the multicast address list or the network interface
1797 * flags are updated. This routine is resposible for configuring the
1798 * hardware for proper multicast, promiscuous mode, and all-multi behavior.
1800 * Argument(s)
1801 * Adapter pointer to ADAPTER_STRUCT struct
1803 * Return(s)
1804 * NONE.
1806 void ks8695_set_multi(struct net_device *netdev)
1808 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
1809 uint32_t uReg;
1810 #if 0
1811 uint32_t HwLowAddress, HwHighAddress;
1812 uint16_t HashValue, HashReg, HashBit;
1813 struct dev_mc_list *mc_ptr;
1814 #endif
1816 BOOLEAN bRxStarted;
1818 #ifdef DEBUG_THIS
1819 DRV_INFO("%s", __FUNCTION__);
1820 #endif
1822 bRxStarted = DI.bRxStarted;
1823 if (bRxStarted)
1824 macStartRx(Adapter, FALSE);
1826 /* read RX mode register in order to set hardware filter mode */
1827 uReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
1828 uReg |= DMA_UNICAST | DMA_BROADCAST;
1829 uReg &= ~(DMA_PROMISCUOUS | DMA_MULTICAST);
1831 if (netdev->flags & IFF_PROMISC) {
1832 uReg |= DMA_PROMISCUOUS;
1834 if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) {
1835 uReg |= DMA_MULTICAST;
1838 KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uReg);
1840 if (bRxStarted)
1841 macStartRx(Adapter, TRUE);
1843 ks8695_relink(Adapter);
1847 * ks8695_watchdog
1848 * This function is a timer callback routine for updating statistics infomration.
1850 * Argument(s)
1851 * data pointer to net_device struct
1853 * Return(s)
1854 * NONE.
1856 void ks8695_watchdog(unsigned long data)
1858 struct net_device *netdev = (struct net_device *)data;
1859 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
1860 int carrier;
1862 if (DMA_LAN == DI.usDMAId) {
1863 static int nCheck = 0;
1865 if (nCheck++ > 6) {
1866 int i;
1867 uint8_t bLinkActive[SW_MAX_LAN_PORTS];
1869 nCheck = 0;
1870 for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
1871 /* keep a track for previous link active state */
1872 bLinkActive[i] = DI.bLinkActive[i];
1874 carrier = swGetPhyStatus(Adapter, i);
1875 /* if current link state is not same as previous state, means link state changed */
1876 if (bLinkActive[i] != DI.bLinkActive[i]) {
1877 DI.bLinkChanged[i] = TRUE;
1878 ks8695_report_carrier(netdev, carrier);
1880 /* note that since LAN doesn't have Interrupt bit for link status change */
1881 /* we have to check it to make sure if link is lost, restart it!!! */
1882 if (!DI.bLinkActive[i]) {
1883 swDetectPhyConnection(Adapter, i);
1888 else {
1889 if (!DI.bLinkActive[0]) {
1890 carrier = swGetPhyStatus(Adapter, 0);
1891 ks8695_report_carrier(netdev, carrier);
1893 #ifndef TX_TASK
1894 /* handling WAN DMA sucked case if any */
1895 /*if (DMA_WAN == DI.usDMAId) {*/
1896 { /* all driver ? */
1897 static int nCount = 0;
1899 /* if no tx resource is reported */
1900 if (DI.bTxNoResource) {
1901 nCount++;
1902 /* if happened 5 times (WATCHDOG_TICK seconds * 5), means most likely, the WAN Tx DMA is died,
1903 reset it again */
1904 if (nCount > 5) {
1905 DI.nResetCount++;
1906 ResetDma(Adapter);
1907 DI.bTxNoResource = FALSE;
1908 /* wake queue will call mark_bh(NET_BH) to resume tx */
1909 netif_wake_queue(netdev);
1910 nCount = 0;
1914 #endif
1916 UpdateStatsCounters(Adapter);
1918 /* Reset the timer */
1919 mod_timer(&Adapter->timer_id, jiffies + WATCHDOG_TICK * HZ);
1923 * ks8695_xmit_frame
1924 * This function is used to called by the stack to initiate a transmit.
1925 * The out of resource condition is checked after each successful Tx
1926 * so that the stack can be notified, preventing the driver from
1927 * ever needing to drop a frame. The atomic operations on
1928 * nTxDescAvail are used to syncronize with the transmit
1929 * interrupt processing code without the need for a spinlock.
1931 * Argument(s)
1932 * skb buffer with frame data to transmit
1933 * netdev pointer to network interface device structure
1935 * Return(s)
1936 * 0 if success
1937 * negative value if failed
1939 int ks8695_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1941 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
1942 TXDESC *pTxDesc;
1943 int i, len;
1944 char *data;
1945 unsigned long flags;
1946 struct sk_buff* org_skb = skb;
1948 #ifdef CONFIG_LEDMAN
1949 ledman_cmd(LEDMAN_CMD_SET,
1950 (netdev->name[3] == '0') ? LEDMAN_LAN1_TX : LEDMAN_LAN2_TX);
1951 #endif
1953 /* Hardware has problem sending out short frames in which the first
1954 * 4 bytes of MAC destination address are replaced with data at
1955 * location 0x28 after sending out ICMP packets.
1957 if ( skb->len <= 48 ) {
1958 skb = dev_alloc_skb( 50 );
1959 if ( !skb ) {
1960 Adapter->net_stats.tx_aborted_errors++;
1961 return 1;
1963 memcpy( skb->data, org_skb->data, org_skb->len );
1964 memset( &skb->data[ org_skb->len ], 0, 50 - org_skb->len );
1965 skb->len = 50;
1966 dev_kfree_skb( org_skb );
1968 len = skb->len;
1969 data = skb->data;
1970 #ifdef DEBUG_THIS
1971 DRV_INFO("%s> len=%d", __FUNCTION__, len);
1972 #endif
1975 i = DI.nTxDescNextAvail;
1976 pTxDesc = &DI.pTxDescriptors[i];
1978 DI.pTxSkb[i].skb = skb;
1979 DI.pTxSkb[i].length = len;
1980 DI.pTxSkb[i].direction = PCI_DMA_TODEVICE;
1981 consistent_sync(data, DI.uRxBufferLen, PCI_DMA_TODEVICE);
1982 DI.pTxSkb[i].dma = virt_to_phys(data);
1984 /* set DMA buffer address */
1985 pTxDesc->TxDMAFragAddr = cpu_to_le32(DI.pTxSkb[i].dma);
1987 #ifdef PACKET_DUMP
1988 ks8695_dump_packet(Adapter, data, len, DI.uDebugDumpTxPkt);
1989 #endif
1992 #if 0
1993 if (DMA_LAN == DI.usDMAId) {
1994 /* may need to set SPN for IGCP for LAN driver, but do it later; */
1996 #endif
1998 local_irq_save(flags);
1999 /* note that since we have set the last Tx descriptor back to the first to form */
2000 /* a ring, there is no need to keep ring end flag for performance sake */
2001 /* clear some bits operation for optimization!!! */
2002 #ifndef USE_TX_UNAVAIL
2003 pTxDesc->TxFrameControl = cpu_to_le32((TFC_FS | TFC_LS | TFC_IC) | (len & TFC_TBS_MASK));
2004 #else
2005 if ((DI.nTransmitCount + 1) % DI.nTransmitCoalescing) {
2006 pTxDesc->TxFrameControl = cpu_to_le32((TFC_FS | TFC_LS) | (len & TFC_TBS_MASK));
2008 else {
2009 pTxDesc->TxFrameControl = cpu_to_le32((TFC_FS | TFC_LS | TFC_IC) | (len & TFC_TBS_MASK));
2011 #endif
2013 /* set own bit */
2014 pTxDesc->TxOwnBit = cpu_to_le32(DESC_OWN_BIT);
2016 /* eanble read transfer for the packet!!! */
2017 KS8695_WRITE_REG(REG_TXSTART + DI.nOffset, 1);
2019 /*atomic_dec(&DI.nTxDescAvail);*/
2020 /*__save_flags_cli(flags);*/
2021 DI.nTxDescAvail.counter--;
2022 /* update pending transimt packet count */
2023 DI.nTransmitCount++;
2024 local_irq_restore(flags);
2025 if (atomic_read(&DI.nTxDescAvail) <= 1) {
2026 #ifdef DEBUG_THIS
2027 if (DMA_WAN == DI.usDMAId)
2028 DRV_WARN("%s> no WAN tx descriptors available, tx suspended, nTransmitCount=%d", __FUNCTION__, DI.nTransmitCount);
2029 else if (DMA_LAN == DI.usDMAId)
2030 DRV_WARN("%s> no LAN tx descriptors available, tx suspended, nTransmitCount=%d", __FUNCTION__, DI.nTransmitCount);
2031 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
2032 else
2033 DRV_WARN("%s> no HPNA tx descriptors available, tx suspended, nTransmitCount=%d", __FUNCTION__, DI.nTransmitCount);
2034 #endif
2035 #endif
2036 DI.bTxNoResource = TRUE;
2037 netif_stop_queue(netdev);
2038 #ifdef TX_TASK
2039 /* try eanble read transfer again */
2040 KS8695_WRITE_REG(REG_TXSTART + DI.nOffset, 1);
2041 if (FALSE == DI.tx_scheduled) {
2042 DI.tx_scheduled = TRUE;
2043 tasklet_hi_schedule(&DI.tx_tasklet);
2045 #endif
2048 /* adv to next available descriptor */
2049 DI.nTxDescNextAvail = ++DI.nTxDescNextAvail % DI.nTxDescTotal;
2050 netdev->trans_start = jiffies;
2052 return 0;
2056 * ks8695_get_stats
2057 * This function is used to get NIC's SNMP staticstics.
2059 * Argument(s)
2060 * netdev network interface device structure
2062 * Return(s)
2063 * pointer to net_device_stats structure
2065 struct net_device_stats *ks8695_get_stats(struct net_device *netdev)
2067 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
2069 #ifdef DEBUG_THIS
2070 DRV_INFO("ks8695_get_stats");
2071 #endif
2073 return &Adapter->net_stats;
2077 * ks8695_change_mtu
2078 * This function is use to change the Maximum Transfer Unit.
2080 * Argument(s)
2081 * netdev pointer to net_device structure.
2082 * new_mtu new_mtu new value for maximum frame size
2084 * Return(s)
2085 * 0 if success
2086 * negative value if failed
2088 int ks8695_change_mtu(struct net_device *netdev, int new_mtu)
2090 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
2091 uint32_t old_mtu = DI.uRxBufferLen;
2093 DRV_INFO("%s", __FUNCTION__);
2095 if (new_mtu <= DI.uRxBufferLen) {
2096 netdev->mtu = new_mtu;
2097 return 0;
2100 if ((new_mtu < MINIMUM_ETHERNET_PACKET_SIZE - ENET_HEADER_SIZE) ||
2101 new_mtu > BUFFER_2048 - ENET_HEADER_SIZE) {
2102 DRV_ERR("%s> Invalid MTU setting", __FUNCTION__);
2103 return -EINVAL;
2106 if (new_mtu <= BUFFER_1568 - ENET_HEADER_SIZE) {
2107 DI.uRxBufferLen = BUFFER_1568;
2108 } else {
2109 DI.uRxBufferLen = BUFFER_2048;
2112 if (old_mtu != DI.uRxBufferLen) {
2113 /* put DEBUG_THIS after verification please */
2114 DRV_INFO("%s, old=%d, new=%d", __FUNCTION__, old_mtu, DI.uRxBufferLen);
2115 ResetDma(Adapter);
2118 netdev->mtu = new_mtu;
2119 ks8695_relink(Adapter);
2121 return 0;
2125 * ks8695_set_mac
2126 * This function is use to change Ethernet Address of the NIC.
2128 * Argument(s)
2129 * netdev pointer to net_device structure.
2130 * p pointer to sockaddr structure
2132 * Return(s)
2133 * 0 if success
2134 * negative value if failed
2136 int ks8695_set_mac(struct net_device *netdev, void *p)
2138 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
2139 struct sockaddr *addr = (struct sockaddr *)p;
2140 BOOLEAN bRxStarted, bTxStarted;
2142 #ifdef DEBUG_THIS
2143 DRV_INFO("%s", __FUNCTION__);
2144 #endif
2146 bRxStarted = DI.bRxStarted;
2147 bTxStarted = DI.bTxStarted;
2148 if (bRxStarted)
2149 macStartRx(Adapter, FALSE);
2150 if (bTxStarted)
2151 macStartTx(Adapter, FALSE);
2153 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
2154 memcpy(DI.stMacCurrent, addr->sa_data, netdev->addr_len);
2155 macSetStationAddress(Adapter, DI.stMacCurrent);
2157 if (bRxStarted)
2158 macStartRx(Adapter, TRUE);
2159 if (bTxStarted)
2160 macStartTx(Adapter, TRUE);
2162 ks8695_relink(Adapter);
2164 return 0;
2168 * UpdateStatsCounters
2169 * This function is used to update the board statistics counters.
2171 * Argument(s)
2172 * Adapter pointer to ADAPTER_STRUCT structure
2174 * Return(s)
2175 * NONE
2177 static void UpdateStatsCounters(PADAPTER_STRUCT Adapter)
2179 struct net_device_stats *stats;
2181 stats= &Adapter->net_stats;
2185 * CheckState
2186 * This function is used to handle error conditions if any.
2188 * Argument(s)
2189 * Adapter pointer to ADAPTER_STRUCT structure
2190 * uISR bit values of ISR register
2192 * Return(s)
2193 * NONE.
2195 static __inline void CheckState(PADAPTER_STRUCT Adapter, UINT32 uISR)
2197 BOOLEAN bTxStopped = FALSE, bRxStopped = FALSE;
2199 #ifdef DEBUG_THIS
2200 DRV_INFO("%s", __FUNCTION__);
2201 #endif
2203 /* clear all bits other than stop */
2204 uISR &= (DI.uIntMask & INT_DMA_STOP_MASK);
2205 switch (DI.usDMAId) {
2206 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
2207 case DMA_HPNA:
2208 if (uISR & INT_HPNA_TX_STOPPED)
2209 bTxStopped = TRUE;
2210 if (uISR & INT_HPNA_RX_STOPPED)
2211 bRxStopped = TRUE;
2212 break;
2213 #endif
2215 case DMA_LAN:
2216 if (uISR & INT_LAN_TX_STOPPED)
2217 bTxStopped = TRUE;
2218 if (uISR & INT_LAN_RX_STOPPED)
2219 bRxStopped = TRUE;
2220 break;
2222 default:
2223 case DMA_WAN:
2224 if (uISR & INT_WAN_TX_STOPPED)
2225 bTxStopped = TRUE;
2226 if (uISR & INT_WAN_RX_STOPPED)
2227 bRxStopped = TRUE;
2228 break;
2231 if (bRxStopped) {
2232 /* if Rx started already, then it is a problem! */
2233 if (DI.bRxStarted) {
2234 DRV_WARN("%s> RX stopped, ISR=0x%08x", __FUNCTION__, uISR);
2236 macStartRx(Adapter, FALSE);
2237 DelayInMilliseconds(2);
2238 macStartRx(Adapter, TRUE);
2240 else {
2241 /* ACK and clear the bit */
2242 KS8695_WRITE_REG(KS8695_INT_STATUS, uISR);
2245 if (bTxStopped) {
2246 /* if Tx started already, then it is a problem! */
2247 if (DI.bTxStarted) {
2248 DRV_WARN("%s> TX stopped, ISR=0x%08x", __FUNCTION__, uISR);
2250 macStartTx(Adapter, FALSE);
2251 DelayInMilliseconds(2);
2252 macStartTx(Adapter, TRUE);
2254 else {
2255 /* ACK and clear the bit */
2256 KS8695_WRITE_REG(KS8695_INT_STATUS, uISR);
2262 * CheckLinkState
2263 * This function is used to check link status to see whether link has changed or not.
2265 * Argument(s)
2266 * Adapter pointer to ADAPTER_STRUCT structure.
2267 * uISR ISR register (should be IMSR) to check
2269 * Return(s)
2270 * TRUE if link change has detected
2271 * FALSE otherwise
2273 static __inline BOOLEAN CheckLinkState(PADAPTER_STRUCT Adapter, UINT uISR)
2275 BOOLEAN bLinkChanged = FALSE;
2276 int i;
2278 switch (DI.usDMAId) {
2279 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
2280 case DMA_HPNA:
2281 /* what to do? */
2282 return FALSE;
2283 #endif
2285 case DMA_WAN:
2286 if (uISR & INT_WAN_LINK) {
2287 bLinkChanged = TRUE;
2288 DI.bLinkChanged[0] = TRUE;
2290 break;
2292 default:
2293 case DMA_LAN:
2294 for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
2295 if (FALSE == DI.bLinkChanged[i]) {
2296 UINT uReg = KS8695_READ_REG(KS8695_SWITCH_AUTO0 + (i >> 1));
2297 if (0 == (i % 2))
2298 uReg >>= 16;
2299 if (!(uReg & SW_AUTONEGO_STAT_LINK)) {
2300 bLinkChanged = TRUE;
2301 DI.bLinkChanged[i] = TRUE;
2305 break;
2308 return bLinkChanged;
2312 * ProcessTxInterrupts
2313 * This function is use to process Tx interrupt, reclaim resources after
2314 * transmit completes.
2316 * Argument(s)
2317 * Adapter pointer to ADAPTER_STRUCT structure.
2319 * Return(s)
2320 * how many number of Tx packets are not processed yet.
2322 static int __inline ProcessTxInterrupts(PADAPTER_STRUCT Adapter)
2324 int i;
2325 TXDESC *TransmitDescriptor;
2326 unsigned long flags;
2328 #ifdef DEBUG_THIS
2329 DRV_INFO("%s> )", __FUNCTION__);
2330 #endif
2332 i = DI.nTxDescUsed;
2333 TransmitDescriptor = &DI.pTxDescriptors[i];
2334 while (!(le32_to_cpu(TransmitDescriptor->TxOwnBit) & DESC_OWN_BIT) && DI.nTransmitCount > 0) {
2335 /* note that WAN DMA doesn't have statistics counters associated with,
2336 therefore use local variables to track them instead */
2337 STAT_NET(tx_packets)++;
2338 STAT_NET(tx_bytes) += DI.pTxSkb[i].length;
2339 dev_kfree_skb_irq(DI.pTxSkb[i].skb);
2340 DI.pTxSkb[i].skb = NULL;
2342 local_irq_save(flags);
2343 DI.nTxDescAvail.counter++;
2344 DI.nTransmitCount--;
2345 local_irq_restore(flags);
2347 /* clear corresponding fields */
2348 TransmitDescriptor->TxDMAFragAddr = 0;
2350 /* clear all related bits, including len field, control bits and port bits */
2351 TransmitDescriptor->TxFrameControl = 0;
2353 /* to next Tx descriptor */
2354 i = (i + 1) % DI.nTxDescTotal;
2355 TransmitDescriptor = &DI.pTxDescriptors[i];
2356 DI.nTxProcessedCount++;
2358 DI.nTxDescUsed = i;
2360 if (DI.bTxNoResource && netif_queue_stopped(Adapter->netdev) &&
2361 (atomic_read(&DI.nTxDescAvail) > ((DI.nTxDescTotal * 3) >> 2))) { /* 3/4 */
2362 DI.bTxNoResource = FALSE;
2363 netif_wake_queue(Adapter->netdev);
2364 #ifdef DEBUG_THIS
2365 DRV_INFO("%s> Tx process resumed", __FUNCTION__);
2366 #endif
2369 return DI.nTransmitCount;
2374 * ProcessRxInterrupts
2375 * This function is use to process Rx interrupt, send received data up
2376 * the network stack.
2378 * Argument(s)
2379 * Adapter pointer to ADAPTER_STRUCT structure.
2381 * Return(s)
2382 * how many Rx packets are processed.
2384 static int __inline ProcessRxInterrupts(PADAPTER_STRUCT Adapter)
2386 RXDESC *CurrentDescriptor, *pBegin;
2387 int i, nProcessed = 0;
2388 uint32_t Length;
2389 uint32_t uFrameCtrl;
2390 struct sk_buff *skb;
2391 struct sk_buff *copy_skb;
2392 int cng_level = 0;
2394 #ifdef DEBUG_THIS
2395 DRV_INFO("%s> )", __FUNCTION__);
2396 #endif
2398 #ifdef CONFIG_LEDMAN
2399 ledman_cmd(LEDMAN_CMD_SET, LEDMAN_LAN1_RX);
2400 /*(dev->name[3] == '0') ? LEDMAN_LAN1_RX : LEDMAN_LAN2_RX);*/
2401 #endif
2402 i = DI.nRxDescNextAvail;
2403 pBegin = CurrentDescriptor = &DI.pRxDescriptors[i];
2405 while (!((uFrameCtrl = le32_to_cpu(CurrentDescriptor->RxFrameControl)) & DESC_OWN_BIT)) {
2406 skb = DI.pRxSkb[i].skb;
2407 /* it should never goes here */
2408 if (NULL == skb)
2410 if (!(0 == CurrentDescriptor->RxFrameControl && 0 == CurrentDescriptor->RxDMAFragLen
2411 && 0 == CurrentDescriptor->RxDMAFragAddr)) {
2412 DRV_INFO("%s: inconsistency error, rx desc index=%d", __FUNCTION__, i);
2414 break;
2417 /* length with CRC bytes included */
2418 Length = (uFrameCtrl & RFC_FL_MASK);
2420 /* test both bits to make sure single packet */
2421 if ((uFrameCtrl & (RFC_LS | RFC_FS)) != (RFC_LS | RFC_FS)) {
2422 DRV_INFO("%s> spanning packet detected (framectrl=0x%08x, rx desc index=%d)", __FUNCTION__, uFrameCtrl, i);
2423 if (uFrameCtrl & RFC_FS) {
2424 /* first segment */
2425 Length = DI.uRxBufferLen;
2426 DRV_INFO(" first segment, len=%d", Length);
2427 /* compensite offset CRC */
2428 Length += ETH_CRC_LENGTH;
2430 else if (uFrameCtrl & RFC_LS) {
2431 /* last segment */
2432 if (Length > DI.uRxBufferLen + ETH_CRC_LENGTH) {
2433 Length -= DI.uRxBufferLen;
2434 DRV_INFO(" last segment, len=%d", Length);
2436 else {
2437 DRV_WARN("%s> under size packet (len=%d, buffer=%d)", __FUNCTION__, Length, DI.uRxBufferLen);
2438 STAT_NET(rx_errors)++;
2439 goto CLEAN_UP;
2442 else {
2443 if (0 == uFrameCtrl) {
2444 /* race condition ? */
2445 DRV_WARN("FragLen=0x%08x, FragAddr=0x%08x, RxNextPtr=0x%08x, RxDescEmpty=%d, pkt dropped",
2446 CurrentDescriptor->RxDMAFragLen, CurrentDescriptor->RxDMAFragAddr, CurrentDescriptor->RxDMANextPtr, atomic_read(&DI.RxDescEmpty));
2447 #ifdef PACKET_DUMP
2448 ks8695_dump_packet(Adapter, skb->data, DI.uRxBufferLen, DEBUG_PACKET_LEN | DEBUG_PACKET_HEADER | DEBUG_PACKET_CONTENT);
2449 #endif
2451 else {
2452 DRV_WARN("%s> error spanning packet, dropped", __FUNCTION__);
2454 STAT_NET(rx_errors)++;
2455 goto CLEAN_UP;
2459 /* if error happened!!! */
2460 if (uFrameCtrl & (RFC_ES | RFC_RE)) {
2461 DRV_WARN("%s> error found (framectrl=0x%08x)", __FUNCTION__, uFrameCtrl);
2462 STAT_NET(rx_errors)++;
2463 if (uFrameCtrl & RFC_TL) {
2464 STAT_NET(rx_length_errors)++;
2466 if (uFrameCtrl & RFC_CRC) {
2467 STAT_NET(rx_crc_errors)++;
2469 if (uFrameCtrl & RFC_RF) {
2470 STAT_NET(rx_length_errors)++;
2472 /* if errors other than ES happened!!! */
2473 if (uFrameCtrl & RFC_RE) {
2474 DRV_WARN("%s> RFC_RE (MII) (framectrl=0x%08x)", __FUNCTION__, uFrameCtrl);
2475 STAT_NET(rx_errors)++;
2477 /* RLQ, 11/07/2002, added more check to IP/TCP/UDP checksum errors */
2478 if (uFrameCtrl | (RFC_IPE | RFC_TCPE | RFC_UDPE)) {
2479 STAT_NET(rx_errors)++;
2481 goto CLEAN_UP;
2484 #ifdef MORE_ERROR_TRACKING
2485 /* for debug purpose */
2486 if (Length > 1518) {
2487 DI.uRx1518plus++;
2489 /* note that printout affects the performance figure quite lots, so don't display
2490 it when conducting performance test, like Chariot */
2491 if (DI.uDebugDumpRxPkt & DEBUG_PACKET_OVSIZE) {
2492 DRV_INFO("%s> oversize pkt, size=%d, RxDesc=%d", __FUNCTION__, Length, i);
2495 /* do early drop */
2496 STAT_NET(rx_errors)++;
2497 goto CLEAN_UP;
2500 /* for debug purpose */
2501 if (Length < 64) {
2502 DI.uRxUnderSize++;
2503 /* note that printout affects the performance figure quite lots, so don't display
2504 it when conducting performance test, like Chariot */
2505 if (DI.uDebugDumpRxPkt & DEBUG_PACKET_UNDERSIZE) {
2506 DRV_INFO("%s> under pkt, size=%d, RxDesc=%d", __FUNCTION__, Length, i);
2508 /* do early drop */
2509 STAT_NET(rx_errors)++;
2510 goto CLEAN_UP;
2512 #endif /* #ifdef MORE_ERROR_TRACKING */
2515 * if we are here, means a valid packet received!!! Get length of the pacekt
2518 /* offset CRC bytes! */
2519 Length -= ETH_CRC_LENGTH;
2521 /* to do something ? */
2522 consistent_sync(skb->data, DI.uRxBufferLen, PCI_DMA_FROMDEVICE);
2524 #ifdef PACKET_DUMP
2525 /* build in debug mechanism */
2526 ks8695_dump_packet(Adapter, skb->data, Length, DI.uDebugDumpRxPkt);
2527 #endif
2530 * copy recevied data to a new skb buffer in order to make IP header 32 bit alignment.
2532 copy_skb = dev_alloc_skb(Length + offset );
2533 if ( copy_skb == NULL)
2535 STAT_NET(rx_dropped)++;
2536 cng_level = NET_RX_DROP;
2537 goto CLEAN_UP;
2539 copy_skb->dev = Adapter->netdev;
2540 skb_reserve(copy_skb, offset); /* offset frame by 2 bytes */
2542 /* read pkt_len bytes into new skb buf */
2543 memcpy ( skb_put(copy_skb, Length), skb->data, Length );
2545 /* pass the copied skb with IP header alignment to uplayer */
2546 skb = copy_skb;
2548 /* check and set Rx Checksum Offload flag */
2549 if (DI.bRxChecksum)
2550 /* tell upper edge that the driver handled it already! */
2551 skb->ip_summed = CHECKSUM_UNNECESSARY;
2552 else
2553 skb->ip_summed = CHECKSUM_NONE;
2555 skb->protocol = eth_type_trans(skb, Adapter->netdev);
2556 cng_level = netif_rx(skb);
2557 nProcessed++;
2559 /* note that WAN DMA doesn't have statistics counters associated with,
2560 therefore use local variables to track them instead */
2561 STAT_NET(rx_packets)++;
2562 STAT_NET(rx_bytes) += Length;
2563 if (uFrameCtrl & RFC_MF)
2564 STAT_NET(multicast)++;
2565 Adapter->netdev->last_rx = jiffies;
2567 CLEAN_UP:
2569 * done with this descriptor, let ks8695 DMA own it again
2571 CurrentDescriptor->RxFrameControl &= cpu_to_le32(~(RFC_FRAMECTRL_MASK));
2572 if (pBegin != CurrentDescriptor)
2573 CurrentDescriptor->RxFrameControl |= cpu_to_le32(DESC_OWN_BIT);
2575 /* go to next rx descriptor */
2576 i = (i + 1) % DI.nRxDescTotal;
2577 CurrentDescriptor = &DI.pRxDescriptors[i];
2578 if (pBegin == CurrentDescriptor) /* one round already */
2579 break;
2580 if (cng_level == NET_RX_DROP || cng_level == NET_RX_CN_HIGH)
2581 break;
2582 } /* while (!((uFrameCtrl = le32_to_cpu(CurrentDescriptor->RxFrameControl)) & DESC_OWN_BIT)) { */
2583 if (nProcessed)
2584 pBegin->RxFrameControl |= cpu_to_le32(DESC_OWN_BIT);
2586 DI.nRxDescNextAvail = i;
2588 /* enable Rx engine!!! */
2589 KS8695_WRITE_REG(REG_RXSTART + DI.nOffset, 1);
2591 return nProcessed;
2594 #ifdef FAST_POLL
2595 static void ks8695_fast_poll(void *arg)
2597 PADAPTER_STRUCT Adapter = netdev_priv((struct net_device *)arg);
2598 int i, irq;
2600 if (ks8695_poll_ready) {
2601 for (i = 0; (i < 6); i++) {
2602 irq = DI.uIntShift + i;
2603 if (DI.uIntMask & (1L << irq))
2604 ks8695_isr(irq, arg);
2608 #endif
2610 #ifdef HANDLE_RXPACKET_BY_INTERRUPT
2612 * ks8695_isr
2613 * This function is the Interrupt Service Routine.
2615 * Argument(s)
2616 * irq interrupt number
2617 * data pointer to net_device structure
2618 * regs pointer to pt_regs structure
2620 * Return(s)
2621 * NONE.
2623 irqreturn_t ks8695_isr(int irq, void *data)
2625 PADAPTER_STRUCT Adapter = netdev_priv((struct net_device *)data);
2626 uint32_t uISR, uISR1, uIER;
2628 #ifdef DEBUG_THIS
2629 DRV_INFO("%s> HANDLE_RXPACKET_BY_INTERRUPT.)", __FUNCTION__);
2630 #endif
2632 uISR1 = (1L << irq);
2633 uIER = KS8695_READ_REG(KS8695_INT_ENABLE);
2635 /* disable corresponding interrupt */
2636 KS8695_WRITE_REG(KS8695_INT_ENABLE, uIER & ~uISR1);
2638 /* ACK */
2639 KS8695_WRITE_REG(KS8695_INT_STATUS, uISR1);
2641 uISR = uISR1 >> DI.uIntShift;
2643 /* handle Receive Interrupt */
2644 if (uISR & INT_RX_BIT)
2645 ProcessRxInterrupts(Adapter);
2647 /* handle Transmit Done Interrupt */
2648 #ifndef USE_TX_UNAVAIL
2649 if (uISR & INT_TX_BIT) {
2650 #else
2651 if (DI.nTransmitCount) {
2652 #endif
2653 ProcessTxInterrupts(Adapter);
2656 /* Restore Previous Interrupt Settings */
2657 KS8695_WRITE_REG(KS8695_INT_ENABLE, uIER );
2659 return IRQ_HANDLED;
2662 #endif /* #ifdef HANDLE_RXPACKET_BY_INTERRUPT */
2665 #ifdef RX_TASK
2667 * ks8695_isr
2668 * This function is the Interrupt Service Routine.
2670 * Argument(s)
2671 * irq interrupt number
2672 * data pointer to net_device structure
2673 * regs pointer to pt_regs structure
2675 * Return(s)
2676 * NONE.
2678 irqreturn_t ks8695_isr(int irq, void *data)
2680 PADAPTER_STRUCT Adapter = netdev_priv((struct net_device *)data);
2681 uint32_t uISR, uISR1, uIER;
2683 #ifdef PACKET_DUMP
2684 DRV_INFO("%s> RX_TASK ?)", __FUNCTION__);
2685 #endif
2687 uISR1 = (1L << irq);
2688 uIER = KS8695_READ_REG(KS8695_INT_ENABLE);
2690 /* disable corresponding interrupt */
2691 KS8695_WRITE_REG(KS8695_INT_ENABLE, uIER & ~uISR1);
2693 /* ACK */
2694 KS8695_WRITE_REG(KS8695_INT_STATUS, uISR1);
2696 uISR = uISR1 >> DI.uIntShift;
2698 switch (uISR) {
2699 /* handle Receive Interrupt */
2700 case INT_RX_BIT:
2701 if (FALSE == DI.rx_scheduled) {
2702 DI.rx_scheduled = TRUE;
2703 tasklet_hi_schedule(&DI.rx_tasklet);
2705 uISR1 = 0;
2706 break;
2708 /* handle Transmit Done Interrupt */
2709 case INT_TX_BIT:
2710 #ifdef USE_TX_UNAVAIL
2711 /* handle Transmit Buffer Unavailable Interrupt */
2712 case INT_TX_UNAVAIL_BIT:
2713 case (INT_TX_UNAVAIL_BIT | INT_TX_BIT):
2714 #endif
2715 #ifndef TX_TASK
2716 ProcessTxInterrupts(Adapter);
2717 #else
2718 if (FALSE == DI.tx_scheduled) {
2719 DI.tx_scheduled = TRUE;
2720 tasklet_hi_schedule(&DI.tx_tasklet);
2722 uISR1 = 0;
2723 #endif
2724 break;
2726 #ifdef USE_RX_UNAVAIL
2727 /* handle Receive Buffer Unavailable Interrupt */
2728 case INT_RX_UNAVAIL_BIT:
2729 break;
2730 #endif
2733 /* Restore Previous Interrupt if not a scheduled task */
2734 if (uISR1) {
2735 KS8695_WRITE_REG(KS8695_INT_ENABLE, uIER );
2738 return IRQ_HANDLED;
2741 #endif /*RX_TASK*/
2744 * ks8695_isre
2745 * for I-cache lockdown or FIQ purpose. Make sure this function is after ks8695_isr immediately.
2747 * Argument(s)
2748 * NONE.
2751 void ks8695_isre(void)
2753 /* just for the end of ks8695_isr routine, unless we find a way to define end of function
2754 within ks8695_isr itself */
2758 * ks8695_isr_link
2759 * This function is to process WAN link change interrupt as a special case
2761 * Argument(s)
2762 * irq interrupt number
2763 * data pointer to net_device structure
2764 * regs pointer to pt_regs structure
2766 * Return(s)
2767 * NONE.
2769 irqreturn_t ks8695_isr_link(int irq, void *data)
2771 PADAPTER_STRUCT Adapter = netdev_priv((struct net_device *)data);
2772 UINT uIER;
2774 spin_lock(&DI.lock);
2775 uIER = KS8695_READ_REG(KS8695_INT_ENABLE) & ~INT_WAN_LINK;
2776 KS8695_WRITE_REG(KS8695_INT_ENABLE, uIER);
2777 spin_unlock(&DI.lock);
2779 DI.nLinkChangeCount++;
2780 DI.bLinkChanged[0] = TRUE;
2782 /* start auto nego only when link is down */
2783 if (!swGetWANLinkStatus(Adapter)) {
2784 swPhyReset(Adapter, 0);
2785 swAutoNegoAdvertisement(Adapter, 0);
2786 swDetectPhyConnection(Adapter, 0);
2789 /* ACK */
2790 KS8695_WRITE_REG(KS8695_INT_STATUS, INT_WAN_LINK);
2791 spin_lock(&DI.lock);
2792 uIER = KS8695_READ_REG(KS8695_INT_ENABLE) | INT_WAN_LINK;
2793 KS8695_WRITE_REG(KS8695_INT_ENABLE, uIER);
2794 spin_unlock(&DI.lock);
2796 return IRQ_HANDLED;
2801 * ReceiveBufferFill
2802 * This function is use to replace used receive buffers with new SBBs
2803 * to Rx descriptors.
2805 * Argument(s)
2806 * Adapter pointer to ADAPTER_STRUCT structure.
2808 * Return(s)
2809 * NONE.
2811 static void ReceiveBufferFill(uintptr_t data)
2813 PADAPTER_STRUCT Adapter = (PADAPTER_STRUCT) data;
2814 RXDESC *CurrentDescriptor, *pBegin;
2815 struct sk_buff *skb;
2816 unsigned long flags;
2817 int i;
2819 if (!test_bit(KS8695_BOARD_OPEN, &Adapter->flags)) {
2820 DI.rx_fill_scheduled = FALSE;
2821 /* enable Rx engine!!! */
2822 KS8695_WRITE_REG(REG_RXSTART + DI.nOffset, 1);
2823 return;
2826 i = DI.nRxDescNextToFill;
2827 pBegin = CurrentDescriptor = &DI.pRxDescriptors[i];
2829 //__save_flags_cli(flags);
2830 while (NULL == DI.pRxSkb[i].skb) {
2831 skb = alloc_skb(DI.uRxBufferLen + offset, GFP_ATOMIC | GFP_DMA);
2832 if (NULL == skb) {
2833 /*DRV_WARN("%s> alloc_skb failed, refill rescheduled again", __FUNCTION__);*/
2834 break;
2837 skb->dev = Adapter->netdev;
2838 DI.pRxSkb[i].length = DI.uRxBufferLen;
2839 DI.pRxSkb[i].direction = PCI_DMA_FROMDEVICE;
2840 #ifndef RX_TASK
2841 consistent_sync(skb->data, DI.uRxBufferLen, PCI_DMA_FROMDEVICE);
2842 #endif
2843 DI.pRxSkb[i].dma = virt_to_phys(skb->data);
2845 /* to avoid possible race problem, make the change of these variables atomic */
2846 local_irq_save(flags);
2847 DI.pRxSkb[i].skb = skb;
2849 /* setup Rx descriptor!!! */
2850 CurrentDescriptor->RxDMAFragAddr = cpu_to_le32(DI.pRxSkb[i].dma);
2851 CurrentDescriptor->RxDMAFragLen = cpu_to_le32(DI.uRxBufferLen);
2852 CurrentDescriptor->RxFrameControl |= cpu_to_le32(DESC_OWN_BIT);
2854 DI.RxDescEmpty.counter--;
2855 local_irq_restore(flags);
2857 i = (i + 1) % DI.nRxDescTotal;
2858 CurrentDescriptor = &DI.pRxDescriptors[i];
2859 if (pBegin == CurrentDescriptor) /* one round already */
2860 break;
2862 DI.nRxDescNextToFill = i;
2863 //__restore_flags(flags);
2865 DI.rx_fill_scheduled = FALSE;
2867 /* enable Rx engine!!! */
2868 KS8695_WRITE_REG(REG_RXSTART + DI.nOffset, 1);
2871 static UINT mii_bmcr(PADAPTER_STRUCT Adapter, struct mii_regs *regs)
2873 UINT out = 0, reg;
2875 reg = KS8695_READ_REG(regs->config.reg);
2876 out |= reg & SW_PORT_FULLDUPLEX ? BMCR_FULLDPLX : 0;
2877 out |= reg & SW_PORT_DISABLE_AUTONEG ? 0 : BMCR_ANENABLE;
2878 out |= reg & SW_PORT_100BASE ? BMCR_SPEED100 : 0;
2880 reg = KS8695_READ_REG(regs->autonego.reg);
2881 out |= reg & (SW_AUTONEGO_RESTART << regs->autonego.shift) ? BMCR_ANRESTART : 0;
2883 reg = KS8695_READ_REG(regs->power.reg);
2884 out |= reg & (POWER_POWERDOWN << regs->power.shift) ? BMCR_PDOWN : 0;
2886 reg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
2887 out |= reg & DMA_LOOPBACK ? BMCR_LOOPBACK : 0;
2889 return out;
2892 static UINT mii_bmsr(PADAPTER_STRUCT Adapter, struct mii_regs *regs)
2894 UINT out = 0, reg;
2896 reg = KS8695_READ_REG(regs->autonego.reg);
2897 out |= reg & (SW_AUTONEGO_STAT_LINK << regs->autonego.shift) ? BMSR_LSTATUS : 0;
2898 out |= reg & (SW_AUTONEGO_COMPLETE << regs->autonego.shift) ? BMSR_ANEGCOMPLETE : 0;
2900 reg = KS8695_READ_REG(regs->config.reg);
2901 if (reg & SW_PORT_DISABLE_AUTONEG) {
2902 if (reg & SW_PORT_100BASE) {
2903 if (reg & SW_PORT_FULLDUPLEX)
2904 out |= BMSR_100FULL;
2905 else
2906 out |= BMSR_100HALF;
2907 } else {
2908 if (reg & SW_PORT_FULLDUPLEX)
2909 out |= BMSR_10FULL;
2910 else
2911 out |= BMSR_10HALF;
2913 } else
2914 out |= BMSR_ANEGCAPABLE | BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL;
2916 return out;
2919 static UINT mii_advertise(PADAPTER_STRUCT Adapter, struct mii_regs *regs)
2921 UINT out = 0, reg;
2923 reg = KS8695_READ_REG(regs->autonego.reg);
2924 out |= ADVERTISE_CSMA; /* Only mode supported */
2925 out |= reg & (SW_AUTONEGO_ADV_10HD << regs->autonego.shift) ? ADVERTISE_10HALF : 0;
2926 out |= reg & (SW_AUTONEGO_ADV_10FD << regs->autonego.shift) ? ADVERTISE_10FULL : 0;
2927 out |= reg & (SW_AUTONEGO_ADV_100HD << regs->autonego.shift) ? ADVERTISE_100HALF : 0;
2928 out |= reg & (SW_AUTONEGO_ADV_100FD << regs->autonego.shift) ? ADVERTISE_100FULL : 0;
2929 out |= reg & (SW_AUTONEGO_PART_10HD << regs->autonego.shift) ||
2930 reg & (SW_AUTONEGO_PART_10FD << regs->autonego.shift) ||
2931 reg & (SW_AUTONEGO_PART_100HD << regs->autonego.shift) ||
2932 reg & (SW_AUTONEGO_PART_100FD << regs->autonego.shift) ? ADVERTISE_LPACK : 0;
2934 return out;
2937 static UINT mii_lpa(PADAPTER_STRUCT Adapter, struct mii_regs *regs)
2939 UINT out = 0, reg;
2941 reg = KS8695_READ_REG(regs->autonego.reg);
2942 out |= ADVERTISE_CSMA; /* Only mode supported */
2943 out |= reg & (SW_AUTONEGO_PART_10HD << regs->autonego.shift) ? ADVERTISE_10HALF : 0;
2944 out |= reg & (SW_AUTONEGO_PART_10FD << regs->autonego.shift) ? ADVERTISE_10FULL : 0;
2945 out |= reg & (SW_AUTONEGO_PART_100HD << regs->autonego.shift) ? ADVERTISE_100HALF : 0;
2946 out |= reg & (SW_AUTONEGO_PART_100FD << regs->autonego.shift) ? ADVERTISE_100FULL : 0;
2947 out |= reg & (SW_AUTONEGO_PART_10HD << regs->autonego.shift) ||
2948 reg & (SW_AUTONEGO_PART_10FD << regs->autonego.shift) ||
2949 reg & (SW_AUTONEGO_PART_100HD << regs->autonego.shift) ||
2950 reg & (SW_AUTONEGO_PART_100FD << regs->autonego.shift) ? LPA_LPACK : 0;
2952 return out;
2955 static int ks8695_ioctl_switch(PADAPTER_STRUCT Adapter, PIOCTRL_SWITCH pIoCtrl);
2958 * ks8695_ioctl
2959 * This function is the ioctl entry point. It handles some driver specific IO
2960 * functions.
2962 * Argument(s)
2963 * netdev pointer to net_device structure.
2964 * ifr pointer to ifreq structure
2965 * cmd io cmd
2967 * Return(s)
2968 * 0 if success
2969 * negative value if failed
2971 int ks8695_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
2973 PADAPTER_STRUCT Adapter = netdev_priv(netdev);
2974 PIOCTRL pIoCtrl;
2975 struct mii_ioctl_data *data;
2976 struct mii_regs *regs;
2977 int nRet = -1;
2979 #ifdef DEBUG_THIS
2980 DRV_INFO("%s> cmd = 0x%x", __FUNCTION__, cmd);
2981 #endif
2983 pIoCtrl = (PIOCTRL)ifr->ifr_data;
2984 data = (struct mii_ioctl_data *)&ifr->ifr_data;
2986 switch(cmd) {
2988 * mii-tool commands
2990 case SIOCGMIIPHY:
2991 case SIOCDEVPRIVATE:
2992 /* Get address of MII PHY */
2993 data->phy_id = 0;
2994 nRet = 0;
2995 break;
2997 case SIOCGMIIREG:
2998 case SIOCDEVPRIVATE + 1:
3000 * Read MII PHY register
3002 if (!strcmp(netdev->name, "eth0")) {
3003 if (data->phy_id >= SW_MAX_LAN_PORTS || DI.usDMAId != DMA_LAN)
3004 return -EOPNOTSUPP;
3005 regs = &mii_regs_lan[data->phy_id];
3006 } else if (!strcmp(netdev->name, "eth1")) {
3007 if (data->phy_id != 0 || DI.usDMAId != DMA_WAN)
3008 return -EOPNOTSUPP;
3009 regs = &mii_regs_wan[0];
3010 } else
3011 return -EOPNOTSUPP;
3013 data->val_out = 0;
3015 switch (data->reg_num)
3017 case MII_BMCR:
3018 /* Basic mode control register */
3019 data->val_out = mii_bmcr(Adapter, regs);
3020 break;
3022 case MII_BMSR:
3023 /* Basic mode status register */
3024 data->val_out = mii_bmsr(Adapter, regs);
3025 break;
3027 case MII_ADVERTISE:
3028 /* Advertisement control register */
3029 data->val_out = mii_advertise(Adapter, regs);
3030 break;
3032 case MII_LPA:
3033 /* Link partner ability register */
3034 data->val_out = mii_lpa(Adapter, regs);
3035 break;
3037 nRet = 0;
3038 break;
3040 case SIOCSMIIREG:
3041 case SIOCDEVPRIVATE + 2:
3043 * Write MII PHY register
3045 if (!strcmp(netdev->name, "eth0")) {
3046 if (data->phy_id >= SW_MAX_LAN_PORTS || DI.usDMAId != DMA_LAN)
3047 return -EOPNOTSUPP;
3048 } else if (!strcmp(netdev->name, "eth1")) {
3049 if (data->phy_id != 0 || DI.usDMAId != DMA_WAN)
3050 return -EOPNOTSUPP;
3051 } else
3052 return -EOPNOTSUPP;
3054 switch (data->reg_num)
3056 case MII_BMCR:
3057 if (skipcmd) {
3058 skipcmd = 0;
3059 break;
3060 } else if (data->val_in & BMCR_ANRESTART) {
3061 /* Restart autonegotiation */
3062 if (DI.byDisableAutoNego[data->phy_id] == LINK_SELECTION_FORCED) {
3063 if ((DI.usCType[data->phy_id] = ctype) == SW_PHY_AUTO)
3064 DI.byDisableAutoNego[data->phy_id] = LINK_SELECTION_FULL_AUTO;
3065 else
3066 DI.byDisableAutoNego[data->phy_id] = LINK_SELECTION_PARTIAL_AUTO;
3068 } else if (data->val_in & BMCR_RESET) {
3069 /* Reset to defaults */
3070 if ((DI.usCType[data->phy_id] = SW_PHY_DEFAULT) == SW_PHY_AUTO)
3071 DI.byDisableAutoNego[data->phy_id] = LINK_SELECTION_FULL_AUTO;
3072 else
3073 DI.byDisableAutoNego[data->phy_id] = LINK_SELECTION_PARTIAL_AUTO;
3074 } else {
3075 /* Force link media type */
3076 if (DI.byDisableAutoNego[data->phy_id] == LINK_SELECTION_PARTIAL_AUTO)
3077 ctype = DI.usCType[data->phy_id]; /* Remember advert media */
3078 DI.byDisableAutoNego[data->phy_id] = LINK_SELECTION_FORCED;
3080 if (data->val_in & BMCR_SPEED100) {
3081 if (data->val_in & BMCR_FULLDPLX)
3082 DI.usCType[data->phy_id] = SW_PHY_100BASE_TX_FD;
3083 else
3084 DI.usCType[data->phy_id] = SW_PHY_100BASE_TX;
3085 } else {
3086 if (data->val_in & BMCR_FULLDPLX)
3087 DI.usCType[data->phy_id] = SW_PHY_10BASE_T_FD;
3088 else
3089 DI.usCType[data->phy_id] = SW_PHY_10BASE_T;
3093 swConfigureMediaType(Adapter,
3094 data->phy_id,
3095 DI.usCType[data->phy_id] == SW_PHY_100BASE_TX ||
3096 DI.usCType[data->phy_id] == SW_PHY_100BASE_TX_FD ? 1 : 0,
3097 DI.usCType[data->phy_id] == SW_PHY_10BASE_T_FD ||
3098 DI.usCType[data->phy_id] == SW_PHY_100BASE_TX_FD ? 1 : 0);
3099 break;
3101 case MII_ADVERTISE:
3102 DI.byDisableAutoNego[data->phy_id] = LINK_SELECTION_PARTIAL_AUTO;
3104 * mii-tool -A tries to disable then re-enable autonego,
3105 * the cmd to disable autonego looks just like the cmd
3106 * to force 10baseT-HD so set skipcmd to ignore it
3108 skipcmd = 1;
3110 if (data->val_in & ADVERTISE_10HALF)
3111 DI.usCType[data->phy_id] = SW_PHY_10BASE_T;
3112 if (data->val_in & ADVERTISE_10FULL)
3113 DI.usCType[data->phy_id] = SW_PHY_10BASE_T_FD;
3114 if (data->val_in & ADVERTISE_100HALF)
3115 DI.usCType[data->phy_id] = SW_PHY_100BASE_TX;
3116 if (data->val_in & ADVERTISE_100FULL)
3117 DI.usCType[data->phy_id] = SW_PHY_100BASE_TX_FD;
3118 break;
3120 default:
3121 break;
3123 nRet = 0;
3124 break;
3127 * Debug commands
3129 case SIOC_KS8695_IOCTRL:
3130 if (ifr->ifr_data) {
3131 UINT32 *pReg, i;
3133 switch (pIoCtrl->byId)
3135 case REG_DMA_DUMP:
3136 if (pIoCtrl->usLen >= (4 * (1 + REG_DMA_MAX) + 3)) { /* 1 + 2 + 4 + 8 * 4 */
3137 pReg = pIoCtrl->u.uData;
3138 /* tell debug application its offset */
3139 *pReg++ = DI.nOffset;
3140 for (i = REG_TXCTRL; i <= REG_STATION_HIGH ; i += 4, pReg++) {
3141 *pReg = (UINT32)KS8695_READ_REG(i + DI.nOffset);
3143 nRet = 0;
3145 break;
3147 case REG_DMA_STATION_DUMP:
3148 if (pIoCtrl->usLen >= (4 * REG_DMA_STATION_MAX + 3)) { /* 1 + 2 + 16 * 2 * 4 */
3149 pReg = pIoCtrl->u.uData;
3150 for (i = REG_MAC0_LOW; i <= REG_MAC15_HIGH ; i += 8) {
3151 *pReg++ = (UINT32)KS8695_READ_REG(i + DI.nOffset);
3152 *pReg++ = (UINT32)KS8695_READ_REG(i + DI.nOffset + 4);
3154 nRet = 0;
3156 break;
3158 case REG_UART_DUMP:
3159 if (pIoCtrl->usLen >= (4 * REG_UART_MAX + 3)) { /* 1 + 2 + 9 * 4 */
3160 pReg = pIoCtrl->u.uData;
3161 for (i = KS8695_UART_RX_BUFFER; i <= KS8695_UART_STATUS ; i += 4, pReg++) {
3162 *pReg = (UINT32)KS8695_READ_REG(i);
3164 nRet = 0;
3166 break;
3168 case REG_INT_DUMP:
3169 if (pIoCtrl->usLen >= (4 * REG_INT_MAX + 3)) { /* 1 + 2 + 14 * 4 */
3170 pReg = pIoCtrl->u.uData;
3171 for (i = KS8695_INT_CONTL; i <= KS8695_IRQ_PEND_PRIORITY ; i += 4, pReg++) {
3172 *pReg = (UINT32)KS8695_READ_REG(i);
3174 nRet = 0;
3176 break;
3178 /* Timer receive related */
3179 case REG_TIMER_DUMP:
3180 if (pIoCtrl->usLen >= (4 * REG_TIMER_MAX + 3)) { /* 1 + 2 + 5 * 4 */
3181 pReg = pIoCtrl->u.uData;
3182 for (i = KS8695_TIMER_CTRL; i <= KS8695_TIMER0_PCOUNT ; i += 4, pReg++) {
3183 *pReg = (UINT32)KS8695_READ_REG(i);
3185 nRet = 0;
3187 break;
3189 /* GPIO receive related */
3190 case REG_GPIO_DUMP:
3191 if (pIoCtrl->usLen >= (4 * REG_GPIO_MAX + 3)) { /* 1 + 2 + 3 * 4 */
3192 pReg = pIoCtrl->u.uData;
3193 for (i = KS8695_GPIO_MODE; i <= KS8695_GPIO_DATA ; i += 4, pReg++) {
3194 *pReg = (UINT32)KS8695_READ_REG(i);
3196 nRet = 0;
3198 break;
3200 case REG_SWITCH_DUMP:
3201 if (pIoCtrl->usLen >= (4 * REG_SWITCH_MAX + 3)) { /* 1 + 2 + 21 * 4 */
3202 pReg = pIoCtrl->u.uData;
3203 for (i = KS8695_SWITCH_CTRL0; i <= KS8695_LAN34_POWERMAGR ; i += 4, pReg++) {
3204 *pReg = (UINT32)KS8695_READ_REG(i);
3206 nRet = 0;
3208 break;
3210 case REG_MISC_DUMP:
3211 if (pIoCtrl->usLen >= (4 * REG_MISC_MAX + 3)) { /* 1 + 2 + 7 * 4 */
3212 pReg = pIoCtrl->u.uData;
3213 for (i = KS8695_DEVICE_ID; i <= KS8695_WAN_PHY_STATUS ; i += 4, pReg++) {
3214 *pReg = (UINT32)KS8695_READ_REG(i);
3216 nRet = 0;
3218 break;
3220 case REG_SNMP_DUMP:
3221 /* do we need to restrict its read to LAN driver only? May be later! */
3222 if (pIoCtrl->usLen >= (4 * REG_SNMP_MAX + 3)) { /* 1 + 2 + 138 * 4 */
3223 /* each port (1-4) takes 32 counters, and last 10 counters for port */
3224 pReg = pIoCtrl->u.uData;
3225 for (i = 0; i <= REG_SNMP_MAX ; i++, pReg++) {
3226 *pReg = swReadSNMPReg(Adapter, i);
3227 DelayInMicroseconds(10);
3229 nRet = 0;
3231 break;
3233 case DRV_VERSION:
3234 if (pIoCtrl->usLen >= 19) { /* 1 + 2 + 16 */
3235 if (0 == Adapter->rev)
3236 strncpy(pIoCtrl->u.byData, ks8695_driver_version, 15);
3237 else {
3238 if ((strlen(ks8695_driver_version) + 4) <= 15) {
3239 sprintf(pIoCtrl->u.byData, "%s, 95P.PING.01", ks8695_driver_version);
3241 else
3242 strncpy(pIoCtrl->u.byData, ks8695_driver_version, 15);
3244 nRet = 0;
3246 break;
3248 #ifdef CONFIG_ARCH_KS8695P
3249 case DUMP_PCI_SPACE:
3250 if (pIoCtrl->usLen >= sizeof(IOCTRL)) { /* 1 + 2 + 1 */
3251 if (Adapter->rev) {
3252 i = 0;
3253 printk("----- PCI conf Space -----\n");
3254 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(KS8695_2000)); i += 4;
3255 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(KS8695_2004)); i += 4;
3256 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(KS8695_2008)); i += 4;
3257 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(KS8695_200C)); i += 4;
3258 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(KS8695_2010)); i += 4;
3259 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(KS8695_2014)); i += 4;
3260 i = 0x2c;
3261 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(KS8695_202C)); i += 4;
3262 i = 0x3c;
3263 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(KS8695_203C)); i += 4;
3264 nRet = 0;
3267 break;
3269 case DUMP_BRIDGE_REG:
3270 if (pIoCtrl->usLen >= sizeof(IOCTRL)) { /* 1 + 2 + 1 + 1 (optional) */
3271 if (Adapter->rev) {
3272 printk("----- Bridge Conf Registers -----\n");
3273 i = KS8695_2100;
3274 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3275 i = KS8695_2104;
3276 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3278 i = KS8695_2200;
3279 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3280 i = KS8695_2204;
3281 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3282 i = KS8695_2208;
3283 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3284 i = KS8695_220C;
3285 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3286 i = KS8695_2210;
3287 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3288 i = KS8695_2214;
3289 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3290 i = KS8695_2218;
3291 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3292 i = KS8695_221C;
3293 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3294 i = KS8695_2220;
3295 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3296 i = KS8695_2224;
3297 printk("0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
3298 nRet = 0;
3301 break;
3302 #endif //CONFIG_ARCH_KS8695P
3303 case MEMORY_DUMP:
3304 /* dump 32 dwords each time */
3305 if (pIoCtrl->usLen >= (4 * 32 + 3)) { /* 1 + 2 + 1 + 1 (optional) */
3306 UINT32 *pReg1;
3308 /* note that the address is in the first dword, when returned will contain data */
3309 pReg = pIoCtrl->u.uData;
3310 pReg1 = (UINT32 *)(*pReg);
3312 #ifdef DEBUG_THIS
3313 DRV_INFO("addr=0x%08x, 0x%0x8", pReg1, *pReg1);
3314 #endif
3315 /* if no null pointer */
3316 if (pReg1 && (0xc0000000 == ((UINT)pReg1 & 0xc0000000))) {
3317 for (i = 0; i <= 32 ; i++, pReg++, pReg1++) {
3318 *pReg = *pReg1;
3320 nRet = 0;
3322 else {
3323 DRV_INFO("%s> invalid address: 0x%08x", __FUNCTION__, *pReg1);
3324 nRet = -EINVAL;
3327 break;
3329 case MEMORY_SEARCH:
3330 /* dump 32 dwords each time */
3331 if (pIoCtrl->usLen > 3 && pIoCtrl->usLen < 128) { /* 1 + 2 + optional length */
3332 DRV_INFO("%s> not implemented yet", __FUNCTION__);
3333 nRet = 0;
3335 break;
3337 case REG_WRITE:
3338 /* write control register */
3339 if (pIoCtrl->usLen >= 7) { /* 1 + 2 + 1 * 4 */
3340 UINT uReg;
3342 uReg = pIoCtrl->u.uData[0];
3343 if (uReg >= 0xffff) {
3344 return -EINVAL;
3346 if (pIoCtrl->usLen < 11) {
3347 /* if no parameter is given, display register value instead */
3348 printk("Reg(0x%04x) = 0x%08x", uReg, KS8695_READ_REG(uReg));
3350 else {
3351 KS8695_WRITE_REG(uReg, pIoCtrl->u.uData[1]);
3353 nRet = 0;
3355 break;
3357 case DEBUG_DUMP_TX_PACKET:
3358 /* set dump tx packet flag */
3359 if (pIoCtrl->usLen >= 7) { /* 1 + 2 + 4 */
3360 DI.uDebugDumpTxPkt = pIoCtrl->u.uData[0];
3361 #ifndef PACKET_DUMP
3362 DRV_INFO("%s> DumpTxPkt was disabled", __FUNCTION__);
3363 #endif
3364 nRet = 0;
3366 break;
3368 case DEBUG_DUMP_RX_PACKET:
3369 /* set dump rx packet flag */
3370 if (pIoCtrl->usLen >= 7) { /* 1 + 2 + 4 */
3371 DI.uDebugDumpRxPkt = pIoCtrl->u.uData[0];
3372 #ifndef PACKET_DUMP
3373 DRV_INFO("%s> DumpRxPkt was disabled", __FUNCTION__);
3374 #endif
3375 nRet = 0;
3377 break;
3379 case DEBUG_RESET_DESC:
3380 /* set dump rx packet flag */
3381 if (pIoCtrl->usLen == 3) { /* 1 + 2 */
3382 ResetDma(Adapter);
3383 nRet = 0;
3385 break;
3387 case DEBUG_STATISTICS:
3388 /* printout statistical counters */
3389 if (pIoCtrl->usLen == 3) { /* 1 + 2 */
3390 printk("------- statistics TX -------\n");
3391 printk("tx_packets = %12u\n", (UINT)STAT_NET(tx_packets));
3392 printk("tx_bytes = %12u\n", (UINT)STAT_NET(tx_bytes));
3393 printk("tx_dropped = %12u\n", (UINT)STAT_NET(tx_dropped));
3394 printk("tx_errors = %12u\n", (UINT)STAT_NET(tx_errors));
3396 printk("------- statistics RX -------\n");
3397 printk("rx_packets = %12u\n", (UINT)STAT_NET(rx_packets));
3398 printk("rx_bytes = %12u\n", (UINT)STAT_NET(rx_bytes));
3399 printk("rx_dropped = %12u\n", (UINT)STAT_NET(rx_dropped));
3400 printk("rx_errors = %12u\n", (UINT)STAT_NET(rx_errors));
3401 printk("rx_length_errors= %12u\n", (UINT)STAT_NET(rx_length_errors));
3402 printk("rx_crc_errors = %12u\n", (UINT)STAT_NET(rx_crc_errors));
3403 printk("collisions = %12u\n", (UINT)STAT_NET(collisions));
3404 printk("multicast = %12u\n", (UINT)STAT_NET(multicast));
3405 printk("rx_missed_errors= %12u\n", (UINT)STAT_NET(rx_missed_errors));
3406 printk("rx_length_errors= %12u\n", (UINT)STAT_NET(rx_length_errors));
3407 printk("over size pkts = %12u\n", (UINT)DI.uRx1518plus);
3408 printk("under size pkts = %12u\n", (UINT)DI.uRxUnderSize);
3409 printk("TransmitCount = %12u\n", DI.nTransmitCount);
3411 printk("------- Misc -------\n");
3412 printk("DMA reset count = %12d\n", DI.nResetCount);
3413 printk("Link change cnt = %12d\n", DI.nLinkChangeCount);
3414 nRet = 0;
3416 break;
3418 case DEBUG_DESCRIPTORS:
3419 /* printout descriptors info */
3420 if (pIoCtrl->usLen == 3) { /* 1 + 2 */
3421 printk("------ TX Descriptors ------\n");
3422 printk("descriptor VA = 0x%08x\n", (UINT)DI.pTxDescriptors);
3423 printk("total = %10d\n", DI.nTxDescTotal);
3424 printk("available = %10d\n", atomic_read(&DI.nTxDescAvail));
3425 printk("next available = %10d\n", DI.nTxDescNextAvail);
3426 printk("no resource = %10d\n", DI.bTxNoResource);
3427 printk("------ RX Descriptors ------\n");
3428 printk("descriptor VA = 0x%08x\n", (UINT)DI.pRxDescriptors);
3429 printk("total = %10d\n", DI.nRxDescTotal);
3430 printk("next to fill = %10d\n", DI.nRxDescNextToFill);
3431 printk("next available = %10d\n", DI.nRxDescNextAvail);
3432 printk("empty = %10d\n", atomic_read(&DI.RxDescEmpty));
3433 nRet = 0;
3435 break;
3437 case DEBUG_LINK_STATUS:
3438 /* printout link status */
3439 if (pIoCtrl->usLen >= 3) { /* 1 + 2 */
3440 int i;
3442 if (DMA_LAN != DI.usDMAId) {
3443 /* RLQ, 1.0.0.14, modified for UPNP query */
3444 if (pIoCtrl->usLen == 15) { /* 3 + 3 * 4 */
3445 UINT32 *pReg;
3447 /* note that the address is in the first dword, when returned will contain data */
3448 pReg = pIoCtrl->u.uData;
3449 i = 0;
3450 *pReg++ = DI.bLinkActive[i]; /* link active */
3451 if (!DI.bLinkActive[i]) {
3452 *pReg++ = 0; /* speed */
3453 *pReg = 0; /* duplex */
3455 else {
3456 *pReg++ = (SPEED_100 == DI.usLinkSpeed[i]) ? 100000000 : 10000000;
3457 *pReg = DI.bHalfDuplex[i];
3460 else { /* for back compatible with ks8695_debug utility */
3461 i = 0;
3462 if (!DI.bLinkActive[i]) {
3463 printk("Link = Down, Speed=Unknown, Duplex=Unknown\n");
3465 else {
3466 if (SW_PHY_AUTO == DI.usCType[i]) {
3467 printk("Link=Up, Speed=%s, Duplex (read)=%s, Duplex (detected)=%s\n",
3468 SPEED_100 == DI.usLinkSpeed[i] ? "100" : "10",
3469 DI.bHalfDuplex[i] ? "Full Duplex" : "Half Duplex",
3470 DI.bHalfDuplexDetected[i] ? "Full Duplex" : "Half Duplex");
3472 else {
3473 printk("Link=Up, Speed=%s, Duplex=%s\n",
3474 SPEED_100 == DI.usLinkSpeed[i] ? "100" : "10",
3475 DI.bHalfDuplex[i] ? "Full Duplex" : "Half Duplex");
3480 else {
3481 /* RLQ, 1.0.0.14, modified for UPNP query */
3482 if (pIoCtrl->usLen == 3 + 3 * 4 * SW_MAX_LAN_PORTS) { /* 3 + 3 * 4 * 4 = 51 */
3483 UINT32 *pReg;
3485 /* note that the address is in the first dword, when returned will contain data */
3486 pReg = pIoCtrl->u.uData;
3487 for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
3488 *pReg++ = DI.bLinkActive[i]; /* link active */
3489 if (!DI.bLinkActive[i]) {
3490 *pReg++ = 0; /* speed */
3491 *pReg++ = 0; /* duplex */
3493 else {
3494 *pReg++ = (SPEED_100 == DI.usLinkSpeed[i]) ? 100000000 : 10000000;
3495 *pReg++ = DI.bHalfDuplex[i];
3499 else {
3500 for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
3501 if (DI.bLinkActive[i]) {
3502 printk("Port[%d] Speed=%s, Duplex (read)=%s, Duplex (detected)=%s\n", (i + 1),
3503 SPEED_100 == DI.usLinkSpeed[i] ? "100" : "10",
3504 DI.bHalfDuplex[i] ? "Full Duplex" : "Half Duplex",
3505 DI.bHalfDuplexDetected[i] ? "Full Duplex" : "Half Duplex");
3507 else {
3508 printk("Port[%d] Speed = Unknown, Duplex = Unknown\n", (i + 1));
3513 nRet = 0;
3515 break;
3517 case CONFIG_LINK_TYPE:
3518 /* configure link media type (forced mode without auto nego) */
3519 if (pIoCtrl->usLen == 19) { /* 1 + 2 + 4 * 4*/
3520 uint32_t uPort;
3521 uint32_t uSpeed;
3522 uint32_t uDuplex;
3524 pReg = pIoCtrl->u.uData;
3525 if (DMA_LAN != DI.usDMAId) {
3526 uPort = 0;
3527 pReg++;
3528 } else {
3529 uPort = *pReg++;
3530 if (uPort >= SW_MAX_LAN_PORTS) {
3531 DRV_WARN("%s> LAN port out of range (%d)", __FUNCTION__, uPort);
3532 break;
3535 DI.byDisableAutoNego[uPort] = *pReg++;
3536 uSpeed = *pReg++;
3537 uDuplex = *pReg;
3538 /*DRV_INFO("%s> port=%d, disable autonego=%d, 100=%d, duplex=%d", __FUNCTION__, uPort, DI.byDisableAutoNego[uPort], uSpeed, uDuplex);*/
3539 swConfigureMediaType(Adapter, uPort, uSpeed, uDuplex);
3540 nRet = 0;
3542 break;
3544 case CONFIG_STATION_EX:
3545 /* configure link media type (forced mode without auto nego) */
3546 if (pIoCtrl->usLen == 13) { /* 1 + 2 + 4 + 6 */
3547 pReg = pIoCtrl->u.uData;
3549 /* uData[0] = set, byData[4-9] = mac address */
3550 if (pIoCtrl->u.uData[0]) {
3551 int i;
3553 i = macGetIndexStationEx(Adapter);
3554 if (i >= 0) {
3555 macSetStationEx(Adapter, &pIoCtrl->u.byData[4], i);
3556 nRet = 0;
3559 else {
3560 macResetStationEx(Adapter, &pIoCtrl->u.byData[4]);
3561 nRet = 0;
3564 break;
3566 case CONFIG_SWITCH_GET:
3567 /* we don't really need it since the OS always boots at super mode */
3568 /* if that is not the case, then enable following line, and add header file if missing ? */
3569 /*if (!capable(CAP_NET_ADMIN)) return -EPERM;*/
3570 /* !!! fall over !!! */
3572 case CONFIG_SWITCH_SET:
3573 /* for LAN driver only */
3574 if (DMA_LAN == DI.usDMAId) {
3575 return ks8695_ioctl_switch(Adapter, (PIOCTRL_SWITCH)ifr->ifr_data);
3577 else {
3578 if (CONFIG_SW_SUBID_ADV_LINK_SELECTION == ((PIOCTRL_SWITCH)ifr->ifr_data)->bySubId) {
3579 return ks8695_ioctl_switch(Adapter, (PIOCTRL_SWITCH)ifr->ifr_data);
3581 else {
3582 /* filter out the IF supported for WAN */
3583 return -EPERM;
3586 break;
3588 default:
3589 DRV_INFO("%s> unsupported parameters: id=%d, len=%d", __FUNCTION__, pIoCtrl->byId, pIoCtrl->usLen);
3590 return -EOPNOTSUPP;
3592 break;
3595 default:
3596 return -EOPNOTSUPP;
3599 return nRet;
3603 * ks8695_ioctl_switch
3604 * This function is used to configure CONFIG_SWITCH_SUBID related functions, for web page based
3605 * configuration or for ks8695_debug tool.
3607 * Argument(s)
3608 * Adapter pointer to ADAPTER_STRUCT structure.
3609 * pIoCtrl pointer to IOCTRL_SWITCH structure.
3611 * Return(s)
3612 * 0 if success
3613 * negative value if failed
3615 int ks8695_ioctl_switch(PADAPTER_STRUCT Adapter, PIOCTRL_SWITCH pIoCtrl)
3617 int nRet = -1;
3618 uint32_t uPort, uReg;
3620 switch(pIoCtrl->bySubId) {
3621 case CONFIG_SW_SUBID_ON:
3622 if (pIoCtrl->usLen == 8) { /* 1 + 2 + 1 + 4 */
3623 if (CONFIG_SWITCH_SET == pIoCtrl->byId)
3624 swEnableSwitch(Adapter, pIoCtrl->u.uData[0]);
3625 else {
3626 /* return current switch status */
3627 pIoCtrl->u.uData[0] = (KS8695_READ_REG(KS8695_SWITCH_CTRL0) & SW_CTRL0_SWITCH_ENABLE) ? TRUE : FALSE;
3629 nRet = 0;
3631 break;
3633 case CONFIG_SW_SUBID_PORT_VLAN:
3634 if (pIoCtrl->usLen == 20) { /* 1 + 2 + 1 + 4 * 4 */
3635 uPort = pIoCtrl->u.uData[0];
3636 if (uPort >= SW_MAX_LAN_PORTS) {
3637 DRV_WARN("%s> LAN port out of range (%d)", __FUNCTION__, uPort);
3638 break;
3640 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3641 uint32_t bInsertion;
3643 DPI[uPort].usTag = (uint16_t)pIoCtrl->u.uData[1];
3644 /* note that the driver doesn't use VLAN name, so the web page needs to remember it */
3645 bInsertion = pIoCtrl->u.uData[2];
3646 DPI[uPort].byCrossTalkMask = (uint8_t)(pIoCtrl->u.uData[3] & 0x1f);
3647 #ifdef DEBUG_THIS
3648 DRV_INFO("%s> port=%d, VID=%d, EgressMode=%s, crosstalk bit=0x%x", __FUNCTION__, uPort, DPI[uPort].usTag, bInsertion ? "tagged" : "untagged");
3649 #endif
3650 swConfigurePort(Adapter, uPort);
3651 swConfigTagInsertion(Adapter, uPort, bInsertion);
3653 else {
3654 pIoCtrl->u.uData[1] = (uint32_t)DPI[uPort].usTag;
3655 pIoCtrl->u.uData[2] = (KS8695_READ_REG(KS8695_SWITCH_ADVANCED) & (1L << (17 + uPort))) ? TRUE : FALSE;
3656 pIoCtrl->u.uData[3] = (uint32_t)DPI[uPort].byCrossTalkMask;
3658 nRet = 0;
3660 break;
3662 case CONFIG_SW_SUBID_PRIORITY:
3663 if (pIoCtrl->usLen == 32) { /* 1 + 2 + 1 + 4 * 7 */
3664 uPort = pIoCtrl->u.uData[0];
3665 if (uPort >= SW_MAX_LAN_PORTS) {
3666 DRV_WARN("%s> LAN port out of range (%d)", __FUNCTION__, uPort);
3667 break;
3669 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3670 uint32_t bRemoval;
3672 DPI[uPort].byIngressPriorityTOS = (uint8_t)pIoCtrl->u.uData[1];
3673 DPI[uPort].byIngressPriority802_1P = (uint8_t)pIoCtrl->u.uData[2];
3674 DPI[uPort].byIngressPriority = (uint8_t)pIoCtrl->u.uData[3];
3675 DPI[uPort].byEgressPriority = (uint8_t)pIoCtrl->u.uData[4];
3676 bRemoval = (uint8_t)pIoCtrl->u.uData[5];
3677 DPI[uPort].byStormProtection = (uint8_t)pIoCtrl->u.uData[6];
3678 #ifdef DEBUG_THIS
3679 DRV_INFO("%s> port=%d, DSCPEnable=%d, IngressPriority802_1P=%d, IngressPriority=%d,"
3680 "EgressPriority=%d, IngressTagRemoval=%d, StormProtection=%d", __FUNCTION__, uPort,
3681 DPI[uPort].byIngressPriorityTOS, DPI[uPort].byIngressPriority802_1P, DPI[uPort].byIngressPriority,
3682 DPI[uPort].byEgressPriority, bRemoval, DPI[uPort].byStormProtection);
3683 #endif
3684 swConfigurePort(Adapter, uPort);
3685 swConfigTagRemoval(Adapter, uPort, bRemoval);
3687 else {
3688 pIoCtrl->u.uData[1] = (uint32_t)DPI[uPort].byIngressPriorityTOS;
3689 pIoCtrl->u.uData[2] = (uint32_t)DPI[uPort].byIngressPriority802_1P;
3690 pIoCtrl->u.uData[3] = (uint32_t)DPI[uPort].byIngressPriority;
3691 pIoCtrl->u.uData[4] = (uint32_t)DPI[uPort].byEgressPriority;
3692 pIoCtrl->u.uData[6] = (uint32_t)DPI[uPort].byStormProtection;
3693 uReg = KS8695_READ_REG(KS8695_SWITCH_ADVANCED);
3694 pIoCtrl->u.uData[5] = uReg & (1L << (22 + uPort)) ? TRUE : FALSE;
3696 nRet = 0;
3698 break;
3700 case CONFIG_SW_SUBID_ADV_LINK_SELECTION:
3701 if (pIoCtrl->usLen >= 16) { /* 1 + 2 + 1 + 4 * (3 | 4) */
3702 uPort = pIoCtrl->u.uData[0];
3703 if (uPort >= SW_MAX_LAN_PORTS) {
3704 DRV_WARN("%s> LAN port out of range (%d)", __FUNCTION__, uPort);
3705 break;
3707 if (DMA_LAN != DI.usDMAId) {
3708 uPort = 0;
3710 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3711 uint32_t uDuplex;
3713 if (pIoCtrl->usLen < 20) {
3714 uDuplex = 0;
3716 else {
3717 uDuplex = pIoCtrl->u.uData[3];
3719 /* auto nego or forced mode */
3720 DI.byDisableAutoNego[uPort] = pIoCtrl->u.uData[1];
3721 swConfigureMediaType(Adapter, uPort, pIoCtrl->u.uData[2], uDuplex);
3723 else {
3724 pIoCtrl->u.uData[1] = DI.usCType[uPort];
3725 pIoCtrl->u.uData[2] = (uint32_t)DI.byDisableAutoNego[uPort];
3727 nRet = 0;
3729 break;
3731 case CONFIG_SW_SUBID_ADV_CTRL:
3732 if (pIoCtrl->usLen == 24) { /* 1 + 2 + 1 + 4 * 5 */
3733 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL0);
3734 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3735 if (pIoCtrl->u.uData[0]) {
3736 uReg |= SW_CTRL0_FLOWCTRL_FAIR;
3738 else {
3739 uReg &= ~SW_CTRL0_FLOWCTRL_FAIR;
3741 if (pIoCtrl->u.uData[1]) {
3742 uReg |= SW_CTRL0_LEN_CHECKING;
3744 else {
3745 uReg &= ~SW_CTRL0_LEN_CHECKING;
3747 if (pIoCtrl->u.uData[2]) {
3748 uReg |= SW_CTRL0_AUTO_FAST_AGING;
3750 else {
3751 uReg &= ~SW_CTRL0_AUTO_FAST_AGING;
3753 if (pIoCtrl->u.uData[3]) {
3754 uReg |= SW_CTRL0_NO_BCAST_STORM_PROT;
3756 else {
3757 uReg &= ~SW_CTRL0_NO_BCAST_STORM_PROT;
3759 uReg &= 0xfffffff3; /* clear priority scheme fields, 3:2 */
3760 uReg |= (pIoCtrl->u.uData[4] & 0x3) << 2;
3761 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0, uReg);
3762 /* need 20 cpu clock delay for switch related registers */
3763 DelayInMicroseconds(10);
3765 else {
3766 pIoCtrl->u.uData[0] = uReg & SW_CTRL0_FLOWCTRL_FAIR ? TRUE : FALSE;
3767 pIoCtrl->u.uData[1] = uReg & SW_CTRL0_LEN_CHECKING ? TRUE : FALSE;
3768 pIoCtrl->u.uData[2] = uReg & SW_CTRL0_AUTO_FAST_AGING ? TRUE : FALSE;
3769 pIoCtrl->u.uData[3] = uReg & SW_CTRL0_NO_BCAST_STORM_PROT ? TRUE : FALSE;
3770 pIoCtrl->u.uData[4] = (uReg >> 2) & 0x3;
3772 nRet = 0;
3774 break;
3776 case CONFIG_SW_SUBID_ADV_MIRRORING:
3777 if (pIoCtrl->usLen == 24) { /* 1 + 2 + 1 + 4 * 5 */
3778 uReg = KS8695_READ_REG(KS8695_SWITCH_ADVANCED);
3779 /* note that the port start from 1 - 5 instead of 0 - 5 used internally in the driver */
3780 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3781 uReg &= 0xfffe0000; /* currently, WEB page allows only on sniffer */
3782 /* sniffer port */
3783 if (pIoCtrl->u.uData[0] > 0 && pIoCtrl->u.uData[0] <= 5) {
3784 uReg |= (1L << (pIoCtrl->u.uData[0] - 1)) << 11;
3786 /* Tx mirror port */
3787 if (pIoCtrl->u.uData[1] > 0 && pIoCtrl->u.uData[1] <= 5) {
3788 uReg |= (1L << (pIoCtrl->u.uData[1] - 1)) << 6;
3790 /* Rx mirror port */
3791 if (pIoCtrl->u.uData[2] > 0 && pIoCtrl->u.uData[2] <= 5) {
3792 uReg |= (1L << (pIoCtrl->u.uData[2] - 1)) << 1;
3794 /* sniffer mode, 1 for AND 0 for OR */
3795 if (pIoCtrl->u.uData[3]) {
3796 uReg |= 0x00010000; /* bit 16 */
3798 /* IGMP trap enable */
3799 if (pIoCtrl->u.uData[4]) {
3800 uReg |= 0x00000001; /* bit 0 */
3802 KS8695_WRITE_REG(KS8695_SWITCH_ADVANCED, uReg);
3803 /* need 20 cpu clock delay for switch related registers */
3804 DelayInMicroseconds(10);
3806 else {
3807 pIoCtrl->u.uData[0] = (uReg >> 11) & 0x1f;
3808 pIoCtrl->u.uData[1] = (uReg >> 6) & 0x1f;
3809 pIoCtrl->u.uData[2] = (uReg >> 1) & 0x1f;
3810 pIoCtrl->u.uData[3] = (uReg & 0x00010000) ? TRUE : FALSE;
3811 pIoCtrl->u.uData[4] = (uReg & 0x00000001) ? TRUE : FALSE;
3813 nRet = 0;
3815 break;
3817 case CONFIG_SW_SUBID_ADV_THRESHOLD:
3818 if (pIoCtrl->usLen == 12) { /* 1 + 2 + 1 + 4 * 2 */
3819 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL1); /* 0xE804 */
3820 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3821 uReg &= 0x00ffffff; /* bit 31:24 */
3822 uReg |= (pIoCtrl->u.uData[0] & 0xff) << 24;
3823 KS8695_WRITE_REG(KS8695_SWITCH_CTRL1, uReg);
3824 DelayInMicroseconds(10);
3826 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL0);
3827 uReg &= 0x8fffffff; /* bit 30:28 */
3828 uReg |= (pIoCtrl->u.uData[1] & 0x07) << 28;
3829 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0, uReg);
3830 /* need 20 cpu clock delay for switch related registers */
3831 DelayInMicroseconds(10);
3833 else {
3834 pIoCtrl->u.uData[0] = (uReg >> 24);
3835 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL0);
3836 pIoCtrl->u.uData[1] = (uReg >> 28) & 0x07;
3838 nRet = 0;
3840 break;
3842 case CONFIG_SW_SUBID_ADV_DSCP:
3843 if (pIoCtrl->usLen == 12) { /* 1 + 2 + 1 + 4 * 2 */
3844 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3845 /* DSCP high */
3846 KS8695_WRITE_REG(KS8695_DSCP_HIGH, pIoCtrl->u.uData[0]);
3847 DelayInMicroseconds(10);
3848 /* DSCP low */
3849 KS8695_WRITE_REG(KS8695_DSCP_LOW, pIoCtrl->u.uData[1]);
3850 DelayInMicroseconds(10);
3852 else {
3853 pIoCtrl->u.uData[0] = KS8695_READ_REG(KS8695_DSCP_HIGH);
3854 pIoCtrl->u.uData[1] = KS8695_READ_REG(KS8695_DSCP_LOW);
3856 nRet = 0;
3858 break;
3860 case CONFIG_SW_SUBID_INTERNAL_LED:
3861 if (pIoCtrl->usLen == 12) { /* 1 + 2 + 1 + 4 * 2 */
3862 uint8_t byLed0, byLed1;
3864 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3865 byLed0 = (uint8_t)pIoCtrl->u.uData[0];
3866 byLed1 = (uint8_t)pIoCtrl->u.uData[1];
3867 if (byLed0 <= LED_LINK_ACTIVITY && byLed1 <= LED_LINK_ACTIVITY) {
3868 swSetLED(Adapter, FALSE, byLed0);
3869 swSetLED(Adapter, TRUE, byLed1);
3871 /* can we set WAN here as well or separate it to WAN driver ? */
3873 uReg = KS8695_READ_REG(KS8695_WAN_CONTROL);
3874 uReg &= 0xffffff88; /* 6:4, 2:0 */
3875 uReg |= (uint32_t)byLed1 << 4;
3876 uReg |= (uint32_t)byLed0;
3877 KS8695_WRITE_REG(KS8695_WAN_CONTROL, uReg);
3878 /* need 20 cpu clock delay for switch related registers */
3879 DelayInMicroseconds(10);
3882 else { /* out of range error */
3883 DRV_WARN("%s> LED setting out of range", __FUNCTION__);
3884 break;
3887 else {
3888 /* note that currently, all LED use same settings, so there is no
3889 need to define port in the IF */
3890 /* LAN */
3891 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL0);
3893 pIoCtrl->u.uData[0] = (uint32_t)((uReg >> 22) & 0x7);
3894 pIoCtrl->u.uData[1] = (uint32_t)((uReg >> 25) & 0x7);
3896 nRet = 0;
3898 break;
3900 case CONFIG_SW_SUBID_INTERNAL_MISC:
3901 if (pIoCtrl->usLen == 44) { /* 1 + 2 + 1 + 4 * 10 */
3902 uReg = KS8695_READ_REG(KS8695_SWITCH_CTRL0);
3903 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3904 if (pIoCtrl->u.uData[0]) {
3905 uReg |= SW_CTRL0_ERROR_PKT;
3907 else {
3908 uReg &= ~SW_CTRL0_ERROR_PKT;
3910 if (pIoCtrl->u.uData[1]) {
3911 uReg |= SW_CTRL0_BUFFER_SHARE;
3913 else {
3914 uReg &= ~SW_CTRL0_BUFFER_SHARE;
3916 if (pIoCtrl->u.uData[2]) {
3917 uReg |= SW_CTRL0_AGING_ENABLE;
3919 else {
3920 uReg &= ~SW_CTRL0_AGING_ENABLE;
3922 if (pIoCtrl->u.uData[3]) {
3923 uReg |= SW_CTRL0_FAST_AGING;
3925 else {
3926 uReg &= ~SW_CTRL0_FAST_AGING;
3928 if (pIoCtrl->u.uData[4]) {
3929 uReg |= SW_CTRL0_FAST_BACKOFF;
3931 else {
3932 uReg &= ~SW_CTRL0_FAST_BACKOFF;
3934 if (pIoCtrl->u.uData[5]) {
3935 uReg |= SW_CTRL0_6K_BUFFER;
3937 else {
3938 uReg &= ~SW_CTRL0_6K_BUFFER;
3940 if (pIoCtrl->u.uData[6]) {
3941 uReg |= SW_CTRL0_MISMATCH_DISCARD;
3943 else {
3944 uReg &= ~SW_CTRL0_MISMATCH_DISCARD;
3946 if (pIoCtrl->u.uData[7]) {
3947 uReg |= SW_CTRL0_COLLISION_DROP;
3949 else {
3950 uReg &= ~SW_CTRL0_COLLISION_DROP;
3952 if (pIoCtrl->u.uData[8]) {
3953 uReg |= SW_CTRL0_BACK_PRESSURE;
3955 else {
3956 uReg &= ~SW_CTRL0_BACK_PRESSURE;
3958 if (pIoCtrl->u.uData[9]) {
3959 uReg |= SW_CTRL0_PREAMBLE_MODE;
3961 else {
3962 uReg &= ~SW_CTRL0_PREAMBLE_MODE;
3964 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0, uReg);
3965 /* need 20 cpu clock delay for switch related registers */
3966 DelayInMicroseconds(10);
3968 else {
3969 pIoCtrl->u.uData[0] = uReg & SW_CTRL0_ERROR_PKT ? TRUE : FALSE;
3970 pIoCtrl->u.uData[1] = uReg & SW_CTRL0_BUFFER_SHARE ? TRUE : FALSE;
3971 pIoCtrl->u.uData[2] = uReg & SW_CTRL0_AGING_ENABLE ? TRUE : FALSE;
3972 pIoCtrl->u.uData[3] = uReg & SW_CTRL0_FAST_AGING ? TRUE : FALSE;
3973 pIoCtrl->u.uData[4] = uReg & SW_CTRL0_FAST_BACKOFF ? TRUE : FALSE;
3974 pIoCtrl->u.uData[5] = uReg & SW_CTRL0_6K_BUFFER ? TRUE : FALSE;
3975 pIoCtrl->u.uData[6] = uReg & SW_CTRL0_MISMATCH_DISCARD ? TRUE : FALSE;
3976 pIoCtrl->u.uData[7] = uReg & SW_CTRL0_COLLISION_DROP ? TRUE : FALSE;
3977 pIoCtrl->u.uData[8] = uReg & SW_CTRL0_BACK_PRESSURE ? TRUE : FALSE;
3978 pIoCtrl->u.uData[9] = uReg & SW_CTRL0_PREAMBLE_MODE ? TRUE : FALSE;
3980 nRet = 0;
3982 break;
3984 case CONFIG_SW_SUBID_INTERNAL_SPANNINGTREE:
3985 if (pIoCtrl->usLen == 20) { /* 1 + 2 + 1 + 4 * 4 */
3986 uint32_t uTxSpanning, uRxSpanning;
3988 uPort = pIoCtrl->u.uData[0];
3989 if (uPort >= SW_MAX_LAN_PORTS) {
3990 DRV_WARN("%s> LAN port out of range (%d)", __FUNCTION__, uPort);
3991 break;
3993 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
3994 uTxSpanning = pIoCtrl->u.uData[1];
3995 uRxSpanning = pIoCtrl->u.uData[2];
3996 DPI[uPort].byDisableSpanningTreeLearn = pIoCtrl->u.uData[3];
3997 if (uTxSpanning) {
3998 if (uRxSpanning)
3999 DPI[uPort].bySpanningTree = SW_SPANNINGTREE_ALL;
4000 else
4001 DPI[uPort].bySpanningTree = SW_SPANNINGTREE_TX;
4003 else {
4004 if (uRxSpanning)
4005 DPI[uPort].bySpanningTree = SW_SPANNINGTREE_RX;
4006 else
4007 DPI[uPort].bySpanningTree = SW_SPANNINGTREE_NONE;
4009 swConfigurePort(Adapter, uPort);
4011 else {
4012 uTxSpanning = uRxSpanning = FALSE;
4013 if (SW_SPANNINGTREE_ALL == DPI[uPort].bySpanningTree) {
4014 uTxSpanning = uRxSpanning = TRUE;
4016 else if (SW_SPANNINGTREE_TX == DPI[uPort].bySpanningTree) {
4017 uTxSpanning = TRUE;
4019 else if (SW_SPANNINGTREE_RX == DPI[uPort].bySpanningTree) {
4020 uRxSpanning = TRUE;
4022 pIoCtrl->u.uData[1] = uTxSpanning;
4023 pIoCtrl->u.uData[2] = uRxSpanning;
4024 pIoCtrl->u.uData[3] = (uint32_t)DPI[uPort].byDisableSpanningTreeLearn;
4026 nRet = 0;
4028 break;
4030 #ifdef CONFIG_ARCH_KS8695P
4031 case CONFIG_SW_SUBID_PHY_IF:
4032 if (pIoCtrl->usLen == 24) { /* 1 + 2 + 1 + 4 + 4 * 4 */
4033 u32 off, shift = 0;
4035 uPort = pIoCtrl->u.uData[0];
4036 if (DMA_WAN == DI.usDMAId)
4037 uPort = 0;
4038 if (uPort > SW_MAX_LAN_PORTS) {
4039 DRV_WARN("%s> LAN port out of range (%d)", __FUNCTION__, uPort);
4040 break;
4042 if (uPort == SW_MAX_LAN_PORTS)
4043 off = KS8695_WAN_POWERMAGR;
4044 else {
4045 if (uPort < 2)
4046 off = KS8695_LPPM12;
4047 else
4048 off = KS8695_LPPM34;
4050 if (!(uPort % 2))
4051 shift = 1;
4052 uReg = KS8695_READ_REG(off);
4053 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
4054 enablePhyLoopback(Adapter, uPort, pIoCtrl->u.uData[1]);
4055 enableRemoteLoopback(Adapter, uPort, pIoCtrl->u.uData[2]);
4056 enablePhyIsolate(Adapter, uPort, pIoCtrl->u.uData[3]);
4057 forcePhyLink(Adapter, uPort, pIoCtrl->u.uData[4]);
4059 else {
4060 pIoCtrl->u.uData[1] = (uReg & (KS8695_LPPM_PHY_LOOPBACK << (shift * 16))) ? 1 : 0;
4061 pIoCtrl->u.uData[2] = (uReg & (KS8695_LPPM_RMT_LOOPBACK << (shift * 16))) ? 1 : 0;
4062 pIoCtrl->u.uData[3] = (uReg & (KS8695_LPPM_PHY_ISOLATE << (shift * 16))) ? 1 : 0;
4063 pIoCtrl->u.uData[4] = (uReg & (KS8695_LPPM_FORCE_LINK << (shift * 16))) ? 1 : 0;
4065 nRet = 0;
4067 break;
4069 case CONFIG_SW_SUBID_SEC1:
4070 if (pIoCtrl->usLen == 36) { /* 1 + 2 + 1 + 4 * 8 */
4071 uReg = KS8695_READ_REG(KS8695_SEC1);
4072 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
4073 if (pIoCtrl->u.uData[0])
4074 uReg |= KS8695_SEC1_NO_IEEE_AN;
4075 else
4076 uReg &= ~KS8695_SEC1_NO_IEEE_AN;
4077 if (pIoCtrl->u.uData[1])
4078 uReg |= KS8695_SEC1_TPID_MODE;
4079 else
4080 uReg &= ~KS8695_SEC1_TPID_MODE;
4081 if (pIoCtrl->u.uData[2])
4082 uReg |= KS8695_SEC1_NO_TX_8021X_FLOW_CTRL;
4083 else
4084 uReg &= ~KS8695_SEC1_NO_TX_8021X_FLOW_CTRL;
4085 if (pIoCtrl->u.uData[3])
4086 uReg |= KS8695_SEC1_NO_RX_8021X_FLOW_CTRL;
4087 else
4088 uReg &= ~KS8695_SEC1_NO_RX_8021X_FLOW_CTRL;
4089 if (pIoCtrl->u.uData[4])
4090 uReg |= KS8695_SEC1_HUGE_PACKET;
4091 else
4092 uReg &= ~KS8695_SEC1_HUGE_PACKET;
4093 if (pIoCtrl->u.uData[5])
4094 uReg |= KS8695_SEC1_8021Q_VLAN_EN;
4095 else
4096 uReg &= ~KS8695_SEC1_8021Q_VLAN_EN;
4097 if (pIoCtrl->u.uData[6])
4098 uReg |= KS8695_SEC1_MII_10BT;
4099 else
4100 uReg &= ~KS8695_SEC1_MII_10BT;
4101 if (pIoCtrl->u.uData[7])
4102 uReg |= KS8695_SEC1_NULL_VID;
4103 else
4104 uReg &= ~KS8695_SEC1_NULL_VID;
4105 KS8695_WRITE_REG(KS8695_SEC1, uReg);
4106 DelayInMicroseconds(10);
4108 else {
4109 pIoCtrl->u.uData[0] = (uReg & KS8695_SEC1_NO_IEEE_AN) ? 1 : 0;
4110 pIoCtrl->u.uData[1] = (uReg & KS8695_SEC1_TPID_MODE) ? 1 : 0;
4111 pIoCtrl->u.uData[2] = (uReg & KS8695_SEC1_NO_TX_8021X_FLOW_CTRL) ? 1 : 0;
4112 pIoCtrl->u.uData[3] = (uReg & KS8695_SEC1_NO_RX_8021X_FLOW_CTRL) ? 1 : 0;
4113 pIoCtrl->u.uData[4] = (uReg & KS8695_SEC1_HUGE_PACKET) ? 1 : 0;
4114 pIoCtrl->u.uData[5] = (uReg & KS8695_SEC1_8021Q_VLAN_EN) ? 1 : 0;
4115 pIoCtrl->u.uData[6] = (uReg & KS8695_SEC1_MII_10BT) ? 1 : 0;
4116 pIoCtrl->u.uData[7] = (uReg & KS8695_SEC1_NULL_VID) ? 1 : 0;
4118 nRet = 0;
4120 break;
4122 case CONFIG_SW_SUBID_GENERIC_DUMP:
4123 if (pIoCtrl->usLen == 8) { /* 1 + 2 + 1 + 4 */
4124 int i;
4126 switch (pIoCtrl->u.uData[0]) {
4127 case GENERIC_DUMP_DYNAMIC:
4128 dumpDynamicMacTable(Adapter);
4129 nRet = 0;
4130 break;
4132 case GENERIC_DUMP_SWITCH_REGS:
4133 printk("--Reg-- ---Value--\n");
4134 for (i = KS8695_SEC0; i <= KS8695_LPPM34; i += 4) {
4135 printk(" 0x%04x 0x%08x\n", i, KS8695_READ_REG(i));
4137 nRet = 0;
4138 break;
4140 case GENERIC_DUMP_STATIC:
4141 dumpStaticMacTable(Adapter);
4142 nRet = 0;
4143 break;
4145 default:
4146 case GENERIC_DUMP_VLAN:
4147 DRV_INFO("%s> not implemented yet", __FUNCTION__);
4148 break;
4151 break;
4153 case CONFIG_SW_SUBID_RATE_CTRL:
4154 if (pIoCtrl->usLen == 32) { /* 1 + 2 + 4 * 7 */
4155 u32 off, tx, v1 = 0;
4157 uPort = pIoCtrl->u.uData[0];
4158 if (DMA_WAN == DI.usDMAId)
4159 uPort = 0;
4160 if (uPort > SW_MAX_LAN_PORTS) {
4161 DRV_WARN("%s> LAN port out of range (%d)", __FUNCTION__, uPort);
4162 break;
4164 tx = pIoCtrl->u.uData[1];
4165 if (uPort == SW_MAX_LAN_PORTS) {
4166 off = KS8695_SEP5C3;
4167 if (tx) v1 = KS8695_READ_REG(KS8695_SEP5C2);
4168 } else {
4169 off = KS8695_SEP1C3 + uPort * 0x0c;
4170 if (tx) v1 = KS8695_READ_REG(KS8695_SEP1C2 + uPort * 0x0c);
4172 uReg = KS8695_READ_REG(off);
4173 if (CONFIG_SWITCH_SET == pIoCtrl->byId) {
4174 if (tx) {
4175 setTxRate(Adapter, uPort, pIoCtrl->u.uData[2], pIoCtrl->u.uData[3]);
4176 enableTxRateControl(Adapter, uPort, pIoCtrl->u.uData[4], pIoCtrl->u.uData[5], pIoCtrl->u.uData[6]);
4178 else {
4179 setRxRate(Adapter, uPort, pIoCtrl->u.uData[2], pIoCtrl->u.uData[3]);
4180 enableRxRateControl(Adapter, uPort, pIoCtrl->u.uData[4], pIoCtrl->u.uData[5], pIoCtrl->u.uData[6]);
4183 else {
4184 if (tx) {
4185 pIoCtrl->u.uData[2] = (v1 & KS8695_SEPC2_TX_L_RATECTRL_MASK);
4186 pIoCtrl->u.uData[3] = ((v1 & KS8695_SEPC2_TX_H_RATECTRL_MASK) >> 12);
4187 pIoCtrl->u.uData[4] = (uReg & KS8695_SEPC3_TX_DIF_RATECTRL_EN) ? 1 : 0;
4188 pIoCtrl->u.uData[5] = (uReg & KS8695_SEPC3_TX_L_RATECTRL_EN) ? 1 : 0;
4189 pIoCtrl->u.uData[6] = (uReg & KS8695_SEPC3_TX_H_RATECTRL_EN) ? 1 : 0;
4191 else {
4192 pIoCtrl->u.uData[2] = ((uReg & KS8695_SEPC3_RX_L_RATECTRL_MASK) >> 8);
4193 pIoCtrl->u.uData[3] = ((uReg & KS8695_SEPC3_RX_H_RATECTRL_MASK) >> 20);
4194 pIoCtrl->u.uData[4] = (uReg & KS8695_SEPC3_RX_DIF_RATECTRL_EN) ? 1 : 0;
4195 pIoCtrl->u.uData[5] = (uReg & KS8695_SEPC3_RX_L_RATECTRL_EN) ? 1 : 0;
4196 pIoCtrl->u.uData[6] = (uReg & KS8695_SEPC3_RX_H_RATECTRL_EN) ? 1 : 0;
4199 nRet = 0;
4201 break;
4202 #endif
4204 default:
4205 DRV_INFO("%s> unsupported parameters: id=%d, len=%d", __FUNCTION__, pIoCtrl->byId, pIoCtrl->usLen);
4206 return -EOPNOTSUPP;
4209 return nRet;
4212 #ifdef __KS8695_CACHE_H
4214 * ks8695_icache_lock
4215 * This function is use to lock given icache
4217 * Argument(s)
4218 * icache_start pointer to starting icache address
4219 * icache_end pointer to ending icache address
4221 * Return(s)
4222 * 0 if success
4223 * error otherwise
4225 int ks8695_icache_lock2(void *icache_start, void *icache_end)
4227 uint32_t victim_base = ICACHE_VICTIM_BASE << ICACHE_VICTIM_INDEX;
4228 spinlock_t lock = SPIN_LOCK_UNLOCKED;
4229 unsigned long flags;
4230 #ifdef DEBUG_THIS
4231 int len;
4233 len = (int)(icache_end - icache_start);
4234 DRV_INFO("%s: start=%p, end=%p, len=%d", __FUNCTION__, icache_start, icache_end, len);
4235 /* if lockdown lines are more than half of max associtivity */
4236 if ((len / ICACHE_BYTES_PER_LINE) > (ICACHE_ASSOCITIVITY >> 1)) {
4237 DRV_WARN("%s: lockdown lines = %d is too many, (Assoc=%d)", __FUNCTION__, (len / ICACHE_BYTES_PER_LINE), ICACHE_ASSOCITIVITY);
4238 return -1;
4240 #endif
4242 spin_lock_irqsave(&lock, flags);
4244 __asm__(
4245 " \n\
4246 ADRL r0, ks8695_isr /* compile complains if icache_start is given instead */ \n\
4247 ADRL r1, ks8695_isre /* compile complains if icache_end is given instead */ \n\
4248 MOV r2, %0 \n\
4249 MCR p15, 0, r2, c9, c4, 1 \n\
4251 lock_loop: \n\
4252 MCR p15, 0, r0, c7, c13, 1 \n\
4253 ADD r0, r0, #32 \n\
4255 AND r3, r0, #0x60 \n\
4256 CMP r3, #0x0 \n\
4257 ADDEQ r2, r2, #0x1<<26 /* ICACHE_VICTIM_INDEX */ \n\
4258 MCREQ p15, 0, r2, c9, c0, 1 \n\
4260 CMP r0, r1 \n\
4261 BLE lock_loop \n\
4263 CMP r3, #0x0 \n\
4264 ADDNE r2, r2, #0x1<<26 /* ICACHE_VICTIM_INDEX */ \n\
4265 MCRNE p15, 0, r2, c9, c0, 1 \n\
4268 : "r" (victim_base)
4269 : "r0", "r1", "r2", "r3"
4272 #ifdef DEBUG_THIS
4273 ks8695_icache_read_c9();
4274 #endif
4276 spin_unlock_irqrestore(&lock, flags);
4278 return 0;
4280 #endif /*__KS8695_CACHE_H*/
4282 #ifdef RX_TASK
4284 * ReceiveProcessTask
4285 * This function is use to process Rx interrupt, send received data up
4286 * the network stack.
4288 * Argument(s)
4289 * data pointer to ADAPTER_STRUCT structure.
4291 * Return(s)
4292 * NONE
4294 static void ReceiveProcessTask(uintptr_t data)
4296 PADAPTER_STRUCT Adapter = (PADAPTER_STRUCT)data;
4297 UINT32 uFrameCtrl;
4298 RXDESC *CurrentDescriptor;
4300 #ifdef DEBUG_THIS
4301 DRV_INFO("%s> )", __FUNCTION__);
4302 #endif
4305 * Process receive packet by call ProcessRxInterrupts()
4307 ProcessRxInterrupts(Adapter);
4310 * if there are pending rx interrupt, reschedule rx task again
4312 CurrentDescriptor = &DI.pRxDescriptors[DI.nRxDescNextAvail];
4313 uFrameCtrl = CurrentDescriptor->RxFrameControl;
4314 if (!(uFrameCtrl & DESC_OWN_BIT))
4316 #ifdef TX_TASK
4317 if (DI.nTransmitCount > (DI.nTxDescTotal >> 1)) {
4318 /* try eanble read transfer again */
4319 KS8695_WRITE_REG(REG_TXSTART + DI.nOffset, 1);
4320 if (FALSE == DI.tx_scheduled) {
4321 DI.tx_scheduled = TRUE;
4322 tasklet_hi_schedule(&DI.tx_tasklet);
4325 #endif
4326 tasklet_hi_schedule(&DI.rx_tasklet);
4328 else
4330 DI.rx_scheduled = FALSE;
4331 /* enable corresponding Rx Interrupt again */
4332 KS8695_WRITE_REG(KS8695_INT_ENABLE, KS8695_READ_REG(KS8695_INT_ENABLE) |
4333 ((uint32_t)INT_RX_BIT << DI.uIntShift));
4337 #endif /*RX_TASK*/
4339 #ifdef TX_TASK
4341 * TransmitProcessTask
4342 * This function is use to process Tx interrupt in task level, reclaim resources after
4343 * transmit completed.
4345 * Argument(s)
4346 * data pointer to ADAPTER_STRUCT structure.
4348 * Return(s)
4349 * NONE.
4351 static void TransmitProcessTask(uintptr_t data)
4353 PADAPTER_STRUCT Adapter = (PADAPTER_STRUCT)data;
4356 #ifdef DEBUG_THIS
4357 DRV_INFO("%s> )", __FUNCTION__);
4358 #endif
4361 * Process free transmit data buffer by call ProcessTxInterrupts()
4363 ProcessTxInterrupts(Adapter);
4367 * if there are pending tx interrupt, reschedule tx task again
4369 #ifndef USE_TX_UNAVAIL
4370 if (KS8695_READ_REG(KS8695_INT_STATUS) & ((uint32_t)INT_TX_BIT << DI.uIntShift)) {
4371 #else
4372 if (KS8695_READ_REG(KS8695_INT_STATUS) &
4373 ((uint32_t)(INT_TX_BIT | INT_TX_UNAVAIL_BIT) << DI.uIntShift) & DI.uIntMask) {
4374 #endif
4375 /* Acknowledge the transmit interrupt let this routine becomes
4376 * an infinite loop.
4378 KS8695_WRITE_REG( KS8695_INT_STATUS,
4379 ( uint32_t ) INT_TX_BIT << DI.uIntShift );
4380 tasklet_hi_schedule(&DI.tx_tasklet);
4382 else
4384 DI.tx_scheduled = FALSE;
4385 /* enable corresponding Tx Interrupt again */
4386 #ifndef USE_TX_UNAVAIL
4387 KS8695_WRITE_REG(KS8695_INT_ENABLE, KS8695_READ_REG(KS8695_INT_ENABLE) |
4388 ((uint32_t)INT_TX_BIT << DI.uIntShift));
4389 #else
4390 KS8695_WRITE_REG(KS8695_INT_ENABLE, KS8695_READ_REG(KS8695_INT_ENABLE) |
4391 ((uint32_t)(INT_TX_BIT | INT_TX_UNAVAIL_BIT) << DI.uIntShift) & DI.uIntMask);
4392 #endif
4398 #endif /*TX_TASK*/
4400 /* ks8695_main.c */