]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
staging: ft1000: fix skb, netdev, memory leaks
[net-next-2.6.git] / drivers / staging / ft1000 / ft1000-pcmcia / ft1000_hw.c
CommitLineData
f7c1be0c
MB
1/*---------------------------------------------------------------------------
2 FT1000 driver for Flarion Flash OFDM NIC Device
bf3146c8 3
f7c1be0c
MB
4 Copyright (C) 2002 Flarion Technologies, All rights reserved.
5 Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
6 Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved.
bf3146c8
GKH
7
8 This program is free software; you can redistribute it and/or modify it
f7c1be0c 9 under the terms of the GNU General Public License as published by the Free
bf3146c8
GKH
10 Software Foundation; either version 2 of the License, or (at your option) any
11 later version. This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 more details. You should have received a copy of the GNU General Public
15 License along with this program; if not, write to the
16 Free Software Foundation, Inc., 59 Temple Place -
17 Suite 330, Boston, MA 02111-1307, USA.
f7c1be0c
MB
18-----------------------------------------------------------------------------*/
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/proc_fs.h>
23
24#include <linux/sched.h>
25#include <linux/ptrace.h>
26#include <linux/slab.h>
27#include <linux/string.h>
28#include <linux/timer.h>
29#include <linux/interrupt.h>
30#include <linux/in.h>
31#include <asm/io.h>
32#include <asm/system.h>
33#include <asm/bitops.h>
34
35#include <linux/netdevice.h>
36#include <linux/etherdevice.h>
37#include <linux/skbuff.h>
38#include <linux/if_arp.h>
39#include <linux/ioport.h>
40#include <linux/wait.h>
41#include <linux/vmalloc.h>
42
43#include <linux/firmware.h>
44#include <linux/ethtool.h>
45
46#ifdef FT_DEBUG
47#define DEBUG(n, args...) printk(KERN_DEBUG args);
48#else
49#define DEBUG(n, args...)
50#endif
51
52#include <linux/delay.h>
53#include "ft1000_dev.h"
54#include "ft1000.h"
55
56int card_download(struct net_device *dev, void *pFileStart, UINT FileLength);
57
58void ft1000InitProc(struct net_device *dev);
59void ft1000CleanupProc(struct net_device *dev);
60
61const struct firmware *fw_entry;
62
63static void ft1000_hbchk(u_long data);
64static struct timer_list poll_timer = {
65 function:ft1000_hbchk
66};
67
68static u16 cmdbuffer[1024];
69static u8 tempbuffer[1600];
70static u8 ft1000_card_present = 0;
71static u8 flarion_ft1000_cnt = 0;
72
73static irqreturn_t ft1000_interrupt(int irq, void *dev_id);
74static void ft1000_enable_interrupts(struct net_device *dev);
75static void ft1000_disable_interrupts(struct net_device *dev);
76
77/* new kernel */
78MODULE_AUTHOR("");
79MODULE_DESCRIPTION
80 ("Support for Flarion Flash OFDM NIC Device. Support for PCMCIA when used with ft1000_cs.");
81MODULE_LICENSE("GPL");
82MODULE_SUPPORTED_DEVICE("FT1000");
83
84#define MAX_RCV_LOOP 100
85
86//---------------------------------------------------------------------------
87//
88// Function: ft1000_asic_read
bf3146c8 89// Descripton: This function will retrieve the value of a specific ASIC
f7c1be0c
MB
90// register.
91// Input:
92// dev - network device structure
93// offset - ASIC register to read
94// Output:
95// value - value of ASIC register
96//
97//---------------------------------------------------------------------------
98inline u16 ft1000_asic_read(struct net_device *dev, u16 offset)
99{
100 return (ft1000_read_reg(dev, offset));
101}
102
103//---------------------------------------------------------------------------
104//
105// Function: ft1000_asic_write
106// Descripton: This function will set the value of a specific ASIC
107// register.
108// Input:
109// dev - network device structure
110// value - value to set ASIC register
111// Output:
112// none
113//
114//---------------------------------------------------------------------------
115inline void ft1000_asic_write(struct net_device *dev, u16 offset, u16 value)
116{
117 ft1000_write_reg(dev, offset, value);
118}
119
120//---------------------------------------------------------------------------
121//
122// Function: ft1000_read_fifo_len
bf3146c8 123// Descripton: This function will read the ASIC Uplink FIFO status register
f7c1be0c
MB
124// which will return the number of bytes remaining in the Uplink FIFO.
125// Sixteen bytes are subtracted to make sure that the ASIC does not
126// reach its threshold.
127// Input:
128// dev - network device structure
129// Output:
130// value - number of bytes available in the ASIC Uplink FIFO.
131//
132//---------------------------------------------------------------------------
133static inline u16 ft1000_read_fifo_len(struct net_device *dev)
134{
135 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
136
137 if (info->AsicID == ELECTRABUZZ_ID) {
138 return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16);
139 } else {
140 return (ft1000_read_reg(dev, FT1000_REG_MAG_UFSR) - 16);
141 }
142}
143
144//---------------------------------------------------------------------------
145//
146// Function: ft1000_read_dpram
147// Descripton: This function will read the specific area of dpram
148// (Electrabuzz ASIC only)
149// Input:
150// dev - device structure
151// offset - index of dpram
152// Output:
153// value - value of dpram
154//
155//---------------------------------------------------------------------------
156u16 ft1000_read_dpram(struct net_device * dev, int offset)
157{
158 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
159 unsigned long flags;
160 u16 data;
161
162 // Provide mutual exclusive access while reading ASIC registers.
163 spin_lock_irqsave(&info->dpram_lock, flags);
164 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
165 data = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
166 spin_unlock_irqrestore(&info->dpram_lock, flags);
167
168 return (data);
169}
170
171//---------------------------------------------------------------------------
172//
173// Function: ft1000_write_dpram
174// Descripton: This function will write to a specific area of dpram
175// (Electrabuzz ASIC only)
176// Input:
177// dev - device structure
178// offset - index of dpram
179// value - value to write
180// Output:
181// none.
182//
183//---------------------------------------------------------------------------
184static inline void ft1000_write_dpram(struct net_device *dev,
185 int offset, u16 value)
186{
187 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
188 unsigned long flags;
189
190 // Provide mutual exclusive access while reading ASIC registers.
191 spin_lock_irqsave(&info->dpram_lock, flags);
192 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
193 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, value);
194 spin_unlock_irqrestore(&info->dpram_lock, flags);
195}
196
197//---------------------------------------------------------------------------
198//
199// Function: ft1000_read_dpram_mag_16
200// Descripton: This function will read the specific area of dpram
201// (Magnemite ASIC only)
202// Input:
203// dev - device structure
204// offset - index of dpram
205// Output:
206// value - value of dpram
207//
208//---------------------------------------------------------------------------
209u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
210{
211 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
212 unsigned long flags;
213 u16 data;
214
215 // Provide mutual exclusive access while reading ASIC registers.
216 spin_lock_irqsave(&info->dpram_lock, flags);
217 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
218 // check if we want to read upper or lower 32-bit word
219 if (Index) {
220 data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL);
221 } else {
222 data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAH);
223 }
224 spin_unlock_irqrestore(&info->dpram_lock, flags);
225
226 return (data);
227}
228
229//---------------------------------------------------------------------------
230//
231// Function: ft1000_write_dpram_mag_16
232// Descripton: This function will write to a specific area of dpram
233// (Magnemite ASIC only)
234// Input:
235// dev - device structure
236// offset - index of dpram
237// value - value to write
238// Output:
239// none.
240//
241//---------------------------------------------------------------------------
242static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
243 int offset, u16 value, int Index)
244{
245 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
246 unsigned long flags;
247
248 // Provide mutual exclusive access while reading ASIC registers.
249 spin_lock_irqsave(&info->dpram_lock, flags);
250 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
251 if (Index) {
252 ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value);
253 } else {
254 ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value);
255 }
256 spin_unlock_irqrestore(&info->dpram_lock, flags);
257}
258
259//---------------------------------------------------------------------------
260//
261// Function: ft1000_read_dpram_mag_32
262// Descripton: This function will read the specific area of dpram
263// (Magnemite ASIC only)
264// Input:
265// dev - device structure
266// offset - index of dpram
267// Output:
268// value - value of dpram
269//
270//---------------------------------------------------------------------------
271u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
272{
273 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
274 unsigned long flags;
275 u32 data;
276
277 // Provide mutual exclusive access while reading ASIC registers.
278 spin_lock_irqsave(&info->dpram_lock, flags);
279 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
280 data = inl(dev->base_addr + FT1000_REG_MAG_DPDATAL);
281 spin_unlock_irqrestore(&info->dpram_lock, flags);
282
283 return (data);
284}
285
286//---------------------------------------------------------------------------
287//
288// Function: ft1000_write_dpram_mag_32
289// Descripton: This function will write to a specific area of dpram
290// (Magnemite ASIC only)
291// Input:
292// dev - device structure
293// offset - index of dpram
294// value - value to write
295// Output:
296// none.
297//
298//---------------------------------------------------------------------------
299void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
300{
301 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
302 unsigned long flags;
303
304 // Provide mutual exclusive access while reading ASIC registers.
305 spin_lock_irqsave(&info->dpram_lock, flags);
306 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
307 outl(value, dev->base_addr + FT1000_REG_MAG_DPDATAL);
308 spin_unlock_irqrestore(&info->dpram_lock, flags);
309}
310
311//---------------------------------------------------------------------------
312//
313// Function: ft1000_enable_interrupts
314// Descripton: This function will enable interrupts base on the current interrupt mask.
315// Input:
316// dev - device structure
317// Output:
318// None.
319//
320//---------------------------------------------------------------------------
321static void ft1000_enable_interrupts(struct net_device *dev)
322{
323 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
324 u16 tempword;
325
326 DEBUG(1, "ft1000_hw:ft1000_enable_interrupts()\n");
327 ft1000_write_reg(dev, FT1000_REG_SUP_IMASK,
328 info->CurrentInterruptEnableMask);
329 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
330 DEBUG(1,
331 "ft1000_hw:ft1000_enable_interrupts:current interrupt enable mask = 0x%x\n",
332 tempword);
333 info->InterruptsEnabled = TRUE;
334}
335
336//---------------------------------------------------------------------------
337//
338// Function: ft1000_disable_interrupts
339// Descripton: This function will disable all interrupts.
340// Input:
341// dev - device structure
342// Output:
343// None.
344//
345//---------------------------------------------------------------------------
346static void ft1000_disable_interrupts(struct net_device *dev)
347{
348 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
349 u16 tempword;
350
351 DEBUG(1, "ft1000_hw: ft1000_disable_interrupts()\n");
352 ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_MASK_ALL);
353 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
354 DEBUG(1,
355 "ft1000_hw:ft1000_disable_interrupts:current interrupt enable mask = 0x%x\n",
356 tempword);
357 info->InterruptsEnabled = FALSE;
358}
359
360//---------------------------------------------------------------------------
361//
362// Function: ft1000_reset_asic
363// Descripton: This function will call the Card Service function to reset the
364// ASIC.
365// Input:
366// dev - device structure
367// Output:
368// none
369//
370//---------------------------------------------------------------------------
371static void ft1000_reset_asic(struct net_device *dev)
372{
373 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
374 u16 tempword;
375
376 DEBUG(1, "ft1000_hw:ft1000_reset_asic called\n");
377
378 (*info->ft1000_reset) (info->link);
379 info->ASICResetNum++;
380
381 // Let's use the register provided by the Magnemite ASIC to reset the
382 // ASIC and DSP.
383 if (info->AsicID == MAGNEMITE_ID) {
384 ft1000_write_reg(dev, FT1000_REG_RESET,
385 (DSP_RESET_BIT | ASIC_RESET_BIT));
386 }
387 mdelay(1);
388 if (info->AsicID == ELECTRABUZZ_ID) {
389 // set watermark to -1 in order to not generate an interrrupt
390 ft1000_write_reg(dev, FT1000_REG_WATERMARK, 0xffff);
391 } else {
392 // set watermark to -1 in order to not generate an interrrupt
393 ft1000_write_reg(dev, FT1000_REG_MAG_WATERMARK, 0xffff);
394 }
395 // clear interrupts
396 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
397 DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
398 ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
399 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
400 DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
401
402}
403
404//---------------------------------------------------------------------------
405//
406// Function: ft1000_reset_card
407// Descripton: This function will reset the card
408// Input:
409// dev - device structure
410// Output:
411// status - FALSE (card reset fail)
bf3146c8 412// TRUE (card reset successful)
f7c1be0c
MB
413//
414//---------------------------------------------------------------------------
415static int ft1000_reset_card(struct net_device *dev)
416{
417 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
418 u16 tempword;
419 int i;
420 unsigned long flags;
421 PPROV_RECORD ptr;
422
423 DEBUG(1, "ft1000_hw:ft1000_reset_card called.....\n");
424
425 info->CardReady = 0;
426 info->ProgConStat = 0;
427 info->squeseqnum = 0;
428 ft1000_disable_interrupts(dev);
429
430// del_timer(&poll_timer);
431
432 // Make sure we free any memory reserve for provisioning
433 while (list_empty(&info->prov_list) == 0) {
434 DEBUG(0,
435 "ft1000_hw:ft1000_reset_card:deleting provisioning record\n");
436 ptr = list_entry(info->prov_list.next, PROV_RECORD, list);
437 list_del(&ptr->list);
438 kfree(ptr->pprov_data);
439 kfree(ptr);
440 }
441
442 if (info->AsicID == ELECTRABUZZ_ID) {
443 DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting DSP\n");
444 ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
445 } else {
446 DEBUG(1,
447 "ft1000_hw:ft1000_reset_card:resetting ASIC and DSP\n");
448 ft1000_write_reg(dev, FT1000_REG_RESET,
449 (DSP_RESET_BIT | ASIC_RESET_BIT));
450 }
451
bf3146c8 452 // Copy DSP session record into info block if this is not a coldstart
f7c1be0c
MB
453 if (ft1000_card_present == 1) {
454 spin_lock_irqsave(&info->dpram_lock, flags);
455 if (info->AsicID == ELECTRABUZZ_ID) {
456 if (info->DspHibernateFlag == 0) {
457 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
458 FT1000_DPRAM_RX_BASE);
459 for (i = 0; i < MAX_DSP_SESS_REC; i++) {
460 info->DSPSess.Rec[i] =
461 ft1000_read_reg(dev,
462 FT1000_REG_DPRAM_DATA);
463 }
464 }
465 } else {
466 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
467 FT1000_DPRAM_MAG_RX_BASE);
468 for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
469 info->DSPSess.MagRec[i] =
470 inl(dev->base_addr + FT1000_REG_MAG_DPDATA);
471 }
472 }
473 spin_unlock_irqrestore(&info->dpram_lock, flags);
474 }
475
476 DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting ASIC\n");
477 mdelay(10);
478 //reset ASIC
479 ft1000_reset_asic(dev);
480
481 info->DSPResetNum++;
482
483 DEBUG(1, "ft1000_hw:ft1000_reset_card:downloading dsp image\n");
484
485 if (info->AsicID == MAGNEMITE_ID) {
486 // Put dsp in reset and take ASIC out of reset
487 DEBUG(0,
488 "ft1000_hw:ft1000_reset_card:Put DSP in reset and take ASIC out of reset\n");
489 ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
490
491 // Setting MAGNEMITE ASIC to big endian mode
492 ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, HOST_INTF_BE);
493 // Download bootloader
494 card_bootload(dev);
495
496 // Take DSP out of reset
497 ft1000_write_reg(dev, FT1000_REG_RESET, 0);
498 // FLARION_DSP_ACTIVE;
499 mdelay(10);
500 DEBUG(0, "ft1000_hw:ft1000_reset_card:Take DSP out of reset\n");
501
502 // Wait for 0xfefe indicating dsp ready before starting download
503 for (i = 0; i < 50; i++) {
504 tempword =
505 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE,
506 FT1000_MAG_DPRAM_FEFE_INDX);
507 if (tempword == 0xfefe) {
508 break;
509 }
510 mdelay(20);
511 }
512
513 if (i == 50) {
514 DEBUG(0,
515 "ft1000_hw:ft1000_reset_card:No FEFE detected from DSP\n");
516 return FALSE;
517 }
518
519 } else {
520 // Take DSP out of reset
521 ft1000_write_reg(dev, FT1000_REG_RESET, ~DSP_RESET_BIT);
522 mdelay(10);
523 }
524
525 if (card_download(dev, fw_entry->data, fw_entry->size)) {
526 DEBUG(1, "card download unsuccessful\n");
527 return FALSE;
528 } else {
529 DEBUG(1, "card download successful\n");
530 }
531
532 mdelay(10);
533
534 if (info->AsicID == ELECTRABUZZ_ID) {
535 // Need to initialize the FIFO length counter to zero in order to sync up
536 // with the DSP
537 info->fifo_cnt = 0;
538 ft1000_write_dpram(dev, FT1000_FIFO_LEN, info->fifo_cnt);
539 // Initialize DSP heartbeat area to ho
540 ft1000_write_dpram(dev, FT1000_HI_HO, ho);
541 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
542 DEBUG(1, "ft1000_hw:ft1000_reset_asic:hi_ho value = 0x%x\n",
543 tempword);
544 } else {
545 // Initialize DSP heartbeat area to ho
546 ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, ho_mag,
547 FT1000_MAG_HI_HO_INDX);
548 tempword =
549 ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO,
550 FT1000_MAG_HI_HO_INDX);
551 DEBUG(1, "ft1000_hw:ft1000_reset_card:hi_ho value = 0x%x\n",
552 tempword);
553 }
554
555 info->CardReady = 1;
556 ft1000_enable_interrupts(dev);
557
558 /* Schedule heartbeat process to run every 2 seconds */
559// poll_timer.expires = jiffies + (2*HZ);
560// poll_timer.data = (u_long)dev;
561// add_timer(&poll_timer);
562
563 return TRUE;
564
565}
566
567//---------------------------------------------------------------------------
568//
569// Function: ft1000_chkcard
570// Descripton: This function will check if the device is presently available on
571// the system.
572// Input:
573// dev - device structure
574// Output:
575// status - FALSE (device is not present)
bf3146c8 576// TRUE (device is present)
f7c1be0c
MB
577//
578//---------------------------------------------------------------------------
579static int ft1000_chkcard(struct net_device *dev)
580{
581 u16 tempword;
582
583 // Mask register is used to check for device presence since it is never
584 // set to zero.
585 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
586 if (tempword == 0) {
587 DEBUG(1,
588 "ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n");
589 return FALSE;
590 }
591 // The system will return the value of 0xffff for the version register
592 // if the device is not present.
593 tempword = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
594 if (tempword == 0xffff) {
595 DEBUG(1,
596 "ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n");
597 return FALSE;
598 }
599 return TRUE;
600}
601
602
603//---------------------------------------------------------------------------
604//
605// Function: ft1000_hbchk
606// Descripton: This function will perform the heart beat check of the DSP as
607// well as the ASIC.
608// Input:
609// dev - device structure
610// Output:
611// none
612//
613//---------------------------------------------------------------------------
614static void ft1000_hbchk(u_long data)
615{
616 struct net_device *dev = (struct net_device *)data;
617
618 FT1000_INFO *info;
619 USHORT tempword;
620
621 info = (FT1000_INFO *) netdev_priv(dev);
622
623 if (info->CardReady == 1) {
624 // Perform dsp heartbeat check
625 if (info->AsicID == ELECTRABUZZ_ID) {
626 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
627 } else {
628 tempword =
629 ntohs(ft1000_read_dpram_mag_16
630 (dev, FT1000_MAG_HI_HO,
631 FT1000_MAG_HI_HO_INDX));
632 }
633 DEBUG(1, "ft1000_hw:ft1000_hbchk:hi_ho value = 0x%x\n",
634 tempword);
635 // Let's perform another check if ho is not detected
636 if (tempword != ho) {
637 if (info->AsicID == ELECTRABUZZ_ID) {
638 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
639 }
640 else {
641 tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX));
642 }
bf3146c8 643 }
f7c1be0c
MB
644 if (tempword != ho) {
645 printk(KERN_INFO
646 "ft1000: heartbeat failed - no ho detected\n");
647 if (info->AsicID == ELECTRABUZZ_ID) {
648 info->DSP_TIME[0] =
649 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
650 info->DSP_TIME[1] =
651 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
652 info->DSP_TIME[2] =
653 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
654 info->DSP_TIME[3] =
655 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
656 } else {
657 info->DSP_TIME[0] =
658 ft1000_read_dpram_mag_16(dev,
659 FT1000_MAG_DSP_TIMER0,
660 FT1000_MAG_DSP_TIMER0_INDX);
661 info->DSP_TIME[1] =
662 ft1000_read_dpram_mag_16(dev,
663 FT1000_MAG_DSP_TIMER1,
664 FT1000_MAG_DSP_TIMER1_INDX);
665 info->DSP_TIME[2] =
666 ft1000_read_dpram_mag_16(dev,
667 FT1000_MAG_DSP_TIMER2,
668 FT1000_MAG_DSP_TIMER2_INDX);
669 info->DSP_TIME[3] =
670 ft1000_read_dpram_mag_16(dev,
671 FT1000_MAG_DSP_TIMER3,
672 FT1000_MAG_DSP_TIMER3_INDX);
673 }
674 info->DrvErrNum = DSP_HB_INFO;
675 if (ft1000_reset_card(dev) == 0) {
676 printk(KERN_INFO
677 "ft1000: Hardware Failure Detected - PC Card disabled\n");
678 info->ProgConStat = 0xff;
679 return;
680 }
681 /* Schedule this module to run every 2 seconds */
682 poll_timer.expires = jiffies + (2*HZ);
683 poll_timer.data = (u_long)dev;
684 add_timer(&poll_timer);
685 return;
686 }
687
688 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
689 // Let's check doorbell again if fail
690 if (tempword & FT1000_DB_HB) {
691 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
bf3146c8 692 }
f7c1be0c
MB
693 if (tempword & FT1000_DB_HB) {
694 printk(KERN_INFO
695 "ft1000: heartbeat doorbell not clear by firmware\n");
696 if (info->AsicID == ELECTRABUZZ_ID) {
697 info->DSP_TIME[0] =
698 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
699 info->DSP_TIME[1] =
700 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
701 info->DSP_TIME[2] =
702 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
703 info->DSP_TIME[3] =
704 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
705 } else {
706 info->DSP_TIME[0] =
707 ft1000_read_dpram_mag_16(dev,
708 FT1000_MAG_DSP_TIMER0,
709 FT1000_MAG_DSP_TIMER0_INDX);
710 info->DSP_TIME[1] =
711 ft1000_read_dpram_mag_16(dev,
712 FT1000_MAG_DSP_TIMER1,
713 FT1000_MAG_DSP_TIMER1_INDX);
714 info->DSP_TIME[2] =
715 ft1000_read_dpram_mag_16(dev,
716 FT1000_MAG_DSP_TIMER2,
717 FT1000_MAG_DSP_TIMER2_INDX);
718 info->DSP_TIME[3] =
719 ft1000_read_dpram_mag_16(dev,
720 FT1000_MAG_DSP_TIMER3,
721 FT1000_MAG_DSP_TIMER3_INDX);
722 }
723 info->DrvErrNum = DSP_HB_INFO;
724 if (ft1000_reset_card(dev) == 0) {
725 printk(KERN_INFO
726 "ft1000: Hardware Failure Detected - PC Card disabled\n");
727 info->ProgConStat = 0xff;
728 return;
729 }
730 /* Schedule this module to run every 2 seconds */
731 poll_timer.expires = jiffies + (2*HZ);
732 poll_timer.data = (u_long)dev;
733 add_timer(&poll_timer);
734 return;
735 }
bf3146c8 736 // Set dedicated area to hi and ring appropriate doorbell according
f7c1be0c
MB
737 // to hi/ho heartbeat protocol
738 if (info->AsicID == ELECTRABUZZ_ID) {
739 ft1000_write_dpram(dev, FT1000_HI_HO, hi);
740 } else {
741 ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag,
742 FT1000_MAG_HI_HO_INDX);
743 }
744
745 if (info->AsicID == ELECTRABUZZ_ID) {
746 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
747 } else {
748 tempword =
749 ntohs(ft1000_read_dpram_mag_16
750 (dev, FT1000_MAG_HI_HO,
751 FT1000_MAG_HI_HO_INDX));
752 }
753 // Let's write hi again if fail
754 if (tempword != hi) {
755 if (info->AsicID == ELECTRABUZZ_ID) {
756 ft1000_write_dpram(dev, FT1000_HI_HO, hi);
757 }
758 else {
759 ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX);
760 }
761
762 if (info->AsicID == ELECTRABUZZ_ID) {
763 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
764 }
765 else {
766 tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX));
767 }
bf3146c8 768
f7c1be0c 769 }
bf3146c8 770
f7c1be0c
MB
771 if (tempword != hi) {
772 printk(KERN_INFO
773 "ft1000: heartbeat failed - cannot write hi into DPRAM\n");
774 if (info->AsicID == ELECTRABUZZ_ID) {
775 info->DSP_TIME[0] =
776 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
777 info->DSP_TIME[1] =
778 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
779 info->DSP_TIME[2] =
780 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
781 info->DSP_TIME[3] =
782 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
783 } else {
784 info->DSP_TIME[0] =
785 ft1000_read_dpram_mag_16(dev,
786 FT1000_MAG_DSP_TIMER0,
787 FT1000_MAG_DSP_TIMER0_INDX);
788 info->DSP_TIME[1] =
789 ft1000_read_dpram_mag_16(dev,
790 FT1000_MAG_DSP_TIMER1,
791 FT1000_MAG_DSP_TIMER1_INDX);
792 info->DSP_TIME[2] =
793 ft1000_read_dpram_mag_16(dev,
794 FT1000_MAG_DSP_TIMER2,
795 FT1000_MAG_DSP_TIMER2_INDX);
796 info->DSP_TIME[3] =
797 ft1000_read_dpram_mag_16(dev,
798 FT1000_MAG_DSP_TIMER3,
799 FT1000_MAG_DSP_TIMER3_INDX);
800 }
801 info->DrvErrNum = DSP_HB_INFO;
802 if (ft1000_reset_card(dev) == 0) {
803 printk(KERN_INFO
804 "ft1000: Hardware Failure Detected - PC Card disabled\n");
805 info->ProgConStat = 0xff;
806 return;
807 }
808 /* Schedule this module to run every 2 seconds */
809 poll_timer.expires = jiffies + (2*HZ);
810 poll_timer.data = (u_long)dev;
811 add_timer(&poll_timer);
812 return;
813 }
814 ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_HB);
815
816 }
817
818 /* Schedule this module to run every 2 seconds */
819 poll_timer.expires = jiffies + (2 * HZ);
820 poll_timer.data = (u_long) dev;
821 add_timer(&poll_timer);
822}
823
824//---------------------------------------------------------------------------
825//
826// Function: ft1000_send_cmd
bf3146c8 827// Descripton:
f7c1be0c
MB
828// Input:
829// Output:
830//
831//---------------------------------------------------------------------------
832void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype)
833{
834 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
835 int i;
836 u16 tempword;
837 unsigned long flags;
838
839 size += PSEUDOSZ;
840 // check for odd byte and increment to 16-bit word align value
841 if ((size & 0x0001)) {
842 size++;
843 }
844 DEBUG(1, "FT1000:ft1000_send_cmd:total length = %d\n", size);
845 DEBUG(1, "FT1000:ft1000_send_cmd:length = %d\n", ntohs(*ptempbuffer));
846 // put message into slow queue area
847 // All messages are in the form total_len + pseudo header + message body
848 spin_lock_irqsave(&info->dpram_lock, flags);
849
850 // Make sure SLOWQ doorbell is clear
851 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
852 i=0;
853 while (tempword & FT1000_DB_DPRAM_TX) {
854 mdelay(10);
855 i++;
856 if (i==10) {
857 spin_unlock_irqrestore(&info->dpram_lock, flags);
858 return;
859 }
860 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
861 }
862
863 if (info->AsicID == ELECTRABUZZ_ID) {
864 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
865 FT1000_DPRAM_TX_BASE);
866 // Write total length to dpram
867 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
868 // Write pseudo header and messgae body
869 for (i = 0; i < (size >> 1); i++) {
870 DEBUG(1, "FT1000:ft1000_send_cmd:data %d = 0x%x\n", i,
871 *ptempbuffer);
872 tempword = htons(*ptempbuffer++);
873 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, tempword);
874 }
875 } else {
876 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
877 FT1000_DPRAM_MAG_TX_BASE);
878 // Write total length to dpram
879 ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, htons(size));
880 // Write pseudo header and messgae body
881 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
882 FT1000_DPRAM_MAG_TX_BASE + 1);
883 for (i = 0; i < (size >> 2); i++) {
884 DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n",
885 *ptempbuffer);
886 outw(*ptempbuffer++,
887 dev->base_addr + FT1000_REG_MAG_DPDATAL);
888 DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n",
889 *ptempbuffer);
890 outw(*ptempbuffer++,
891 dev->base_addr + FT1000_REG_MAG_DPDATAH);
892 }
893 DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", *ptempbuffer);
894 outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAL);
895 DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", *ptempbuffer);
896 outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAH);
897 }
898 spin_unlock_irqrestore(&info->dpram_lock, flags);
899
900 // ring doorbell to notify DSP that we have a message ready
901 ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_TX);
902}
903
904//---------------------------------------------------------------------------
905//
906// Function: ft1000_receive_cmd
bf3146c8 907// Descripton: This function will read a message from the dpram area.
f7c1be0c
MB
908// Input:
909// dev - network device structure
910// pbuffer - caller supply address to buffer
911// pnxtph - pointer to next pseudo header
912// Output:
913// Status = 0 (unsuccessful)
914// = 1 (successful)
915//
916//---------------------------------------------------------------------------
917BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16 *pnxtph)
918{
919 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
920 u16 size;
921 u16 *ppseudohdr;
922 int i;
923 u16 tempword;
924 unsigned long flags;
925
926 if (info->AsicID == ELECTRABUZZ_ID) {
927 size = ( ft1000_read_dpram(dev, *pnxtph) ) + PSEUDOSZ;
928 } else {
929 size =
930 ntohs(ft1000_read_dpram_mag_16
931 (dev, FT1000_MAG_PH_LEN,
932 FT1000_MAG_PH_LEN_INDX)) + PSEUDOSZ;
933 }
934 if (size > maxsz) {
935 DEBUG(1,
936 "FT1000:ft1000_receive_cmd:Invalid command length = %d\n",
937 size);
938 return FALSE;
939 } else {
940 ppseudohdr = (u16 *) pbuffer;
941 spin_lock_irqsave(&info->dpram_lock, flags);
942 if (info->AsicID == ELECTRABUZZ_ID) {
943 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
944 FT1000_DPRAM_RX_BASE + 2);
945 for (i = 0; i <= (size >> 1); i++) {
946 tempword =
947 ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
948 *pbuffer++ = ntohs(tempword);
949 }
950 } else {
951 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
952 FT1000_DPRAM_MAG_RX_BASE);
953 *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
954 DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
955 pbuffer++;
956 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
957 FT1000_DPRAM_MAG_RX_BASE + 1);
958 for (i = 0; i <= (size >> 2); i++) {
959 *pbuffer =
960 inw(dev->base_addr +
961 FT1000_REG_MAG_DPDATAL);
962 pbuffer++;
963 *pbuffer =
964 inw(dev->base_addr +
965 FT1000_REG_MAG_DPDATAH);
966 pbuffer++;
967 }
968 //copy odd aligned word
969 *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL);
970 DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
971 pbuffer++;
972 *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
973 DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
974 pbuffer++;
975 }
976 if (size & 0x0001) {
977 //copy odd byte from fifo
978 tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
979 *pbuffer = ntohs(tempword);
980 }
981 spin_unlock_irqrestore(&info->dpram_lock, flags);
982
983 // Check if pseudo header checksum is good
984 // Calculate pseudo header checksum
985 tempword = *ppseudohdr++;
986 for (i = 1; i < 7; i++) {
987 tempword ^= *ppseudohdr++;
988 }
989 if ((tempword != *ppseudohdr)) {
990 DEBUG(1,
991 "FT1000:ft1000_receive_cmd:Pseudo header checksum mismatch\n");
992 // Drop this message
993 return FALSE;
994 }
995 return TRUE;
996 }
997}
998
999//---------------------------------------------------------------------------
1000//
1001// Function: ft1000_proc_drvmsg
1002// Descripton: This function will process the various driver messages.
1003// Input:
1004// dev - device structure
1005// pnxtph - pointer to next pseudo header
1006// Output:
1007// none
1008//
1009//---------------------------------------------------------------------------
1010void ft1000_proc_drvmsg(struct net_device *dev)
1011{
1012 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
1013 u16 msgtype;
1014 u16 tempword;
1015 PMEDIAMSG pmediamsg;
1016 PDSPINITMSG pdspinitmsg;
1017 PDRVMSG pdrvmsg;
1018 u16 len;
1019 u16 i;
1020 PPROV_RECORD ptr;
1021 PPSEUDO_HDR ppseudo_hdr;
1022 PUSHORT pmsg;
1023 struct timeval tv;
1024 union {
1025 u8 byte[2];
1026 u16 wrd;
1027 } convert;
1028
1029 if (info->AsicID == ELECTRABUZZ_ID) {
1030 tempword = FT1000_DPRAM_RX_BASE+2;
1031 }
1032 else {
1033 tempword = FT1000_DPRAM_MAG_RX_BASE;
1034 }
1035 if ( ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword) ) {
1036
1037 // Get the message type which is total_len + PSEUDO header + msgtype + message body
1038 pdrvmsg = (PDRVMSG) & cmdbuffer[0];
1039 msgtype = ntohs(pdrvmsg->type);
1040 DEBUG(1, "Command message type = 0x%x\n", msgtype);
1041 switch (msgtype) {
1042 case DSP_PROVISION:
1043 DEBUG(0,
1044 "Got a provisioning request message from DSP\n");
1045 mdelay(25);
1046 while (list_empty(&info->prov_list) == 0) {
1047 DEBUG(0, "Sending a provisioning message\n");
1048 // Make sure SLOWQ doorbell is clear
1049 tempword =
1050 ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1051 i = 0;
1052 while (tempword & FT1000_DB_DPRAM_TX) {
1053 mdelay(5);
1054 i++;
1055 if (i == 10) {
1056 break;
1057 }
1058 }
1059 ptr =
1060 list_entry(info->prov_list.next,
1061 PROV_RECORD, list);
1062 len = *(u16 *) ptr->pprov_data;
1063 len = htons(len);
1064
1065 pmsg = (PUSHORT) ptr->pprov_data;
1066 ppseudo_hdr = (PPSEUDO_HDR) pmsg;
1067 // Insert slow queue sequence number
1068 ppseudo_hdr->seq_num = info->squeseqnum++;
1069 ppseudo_hdr->portsrc = 0;
1070 // Calculate new checksum
1071 ppseudo_hdr->checksum = *pmsg++;
1072 DEBUG(1, "checksum = 0x%x\n",
1073 ppseudo_hdr->checksum);
1074 for (i = 1; i < 7; i++) {
1075 ppseudo_hdr->checksum ^= *pmsg++;
1076 DEBUG(1, "checksum = 0x%x\n",
1077 ppseudo_hdr->checksum);
1078 }
1079
1080 ft1000_send_cmd (dev, (u16 *)ptr->pprov_data, len, SLOWQ_TYPE);
1081 list_del(&ptr->list);
1082 kfree(ptr->pprov_data);
1083 kfree(ptr);
1084 }
1085 // Indicate adapter is ready to take application messages after all
1086 // provisioning messages are sent
1087 info->CardReady = 1;
1088 break;
1089 case MEDIA_STATE:
1090 pmediamsg = (PMEDIAMSG) & cmdbuffer[0];
1091 if (info->ProgConStat != 0xFF) {
1092 if (pmediamsg->state) {
1093 DEBUG(1, "Media is up\n");
1094 if (info->mediastate == 0) {
1095 netif_carrier_on(dev);
1096 netif_wake_queue(dev);
1097 info->mediastate = 1;
1098 do_gettimeofday(&tv);
1099 info->ConTm = tv.tv_sec;
1100 }
1101 } else {
1102 DEBUG(1, "Media is down\n");
1103 if (info->mediastate == 1) {
1104 info->mediastate = 0;
1105 netif_carrier_off(dev);
1106 netif_stop_queue(dev);
1107 info->ConTm = 0;
bf3146c8 1108 }
f7c1be0c
MB
1109 }
1110 }
1111 else {
1112 DEBUG(1,"Media is down\n");
1113 if (info->mediastate == 1) {
1114 info->mediastate = 0;
1115 netif_carrier_off(dev);
1116 netif_stop_queue(dev);
1117 info->ConTm = 0;
1118 }
1119 }
1120 break;
1121 case DSP_INIT_MSG:
1122 pdspinitmsg = (PDSPINITMSG) & cmdbuffer[0];
1123 memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
1124 DEBUG(1, "DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
1125 info->DspVer[0], info->DspVer[1], info->DspVer[2],
1126 info->DspVer[3]);
1127 memcpy(info->HwSerNum, pdspinitmsg->HwSerNum,
1128 HWSERNUMSZ);
1129 memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
1130 memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
1131 dev->dev_addr[0] = info->eui64[0];
1132 dev->dev_addr[1] = info->eui64[1];
1133 dev->dev_addr[2] = info->eui64[2];
1134 dev->dev_addr[3] = info->eui64[5];
1135 dev->dev_addr[4] = info->eui64[6];
1136 dev->dev_addr[5] = info->eui64[7];
1137
1138 if (ntohs(pdspinitmsg->length) ==
1139 (sizeof(DSPINITMSG) - 20)) {
1140 memcpy(info->ProductMode,
1141 pdspinitmsg->ProductMode, MODESZ);
1142 memcpy(info->RfCalVer, pdspinitmsg->RfCalVer,
1143 CALVERSZ);
1144 memcpy(info->RfCalDate, pdspinitmsg->RfCalDate,
1145 CALDATESZ);
1146 DEBUG(1, "RFCalVer = 0x%2x 0x%2x\n",
1147 info->RfCalVer[0], info->RfCalVer[1]);
1148 }
1149
1150 break ;
1151 case DSP_STORE_INFO:
1152 DEBUG(1, "FT1000:drivermsg:Got DSP_STORE_INFO\n");
1153 tempword = ntohs(pdrvmsg->length);
1154 info->DSPInfoBlklen = tempword;
1155 if (tempword < (MAX_DSP_SESS_REC - 4)) {
1156 pmsg = (PUSHORT) & pdrvmsg->data[0];
1157 for (i = 0; i < ((tempword + 1) / 2); i++) {
1158 DEBUG(1,
1159 "FT1000:drivermsg:dsp info data = 0x%x\n",
1160 *pmsg);
1161 info->DSPInfoBlk[i + 10] = *pmsg++;
1162 }
1163 }
1164 break;
1165 case DSP_GET_INFO:
1166 DEBUG(1, "FT1000:drivermsg:Got DSP_GET_INFO\n");
1167 // copy dsp info block to dsp
1168 info->DrvMsgPend = 1;
1169 // allow any outstanding ioctl to finish
1170 mdelay(10);
1171 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1172 if (tempword & FT1000_DB_DPRAM_TX) {
1173 mdelay(10);
1174 tempword =
1175 ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1176 if (tempword & FT1000_DB_DPRAM_TX) {
1177 mdelay(10);
1178 }
1179 }
1180
1181 if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
1182 // Put message into Slow Queue
1183 // Form Pseudo header
1184 pmsg = (PUSHORT) info->DSPInfoBlk;
1185 ppseudo_hdr = (PPSEUDO_HDR) pmsg;
1186 ppseudo_hdr->length =
1187 htons(info->DSPInfoBlklen + 4);
1188 ppseudo_hdr->source = 0x10;
1189 ppseudo_hdr->destination = 0x20;
1190 ppseudo_hdr->portdest = 0;
1191 ppseudo_hdr->portsrc = 0;
1192 ppseudo_hdr->sh_str_id = 0;
1193 ppseudo_hdr->control = 0;
1194 ppseudo_hdr->rsvd1 = 0;
1195 ppseudo_hdr->rsvd2 = 0;
1196 ppseudo_hdr->qos_class = 0;
1197 // Insert slow queue sequence number
1198 ppseudo_hdr->seq_num = info->squeseqnum++;
bf3146c8 1199 // Insert application id
f7c1be0c
MB
1200 ppseudo_hdr->portsrc = 0;
1201 // Calculate new checksum
1202 ppseudo_hdr->checksum = *pmsg++;
1203 for (i = 1; i < 7; i++) {
1204 ppseudo_hdr->checksum ^= *pmsg++;
1205 }
1206 info->DSPInfoBlk[8] = 0x7200;
1207 info->DSPInfoBlk[9] =
1208 htons(info->DSPInfoBlklen);
1209 ft1000_send_cmd (dev, (PUSHORT)info->DSPInfoBlk, (USHORT)(info->DSPInfoBlklen+4), 0);
1210 }
1211 info->DrvMsgPend = 0;
1212
1213 break;
1214 case GET_DRV_ERR_RPT_MSG:
1215 DEBUG(1, "FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n");
1216 // copy driver error message to dsp
1217 info->DrvMsgPend = 1;
1218 // allow any outstanding ioctl to finish
1219 mdelay(10);
1220 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1221 if (tempword & FT1000_DB_DPRAM_TX) {
1222 mdelay(10);
1223 tempword =
1224 ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1225 if (tempword & FT1000_DB_DPRAM_TX) {
1226 mdelay(10);
1227 }
1228 }
1229
1230 if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
1231 // Put message into Slow Queue
1232 // Form Pseudo header
1233 pmsg = (PUSHORT) & tempbuffer[0];
1234 ppseudo_hdr = (PPSEUDO_HDR) pmsg;
1235 ppseudo_hdr->length = htons(0x0012);
1236 ppseudo_hdr->source = 0x10;
1237 ppseudo_hdr->destination = 0x20;
1238 ppseudo_hdr->portdest = 0;
1239 ppseudo_hdr->portsrc = 0;
1240 ppseudo_hdr->sh_str_id = 0;
1241 ppseudo_hdr->control = 0;
1242 ppseudo_hdr->rsvd1 = 0;
1243 ppseudo_hdr->rsvd2 = 0;
1244 ppseudo_hdr->qos_class = 0;
1245 // Insert slow queue sequence number
1246 ppseudo_hdr->seq_num = info->squeseqnum++;
bf3146c8 1247 // Insert application id
f7c1be0c
MB
1248 ppseudo_hdr->portsrc = 0;
1249 // Calculate new checksum
1250 ppseudo_hdr->checksum = *pmsg++;
1251 for (i=1; i<7; i++) {
1252 ppseudo_hdr->checksum ^= *pmsg++;
1253 }
1254 pmsg = (PUSHORT) & tempbuffer[16];
1255 *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
1256 *pmsg++ = htons(0x000e);
1257 *pmsg++ = htons(info->DSP_TIME[0]);
1258 *pmsg++ = htons(info->DSP_TIME[1]);
1259 *pmsg++ = htons(info->DSP_TIME[2]);
1260 *pmsg++ = htons(info->DSP_TIME[3]);
1261 convert.byte[0] = info->DspVer[0];
1262 convert.byte[1] = info->DspVer[1];
1263 *pmsg++ = convert.wrd;
1264 convert.byte[0] = info->DspVer[2];
1265 convert.byte[1] = info->DspVer[3];
1266 *pmsg++ = convert.wrd;
1267 *pmsg++ = htons(info->DrvErrNum);
1268
1269 ft1000_send_cmd (dev, (PUSHORT)&tempbuffer[0], (USHORT)(0x0012), 0);
1270 info->DrvErrNum = 0;
1271 }
1272 info->DrvMsgPend = 0;
1273
1274 break;
1275 default:
1276 break;
1277 }
1278 }
1279}
1280
1281//---------------------------------------------------------------------------
1282//
1283// Function: ft1000_parse_dpram_msg
1284// Descripton: This function will parse the message received from the DSP
1285// via the DPRAM interface.
1286// Input:
1287// dev - device structure
1288// Output:
bf3146c8
GKH
1289// status - FAILURE
1290// SUCCESS
f7c1be0c
MB
1291//
1292//---------------------------------------------------------------------------
1293int ft1000_parse_dpram_msg(struct net_device *dev)
1294{
1295 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
1296 u16 doorbell;
1297 u16 portid;
1298 u16 nxtph;
1299 u16 total_len;
1300 int i = 0;
1301 int cnt;
1302 unsigned long flags;
1303
1304 doorbell = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1305 DEBUG(1, "Doorbell = 0x%x\n", doorbell);
1306
1307 if (doorbell & FT1000_ASIC_RESET_REQ) {
1308 // Copy DSP session record from info block
1309 spin_lock_irqsave(&info->dpram_lock, flags);
1310 if (info->AsicID == ELECTRABUZZ_ID) {
1311 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
1312 FT1000_DPRAM_RX_BASE);
1313 for (i = 0; i < MAX_DSP_SESS_REC; i++) {
1314 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA,
1315 info->DSPSess.Rec[i]);
1316 }
1317 } else {
1318 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
1319 FT1000_DPRAM_MAG_RX_BASE);
1320 for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
1321 outl(info->DSPSess.MagRec[i],
1322 dev->base_addr + FT1000_REG_MAG_DPDATA);
1323 }
1324 }
1325 spin_unlock_irqrestore(&info->dpram_lock, flags);
1326
1327 // clear ASIC RESET request
1328 ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1329 FT1000_ASIC_RESET_REQ);
1330 DEBUG(1, "Got an ASIC RESET Request\n");
1331 ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1332 FT1000_ASIC_RESET_DSP);
1333
1334 if (info->AsicID == MAGNEMITE_ID) {
1335 // Setting MAGNEMITE ASIC to big endian mode
1336 ft1000_write_reg(dev, FT1000_REG_SUP_CTRL,
1337 HOST_INTF_BE);
1338 }
1339 info->DspAsicReset = 0;
1340 }
1341
1342 if (doorbell & FT1000_DSP_ASIC_RESET) {
1343 DEBUG(0,
1344 "FT1000:ft1000_parse_dpram_msg: Got a dsp ASIC reset message\n");
1345 info->DspAsicReset = 1;
1346 ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1347 FT1000_DSP_ASIC_RESET);
1348 udelay(200);
1349 return SUCCESS;
1350 }
1351
1352 if (doorbell & FT1000_DB_DPRAM_RX) {
1353 DEBUG(1,
1354 "FT1000:ft1000_parse_dpram_msg: Got a slow queue message\n");
1355 nxtph = FT1000_DPRAM_RX_BASE + 2;
1356 if (info->AsicID == ELECTRABUZZ_ID) {
1357 total_len =
1358 ft1000_read_dpram(dev, FT1000_DPRAM_RX_BASE);
1359 } else {
1360 total_len =
1361 ntohs(ft1000_read_dpram_mag_16
1362 (dev, FT1000_MAG_TOTAL_LEN,
1363 FT1000_MAG_TOTAL_LEN_INDX));
1364 }
1365 DEBUG(1, "FT1000:ft1000_parse_dpram_msg:total length = %d\n",
1366 total_len);
1367 if ((total_len < MAX_CMD_SQSIZE) && (total_len > PSEUDOSZ)) {
1368 total_len += nxtph;
1369 cnt = 0;
1370 // ft1000_read_reg will return a value that needs to be byteswap
1371 // in order to get DSP_QID_OFFSET.
1372 if (info->AsicID == ELECTRABUZZ_ID) {
1373 portid =
1374 (ft1000_read_dpram
1375 (dev,
1376 DSP_QID_OFFSET + FT1000_DPRAM_RX_BASE +
1377 2) >> 8) & 0xff;
1378 } else {
1379 portid =
1380 (ft1000_read_dpram_mag_16
1381 (dev, FT1000_MAG_PORT_ID,
1382 FT1000_MAG_PORT_ID_INDX) & 0xff);
1383 }
1384 DEBUG(1, "DSP_QID = 0x%x\n", portid);
1385
1386 if (portid == DRIVERID) {
1387 // We are assumming one driver message from the DSP at a time.
1388 ft1000_proc_drvmsg(dev);
1389 }
1390 }
1391 ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_RX);
1392 }
1393
1394 if (doorbell & FT1000_DB_COND_RESET) {
bf3146c8 1395 // Reset ASIC and DSP
f7c1be0c
MB
1396 if (info->AsicID == ELECTRABUZZ_ID) {
1397 info->DSP_TIME[0] =
1398 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
1399 info->DSP_TIME[1] =
1400 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
1401 info->DSP_TIME[2] =
1402 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
1403 info->DSP_TIME[3] =
1404 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
1405 } else {
1406 info->DSP_TIME[0] =
1407 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
1408 FT1000_MAG_DSP_TIMER0_INDX);
1409 info->DSP_TIME[1] =
1410 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
1411 FT1000_MAG_DSP_TIMER1_INDX);
1412 info->DSP_TIME[2] =
1413 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
1414 FT1000_MAG_DSP_TIMER2_INDX);
1415 info->DSP_TIME[3] =
1416 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
1417 FT1000_MAG_DSP_TIMER3_INDX);
1418 }
1419 info->DrvErrNum = DSP_CONDRESET_INFO;
1420 DEBUG(1, "ft1000_hw:DSP conditional reset requested\n");
1421 ft1000_reset_card(dev);
1422 ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1423 FT1000_DB_COND_RESET);
1424 }
1425 // let's clear any unexpected doorbells from DSP
1426 doorbell =
1427 doorbell & ~(FT1000_DB_DPRAM_RX | FT1000_ASIC_RESET_REQ |
1428 FT1000_DB_COND_RESET | 0xff00);
1429 if (doorbell) {
1430 DEBUG(1, "Clearing unexpected doorbell = 0x%x\n", doorbell);
1431 ft1000_write_reg(dev, FT1000_REG_DOORBELL, doorbell);
1432 }
1433
1434 return SUCCESS;
1435
1436}
1437
1438//---------------------------------------------------------------------------
1439//
1440// Function: ft1000_flush_fifo
1441// Descripton: This function will flush one packet from the downlink
1442// FIFO.
1443// Input:
1444// dev - device structure
1445// drv_err - driver error causing the flush fifo
1446// Output:
1447// None.
1448//
1449//---------------------------------------------------------------------------
1450static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
1451{
1452 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
1453 u16 i;
1454 u32 templong;
1455 u16 tempword;
1456
1457 DEBUG(1, "ft1000:ft1000_hw:ft1000_flush_fifo called\n");
1458 if (info->PktIntfErr > MAX_PH_ERR) {
1459 if (info->AsicID == ELECTRABUZZ_ID) {
1460 info->DSP_TIME[0] =
1461 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
1462 info->DSP_TIME[1] =
1463 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
1464 info->DSP_TIME[2] =
1465 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
1466 info->DSP_TIME[3] =
1467 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
1468 } else {
1469 info->DSP_TIME[0] =
1470 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
1471 FT1000_MAG_DSP_TIMER0_INDX);
1472 info->DSP_TIME[1] =
1473 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
1474 FT1000_MAG_DSP_TIMER1_INDX);
1475 info->DSP_TIME[2] =
1476 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
1477 FT1000_MAG_DSP_TIMER2_INDX);
1478 info->DSP_TIME[3] =
1479 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
1480 FT1000_MAG_DSP_TIMER3_INDX);
1481 }
1482 info->DrvErrNum = DrvErrNum;
1483 ft1000_reset_card(dev);
1484 return;
1485 } else {
1486 // Flush corrupted pkt from FIFO
1487 i = 0;
1488 do {
1489 if (info->AsicID == ELECTRABUZZ_ID) {
1490 tempword =
1491 ft1000_read_reg(dev, FT1000_REG_DFIFO);
1492 tempword =
1493 ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
1494 } else {
1495 templong =
1496 inl(dev->base_addr + FT1000_REG_MAG_DFR);
1497 tempword =
1498 inw(dev->base_addr + FT1000_REG_MAG_DFSR);
1499 }
1500 i++;
1501 // This should never happen unless the ASIC is broken.
1502 // We must reset to recover.
1503 if ((i > 2048) || (tempword == 0)) {
1504 if (info->AsicID == ELECTRABUZZ_ID) {
1505 info->DSP_TIME[0] =
1506 ft1000_read_dpram(dev,
1507 FT1000_DSP_TIMER0);
1508 info->DSP_TIME[1] =
1509 ft1000_read_dpram(dev,
1510 FT1000_DSP_TIMER1);
1511 info->DSP_TIME[2] =
1512 ft1000_read_dpram(dev,
1513 FT1000_DSP_TIMER2);
1514 info->DSP_TIME[3] =
1515 ft1000_read_dpram(dev,
1516 FT1000_DSP_TIMER3);
1517 } else {
1518 info->DSP_TIME[0] =
1519 ft1000_read_dpram_mag_16(dev,
1520 FT1000_MAG_DSP_TIMER0,
1521 FT1000_MAG_DSP_TIMER0_INDX);
1522 info->DSP_TIME[1] =
1523 ft1000_read_dpram_mag_16(dev,
1524 FT1000_MAG_DSP_TIMER1,
1525 FT1000_MAG_DSP_TIMER1_INDX);
1526 info->DSP_TIME[2] =
1527 ft1000_read_dpram_mag_16(dev,
1528 FT1000_MAG_DSP_TIMER2,
1529 FT1000_MAG_DSP_TIMER2_INDX);
1530 info->DSP_TIME[3] =
1531 ft1000_read_dpram_mag_16(dev,
1532 FT1000_MAG_DSP_TIMER3,
1533 FT1000_MAG_DSP_TIMER3_INDX);
1534 }
1535 if (tempword == 0) {
1536 // Let's check if ASIC reads are still ok by reading the Mask register
1537 // which is never zero at this point of the code.
1538 tempword =
1539 inw(dev->base_addr +
1540 FT1000_REG_SUP_IMASK);
1541 if (tempword == 0) {
1542 // This indicates that we can not communicate with the ASIC
1543 info->DrvErrNum =
1544 FIFO_FLUSH_BADCNT;
1545 } else {
1546 // Let's assume that we really flush the FIFO
1547 info->PktIntfErr++;
1548 return;
1549 }
1550 } else {
1551 info->DrvErrNum = FIFO_FLUSH_MAXLIMIT;
1552 }
1553 return;
1554 }
1555 tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
1556 } while ((tempword & 0x03) != 0x03);
1557 if (info->AsicID == ELECTRABUZZ_ID) {
1558 i++;
1559 DEBUG(0, "Flushing FIFO complete = %x\n", tempword);
1560 // Flush last word in FIFO.
1561 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1562 // Update FIFO counter for DSP
1563 i = i * 2;
1564 DEBUG(0, "Flush Data byte count to dsp = %d\n", i);
1565 info->fifo_cnt += i;
1566 ft1000_write_dpram(dev, FT1000_FIFO_LEN,
1567 info->fifo_cnt);
1568 } else {
1569 DEBUG(0, "Flushing FIFO complete = %x\n", tempword);
1570 // Flush last word in FIFO
1571 templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1572 tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
1573 DEBUG(0, "FT1000_REG_SUP_STAT = 0x%x\n", tempword);
1574 tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR);
1575 DEBUG(0, "FT1000_REG_MAG_DFSR = 0x%x\n", tempword);
1576 }
1577 if (DrvErrNum) {
1578 info->PktIntfErr++;
1579 }
1580 }
1581}
1582
1583//---------------------------------------------------------------------------
1584//
1585// Function: ft1000_copy_up_pkt
bf3146c8 1586// Descripton: This function will pull Flarion packets out of the Downlink
f7c1be0c
MB
1587// FIFO and convert it to an ethernet packet. The ethernet packet will
1588// then be deliver to the TCP/IP stack.
1589// Input:
1590// dev - device structure
1591// Output:
bf3146c8
GKH
1592// status - FAILURE
1593// SUCCESS
f7c1be0c
MB
1594//
1595//---------------------------------------------------------------------------
1596int ft1000_copy_up_pkt(struct net_device *dev)
1597{
1598 u16 tempword;
1599 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
1600 u16 len;
1601 struct sk_buff *skb;
1602 u16 i;
1603 u8 *pbuffer = NULL;
1604 u8 *ptemp = NULL;
1605 u16 chksum;
1606 u32 *ptemplong;
1607 u32 templong;
1608
1609 DEBUG(1, "ft1000_copy_up_pkt\n");
1610 // Read length
1611 if (info->AsicID == ELECTRABUZZ_ID) {
1612 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1613 len = tempword;
1614 } else {
1615 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1616 len = ntohs(tempword);
1617 }
1618 chksum = tempword;
1619 DEBUG(1, "Number of Bytes in FIFO = %d\n", len);
1620
1621 if (len > ENET_MAX_SIZE) {
1622 DEBUG(0, "size of ethernet packet invalid\n");
1623 if (info->AsicID == MAGNEMITE_ID) {
1624 // Read High word to complete 32 bit access
1625 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1626 }
1627 ft1000_flush_fifo(dev, DSP_PKTLEN_INFO);
1628 info->stats.rx_errors++;
1629 return FAILURE;
1630 }
1631
1632 skb = dev_alloc_skb(len + 12 + 2);
1633
1634 if (skb == NULL) {
1635 DEBUG(0, "No Network buffers available\n");
1636 // Read High word to complete 32 bit access
1637 if (info->AsicID == MAGNEMITE_ID) {
1638 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1639 }
1640 ft1000_flush_fifo(dev, 0);
1641 info->stats.rx_errors++;
1642 return FAILURE;
1643 }
1644 pbuffer = (u8 *) skb_put(skb, len + 12);
1645
1646 // Pseudo header
1647 if (info->AsicID == ELECTRABUZZ_ID) {
1648 for (i = 1; i < 7; i++) {
1649 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1650 chksum ^= tempword;
1651 }
1652 // read checksum value
1653 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1654 } else {
1655 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1656 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1657 chksum ^= tempword;
1658
1659 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1660 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1661 chksum ^= tempword;
1662
1663 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1664 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1665 chksum ^= tempword;
1666
1667 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1668 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1669 chksum ^= tempword;
1670
1671 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1672 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1673 chksum ^= tempword;
1674
1675 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1676 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1677 chksum ^= tempword;
1678
1679 // read checksum value
1680 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1681 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1682 }
1683
1684 if (chksum != tempword) {
1685 DEBUG(0, "Packet checksum mismatch 0x%x 0x%x\n", chksum,
1686 tempword);
1687 ft1000_flush_fifo(dev, DSP_PKTPHCKSUM_INFO);
1688 info->stats.rx_errors++;
c95aef41 1689 kfree_skb(skb);
f7c1be0c
MB
1690 return FAILURE;
1691 }
1692 //subtract the number of bytes read already
1693 ptemp = pbuffer;
1694
1695 // fake MAC address
1696 *pbuffer++ = dev->dev_addr[0];
1697 *pbuffer++ = dev->dev_addr[1];
1698 *pbuffer++ = dev->dev_addr[2];
1699 *pbuffer++ = dev->dev_addr[3];
1700 *pbuffer++ = dev->dev_addr[4];
1701 *pbuffer++ = dev->dev_addr[5];
1702 *pbuffer++ = 0x00;
1703 *pbuffer++ = 0x07;
1704 *pbuffer++ = 0x35;
1705 *pbuffer++ = 0xff;
1706 *pbuffer++ = 0xff;
1707 *pbuffer++ = 0xfe;
1708
1709 if (info->AsicID == ELECTRABUZZ_ID) {
1710 for (i = 0; i < len / 2; i++) {
1711 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1712 *pbuffer++ = (u8) (tempword >> 8);
1713 *pbuffer++ = (u8) tempword;
1714 if (ft1000_chkcard(dev) == FALSE) {
c95aef41 1715 kfree_skb(skb);
f7c1be0c
MB
1716 return FAILURE;
1717 }
1718 }
1719
1720 // Need to read one more word if odd byte
1721 if (len & 0x0001) {
1722 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1723 *pbuffer++ = (u8) (tempword >> 8);
1724 }
1725 } else {
1726 ptemplong = (u32 *) pbuffer;
1727 for (i = 0; i < len / 4; i++) {
1728 templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1729 DEBUG(1, "Data = 0x%8x\n", templong);
1730 *ptemplong++ = templong;
1731 }
1732
1733 // Need to read one more word if odd align.
1734 if (len & 0x0003) {
1735 templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1736 DEBUG(1, "Data = 0x%8x\n", templong);
1737 *ptemplong++ = templong;
1738 }
1739
1740 }
1741
1742 DEBUG(1, "Data passed to Protocol layer:\n");
1743 for (i = 0; i < len + 12; i++) {
1744 DEBUG(1, "Protocol Data: 0x%x\n ", *ptemp++);
1745 }
1746
1747 skb->dev = dev;
1748 skb->protocol = eth_type_trans(skb, dev);
1749 skb->ip_summed = CHECKSUM_UNNECESSARY;
1750 netif_rx(skb);
1751
1752 info->stats.rx_packets++;
1753 // Add on 12 bytes for MAC address which was removed
1754 info->stats.rx_bytes += (len + 12);
1755
1756 if (info->AsicID == ELECTRABUZZ_ID) {
1757 // track how many bytes have been read from FIFO - round up to 16 bit word
1758 tempword = len + 16;
1759 if (tempword & 0x01)
1760 tempword++;
1761 info->fifo_cnt += tempword;
1762 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_FIFO_LEN);
1763 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, info->fifo_cnt);
1764 }
1765
1766 return SUCCESS;
1767}
1768
1769//---------------------------------------------------------------------------
1770//
1771// Function: ft1000_copy_down_pkt
bf3146c8
GKH
1772// Descripton: This function will take an ethernet packet and convert it to
1773// a Flarion packet prior to sending it to the ASIC Downlink
f7c1be0c
MB
1774// FIFO.
1775// Input:
1776// dev - device structure
1777// packet - address of ethernet packet
1778// len - length of IP packet
1779// Output:
bf3146c8
GKH
1780// status - FAILURE
1781// SUCCESS
f7c1be0c
MB
1782//
1783//---------------------------------------------------------------------------
1784int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
1785{
1786 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
1787 union {
1788 PSEUDO_HDR blk;
1789 u16 buff[sizeof(PSEUDO_HDR) >> 1];
1790 u8 buffc[sizeof(PSEUDO_HDR)];
1791 } pseudo;
1792 int i;
1793 u32 *plong;
1794
1795 DEBUG(1, "ft1000_hw: copy_down_pkt()\n");
1796
bf3146c8 1797 // Check if there is room on the FIFO
f7c1be0c
MB
1798 if (len > ft1000_read_fifo_len(dev)) {
1799 udelay(10);
1800 if (len > ft1000_read_fifo_len(dev)) {
1801 udelay(20);
1802 }
1803 if (len > ft1000_read_fifo_len(dev)) {
1804 udelay(20);
1805 }
1806 if (len > ft1000_read_fifo_len(dev)) {
1807 udelay(20);
1808 }
1809 if (len > ft1000_read_fifo_len(dev)) {
1810 udelay(20);
1811 }
1812 if (len > ft1000_read_fifo_len(dev)) {
1813 udelay(20);
1814 }
1815 if (len > ft1000_read_fifo_len(dev)) {
1816 DEBUG(1,
1817 "ft1000_hw:ft1000_copy_down_pkt:Transmit FIFO is fulli - pkt drop\n");
1818 info->stats.tx_errors++;
1819 return SUCCESS;
1820 }
1821 }
1822 // Create pseudo header and send pseudo/ip to hardware
1823 if (info->AsicID == ELECTRABUZZ_ID) {
1824 pseudo.blk.length = len;
1825 } else {
1826 pseudo.blk.length = ntohs(len);
1827 }
1828 pseudo.blk.source = DSPID; // Need to swap to get in correct order
1829 pseudo.blk.destination = HOSTID;
1830 pseudo.blk.portdest = NETWORKID; // Need to swap to get in correct order
1831 pseudo.blk.portsrc = DSPAIRID;
1832 pseudo.blk.sh_str_id = 0;
1833 pseudo.blk.control = 0;
1834 pseudo.blk.rsvd1 = 0;
1835 pseudo.blk.seq_num = 0;
1836 pseudo.blk.rsvd2 = info->packetseqnum++;
1837 pseudo.blk.qos_class = 0;
1838 /* Calculate pseudo header checksum */
1839 pseudo.blk.checksum = pseudo.buff[0];
1840 for (i = 1; i < 7; i++) {
1841 pseudo.blk.checksum ^= pseudo.buff[i];
1842 }
1843
1844 // Production Mode
1845 if (info->AsicID == ELECTRABUZZ_ID) {
bf3146c8 1846 // copy first word to UFIFO_BEG reg
f7c1be0c
MB
1847 ft1000_write_reg(dev, FT1000_REG_UFIFO_BEG, pseudo.buff[0]);
1848 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 0 BEG = 0x%04x\n",
1849 pseudo.buff[0]);
1850
bf3146c8 1851 // copy subsequent words to UFIFO_MID reg
f7c1be0c
MB
1852 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[1]);
1853 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 1 MID = 0x%04x\n",
1854 pseudo.buff[1]);
1855 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[2]);
1856 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 2 MID = 0x%04x\n",
1857 pseudo.buff[2]);
1858 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[3]);
1859 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 3 MID = 0x%04x\n",
1860 pseudo.buff[3]);
1861 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[4]);
1862 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 4 MID = 0x%04x\n",
1863 pseudo.buff[4]);
1864 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[5]);
1865 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 5 MID = 0x%04x\n",
1866 pseudo.buff[5]);
1867 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[6]);
1868 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 6 MID = 0x%04x\n",
1869 pseudo.buff[6]);
1870 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[7]);
1871 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 7 MID = 0x%04x\n",
1872 pseudo.buff[7]);
1873
1874 // Write PPP type + IP Packet into Downlink FIFO
1875 for (i = 0; i < (len >> 1) - 1; i++) {
1876 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
1877 htons(*packet));
1878 DEBUG(1,
1879 "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1880 i + 8, htons(*packet));
1881 packet++;
1882 }
1883
bf3146c8 1884 // Check for odd byte
f7c1be0c
MB
1885 if (len & 0x0001) {
1886 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
1887 htons(*packet));
1888 DEBUG(1,
1889 "ft1000_hw:ft1000_copy_down_pkt:data MID = 0x%04x\n",
1890 htons(*packet));
1891 packet++;
1892 ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
1893 htons(*packet));
1894 DEBUG(1,
1895 "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1896 i + 8, htons(*packet));
1897 } else {
1898 ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
1899 htons(*packet));
1900 DEBUG(1,
1901 "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1902 i + 8, htons(*packet));
1903 }
1904 } else {
1905 outl(*(u32 *) & pseudo.buff[0],
1906 dev->base_addr + FT1000_REG_MAG_UFDR);
1907 DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1908 *(u32 *) & pseudo.buff[0]);
1909 outl(*(u32 *) & pseudo.buff[2],
1910 dev->base_addr + FT1000_REG_MAG_UFDR);
1911 DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1912 *(u32 *) & pseudo.buff[2]);
1913 outl(*(u32 *) & pseudo.buff[4],
1914 dev->base_addr + FT1000_REG_MAG_UFDR);
1915 DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1916 *(u32 *) & pseudo.buff[4]);
1917 outl(*(u32 *) & pseudo.buff[6],
1918 dev->base_addr + FT1000_REG_MAG_UFDR);
1919 DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1920 *(u32 *) & pseudo.buff[6]);
1921
1922 plong = (u32 *) packet;
1923 // Write PPP type + IP Packet into Downlink FIFO
1924 for (i = 0; i < (len >> 2); i++) {
1925 outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
1926 }
1927
bf3146c8 1928 // Check for odd alignment
f7c1be0c
MB
1929 if (len & 0x0003) {
1930 DEBUG(1,
1931 "ft1000_hw:ft1000_copy_down_pkt:data = 0x%8x\n",
1932 *plong);
1933 outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
1934 }
1935 outl(1, dev->base_addr + FT1000_REG_MAG_UFER);
1936 }
1937
1938 info->stats.tx_packets++;
1939 // Add 14 bytes for MAC adddress plus ethernet type
1940 info->stats.tx_bytes += (len + 14);
1941 return SUCCESS;
1942}
1943
1944static struct net_device_stats *ft1000_stats(struct net_device *dev)
1945{
1946 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
1947 return (&info->stats);
1948}
1949
1950static int ft1000_open(struct net_device *dev)
1951{
1952
1953 DEBUG(0, "ft1000_hw: ft1000_open is called\n");
1954
1955 ft1000_reset_card(dev);
1956 DEBUG(0, "ft1000_hw: ft1000_open is ended\n");
1957
1958 /* schedule ft1000_hbchk to perform periodic heartbeat checks on DSP and ASIC */
1959 init_timer(&poll_timer);
1960 poll_timer.expires = jiffies + (2 * HZ);
1961 poll_timer.data = (u_long) dev;
1962 add_timer(&poll_timer);
1963
1964 DEBUG(0, "ft1000_hw: ft1000_open is ended2\n");
1965 return 0;
1966}
1967
1968static int ft1000_close(struct net_device *dev)
1969{
1970 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
1971
1972 DEBUG(0, "ft1000_hw: ft1000_close()\n");
1973
1974 info->CardReady = 0;
1975 del_timer(&poll_timer);
1976
1977 if (ft1000_card_present == 1) {
1978 DEBUG(0, "Media is down\n");
1979 netif_stop_queue(dev);
1980
1981 ft1000_disable_interrupts(dev);
1982 ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
1983
1984 //reset ASIC
1985 ft1000_reset_asic(dev);
1986 }
1987 return 0;
1988}
1989
1990static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
1991{
1992 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
1993 u8 *pdata;
1994
1995 DEBUG(1, "ft1000_hw: ft1000_start_xmit()\n");
1996 if (skb == NULL) {
1997 DEBUG(1, "ft1000_hw: ft1000_start_xmit:skb == NULL!!!\n");
1998 return 0;
1999 }
2000
2001 DEBUG(1, "ft1000_hw: ft1000_start_xmit:length of packet = %d\n",
2002 skb->len);
2003
2004 pdata = (u8 *) skb->data;
2005
2006 if (info->mediastate == 0) {
2007 /* Drop packet is mediastate is down */
2008 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:mediastate is down\n");
2009 return SUCCESS;
2010 }
2011
2012 if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) {
2013 /* Drop packet which has invalid size */
2014 DEBUG(1,
2015 "ft1000_hw:ft1000_copy_down_pkt:invalid ethernet length\n");
2016 return SUCCESS;
2017 }
2018 ft1000_copy_down_pkt(dev, (u16 *) (pdata + ENET_HEADER_SIZE - 2),
2019 skb->len - ENET_HEADER_SIZE + 2);
2020
2021 dev_kfree_skb(skb);
2022
2023 return 0;
2024}
2025
2026static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
2027{
2028 struct net_device *dev = (struct net_device *)dev_id;
2029 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
2030 u16 tempword;
2031 u16 inttype;
2032 int cnt;
2033
2034 DEBUG(1, "ft1000_hw: ft1000_interrupt()\n");
2035
2036 if (info->CardReady == 0) {
2037 ft1000_disable_interrupts(dev);
2038 return IRQ_HANDLED;
2039 }
2040
2041 if (ft1000_chkcard(dev) == FALSE) {
2042 ft1000_disable_interrupts(dev);
2043 return IRQ_HANDLED;
2044 }
2045
2046 ft1000_disable_interrupts(dev);
2047
2048 // Read interrupt type
2049 inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
2050
2051 // Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type
2052 while (inttype) {
2053 if (inttype & ISR_DOORBELL_PEND) {
2054 ft1000_parse_dpram_msg(dev);
2055 }
2056
2057 if (inttype & ISR_RCV) {
2058 DEBUG(1, "Data in FIFO\n");
2059
2060 cnt = 0;
2061 do {
2062 // Check if we have packets in the Downlink FIFO
2063 if (info->AsicID == ELECTRABUZZ_ID) {
2064 tempword =
2065 ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
2066 } else {
2067 tempword =
2068 ft1000_read_reg(dev, FT1000_REG_MAG_DFSR);
2069 }
2070 if (tempword & 0x1f) {
2071 ft1000_copy_up_pkt(dev);
2072 } else {
2073 break;
2074 }
2075 cnt++;
2076 } while (cnt < MAX_RCV_LOOP);
2077
2078 }
2079 // clear interrupts
2080 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
2081 DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
2082 ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
2083
2084 // Read interrupt type
2085 inttype = ft1000_read_reg (dev, FT1000_REG_SUP_ISR);
2086 DEBUG(1,"ft1000_hw: interrupt status register after clear = 0x%x\n",inttype);
2087 }
2088 ft1000_enable_interrupts(dev);
2089 return IRQ_HANDLED;
2090}
2091
2092void stop_ft1000_card(struct net_device *dev)
2093{
2094 FT1000_INFO *info = (FT1000_INFO *) netdev_priv(dev);
2095 PPROV_RECORD ptr;
2096// int cnt;
2097
2098 DEBUG(0, "ft1000_hw: stop_ft1000_card()\n");
2099
2100 info->CardReady = 0;
2101 ft1000_card_present = 0;
2102 netif_stop_queue(dev);
2103 ft1000_disable_interrupts(dev);
2104
2105 // Make sure we free any memory reserve for provisioning
2106 while (list_empty(&info->prov_list) == 0) {
2107 ptr = list_entry(info->prov_list.next, PROV_RECORD, list);
2108 list_del(&ptr->list);
2109 kfree(ptr->pprov_data);
2110 kfree(ptr);
2111 }
2112
2113 if (info->registered) {
2114 unregister_netdev(dev);
2115 info->registered = 0;
2116 }
2117
2118 free_irq(dev->irq, dev);
2119 release_region(dev->base_addr,256);
2120 release_firmware(fw_entry);
2121 flarion_ft1000_cnt--;
2122 ft1000CleanupProc(dev);
2123
2124}
2125
2126static void ft1000_get_drvinfo(struct net_device *dev,
2127 struct ethtool_drvinfo *info)
2128{
2129 FT1000_INFO *ft_info;
2130 ft_info = (FT1000_INFO *) netdev_priv(dev);
2131
2132 snprintf(info->driver, 32, "ft1000");
2133 snprintf(info->bus_info, ETHTOOL_BUSINFO_LEN, "PCMCIA 0x%lx",
2134 dev->base_addr);
2135 snprintf(info->fw_version, 32, "%d.%d.%d.%d", ft_info->DspVer[0],
2136 ft_info->DspVer[1], ft_info->DspVer[2], ft_info->DspVer[3]);
2137}
2138
2139static u32 ft1000_get_link(struct net_device *dev)
2140{
2141 FT1000_INFO *info;
2142 info = (FT1000_INFO *) netdev_priv(dev);
2143 return info->mediastate;
2144}
2145
2146static const struct ethtool_ops ops = {
2147 .get_drvinfo = ft1000_get_drvinfo,
2148 .get_link = ft1000_get_link
2149};
2150
2151struct net_device *init_ft1000_card(unsigned short irq, int port,
2152 unsigned char *mac_addr, void *ft1000_reset,
2153 void *link, struct device *fdev)
2154{
2155 FT1000_INFO *info;
2156 struct net_device *dev;
2157 int i;
2158
2159 static const struct net_device_ops ft1000ops = // Slavius 21.10.2009 due to kernel changes
2160 {
2161 .ndo_open = &ft1000_open,
2162 .ndo_stop = &ft1000_close,
2163 .ndo_start_xmit = &ft1000_start_xmit,
2164 .ndo_get_stats = &ft1000_stats,
2165 };
2166
2167 DEBUG(1, "ft1000_hw: init_ft1000_card()\n");
2168 DEBUG(1, "ft1000_hw: irq = %d\n", irq);
2169 DEBUG(1, "ft1000_hw: port = 0x%04x\n", port);
2170
2171 flarion_ft1000_cnt++;
2172
2173 if (flarion_ft1000_cnt > 1) {
2174 flarion_ft1000_cnt--;
2175
2176 printk(KERN_INFO
2177 "ft1000: This driver can not support more than one instance\n");
2178 return NULL;
2179 }
2180
2181 dev = alloc_etherdev(sizeof(FT1000_INFO));
2182 if (!dev) {
2183 printk(KERN_ERR "ft1000: failed to allocate etherdev\n");
2184 return NULL;
2185 }
2186
2187 SET_NETDEV_DEV(dev, fdev);
2188 info = (FT1000_INFO *) netdev_priv(dev);
2189
2190 memset(info, 0, sizeof(FT1000_INFO));
2191
2192 DEBUG(1, "address of dev = 0x%8x\n", (u32) dev);
2193 DEBUG(1, "address of dev info = 0x%8x\n", (u32) info);
2194 DEBUG(0, "device name = %s\n", dev->name);
2195
2196 memset(&info->stats, 0, sizeof(struct net_device_stats));
2197
2198 spin_lock_init(&info->dpram_lock);
2199 info->DrvErrNum = 0;
2200 info->ASICResetNum = 0;
2201 info->registered = 1;
2202 info->link = link;
2203 info->ft1000_reset = ft1000_reset;
2204 info->mediastate = 0;
2205 info->fifo_cnt = 0;
2206 info->DeviceCreated = FALSE;
2207 info->DeviceMajor = 0;
2208 info->CurrentInterruptEnableMask = ISR_DEFAULT_MASK;
2209 info->InterruptsEnabled = FALSE;
2210 info->CardReady = 0;
2211 info->DSP_TIME[0] = 0;
2212 info->DSP_TIME[1] = 0;
2213 info->DSP_TIME[2] = 0;
2214 info->DSP_TIME[3] = 0;
2215 flarion_ft1000_cnt = 0;
2216
2217 INIT_LIST_HEAD(&info->prov_list);
2218
2219 info->squeseqnum = 0;
2220
2221// dev->hard_start_xmit = &ft1000_start_xmit;
2222// dev->get_stats = &ft1000_stats;
2223// dev->open = &ft1000_open;
2224// dev->stop = &ft1000_close;
2225
2226 dev->netdev_ops = &ft1000ops; // Slavius 21.10.2009 due to kernel changes
2227
2228 DEBUG(0, "device name = %s\n", dev->name);
2229
2230 for (i = 0; i < 6; i++) {
2231 dev->dev_addr[i] = mac_addr[i];
2232 DEBUG(1, "ft1000_hw: mac_addr %d = 0x%02x\n", i, mac_addr[i]);
2233 }
2234
2235 netif_stop_queue(dev);
2236 dev->irq = irq;
2237 dev->base_addr = port;
2238
2239 if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name, dev)) {
2240 printk(KERN_ERR "ft1000: Could not request_irq\n");
c95aef41 2241 goto err_dev;
f7c1be0c
MB
2242 }
2243
c95aef41
VK
2244 if (request_region(dev->base_addr, 256, dev->name) == NULL) {
2245 printk(KERN_ERR "ft1000: Could not request_region\n");
2246 goto err_irq;
2247 }
f7c1be0c
MB
2248
2249 if (register_netdev(dev) != 0) {
2250 DEBUG(0, "ft1000: Could not register netdev");
c95aef41 2251 goto err_reg;
f7c1be0c
MB
2252 }
2253
2254 info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
2255 if (info->AsicID == ELECTRABUZZ_ID) {
2256 DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n");
2257 if (request_firmware(&fw_entry, "ft1000.img", fdev) != 0) {
2258 printk(KERN_INFO "ft1000: Could not open ft1000.img\n");
c95aef41 2259 goto err_unreg;
f7c1be0c
MB
2260 }
2261 } else {
2262 DEBUG(0, "ft1000_hw: MAGNEMITE ASIC\n");
2263 if (request_firmware(&fw_entry, "ft2000.img", fdev) != 0) {
2264 printk(KERN_INFO "ft1000: Could not open ft2000.img\n");
c95aef41 2265 goto err_unreg;
f7c1be0c
MB
2266 }
2267 }
2268
2269 ft1000_enable_interrupts(dev);
2270
2271 ft1000InitProc(dev);
2272 ft1000_card_present = 1;
2273 SET_ETHTOOL_OPS(dev, &ops);
2274 printk(KERN_INFO
2275 "ft1000: %s: addr 0x%04lx irq %d, MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n",
2276 dev->name, dev->base_addr, dev->irq, dev->dev_addr[0],
2277 dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3],
2278 dev->dev_addr[4], dev->dev_addr[5]);
2279 return dev;
c95aef41
VK
2280
2281err_unreg:
2282 unregister_netdev(dev);
2283err_reg:
2284 release_region(dev->base_addr, 256);
2285err_irq:
2286 free_irq(dev->irq, dev);
2287err_dev:
2288 free_netdev(dev);
2289 return NULL;
f7c1be0c
MB
2290}
2291
2292EXPORT_SYMBOL(init_ft1000_card);
2293EXPORT_SYMBOL(stop_ft1000_card);
2294EXPORT_SYMBOL(flarion_ft1000_cnt);