blob: 86a680c09ba2a7e2bf62276d1f85e3415c0827c6 [file] [log] [blame]
Marek Beliskof7c1be02010-09-22 07:56:27 +02001/*---------------------------------------------------------------------------
2 FT1000 driver for Flarion Flash OFDM NIC Device
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07003
Marek Beliskof7c1be02010-09-22 07:56:27 +02004 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.
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07007
8 This program is free software; you can redistribute it and/or modify it
Marek Beliskof7c1be02010-09-22 07:56:27 +02009 under the terms of the GNU General Public License as published by the Free
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -070010 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.
Marek Beliskof7c1be02010-09-22 07:56:27 +020018-----------------------------------------------------------------------------*/
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>
Marek Beliskof7c1be02010-09-22 07:56:27 +020032#include <asm/bitops.h>
33
34#include <linux/netdevice.h>
35#include <linux/etherdevice.h>
36#include <linux/skbuff.h>
37#include <linux/if_arp.h>
38#include <linux/ioport.h>
39#include <linux/wait.h>
40#include <linux/vmalloc.h>
41
42#include <linux/firmware.h>
43#include <linux/ethtool.h>
44
Marek Beliskoc331e762011-01-10 13:14:28 +010045#include <pcmcia/cistpl.h>
46#include <pcmcia/cisreg.h>
47#include <pcmcia/ds.h>
48
Marek Beliskof7c1be02010-09-22 07:56:27 +020049#ifdef FT_DEBUG
50#define DEBUG(n, args...) printk(KERN_DEBUG args);
51#else
52#define DEBUG(n, args...)
53#endif
54
55#include <linux/delay.h>
Marek Beliskof7c1be02010-09-22 07:56:27 +020056#include "ft1000.h"
57
Randy Dunlapeb93ca42011-08-08 11:31:48 -070058static const struct firmware *fw_entry;
Marek Beliskof7c1be02010-09-22 07:56:27 +020059
60static void ft1000_hbchk(u_long data);
61static struct timer_list poll_timer = {
Randy Dunlapeb93ca42011-08-08 11:31:48 -070062 .function = ft1000_hbchk
Marek Beliskof7c1be02010-09-22 07:56:27 +020063};
64
65static u16 cmdbuffer[1024];
66static u8 tempbuffer[1600];
67static u8 ft1000_card_present = 0;
68static u8 flarion_ft1000_cnt = 0;
69
70static irqreturn_t ft1000_interrupt(int irq, void *dev_id);
71static void ft1000_enable_interrupts(struct net_device *dev);
72static void ft1000_disable_interrupts(struct net_device *dev);
73
74/* new kernel */
75MODULE_AUTHOR("");
76MODULE_DESCRIPTION
77 ("Support for Flarion Flash OFDM NIC Device. Support for PCMCIA when used with ft1000_cs.");
78MODULE_LICENSE("GPL");
79MODULE_SUPPORTED_DEVICE("FT1000");
80
81#define MAX_RCV_LOOP 100
82
83//---------------------------------------------------------------------------
84//
Marek Beliskof7c1be02010-09-22 07:56:27 +020085// Function: ft1000_read_fifo_len
Lucas De Marchi25985ed2011-03-30 22:57:33 -030086// Description: This function will read the ASIC Uplink FIFO status register
Marek Beliskof7c1be02010-09-22 07:56:27 +020087// which will return the number of bytes remaining in the Uplink FIFO.
88// Sixteen bytes are subtracted to make sure that the ASIC does not
89// reach its threshold.
90// Input:
91// dev - network device structure
92// Output:
93// value - number of bytes available in the ASIC Uplink FIFO.
94//
95//---------------------------------------------------------------------------
96static inline u16 ft1000_read_fifo_len(struct net_device *dev)
97{
Ondrej Zaryd3706552011-07-01 00:03:42 +020098 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +020099
Devendra Nagab3a87c32012-07-07 17:35:16 +0530100 if (info->AsicID == ELECTRABUZZ_ID)
Marek Beliskof7c1be02010-09-22 07:56:27 +0200101 return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16);
Devendra Nagab3a87c32012-07-07 17:35:16 +0530102 else
Marek Beliskof7c1be02010-09-22 07:56:27 +0200103 return (ft1000_read_reg(dev, FT1000_REG_MAG_UFSR) - 16);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200104}
105
106//---------------------------------------------------------------------------
107//
108// Function: ft1000_read_dpram
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300109// Description: This function will read the specific area of dpram
Marek Beliskof7c1be02010-09-22 07:56:27 +0200110// (Electrabuzz ASIC only)
111// Input:
112// dev - device structure
113// offset - index of dpram
114// Output:
115// value - value of dpram
116//
117//---------------------------------------------------------------------------
Devendra Nagacfe116c2012-07-07 17:35:17 +0530118u16 ft1000_read_dpram(struct net_device *dev, int offset)
Marek Beliskof7c1be02010-09-22 07:56:27 +0200119{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200120 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200121 unsigned long flags;
122 u16 data;
123
124 // Provide mutual exclusive access while reading ASIC registers.
125 spin_lock_irqsave(&info->dpram_lock, flags);
126 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
127 data = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
128 spin_unlock_irqrestore(&info->dpram_lock, flags);
129
130 return (data);
131}
132
133//---------------------------------------------------------------------------
134//
135// Function: ft1000_write_dpram
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300136// Description: This function will write to a specific area of dpram
Marek Beliskof7c1be02010-09-22 07:56:27 +0200137// (Electrabuzz ASIC only)
138// Input:
139// dev - device structure
140// offset - index of dpram
141// value - value to write
142// Output:
143// none.
144//
145//---------------------------------------------------------------------------
146static inline void ft1000_write_dpram(struct net_device *dev,
147 int offset, u16 value)
148{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200149 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200150 unsigned long flags;
151
152 // Provide mutual exclusive access while reading ASIC registers.
153 spin_lock_irqsave(&info->dpram_lock, flags);
154 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
155 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, value);
156 spin_unlock_irqrestore(&info->dpram_lock, flags);
157}
158
159//---------------------------------------------------------------------------
160//
161// Function: ft1000_read_dpram_mag_16
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300162// Description: This function will read the specific area of dpram
Marek Beliskof7c1be02010-09-22 07:56:27 +0200163// (Magnemite ASIC only)
164// Input:
165// dev - device structure
166// offset - index of dpram
167// Output:
168// value - value of dpram
169//
170//---------------------------------------------------------------------------
171u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
172{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200173 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200174 unsigned long flags;
175 u16 data;
176
177 // Provide mutual exclusive access while reading ASIC registers.
178 spin_lock_irqsave(&info->dpram_lock, flags);
179 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
180 // check if we want to read upper or lower 32-bit word
181 if (Index) {
182 data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL);
183 } else {
184 data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAH);
185 }
186 spin_unlock_irqrestore(&info->dpram_lock, flags);
187
188 return (data);
189}
190
191//---------------------------------------------------------------------------
192//
193// Function: ft1000_write_dpram_mag_16
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300194// Description: This function will write to a specific area of dpram
Marek Beliskof7c1be02010-09-22 07:56:27 +0200195// (Magnemite ASIC only)
196// Input:
197// dev - device structure
198// offset - index of dpram
199// value - value to write
200// Output:
201// none.
202//
203//---------------------------------------------------------------------------
204static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
205 int offset, u16 value, int Index)
206{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200207 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200208 unsigned long flags;
209
210 // Provide mutual exclusive access while reading ASIC registers.
211 spin_lock_irqsave(&info->dpram_lock, flags);
212 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
213 if (Index) {
214 ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value);
215 } else {
216 ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value);
217 }
218 spin_unlock_irqrestore(&info->dpram_lock, flags);
219}
220
221//---------------------------------------------------------------------------
222//
223// Function: ft1000_read_dpram_mag_32
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300224// Description: This function will read the specific area of dpram
Marek Beliskof7c1be02010-09-22 07:56:27 +0200225// (Magnemite ASIC only)
226// Input:
227// dev - device structure
228// offset - index of dpram
229// Output:
230// value - value of dpram
231//
232//---------------------------------------------------------------------------
233u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
234{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200235 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200236 unsigned long flags;
237 u32 data;
238
239 // Provide mutual exclusive access while reading ASIC registers.
240 spin_lock_irqsave(&info->dpram_lock, flags);
241 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
242 data = inl(dev->base_addr + FT1000_REG_MAG_DPDATAL);
243 spin_unlock_irqrestore(&info->dpram_lock, flags);
244
245 return (data);
246}
247
248//---------------------------------------------------------------------------
249//
250// Function: ft1000_write_dpram_mag_32
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300251// Description: This function will write to a specific area of dpram
Marek Beliskof7c1be02010-09-22 07:56:27 +0200252// (Magnemite ASIC only)
253// Input:
254// dev - device structure
255// offset - index of dpram
256// value - value to write
257// Output:
258// none.
259//
260//---------------------------------------------------------------------------
261void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
262{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200263 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200264 unsigned long flags;
265
266 // Provide mutual exclusive access while reading ASIC registers.
267 spin_lock_irqsave(&info->dpram_lock, flags);
268 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset);
269 outl(value, dev->base_addr + FT1000_REG_MAG_DPDATAL);
270 spin_unlock_irqrestore(&info->dpram_lock, flags);
271}
272
273//---------------------------------------------------------------------------
274//
275// Function: ft1000_enable_interrupts
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300276// Description: This function will enable interrupts base on the current interrupt mask.
Marek Beliskof7c1be02010-09-22 07:56:27 +0200277// Input:
278// dev - device structure
279// Output:
280// None.
281//
282//---------------------------------------------------------------------------
283static void ft1000_enable_interrupts(struct net_device *dev)
284{
Marek Beliskof7c1be02010-09-22 07:56:27 +0200285 u16 tempword;
286
287 DEBUG(1, "ft1000_hw:ft1000_enable_interrupts()\n");
Ondrej Zarycefe8ad2011-07-01 00:03:46 +0200288 ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_DEFAULT_MASK);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200289 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
290 DEBUG(1,
291 "ft1000_hw:ft1000_enable_interrupts:current interrupt enable mask = 0x%x\n",
292 tempword);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200293}
294
295//---------------------------------------------------------------------------
296//
297// Function: ft1000_disable_interrupts
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300298// Description: This function will disable all interrupts.
Marek Beliskof7c1be02010-09-22 07:56:27 +0200299// Input:
300// dev - device structure
301// Output:
302// None.
303//
304//---------------------------------------------------------------------------
305static void ft1000_disable_interrupts(struct net_device *dev)
306{
Marek Beliskof7c1be02010-09-22 07:56:27 +0200307 u16 tempword;
308
309 DEBUG(1, "ft1000_hw: ft1000_disable_interrupts()\n");
310 ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_MASK_ALL);
311 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
312 DEBUG(1,
313 "ft1000_hw:ft1000_disable_interrupts:current interrupt enable mask = 0x%x\n",
314 tempword);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200315}
316
317//---------------------------------------------------------------------------
318//
319// Function: ft1000_reset_asic
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300320// Description: This function will call the Card Service function to reset the
Marek Beliskof7c1be02010-09-22 07:56:27 +0200321// ASIC.
322// Input:
323// dev - device structure
324// Output:
325// none
326//
327//---------------------------------------------------------------------------
328static void ft1000_reset_asic(struct net_device *dev)
329{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200330 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200331 u16 tempword;
332
333 DEBUG(1, "ft1000_hw:ft1000_reset_asic called\n");
334
335 (*info->ft1000_reset) (info->link);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200336
337 // Let's use the register provided by the Magnemite ASIC to reset the
338 // ASIC and DSP.
339 if (info->AsicID == MAGNEMITE_ID) {
340 ft1000_write_reg(dev, FT1000_REG_RESET,
341 (DSP_RESET_BIT | ASIC_RESET_BIT));
342 }
343 mdelay(1);
344 if (info->AsicID == ELECTRABUZZ_ID) {
Justin P. Mattock42b2aa82011-11-28 20:31:00 -0800345 // set watermark to -1 in order to not generate an interrupt
Marek Beliskof7c1be02010-09-22 07:56:27 +0200346 ft1000_write_reg(dev, FT1000_REG_WATERMARK, 0xffff);
347 } else {
Justin P. Mattock42b2aa82011-11-28 20:31:00 -0800348 // set watermark to -1 in order to not generate an interrupt
Marek Beliskof7c1be02010-09-22 07:56:27 +0200349 ft1000_write_reg(dev, FT1000_REG_MAG_WATERMARK, 0xffff);
350 }
351 // clear interrupts
352 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
353 DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
354 ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
355 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
356 DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
357
358}
359
360//---------------------------------------------------------------------------
361//
362// Function: ft1000_reset_card
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300363// Description: This function will reset the card
Marek Beliskof7c1be02010-09-22 07:56:27 +0200364// Input:
365// dev - device structure
366// Output:
Ondrej Zaryca145272011-07-01 00:03:47 +0200367// status - false (card reset fail)
368// true (card reset successful)
Marek Beliskof7c1be02010-09-22 07:56:27 +0200369//
370//---------------------------------------------------------------------------
371static int ft1000_reset_card(struct net_device *dev)
372{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200373 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200374 u16 tempword;
375 int i;
376 unsigned long flags;
Ondrej Zary3aaf8072011-07-01 00:03:41 +0200377 struct prov_record *ptr;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200378
379 DEBUG(1, "ft1000_hw:ft1000_reset_card called.....\n");
380
381 info->CardReady = 0;
382 info->ProgConStat = 0;
383 info->squeseqnum = 0;
384 ft1000_disable_interrupts(dev);
385
386// del_timer(&poll_timer);
387
388 // Make sure we free any memory reserve for provisioning
389 while (list_empty(&info->prov_list) == 0) {
390 DEBUG(0,
391 "ft1000_hw:ft1000_reset_card:deleting provisioning record\n");
Ondrej Zary3aaf8072011-07-01 00:03:41 +0200392 ptr = list_entry(info->prov_list.next, struct prov_record, list);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200393 list_del(&ptr->list);
394 kfree(ptr->pprov_data);
395 kfree(ptr);
396 }
397
398 if (info->AsicID == ELECTRABUZZ_ID) {
399 DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting DSP\n");
400 ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
401 } else {
402 DEBUG(1,
403 "ft1000_hw:ft1000_reset_card:resetting ASIC and DSP\n");
404 ft1000_write_reg(dev, FT1000_REG_RESET,
405 (DSP_RESET_BIT | ASIC_RESET_BIT));
406 }
407
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -0700408 // Copy DSP session record into info block if this is not a coldstart
Marek Beliskof7c1be02010-09-22 07:56:27 +0200409 if (ft1000_card_present == 1) {
410 spin_lock_irqsave(&info->dpram_lock, flags);
411 if (info->AsicID == ELECTRABUZZ_ID) {
Ondrej Zarycefe8ad2011-07-01 00:03:46 +0200412 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
413 FT1000_DPRAM_RX_BASE);
414 for (i = 0; i < MAX_DSP_SESS_REC; i++) {
415 info->DSPSess.Rec[i] =
416 ft1000_read_reg(dev,
417 FT1000_REG_DPRAM_DATA);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200418 }
419 } else {
420 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
421 FT1000_DPRAM_MAG_RX_BASE);
422 for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
423 info->DSPSess.MagRec[i] =
424 inl(dev->base_addr + FT1000_REG_MAG_DPDATA);
425 }
426 }
427 spin_unlock_irqrestore(&info->dpram_lock, flags);
428 }
429
430 DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting ASIC\n");
431 mdelay(10);
432 //reset ASIC
433 ft1000_reset_asic(dev);
434
Marek Beliskof7c1be02010-09-22 07:56:27 +0200435 DEBUG(1, "ft1000_hw:ft1000_reset_card:downloading dsp image\n");
436
437 if (info->AsicID == MAGNEMITE_ID) {
438 // Put dsp in reset and take ASIC out of reset
439 DEBUG(0,
440 "ft1000_hw:ft1000_reset_card:Put DSP in reset and take ASIC out of reset\n");
441 ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
442
443 // Setting MAGNEMITE ASIC to big endian mode
444 ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, HOST_INTF_BE);
445 // Download bootloader
446 card_bootload(dev);
447
448 // Take DSP out of reset
449 ft1000_write_reg(dev, FT1000_REG_RESET, 0);
450 // FLARION_DSP_ACTIVE;
451 mdelay(10);
452 DEBUG(0, "ft1000_hw:ft1000_reset_card:Take DSP out of reset\n");
453
454 // Wait for 0xfefe indicating dsp ready before starting download
455 for (i = 0; i < 50; i++) {
456 tempword =
457 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE,
458 FT1000_MAG_DPRAM_FEFE_INDX);
459 if (tempword == 0xfefe) {
460 break;
461 }
462 mdelay(20);
463 }
464
465 if (i == 50) {
466 DEBUG(0,
467 "ft1000_hw:ft1000_reset_card:No FEFE detected from DSP\n");
Ondrej Zaryca145272011-07-01 00:03:47 +0200468 return false;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200469 }
470
471 } else {
472 // Take DSP out of reset
473 ft1000_write_reg(dev, FT1000_REG_RESET, ~DSP_RESET_BIT);
474 mdelay(10);
475 }
476
477 if (card_download(dev, fw_entry->data, fw_entry->size)) {
478 DEBUG(1, "card download unsuccessful\n");
Ondrej Zaryca145272011-07-01 00:03:47 +0200479 return false;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200480 } else {
481 DEBUG(1, "card download successful\n");
482 }
483
484 mdelay(10);
485
486 if (info->AsicID == ELECTRABUZZ_ID) {
487 // Need to initialize the FIFO length counter to zero in order to sync up
488 // with the DSP
489 info->fifo_cnt = 0;
490 ft1000_write_dpram(dev, FT1000_FIFO_LEN, info->fifo_cnt);
491 // Initialize DSP heartbeat area to ho
492 ft1000_write_dpram(dev, FT1000_HI_HO, ho);
493 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
494 DEBUG(1, "ft1000_hw:ft1000_reset_asic:hi_ho value = 0x%x\n",
495 tempword);
496 } else {
497 // Initialize DSP heartbeat area to ho
498 ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, ho_mag,
499 FT1000_MAG_HI_HO_INDX);
500 tempword =
501 ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO,
502 FT1000_MAG_HI_HO_INDX);
503 DEBUG(1, "ft1000_hw:ft1000_reset_card:hi_ho value = 0x%x\n",
504 tempword);
505 }
506
507 info->CardReady = 1;
508 ft1000_enable_interrupts(dev);
509
510 /* Schedule heartbeat process to run every 2 seconds */
511// poll_timer.expires = jiffies + (2*HZ);
512// poll_timer.data = (u_long)dev;
513// add_timer(&poll_timer);
514
Ondrej Zaryca145272011-07-01 00:03:47 +0200515 return true;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200516
517}
518
519//---------------------------------------------------------------------------
520//
521// Function: ft1000_chkcard
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300522// Description: This function will check if the device is presently available on
Marek Beliskof7c1be02010-09-22 07:56:27 +0200523// the system.
524// Input:
525// dev - device structure
526// Output:
Ondrej Zaryca145272011-07-01 00:03:47 +0200527// status - false (device is not present)
528// true (device is present)
Marek Beliskof7c1be02010-09-22 07:56:27 +0200529//
530//---------------------------------------------------------------------------
531static int ft1000_chkcard(struct net_device *dev)
532{
533 u16 tempword;
534
535 // Mask register is used to check for device presence since it is never
536 // set to zero.
537 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
538 if (tempword == 0) {
539 DEBUG(1,
540 "ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n");
Ondrej Zaryca145272011-07-01 00:03:47 +0200541 return false;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200542 }
543 // The system will return the value of 0xffff for the version register
544 // if the device is not present.
545 tempword = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
546 if (tempword == 0xffff) {
547 DEBUG(1,
548 "ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n");
Ondrej Zaryca145272011-07-01 00:03:47 +0200549 return false;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200550 }
Ondrej Zaryca145272011-07-01 00:03:47 +0200551 return true;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200552}
553
554
555//---------------------------------------------------------------------------
556//
557// Function: ft1000_hbchk
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300558// Description: This function will perform the heart beat check of the DSP as
Marek Beliskof7c1be02010-09-22 07:56:27 +0200559// well as the ASIC.
560// Input:
561// dev - device structure
562// Output:
563// none
564//
565//---------------------------------------------------------------------------
566static void ft1000_hbchk(u_long data)
567{
568 struct net_device *dev = (struct net_device *)data;
569
Ondrej Zaryd3706552011-07-01 00:03:42 +0200570 struct ft1000_info *info;
Ondrej Zaryca145272011-07-01 00:03:47 +0200571 u16 tempword;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200572
Joe Perchese33196e2010-11-15 13:12:32 -0800573 info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200574
575 if (info->CardReady == 1) {
576 // Perform dsp heartbeat check
577 if (info->AsicID == ELECTRABUZZ_ID) {
578 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
579 } else {
580 tempword =
581 ntohs(ft1000_read_dpram_mag_16
582 (dev, FT1000_MAG_HI_HO,
583 FT1000_MAG_HI_HO_INDX));
584 }
585 DEBUG(1, "ft1000_hw:ft1000_hbchk:hi_ho value = 0x%x\n",
586 tempword);
587 // Let's perform another check if ho is not detected
588 if (tempword != ho) {
589 if (info->AsicID == ELECTRABUZZ_ID) {
590 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
591 }
592 else {
593 tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX));
594 }
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -0700595 }
Marek Beliskof7c1be02010-09-22 07:56:27 +0200596 if (tempword != ho) {
597 printk(KERN_INFO
598 "ft1000: heartbeat failed - no ho detected\n");
599 if (info->AsicID == ELECTRABUZZ_ID) {
600 info->DSP_TIME[0] =
601 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
602 info->DSP_TIME[1] =
603 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
604 info->DSP_TIME[2] =
605 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
606 info->DSP_TIME[3] =
607 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
608 } else {
609 info->DSP_TIME[0] =
610 ft1000_read_dpram_mag_16(dev,
611 FT1000_MAG_DSP_TIMER0,
612 FT1000_MAG_DSP_TIMER0_INDX);
613 info->DSP_TIME[1] =
614 ft1000_read_dpram_mag_16(dev,
615 FT1000_MAG_DSP_TIMER1,
616 FT1000_MAG_DSP_TIMER1_INDX);
617 info->DSP_TIME[2] =
618 ft1000_read_dpram_mag_16(dev,
619 FT1000_MAG_DSP_TIMER2,
620 FT1000_MAG_DSP_TIMER2_INDX);
621 info->DSP_TIME[3] =
622 ft1000_read_dpram_mag_16(dev,
623 FT1000_MAG_DSP_TIMER3,
624 FT1000_MAG_DSP_TIMER3_INDX);
625 }
626 info->DrvErrNum = DSP_HB_INFO;
627 if (ft1000_reset_card(dev) == 0) {
628 printk(KERN_INFO
629 "ft1000: Hardware Failure Detected - PC Card disabled\n");
630 info->ProgConStat = 0xff;
631 return;
632 }
633 /* Schedule this module to run every 2 seconds */
634 poll_timer.expires = jiffies + (2*HZ);
635 poll_timer.data = (u_long)dev;
636 add_timer(&poll_timer);
637 return;
638 }
639
640 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
641 // Let's check doorbell again if fail
642 if (tempword & FT1000_DB_HB) {
643 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -0700644 }
Marek Beliskof7c1be02010-09-22 07:56:27 +0200645 if (tempword & FT1000_DB_HB) {
646 printk(KERN_INFO
647 "ft1000: heartbeat doorbell not clear by firmware\n");
648 if (info->AsicID == ELECTRABUZZ_ID) {
649 info->DSP_TIME[0] =
650 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
651 info->DSP_TIME[1] =
652 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
653 info->DSP_TIME[2] =
654 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
655 info->DSP_TIME[3] =
656 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
657 } else {
658 info->DSP_TIME[0] =
659 ft1000_read_dpram_mag_16(dev,
660 FT1000_MAG_DSP_TIMER0,
661 FT1000_MAG_DSP_TIMER0_INDX);
662 info->DSP_TIME[1] =
663 ft1000_read_dpram_mag_16(dev,
664 FT1000_MAG_DSP_TIMER1,
665 FT1000_MAG_DSP_TIMER1_INDX);
666 info->DSP_TIME[2] =
667 ft1000_read_dpram_mag_16(dev,
668 FT1000_MAG_DSP_TIMER2,
669 FT1000_MAG_DSP_TIMER2_INDX);
670 info->DSP_TIME[3] =
671 ft1000_read_dpram_mag_16(dev,
672 FT1000_MAG_DSP_TIMER3,
673 FT1000_MAG_DSP_TIMER3_INDX);
674 }
675 info->DrvErrNum = DSP_HB_INFO;
676 if (ft1000_reset_card(dev) == 0) {
677 printk(KERN_INFO
678 "ft1000: Hardware Failure Detected - PC Card disabled\n");
679 info->ProgConStat = 0xff;
680 return;
681 }
682 /* Schedule this module to run every 2 seconds */
683 poll_timer.expires = jiffies + (2*HZ);
684 poll_timer.data = (u_long)dev;
685 add_timer(&poll_timer);
686 return;
687 }
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -0700688 // Set dedicated area to hi and ring appropriate doorbell according
Marek Beliskof7c1be02010-09-22 07:56:27 +0200689 // to hi/ho heartbeat protocol
690 if (info->AsicID == ELECTRABUZZ_ID) {
691 ft1000_write_dpram(dev, FT1000_HI_HO, hi);
692 } else {
693 ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag,
694 FT1000_MAG_HI_HO_INDX);
695 }
696
697 if (info->AsicID == ELECTRABUZZ_ID) {
698 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
699 } else {
700 tempword =
701 ntohs(ft1000_read_dpram_mag_16
702 (dev, FT1000_MAG_HI_HO,
703 FT1000_MAG_HI_HO_INDX));
704 }
705 // Let's write hi again if fail
706 if (tempword != hi) {
707 if (info->AsicID == ELECTRABUZZ_ID) {
708 ft1000_write_dpram(dev, FT1000_HI_HO, hi);
709 }
710 else {
711 ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX);
712 }
713
714 if (info->AsicID == ELECTRABUZZ_ID) {
715 tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
716 }
717 else {
718 tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX));
719 }
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -0700720
Marek Beliskof7c1be02010-09-22 07:56:27 +0200721 }
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -0700722
Marek Beliskof7c1be02010-09-22 07:56:27 +0200723 if (tempword != hi) {
724 printk(KERN_INFO
725 "ft1000: heartbeat failed - cannot write hi into DPRAM\n");
726 if (info->AsicID == ELECTRABUZZ_ID) {
727 info->DSP_TIME[0] =
728 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
729 info->DSP_TIME[1] =
730 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
731 info->DSP_TIME[2] =
732 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
733 info->DSP_TIME[3] =
734 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
735 } else {
736 info->DSP_TIME[0] =
737 ft1000_read_dpram_mag_16(dev,
738 FT1000_MAG_DSP_TIMER0,
739 FT1000_MAG_DSP_TIMER0_INDX);
740 info->DSP_TIME[1] =
741 ft1000_read_dpram_mag_16(dev,
742 FT1000_MAG_DSP_TIMER1,
743 FT1000_MAG_DSP_TIMER1_INDX);
744 info->DSP_TIME[2] =
745 ft1000_read_dpram_mag_16(dev,
746 FT1000_MAG_DSP_TIMER2,
747 FT1000_MAG_DSP_TIMER2_INDX);
748 info->DSP_TIME[3] =
749 ft1000_read_dpram_mag_16(dev,
750 FT1000_MAG_DSP_TIMER3,
751 FT1000_MAG_DSP_TIMER3_INDX);
752 }
753 info->DrvErrNum = DSP_HB_INFO;
754 if (ft1000_reset_card(dev) == 0) {
755 printk(KERN_INFO
756 "ft1000: Hardware Failure Detected - PC Card disabled\n");
757 info->ProgConStat = 0xff;
758 return;
759 }
760 /* Schedule this module to run every 2 seconds */
761 poll_timer.expires = jiffies + (2*HZ);
762 poll_timer.data = (u_long)dev;
763 add_timer(&poll_timer);
764 return;
765 }
766 ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_HB);
767
768 }
769
770 /* Schedule this module to run every 2 seconds */
771 poll_timer.expires = jiffies + (2 * HZ);
772 poll_timer.data = (u_long) dev;
773 add_timer(&poll_timer);
774}
775
776//---------------------------------------------------------------------------
777//
778// Function: ft1000_send_cmd
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300779// Description:
Marek Beliskof7c1be02010-09-22 07:56:27 +0200780// Input:
781// Output:
782//
783//---------------------------------------------------------------------------
Randy Dunlapeb93ca42011-08-08 11:31:48 -0700784static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype)
Marek Beliskof7c1be02010-09-22 07:56:27 +0200785{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200786 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200787 int i;
788 u16 tempword;
789 unsigned long flags;
790
Ondrej Zarye1328c62011-07-01 00:03:56 +0200791 size += sizeof(struct pseudo_hdr);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200792 // check for odd byte and increment to 16-bit word align value
793 if ((size & 0x0001)) {
794 size++;
795 }
796 DEBUG(1, "FT1000:ft1000_send_cmd:total length = %d\n", size);
797 DEBUG(1, "FT1000:ft1000_send_cmd:length = %d\n", ntohs(*ptempbuffer));
798 // put message into slow queue area
799 // All messages are in the form total_len + pseudo header + message body
800 spin_lock_irqsave(&info->dpram_lock, flags);
801
802 // Make sure SLOWQ doorbell is clear
803 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
804 i=0;
805 while (tempword & FT1000_DB_DPRAM_TX) {
806 mdelay(10);
807 i++;
808 if (i==10) {
809 spin_unlock_irqrestore(&info->dpram_lock, flags);
810 return;
811 }
812 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
813 }
814
815 if (info->AsicID == ELECTRABUZZ_ID) {
816 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
817 FT1000_DPRAM_TX_BASE);
818 // Write total length to dpram
819 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
820 // Write pseudo header and messgae body
821 for (i = 0; i < (size >> 1); i++) {
822 DEBUG(1, "FT1000:ft1000_send_cmd:data %d = 0x%x\n", i,
823 *ptempbuffer);
824 tempword = htons(*ptempbuffer++);
825 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, tempword);
826 }
827 } else {
828 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
829 FT1000_DPRAM_MAG_TX_BASE);
830 // Write total length to dpram
831 ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, htons(size));
832 // Write pseudo header and messgae body
833 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
834 FT1000_DPRAM_MAG_TX_BASE + 1);
835 for (i = 0; i < (size >> 2); i++) {
836 DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n",
837 *ptempbuffer);
838 outw(*ptempbuffer++,
839 dev->base_addr + FT1000_REG_MAG_DPDATAL);
840 DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n",
841 *ptempbuffer);
842 outw(*ptempbuffer++,
843 dev->base_addr + FT1000_REG_MAG_DPDATAH);
844 }
845 DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", *ptempbuffer);
846 outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAL);
847 DEBUG(1, "FT1000:ft1000_send_cmd:data = 0x%x\n", *ptempbuffer);
848 outw(*ptempbuffer++, dev->base_addr + FT1000_REG_MAG_DPDATAH);
849 }
850 spin_unlock_irqrestore(&info->dpram_lock, flags);
851
852 // ring doorbell to notify DSP that we have a message ready
853 ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_TX);
854}
855
856//---------------------------------------------------------------------------
857//
858// Function: ft1000_receive_cmd
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300859// Description: This function will read a message from the dpram area.
Marek Beliskof7c1be02010-09-22 07:56:27 +0200860// Input:
861// dev - network device structure
862// pbuffer - caller supply address to buffer
863// pnxtph - pointer to next pseudo header
864// Output:
865// Status = 0 (unsuccessful)
866// = 1 (successful)
867//
868//---------------------------------------------------------------------------
Randy Dunlapeb93ca42011-08-08 11:31:48 -0700869static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer,
870 int maxsz, u16 *pnxtph)
Marek Beliskof7c1be02010-09-22 07:56:27 +0200871{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200872 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200873 u16 size;
874 u16 *ppseudohdr;
875 int i;
876 u16 tempword;
877 unsigned long flags;
878
879 if (info->AsicID == ELECTRABUZZ_ID) {
Ondrej Zarye1328c62011-07-01 00:03:56 +0200880 size = ( ft1000_read_dpram(dev, *pnxtph) ) + sizeof(struct pseudo_hdr);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200881 } else {
882 size =
883 ntohs(ft1000_read_dpram_mag_16
884 (dev, FT1000_MAG_PH_LEN,
Ondrej Zarye1328c62011-07-01 00:03:56 +0200885 FT1000_MAG_PH_LEN_INDX)) + sizeof(struct pseudo_hdr);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200886 }
887 if (size > maxsz) {
888 DEBUG(1,
889 "FT1000:ft1000_receive_cmd:Invalid command length = %d\n",
890 size);
Ondrej Zaryca145272011-07-01 00:03:47 +0200891 return false;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200892 } else {
893 ppseudohdr = (u16 *) pbuffer;
894 spin_lock_irqsave(&info->dpram_lock, flags);
895 if (info->AsicID == ELECTRABUZZ_ID) {
896 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
897 FT1000_DPRAM_RX_BASE + 2);
898 for (i = 0; i <= (size >> 1); i++) {
899 tempword =
900 ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
901 *pbuffer++ = ntohs(tempword);
902 }
903 } else {
904 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
905 FT1000_DPRAM_MAG_RX_BASE);
906 *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
907 DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
908 pbuffer++;
909 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
910 FT1000_DPRAM_MAG_RX_BASE + 1);
911 for (i = 0; i <= (size >> 2); i++) {
912 *pbuffer =
913 inw(dev->base_addr +
914 FT1000_REG_MAG_DPDATAL);
915 pbuffer++;
916 *pbuffer =
917 inw(dev->base_addr +
918 FT1000_REG_MAG_DPDATAH);
919 pbuffer++;
920 }
921 //copy odd aligned word
922 *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL);
923 DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
924 pbuffer++;
925 *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
926 DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer);
927 pbuffer++;
928 }
929 if (size & 0x0001) {
930 //copy odd byte from fifo
931 tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
932 *pbuffer = ntohs(tempword);
933 }
934 spin_unlock_irqrestore(&info->dpram_lock, flags);
935
936 // Check if pseudo header checksum is good
937 // Calculate pseudo header checksum
938 tempword = *ppseudohdr++;
939 for (i = 1; i < 7; i++) {
940 tempword ^= *ppseudohdr++;
941 }
942 if ((tempword != *ppseudohdr)) {
943 DEBUG(1,
944 "FT1000:ft1000_receive_cmd:Pseudo header checksum mismatch\n");
945 // Drop this message
Ondrej Zaryca145272011-07-01 00:03:47 +0200946 return false;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200947 }
Ondrej Zaryca145272011-07-01 00:03:47 +0200948 return true;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200949 }
950}
951
952//---------------------------------------------------------------------------
953//
954// Function: ft1000_proc_drvmsg
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300955// Description: This function will process the various driver messages.
Marek Beliskof7c1be02010-09-22 07:56:27 +0200956// Input:
957// dev - device structure
958// pnxtph - pointer to next pseudo header
959// Output:
960// none
961//
962//---------------------------------------------------------------------------
Randy Dunlapeb93ca42011-08-08 11:31:48 -0700963static void ft1000_proc_drvmsg(struct net_device *dev)
Marek Beliskof7c1be02010-09-22 07:56:27 +0200964{
Ondrej Zaryd3706552011-07-01 00:03:42 +0200965 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +0200966 u16 msgtype;
967 u16 tempword;
Ondrej Zary24c5b192011-07-01 00:03:36 +0200968 struct media_msg *pmediamsg;
Ondrej Zary2cbdcdc2011-07-01 00:03:38 +0200969 struct dsp_init_msg *pdspinitmsg;
Ondrej Zary8bc0d6f2011-07-01 00:03:35 +0200970 struct drv_msg *pdrvmsg;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200971 u16 len;
972 u16 i;
Ondrej Zary3aaf8072011-07-01 00:03:41 +0200973 struct prov_record *ptr;
Ondrej Zary2c9bf832011-07-01 00:03:34 +0200974 struct pseudo_hdr *ppseudo_hdr;
Ondrej Zaryca145272011-07-01 00:03:47 +0200975 u16 *pmsg;
Marek Beliskof7c1be02010-09-22 07:56:27 +0200976 struct timeval tv;
977 union {
978 u8 byte[2];
979 u16 wrd;
980 } convert;
981
982 if (info->AsicID == ELECTRABUZZ_ID) {
983 tempword = FT1000_DPRAM_RX_BASE+2;
984 }
985 else {
986 tempword = FT1000_DPRAM_MAG_RX_BASE;
987 }
988 if ( ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword) ) {
989
990 // Get the message type which is total_len + PSEUDO header + msgtype + message body
Ondrej Zary8bc0d6f2011-07-01 00:03:35 +0200991 pdrvmsg = (struct drv_msg *) & cmdbuffer[0];
Marek Beliskof7c1be02010-09-22 07:56:27 +0200992 msgtype = ntohs(pdrvmsg->type);
993 DEBUG(1, "Command message type = 0x%x\n", msgtype);
994 switch (msgtype) {
995 case DSP_PROVISION:
996 DEBUG(0,
997 "Got a provisioning request message from DSP\n");
998 mdelay(25);
999 while (list_empty(&info->prov_list) == 0) {
1000 DEBUG(0, "Sending a provisioning message\n");
1001 // Make sure SLOWQ doorbell is clear
1002 tempword =
1003 ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1004 i = 0;
1005 while (tempword & FT1000_DB_DPRAM_TX) {
1006 mdelay(5);
1007 i++;
1008 if (i == 10) {
1009 break;
1010 }
1011 }
1012 ptr =
1013 list_entry(info->prov_list.next,
Ondrej Zary3aaf8072011-07-01 00:03:41 +02001014 struct prov_record, list);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001015 len = *(u16 *) ptr->pprov_data;
1016 len = htons(len);
1017
Ondrej Zaryca145272011-07-01 00:03:47 +02001018 pmsg = (u16 *) ptr->pprov_data;
Ondrej Zary2c9bf832011-07-01 00:03:34 +02001019 ppseudo_hdr = (struct pseudo_hdr *) pmsg;
Marek Beliskof7c1be02010-09-22 07:56:27 +02001020 // Insert slow queue sequence number
1021 ppseudo_hdr->seq_num = info->squeseqnum++;
1022 ppseudo_hdr->portsrc = 0;
1023 // Calculate new checksum
1024 ppseudo_hdr->checksum = *pmsg++;
1025 DEBUG(1, "checksum = 0x%x\n",
1026 ppseudo_hdr->checksum);
1027 for (i = 1; i < 7; i++) {
1028 ppseudo_hdr->checksum ^= *pmsg++;
1029 DEBUG(1, "checksum = 0x%x\n",
1030 ppseudo_hdr->checksum);
1031 }
1032
1033 ft1000_send_cmd (dev, (u16 *)ptr->pprov_data, len, SLOWQ_TYPE);
1034 list_del(&ptr->list);
1035 kfree(ptr->pprov_data);
1036 kfree(ptr);
1037 }
1038 // Indicate adapter is ready to take application messages after all
1039 // provisioning messages are sent
1040 info->CardReady = 1;
1041 break;
1042 case MEDIA_STATE:
Ondrej Zary24c5b192011-07-01 00:03:36 +02001043 pmediamsg = (struct media_msg *) & cmdbuffer[0];
Marek Beliskof7c1be02010-09-22 07:56:27 +02001044 if (info->ProgConStat != 0xFF) {
1045 if (pmediamsg->state) {
1046 DEBUG(1, "Media is up\n");
1047 if (info->mediastate == 0) {
1048 netif_carrier_on(dev);
1049 netif_wake_queue(dev);
1050 info->mediastate = 1;
1051 do_gettimeofday(&tv);
1052 info->ConTm = tv.tv_sec;
1053 }
1054 } else {
1055 DEBUG(1, "Media is down\n");
1056 if (info->mediastate == 1) {
1057 info->mediastate = 0;
1058 netif_carrier_off(dev);
1059 netif_stop_queue(dev);
1060 info->ConTm = 0;
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001061 }
Marek Beliskof7c1be02010-09-22 07:56:27 +02001062 }
1063 }
1064 else {
1065 DEBUG(1,"Media is down\n");
1066 if (info->mediastate == 1) {
1067 info->mediastate = 0;
1068 netif_carrier_off(dev);
1069 netif_stop_queue(dev);
1070 info->ConTm = 0;
1071 }
1072 }
1073 break;
1074 case DSP_INIT_MSG:
Ondrej Zary2cbdcdc2011-07-01 00:03:38 +02001075 pdspinitmsg = (struct dsp_init_msg *) & cmdbuffer[0];
Marek Beliskof7c1be02010-09-22 07:56:27 +02001076 memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
1077 DEBUG(1, "DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
1078 info->DspVer[0], info->DspVer[1], info->DspVer[2],
1079 info->DspVer[3]);
1080 memcpy(info->HwSerNum, pdspinitmsg->HwSerNum,
1081 HWSERNUMSZ);
1082 memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
1083 memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
1084 dev->dev_addr[0] = info->eui64[0];
1085 dev->dev_addr[1] = info->eui64[1];
1086 dev->dev_addr[2] = info->eui64[2];
1087 dev->dev_addr[3] = info->eui64[5];
1088 dev->dev_addr[4] = info->eui64[6];
1089 dev->dev_addr[5] = info->eui64[7];
1090
1091 if (ntohs(pdspinitmsg->length) ==
Ondrej Zary2cbdcdc2011-07-01 00:03:38 +02001092 (sizeof(struct dsp_init_msg) - 20)) {
Marek Beliskof7c1be02010-09-22 07:56:27 +02001093 memcpy(info->ProductMode,
1094 pdspinitmsg->ProductMode, MODESZ);
1095 memcpy(info->RfCalVer, pdspinitmsg->RfCalVer,
1096 CALVERSZ);
1097 memcpy(info->RfCalDate, pdspinitmsg->RfCalDate,
1098 CALDATESZ);
1099 DEBUG(1, "RFCalVer = 0x%2x 0x%2x\n",
1100 info->RfCalVer[0], info->RfCalVer[1]);
1101 }
1102
1103 break ;
1104 case DSP_STORE_INFO:
1105 DEBUG(1, "FT1000:drivermsg:Got DSP_STORE_INFO\n");
1106 tempword = ntohs(pdrvmsg->length);
1107 info->DSPInfoBlklen = tempword;
1108 if (tempword < (MAX_DSP_SESS_REC - 4)) {
Ondrej Zaryca145272011-07-01 00:03:47 +02001109 pmsg = (u16 *) & pdrvmsg->data[0];
Marek Beliskof7c1be02010-09-22 07:56:27 +02001110 for (i = 0; i < ((tempword + 1) / 2); i++) {
1111 DEBUG(1,
1112 "FT1000:drivermsg:dsp info data = 0x%x\n",
1113 *pmsg);
1114 info->DSPInfoBlk[i + 10] = *pmsg++;
1115 }
1116 }
1117 break;
1118 case DSP_GET_INFO:
1119 DEBUG(1, "FT1000:drivermsg:Got DSP_GET_INFO\n");
1120 // copy dsp info block to dsp
Marek Beliskof7c1be02010-09-22 07:56:27 +02001121 // allow any outstanding ioctl to finish
1122 mdelay(10);
1123 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1124 if (tempword & FT1000_DB_DPRAM_TX) {
1125 mdelay(10);
1126 tempword =
1127 ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1128 if (tempword & FT1000_DB_DPRAM_TX) {
1129 mdelay(10);
1130 }
1131 }
1132
1133 if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
1134 // Put message into Slow Queue
1135 // Form Pseudo header
Ondrej Zaryca145272011-07-01 00:03:47 +02001136 pmsg = (u16 *) info->DSPInfoBlk;
Ondrej Zary2c9bf832011-07-01 00:03:34 +02001137 ppseudo_hdr = (struct pseudo_hdr *) pmsg;
Marek Beliskof7c1be02010-09-22 07:56:27 +02001138 ppseudo_hdr->length =
1139 htons(info->DSPInfoBlklen + 4);
1140 ppseudo_hdr->source = 0x10;
1141 ppseudo_hdr->destination = 0x20;
1142 ppseudo_hdr->portdest = 0;
1143 ppseudo_hdr->portsrc = 0;
1144 ppseudo_hdr->sh_str_id = 0;
1145 ppseudo_hdr->control = 0;
1146 ppseudo_hdr->rsvd1 = 0;
1147 ppseudo_hdr->rsvd2 = 0;
1148 ppseudo_hdr->qos_class = 0;
1149 // Insert slow queue sequence number
1150 ppseudo_hdr->seq_num = info->squeseqnum++;
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001151 // Insert application id
Marek Beliskof7c1be02010-09-22 07:56:27 +02001152 ppseudo_hdr->portsrc = 0;
1153 // Calculate new checksum
1154 ppseudo_hdr->checksum = *pmsg++;
1155 for (i = 1; i < 7; i++) {
1156 ppseudo_hdr->checksum ^= *pmsg++;
1157 }
1158 info->DSPInfoBlk[8] = 0x7200;
1159 info->DSPInfoBlk[9] =
1160 htons(info->DSPInfoBlklen);
Ondrej Zaryca145272011-07-01 00:03:47 +02001161 ft1000_send_cmd (dev, (u16 *)info->DSPInfoBlk, (u16)(info->DSPInfoBlklen+4), 0);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001162 }
Marek Beliskof7c1be02010-09-22 07:56:27 +02001163
1164 break;
1165 case GET_DRV_ERR_RPT_MSG:
1166 DEBUG(1, "FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n");
1167 // copy driver error message to dsp
Marek Beliskof7c1be02010-09-22 07:56:27 +02001168 // allow any outstanding ioctl to finish
1169 mdelay(10);
1170 tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1171 if (tempword & FT1000_DB_DPRAM_TX) {
1172 mdelay(10);
1173 tempword =
1174 ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1175 if (tempword & FT1000_DB_DPRAM_TX) {
1176 mdelay(10);
1177 }
1178 }
1179
1180 if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
1181 // Put message into Slow Queue
1182 // Form Pseudo header
Ondrej Zaryca145272011-07-01 00:03:47 +02001183 pmsg = (u16 *) & tempbuffer[0];
Ondrej Zary2c9bf832011-07-01 00:03:34 +02001184 ppseudo_hdr = (struct pseudo_hdr *) pmsg;
Marek Beliskof7c1be02010-09-22 07:56:27 +02001185 ppseudo_hdr->length = htons(0x0012);
1186 ppseudo_hdr->source = 0x10;
1187 ppseudo_hdr->destination = 0x20;
1188 ppseudo_hdr->portdest = 0;
1189 ppseudo_hdr->portsrc = 0;
1190 ppseudo_hdr->sh_str_id = 0;
1191 ppseudo_hdr->control = 0;
1192 ppseudo_hdr->rsvd1 = 0;
1193 ppseudo_hdr->rsvd2 = 0;
1194 ppseudo_hdr->qos_class = 0;
1195 // Insert slow queue sequence number
1196 ppseudo_hdr->seq_num = info->squeseqnum++;
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001197 // Insert application id
Marek Beliskof7c1be02010-09-22 07:56:27 +02001198 ppseudo_hdr->portsrc = 0;
1199 // Calculate new checksum
1200 ppseudo_hdr->checksum = *pmsg++;
1201 for (i=1; i<7; i++) {
1202 ppseudo_hdr->checksum ^= *pmsg++;
1203 }
Ondrej Zaryca145272011-07-01 00:03:47 +02001204 pmsg = (u16 *) & tempbuffer[16];
Marek Beliskof7c1be02010-09-22 07:56:27 +02001205 *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
1206 *pmsg++ = htons(0x000e);
1207 *pmsg++ = htons(info->DSP_TIME[0]);
1208 *pmsg++ = htons(info->DSP_TIME[1]);
1209 *pmsg++ = htons(info->DSP_TIME[2]);
1210 *pmsg++ = htons(info->DSP_TIME[3]);
1211 convert.byte[0] = info->DspVer[0];
1212 convert.byte[1] = info->DspVer[1];
1213 *pmsg++ = convert.wrd;
1214 convert.byte[0] = info->DspVer[2];
1215 convert.byte[1] = info->DspVer[3];
1216 *pmsg++ = convert.wrd;
1217 *pmsg++ = htons(info->DrvErrNum);
1218
Ondrej Zaryca145272011-07-01 00:03:47 +02001219 ft1000_send_cmd (dev, (u16 *)&tempbuffer[0], (u16)(0x0012), 0);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001220 info->DrvErrNum = 0;
1221 }
Marek Beliskof7c1be02010-09-22 07:56:27 +02001222
1223 break;
1224 default:
1225 break;
1226 }
1227 }
1228}
1229
1230//---------------------------------------------------------------------------
1231//
1232// Function: ft1000_parse_dpram_msg
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001233// Description: This function will parse the message received from the DSP
Marek Beliskof7c1be02010-09-22 07:56:27 +02001234// via the DPRAM interface.
1235// Input:
1236// dev - device structure
1237// Output:
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001238// status - FAILURE
1239// SUCCESS
Marek Beliskof7c1be02010-09-22 07:56:27 +02001240//
1241//---------------------------------------------------------------------------
Randy Dunlapeb93ca42011-08-08 11:31:48 -07001242static int ft1000_parse_dpram_msg(struct net_device *dev)
Marek Beliskof7c1be02010-09-22 07:56:27 +02001243{
Ondrej Zaryd3706552011-07-01 00:03:42 +02001244 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001245 u16 doorbell;
1246 u16 portid;
1247 u16 nxtph;
1248 u16 total_len;
1249 int i = 0;
1250 int cnt;
1251 unsigned long flags;
1252
1253 doorbell = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
1254 DEBUG(1, "Doorbell = 0x%x\n", doorbell);
1255
1256 if (doorbell & FT1000_ASIC_RESET_REQ) {
1257 // Copy DSP session record from info block
1258 spin_lock_irqsave(&info->dpram_lock, flags);
1259 if (info->AsicID == ELECTRABUZZ_ID) {
1260 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
1261 FT1000_DPRAM_RX_BASE);
1262 for (i = 0; i < MAX_DSP_SESS_REC; i++) {
1263 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA,
1264 info->DSPSess.Rec[i]);
1265 }
1266 } else {
1267 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
1268 FT1000_DPRAM_MAG_RX_BASE);
1269 for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
1270 outl(info->DSPSess.MagRec[i],
1271 dev->base_addr + FT1000_REG_MAG_DPDATA);
1272 }
1273 }
1274 spin_unlock_irqrestore(&info->dpram_lock, flags);
1275
1276 // clear ASIC RESET request
1277 ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1278 FT1000_ASIC_RESET_REQ);
1279 DEBUG(1, "Got an ASIC RESET Request\n");
1280 ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1281 FT1000_ASIC_RESET_DSP);
1282
1283 if (info->AsicID == MAGNEMITE_ID) {
1284 // Setting MAGNEMITE ASIC to big endian mode
1285 ft1000_write_reg(dev, FT1000_REG_SUP_CTRL,
1286 HOST_INTF_BE);
1287 }
Marek Beliskof7c1be02010-09-22 07:56:27 +02001288 }
1289
1290 if (doorbell & FT1000_DSP_ASIC_RESET) {
1291 DEBUG(0,
1292 "FT1000:ft1000_parse_dpram_msg: Got a dsp ASIC reset message\n");
Marek Beliskof7c1be02010-09-22 07:56:27 +02001293 ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1294 FT1000_DSP_ASIC_RESET);
1295 udelay(200);
1296 return SUCCESS;
1297 }
1298
1299 if (doorbell & FT1000_DB_DPRAM_RX) {
1300 DEBUG(1,
1301 "FT1000:ft1000_parse_dpram_msg: Got a slow queue message\n");
1302 nxtph = FT1000_DPRAM_RX_BASE + 2;
1303 if (info->AsicID == ELECTRABUZZ_ID) {
1304 total_len =
1305 ft1000_read_dpram(dev, FT1000_DPRAM_RX_BASE);
1306 } else {
1307 total_len =
1308 ntohs(ft1000_read_dpram_mag_16
1309 (dev, FT1000_MAG_TOTAL_LEN,
1310 FT1000_MAG_TOTAL_LEN_INDX));
1311 }
1312 DEBUG(1, "FT1000:ft1000_parse_dpram_msg:total length = %d\n",
1313 total_len);
Ondrej Zarye1328c62011-07-01 00:03:56 +02001314 if ((total_len < MAX_CMD_SQSIZE) && (total_len > sizeof(struct pseudo_hdr))) {
Marek Beliskof7c1be02010-09-22 07:56:27 +02001315 total_len += nxtph;
1316 cnt = 0;
1317 // ft1000_read_reg will return a value that needs to be byteswap
1318 // in order to get DSP_QID_OFFSET.
1319 if (info->AsicID == ELECTRABUZZ_ID) {
1320 portid =
1321 (ft1000_read_dpram
1322 (dev,
1323 DSP_QID_OFFSET + FT1000_DPRAM_RX_BASE +
1324 2) >> 8) & 0xff;
1325 } else {
1326 portid =
1327 (ft1000_read_dpram_mag_16
1328 (dev, FT1000_MAG_PORT_ID,
1329 FT1000_MAG_PORT_ID_INDX) & 0xff);
1330 }
1331 DEBUG(1, "DSP_QID = 0x%x\n", portid);
1332
1333 if (portid == DRIVERID) {
1334 // We are assumming one driver message from the DSP at a time.
1335 ft1000_proc_drvmsg(dev);
1336 }
1337 }
1338 ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_RX);
1339 }
1340
1341 if (doorbell & FT1000_DB_COND_RESET) {
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001342 // Reset ASIC and DSP
Marek Beliskof7c1be02010-09-22 07:56:27 +02001343 if (info->AsicID == ELECTRABUZZ_ID) {
1344 info->DSP_TIME[0] =
1345 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
1346 info->DSP_TIME[1] =
1347 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
1348 info->DSP_TIME[2] =
1349 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
1350 info->DSP_TIME[3] =
1351 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
1352 } else {
1353 info->DSP_TIME[0] =
1354 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
1355 FT1000_MAG_DSP_TIMER0_INDX);
1356 info->DSP_TIME[1] =
1357 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
1358 FT1000_MAG_DSP_TIMER1_INDX);
1359 info->DSP_TIME[2] =
1360 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
1361 FT1000_MAG_DSP_TIMER2_INDX);
1362 info->DSP_TIME[3] =
1363 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
1364 FT1000_MAG_DSP_TIMER3_INDX);
1365 }
1366 info->DrvErrNum = DSP_CONDRESET_INFO;
1367 DEBUG(1, "ft1000_hw:DSP conditional reset requested\n");
1368 ft1000_reset_card(dev);
1369 ft1000_write_reg(dev, FT1000_REG_DOORBELL,
1370 FT1000_DB_COND_RESET);
1371 }
1372 // let's clear any unexpected doorbells from DSP
1373 doorbell =
1374 doorbell & ~(FT1000_DB_DPRAM_RX | FT1000_ASIC_RESET_REQ |
1375 FT1000_DB_COND_RESET | 0xff00);
1376 if (doorbell) {
1377 DEBUG(1, "Clearing unexpected doorbell = 0x%x\n", doorbell);
1378 ft1000_write_reg(dev, FT1000_REG_DOORBELL, doorbell);
1379 }
1380
1381 return SUCCESS;
1382
1383}
1384
1385//---------------------------------------------------------------------------
1386//
1387// Function: ft1000_flush_fifo
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001388// Description: This function will flush one packet from the downlink
Marek Beliskof7c1be02010-09-22 07:56:27 +02001389// FIFO.
1390// Input:
1391// dev - device structure
1392// drv_err - driver error causing the flush fifo
1393// Output:
1394// None.
1395//
1396//---------------------------------------------------------------------------
1397static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
1398{
Ondrej Zaryd3706552011-07-01 00:03:42 +02001399 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001400 u16 i;
1401 u32 templong;
1402 u16 tempword;
1403
1404 DEBUG(1, "ft1000:ft1000_hw:ft1000_flush_fifo called\n");
1405 if (info->PktIntfErr > MAX_PH_ERR) {
1406 if (info->AsicID == ELECTRABUZZ_ID) {
1407 info->DSP_TIME[0] =
1408 ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
1409 info->DSP_TIME[1] =
1410 ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
1411 info->DSP_TIME[2] =
1412 ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
1413 info->DSP_TIME[3] =
1414 ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
1415 } else {
1416 info->DSP_TIME[0] =
1417 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
1418 FT1000_MAG_DSP_TIMER0_INDX);
1419 info->DSP_TIME[1] =
1420 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
1421 FT1000_MAG_DSP_TIMER1_INDX);
1422 info->DSP_TIME[2] =
1423 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
1424 FT1000_MAG_DSP_TIMER2_INDX);
1425 info->DSP_TIME[3] =
1426 ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
1427 FT1000_MAG_DSP_TIMER3_INDX);
1428 }
1429 info->DrvErrNum = DrvErrNum;
1430 ft1000_reset_card(dev);
1431 return;
1432 } else {
1433 // Flush corrupted pkt from FIFO
1434 i = 0;
1435 do {
1436 if (info->AsicID == ELECTRABUZZ_ID) {
1437 tempword =
1438 ft1000_read_reg(dev, FT1000_REG_DFIFO);
1439 tempword =
1440 ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
1441 } else {
1442 templong =
1443 inl(dev->base_addr + FT1000_REG_MAG_DFR);
1444 tempword =
1445 inw(dev->base_addr + FT1000_REG_MAG_DFSR);
1446 }
1447 i++;
1448 // This should never happen unless the ASIC is broken.
1449 // We must reset to recover.
1450 if ((i > 2048) || (tempword == 0)) {
1451 if (info->AsicID == ELECTRABUZZ_ID) {
1452 info->DSP_TIME[0] =
1453 ft1000_read_dpram(dev,
1454 FT1000_DSP_TIMER0);
1455 info->DSP_TIME[1] =
1456 ft1000_read_dpram(dev,
1457 FT1000_DSP_TIMER1);
1458 info->DSP_TIME[2] =
1459 ft1000_read_dpram(dev,
1460 FT1000_DSP_TIMER2);
1461 info->DSP_TIME[3] =
1462 ft1000_read_dpram(dev,
1463 FT1000_DSP_TIMER3);
1464 } else {
1465 info->DSP_TIME[0] =
1466 ft1000_read_dpram_mag_16(dev,
1467 FT1000_MAG_DSP_TIMER0,
1468 FT1000_MAG_DSP_TIMER0_INDX);
1469 info->DSP_TIME[1] =
1470 ft1000_read_dpram_mag_16(dev,
1471 FT1000_MAG_DSP_TIMER1,
1472 FT1000_MAG_DSP_TIMER1_INDX);
1473 info->DSP_TIME[2] =
1474 ft1000_read_dpram_mag_16(dev,
1475 FT1000_MAG_DSP_TIMER2,
1476 FT1000_MAG_DSP_TIMER2_INDX);
1477 info->DSP_TIME[3] =
1478 ft1000_read_dpram_mag_16(dev,
1479 FT1000_MAG_DSP_TIMER3,
1480 FT1000_MAG_DSP_TIMER3_INDX);
1481 }
1482 if (tempword == 0) {
1483 // Let's check if ASIC reads are still ok by reading the Mask register
1484 // which is never zero at this point of the code.
1485 tempword =
1486 inw(dev->base_addr +
1487 FT1000_REG_SUP_IMASK);
1488 if (tempword == 0) {
1489 // This indicates that we can not communicate with the ASIC
1490 info->DrvErrNum =
1491 FIFO_FLUSH_BADCNT;
1492 } else {
1493 // Let's assume that we really flush the FIFO
1494 info->PktIntfErr++;
1495 return;
1496 }
1497 } else {
1498 info->DrvErrNum = FIFO_FLUSH_MAXLIMIT;
1499 }
1500 return;
1501 }
1502 tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
1503 } while ((tempword & 0x03) != 0x03);
1504 if (info->AsicID == ELECTRABUZZ_ID) {
1505 i++;
1506 DEBUG(0, "Flushing FIFO complete = %x\n", tempword);
1507 // Flush last word in FIFO.
1508 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1509 // Update FIFO counter for DSP
1510 i = i * 2;
1511 DEBUG(0, "Flush Data byte count to dsp = %d\n", i);
1512 info->fifo_cnt += i;
1513 ft1000_write_dpram(dev, FT1000_FIFO_LEN,
1514 info->fifo_cnt);
1515 } else {
1516 DEBUG(0, "Flushing FIFO complete = %x\n", tempword);
1517 // Flush last word in FIFO
1518 templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1519 tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
1520 DEBUG(0, "FT1000_REG_SUP_STAT = 0x%x\n", tempword);
1521 tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR);
1522 DEBUG(0, "FT1000_REG_MAG_DFSR = 0x%x\n", tempword);
1523 }
1524 if (DrvErrNum) {
1525 info->PktIntfErr++;
1526 }
1527 }
1528}
1529
1530//---------------------------------------------------------------------------
1531//
1532// Function: ft1000_copy_up_pkt
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001533// Description: This function will pull Flarion packets out of the Downlink
Marek Beliskof7c1be02010-09-22 07:56:27 +02001534// FIFO and convert it to an ethernet packet. The ethernet packet will
1535// then be deliver to the TCP/IP stack.
1536// Input:
1537// dev - device structure
1538// Output:
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001539// status - FAILURE
1540// SUCCESS
Marek Beliskof7c1be02010-09-22 07:56:27 +02001541//
1542//---------------------------------------------------------------------------
Randy Dunlapeb93ca42011-08-08 11:31:48 -07001543static int ft1000_copy_up_pkt(struct net_device *dev)
Marek Beliskof7c1be02010-09-22 07:56:27 +02001544{
1545 u16 tempword;
Ondrej Zaryd3706552011-07-01 00:03:42 +02001546 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001547 u16 len;
1548 struct sk_buff *skb;
1549 u16 i;
1550 u8 *pbuffer = NULL;
1551 u8 *ptemp = NULL;
1552 u16 chksum;
1553 u32 *ptemplong;
1554 u32 templong;
1555
1556 DEBUG(1, "ft1000_copy_up_pkt\n");
1557 // Read length
1558 if (info->AsicID == ELECTRABUZZ_ID) {
1559 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1560 len = tempword;
1561 } else {
1562 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1563 len = ntohs(tempword);
1564 }
1565 chksum = tempword;
1566 DEBUG(1, "Number of Bytes in FIFO = %d\n", len);
1567
1568 if (len > ENET_MAX_SIZE) {
1569 DEBUG(0, "size of ethernet packet invalid\n");
1570 if (info->AsicID == MAGNEMITE_ID) {
1571 // Read High word to complete 32 bit access
1572 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1573 }
1574 ft1000_flush_fifo(dev, DSP_PKTLEN_INFO);
1575 info->stats.rx_errors++;
1576 return FAILURE;
1577 }
1578
1579 skb = dev_alloc_skb(len + 12 + 2);
1580
1581 if (skb == NULL) {
1582 DEBUG(0, "No Network buffers available\n");
1583 // Read High word to complete 32 bit access
1584 if (info->AsicID == MAGNEMITE_ID) {
1585 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1586 }
1587 ft1000_flush_fifo(dev, 0);
1588 info->stats.rx_errors++;
1589 return FAILURE;
1590 }
1591 pbuffer = (u8 *) skb_put(skb, len + 12);
1592
1593 // Pseudo header
1594 if (info->AsicID == ELECTRABUZZ_ID) {
1595 for (i = 1; i < 7; i++) {
1596 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1597 chksum ^= tempword;
1598 }
1599 // read checksum value
1600 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1601 } else {
1602 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1603 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1604 chksum ^= tempword;
1605
1606 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1607 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1608 chksum ^= tempword;
1609
1610 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1611 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1612 chksum ^= tempword;
1613
1614 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1615 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1616 chksum ^= tempword;
1617
1618 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1619 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1620 chksum ^= tempword;
1621
1622 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRL);
1623 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1624 chksum ^= tempword;
1625
1626 // read checksum value
1627 tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
1628 DEBUG(1, "Pseudo = 0x%x\n", tempword);
1629 }
1630
1631 if (chksum != tempword) {
1632 DEBUG(0, "Packet checksum mismatch 0x%x 0x%x\n", chksum,
1633 tempword);
1634 ft1000_flush_fifo(dev, DSP_PKTPHCKSUM_INFO);
1635 info->stats.rx_errors++;
Vasiliy Kulikovc95aef42010-09-28 21:49:35 +04001636 kfree_skb(skb);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001637 return FAILURE;
1638 }
1639 //subtract the number of bytes read already
1640 ptemp = pbuffer;
1641
1642 // fake MAC address
1643 *pbuffer++ = dev->dev_addr[0];
1644 *pbuffer++ = dev->dev_addr[1];
1645 *pbuffer++ = dev->dev_addr[2];
1646 *pbuffer++ = dev->dev_addr[3];
1647 *pbuffer++ = dev->dev_addr[4];
1648 *pbuffer++ = dev->dev_addr[5];
1649 *pbuffer++ = 0x00;
1650 *pbuffer++ = 0x07;
1651 *pbuffer++ = 0x35;
1652 *pbuffer++ = 0xff;
1653 *pbuffer++ = 0xff;
1654 *pbuffer++ = 0xfe;
1655
1656 if (info->AsicID == ELECTRABUZZ_ID) {
1657 for (i = 0; i < len / 2; i++) {
1658 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1659 *pbuffer++ = (u8) (tempword >> 8);
1660 *pbuffer++ = (u8) tempword;
Ondrej Zaryca145272011-07-01 00:03:47 +02001661 if (ft1000_chkcard(dev) == false) {
Vasiliy Kulikovc95aef42010-09-28 21:49:35 +04001662 kfree_skb(skb);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001663 return FAILURE;
1664 }
1665 }
1666
1667 // Need to read one more word if odd byte
1668 if (len & 0x0001) {
1669 tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
1670 *pbuffer++ = (u8) (tempword >> 8);
1671 }
1672 } else {
1673 ptemplong = (u32 *) pbuffer;
1674 for (i = 0; i < len / 4; i++) {
1675 templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1676 DEBUG(1, "Data = 0x%8x\n", templong);
1677 *ptemplong++ = templong;
1678 }
1679
1680 // Need to read one more word if odd align.
1681 if (len & 0x0003) {
1682 templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
1683 DEBUG(1, "Data = 0x%8x\n", templong);
1684 *ptemplong++ = templong;
1685 }
1686
1687 }
1688
1689 DEBUG(1, "Data passed to Protocol layer:\n");
1690 for (i = 0; i < len + 12; i++) {
1691 DEBUG(1, "Protocol Data: 0x%x\n ", *ptemp++);
1692 }
1693
1694 skb->dev = dev;
1695 skb->protocol = eth_type_trans(skb, dev);
1696 skb->ip_summed = CHECKSUM_UNNECESSARY;
1697 netif_rx(skb);
1698
1699 info->stats.rx_packets++;
1700 // Add on 12 bytes for MAC address which was removed
1701 info->stats.rx_bytes += (len + 12);
1702
1703 if (info->AsicID == ELECTRABUZZ_ID) {
1704 // track how many bytes have been read from FIFO - round up to 16 bit word
1705 tempword = len + 16;
1706 if (tempword & 0x01)
1707 tempword++;
1708 info->fifo_cnt += tempword;
1709 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_FIFO_LEN);
1710 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, info->fifo_cnt);
1711 }
1712
1713 return SUCCESS;
1714}
1715
1716//---------------------------------------------------------------------------
1717//
1718// Function: ft1000_copy_down_pkt
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001719// Description: This function will take an ethernet packet and convert it to
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001720// a Flarion packet prior to sending it to the ASIC Downlink
Marek Beliskof7c1be02010-09-22 07:56:27 +02001721// FIFO.
1722// Input:
1723// dev - device structure
1724// packet - address of ethernet packet
1725// len - length of IP packet
1726// Output:
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001727// status - FAILURE
1728// SUCCESS
Marek Beliskof7c1be02010-09-22 07:56:27 +02001729//
1730//---------------------------------------------------------------------------
Randy Dunlapeb93ca42011-08-08 11:31:48 -07001731static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
Marek Beliskof7c1be02010-09-22 07:56:27 +02001732{
Ondrej Zaryd3706552011-07-01 00:03:42 +02001733 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001734 union {
Ondrej Zary2c9bf832011-07-01 00:03:34 +02001735 struct pseudo_hdr blk;
1736 u16 buff[sizeof(struct pseudo_hdr) >> 1];
1737 u8 buffc[sizeof(struct pseudo_hdr)];
Marek Beliskof7c1be02010-09-22 07:56:27 +02001738 } pseudo;
1739 int i;
1740 u32 *plong;
1741
1742 DEBUG(1, "ft1000_hw: copy_down_pkt()\n");
1743
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001744 // Check if there is room on the FIFO
Marek Beliskof7c1be02010-09-22 07:56:27 +02001745 if (len > ft1000_read_fifo_len(dev)) {
1746 udelay(10);
1747 if (len > ft1000_read_fifo_len(dev)) {
1748 udelay(20);
1749 }
1750 if (len > ft1000_read_fifo_len(dev)) {
1751 udelay(20);
1752 }
1753 if (len > ft1000_read_fifo_len(dev)) {
1754 udelay(20);
1755 }
1756 if (len > ft1000_read_fifo_len(dev)) {
1757 udelay(20);
1758 }
1759 if (len > ft1000_read_fifo_len(dev)) {
1760 udelay(20);
1761 }
1762 if (len > ft1000_read_fifo_len(dev)) {
1763 DEBUG(1,
1764 "ft1000_hw:ft1000_copy_down_pkt:Transmit FIFO is fulli - pkt drop\n");
1765 info->stats.tx_errors++;
1766 return SUCCESS;
1767 }
1768 }
1769 // Create pseudo header and send pseudo/ip to hardware
1770 if (info->AsicID == ELECTRABUZZ_ID) {
1771 pseudo.blk.length = len;
1772 } else {
1773 pseudo.blk.length = ntohs(len);
1774 }
1775 pseudo.blk.source = DSPID; // Need to swap to get in correct order
1776 pseudo.blk.destination = HOSTID;
1777 pseudo.blk.portdest = NETWORKID; // Need to swap to get in correct order
1778 pseudo.blk.portsrc = DSPAIRID;
1779 pseudo.blk.sh_str_id = 0;
1780 pseudo.blk.control = 0;
1781 pseudo.blk.rsvd1 = 0;
1782 pseudo.blk.seq_num = 0;
1783 pseudo.blk.rsvd2 = info->packetseqnum++;
1784 pseudo.blk.qos_class = 0;
1785 /* Calculate pseudo header checksum */
1786 pseudo.blk.checksum = pseudo.buff[0];
1787 for (i = 1; i < 7; i++) {
1788 pseudo.blk.checksum ^= pseudo.buff[i];
1789 }
1790
1791 // Production Mode
1792 if (info->AsicID == ELECTRABUZZ_ID) {
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001793 // copy first word to UFIFO_BEG reg
Marek Beliskof7c1be02010-09-22 07:56:27 +02001794 ft1000_write_reg(dev, FT1000_REG_UFIFO_BEG, pseudo.buff[0]);
1795 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 0 BEG = 0x%04x\n",
1796 pseudo.buff[0]);
1797
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001798 // copy subsequent words to UFIFO_MID reg
Marek Beliskof7c1be02010-09-22 07:56:27 +02001799 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[1]);
1800 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 1 MID = 0x%04x\n",
1801 pseudo.buff[1]);
1802 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[2]);
1803 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 2 MID = 0x%04x\n",
1804 pseudo.buff[2]);
1805 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[3]);
1806 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 3 MID = 0x%04x\n",
1807 pseudo.buff[3]);
1808 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[4]);
1809 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 4 MID = 0x%04x\n",
1810 pseudo.buff[4]);
1811 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[5]);
1812 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 5 MID = 0x%04x\n",
1813 pseudo.buff[5]);
1814 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[6]);
1815 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 6 MID = 0x%04x\n",
1816 pseudo.buff[6]);
1817 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[7]);
1818 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 7 MID = 0x%04x\n",
1819 pseudo.buff[7]);
1820
1821 // Write PPP type + IP Packet into Downlink FIFO
1822 for (i = 0; i < (len >> 1) - 1; i++) {
1823 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
1824 htons(*packet));
1825 DEBUG(1,
1826 "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1827 i + 8, htons(*packet));
1828 packet++;
1829 }
1830
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001831 // Check for odd byte
Marek Beliskof7c1be02010-09-22 07:56:27 +02001832 if (len & 0x0001) {
1833 ft1000_write_reg(dev, FT1000_REG_UFIFO_MID,
1834 htons(*packet));
1835 DEBUG(1,
1836 "ft1000_hw:ft1000_copy_down_pkt:data MID = 0x%04x\n",
1837 htons(*packet));
1838 packet++;
1839 ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
1840 htons(*packet));
1841 DEBUG(1,
1842 "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1843 i + 8, htons(*packet));
1844 } else {
1845 ft1000_write_reg(dev, FT1000_REG_UFIFO_END,
1846 htons(*packet));
1847 DEBUG(1,
1848 "ft1000_hw:ft1000_copy_down_pkt:data %d MID = 0x%04x\n",
1849 i + 8, htons(*packet));
1850 }
1851 } else {
1852 outl(*(u32 *) & pseudo.buff[0],
1853 dev->base_addr + FT1000_REG_MAG_UFDR);
1854 DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1855 *(u32 *) & pseudo.buff[0]);
1856 outl(*(u32 *) & pseudo.buff[2],
1857 dev->base_addr + FT1000_REG_MAG_UFDR);
1858 DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1859 *(u32 *) & pseudo.buff[2]);
1860 outl(*(u32 *) & pseudo.buff[4],
1861 dev->base_addr + FT1000_REG_MAG_UFDR);
1862 DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1863 *(u32 *) & pseudo.buff[4]);
1864 outl(*(u32 *) & pseudo.buff[6],
1865 dev->base_addr + FT1000_REG_MAG_UFDR);
1866 DEBUG(1, "ft1000_copy_down_pkt: Pseudo = 0x%8x\n",
1867 *(u32 *) & pseudo.buff[6]);
1868
1869 plong = (u32 *) packet;
1870 // Write PPP type + IP Packet into Downlink FIFO
1871 for (i = 0; i < (len >> 2); i++) {
1872 outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
1873 }
1874
Greg Kroah-Hartmanbf3146c2010-09-22 08:34:49 -07001875 // Check for odd alignment
Marek Beliskof7c1be02010-09-22 07:56:27 +02001876 if (len & 0x0003) {
1877 DEBUG(1,
1878 "ft1000_hw:ft1000_copy_down_pkt:data = 0x%8x\n",
1879 *plong);
1880 outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR);
1881 }
1882 outl(1, dev->base_addr + FT1000_REG_MAG_UFER);
1883 }
1884
1885 info->stats.tx_packets++;
Uwe Kleine-Königaec563b2011-02-10 11:16:00 +01001886 // Add 14 bytes for MAC address plus ethernet type
Marek Beliskof7c1be02010-09-22 07:56:27 +02001887 info->stats.tx_bytes += (len + 14);
1888 return SUCCESS;
1889}
1890
1891static struct net_device_stats *ft1000_stats(struct net_device *dev)
1892{
Ondrej Zaryd3706552011-07-01 00:03:42 +02001893 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001894 return (&info->stats);
1895}
1896
1897static int ft1000_open(struct net_device *dev)
1898{
1899
1900 DEBUG(0, "ft1000_hw: ft1000_open is called\n");
1901
1902 ft1000_reset_card(dev);
1903 DEBUG(0, "ft1000_hw: ft1000_open is ended\n");
1904
1905 /* schedule ft1000_hbchk to perform periodic heartbeat checks on DSP and ASIC */
1906 init_timer(&poll_timer);
1907 poll_timer.expires = jiffies + (2 * HZ);
1908 poll_timer.data = (u_long) dev;
1909 add_timer(&poll_timer);
1910
1911 DEBUG(0, "ft1000_hw: ft1000_open is ended2\n");
1912 return 0;
1913}
1914
1915static int ft1000_close(struct net_device *dev)
1916{
Ondrej Zaryd3706552011-07-01 00:03:42 +02001917 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001918
1919 DEBUG(0, "ft1000_hw: ft1000_close()\n");
1920
1921 info->CardReady = 0;
1922 del_timer(&poll_timer);
1923
1924 if (ft1000_card_present == 1) {
1925 DEBUG(0, "Media is down\n");
1926 netif_stop_queue(dev);
1927
1928 ft1000_disable_interrupts(dev);
1929 ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT);
1930
1931 //reset ASIC
1932 ft1000_reset_asic(dev);
1933 }
1934 return 0;
1935}
1936
1937static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
1938{
Ondrej Zaryd3706552011-07-01 00:03:42 +02001939 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001940 u8 *pdata;
1941
1942 DEBUG(1, "ft1000_hw: ft1000_start_xmit()\n");
1943 if (skb == NULL) {
1944 DEBUG(1, "ft1000_hw: ft1000_start_xmit:skb == NULL!!!\n");
1945 return 0;
1946 }
1947
1948 DEBUG(1, "ft1000_hw: ft1000_start_xmit:length of packet = %d\n",
1949 skb->len);
1950
1951 pdata = (u8 *) skb->data;
1952
1953 if (info->mediastate == 0) {
1954 /* Drop packet is mediastate is down */
1955 DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:mediastate is down\n");
1956 return SUCCESS;
1957 }
1958
1959 if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) {
1960 /* Drop packet which has invalid size */
1961 DEBUG(1,
1962 "ft1000_hw:ft1000_copy_down_pkt:invalid ethernet length\n");
1963 return SUCCESS;
1964 }
1965 ft1000_copy_down_pkt(dev, (u16 *) (pdata + ENET_HEADER_SIZE - 2),
1966 skb->len - ENET_HEADER_SIZE + 2);
1967
1968 dev_kfree_skb(skb);
1969
1970 return 0;
1971}
1972
1973static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
1974{
1975 struct net_device *dev = (struct net_device *)dev_id;
Ondrej Zaryd3706552011-07-01 00:03:42 +02001976 struct ft1000_info *info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02001977 u16 tempword;
1978 u16 inttype;
1979 int cnt;
1980
1981 DEBUG(1, "ft1000_hw: ft1000_interrupt()\n");
1982
1983 if (info->CardReady == 0) {
1984 ft1000_disable_interrupts(dev);
1985 return IRQ_HANDLED;
1986 }
1987
Ondrej Zaryca145272011-07-01 00:03:47 +02001988 if (ft1000_chkcard(dev) == false) {
Marek Beliskof7c1be02010-09-22 07:56:27 +02001989 ft1000_disable_interrupts(dev);
1990 return IRQ_HANDLED;
1991 }
1992
1993 ft1000_disable_interrupts(dev);
1994
1995 // Read interrupt type
1996 inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
1997
1998 // Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type
Devendra Naga80145a52012-07-10 10:36:05 +05301999 while (inttype) {
Devendra Naga64cab4e2012-07-07 17:35:12 +05302000 if (inttype & ISR_DOORBELL_PEND)
2001 ft1000_parse_dpram_msg(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002002
Devendra Naga80145a52012-07-10 10:36:05 +05302003 if (inttype & ISR_RCV) {
2004 DEBUG(1, "Data in FIFO\n");
Marek Beliskof7c1be02010-09-22 07:56:27 +02002005
Devendra Naga80145a52012-07-10 10:36:05 +05302006 cnt = 0;
2007 do {
2008 // Check if we have packets in the Downlink FIFO
2009 if (info->AsicID == ELECTRABUZZ_ID) {
2010 tempword =
2011 ft1000_read_reg(dev,
2012 FT1000_REG_DFIFO_STAT);
2013 } else {
2014 tempword =
2015 ft1000_read_reg(dev,
2016 FT1000_REG_MAG_DFSR);
2017 }
2018 if (tempword & 0x1f) {
2019 ft1000_copy_up_pkt(dev);
2020 } else {
2021 break;
2022 }
2023 cnt++;
2024 } while (cnt < MAX_RCV_LOOP);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002025
Devendra Naga80145a52012-07-10 10:36:05 +05302026 }
2027 // clear interrupts
2028 tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
2029 DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword);
2030 ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword);
2031
2032 // Read interrupt type
2033 inttype = ft1000_read_reg (dev, FT1000_REG_SUP_ISR);
2034 DEBUG(1,"ft1000_hw: interrupt status register after clear = 0x%x\n",inttype);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002035 }
Marek Beliskof7c1be02010-09-22 07:56:27 +02002036 ft1000_enable_interrupts(dev);
2037 return IRQ_HANDLED;
2038}
2039
2040void stop_ft1000_card(struct net_device *dev)
2041{
Ondrej Zaryd3706552011-07-01 00:03:42 +02002042 struct ft1000_info *info = netdev_priv(dev);
Ondrej Zary3aaf8072011-07-01 00:03:41 +02002043 struct prov_record *ptr;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002044// int cnt;
2045
2046 DEBUG(0, "ft1000_hw: stop_ft1000_card()\n");
2047
2048 info->CardReady = 0;
2049 ft1000_card_present = 0;
2050 netif_stop_queue(dev);
2051 ft1000_disable_interrupts(dev);
2052
2053 // Make sure we free any memory reserve for provisioning
2054 while (list_empty(&info->prov_list) == 0) {
Ondrej Zary3aaf8072011-07-01 00:03:41 +02002055 ptr = list_entry(info->prov_list.next, struct prov_record, list);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002056 list_del(&ptr->list);
2057 kfree(ptr->pprov_data);
2058 kfree(ptr);
2059 }
2060
2061 if (info->registered) {
2062 unregister_netdev(dev);
2063 info->registered = 0;
2064 }
2065
2066 free_irq(dev->irq, dev);
2067 release_region(dev->base_addr,256);
2068 release_firmware(fw_entry);
2069 flarion_ft1000_cnt--;
2070 ft1000CleanupProc(dev);
2071
2072}
2073
2074static void ft1000_get_drvinfo(struct net_device *dev,
2075 struct ethtool_drvinfo *info)
2076{
Ondrej Zaryd3706552011-07-01 00:03:42 +02002077 struct ft1000_info *ft_info;
Joe Perchese33196e2010-11-15 13:12:32 -08002078 ft_info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002079
2080 snprintf(info->driver, 32, "ft1000");
2081 snprintf(info->bus_info, ETHTOOL_BUSINFO_LEN, "PCMCIA 0x%lx",
2082 dev->base_addr);
2083 snprintf(info->fw_version, 32, "%d.%d.%d.%d", ft_info->DspVer[0],
2084 ft_info->DspVer[1], ft_info->DspVer[2], ft_info->DspVer[3]);
2085}
2086
2087static u32 ft1000_get_link(struct net_device *dev)
2088{
Ondrej Zaryd3706552011-07-01 00:03:42 +02002089 struct ft1000_info *info;
Joe Perchese33196e2010-11-15 13:12:32 -08002090 info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002091 return info->mediastate;
2092}
2093
2094static const struct ethtool_ops ops = {
2095 .get_drvinfo = ft1000_get_drvinfo,
2096 .get_link = ft1000_get_link
2097};
2098
Marek Beliskoc331e762011-01-10 13:14:28 +01002099struct net_device *init_ft1000_card(struct pcmcia_device *link,
Randy Dunlapeb93ca42011-08-08 11:31:48 -07002100 void *ft1000_reset)
Marek Beliskof7c1be02010-09-22 07:56:27 +02002101{
Ondrej Zaryd3706552011-07-01 00:03:42 +02002102 struct ft1000_info *info;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002103 struct net_device *dev;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002104
2105 static const struct net_device_ops ft1000ops = // Slavius 21.10.2009 due to kernel changes
2106 {
2107 .ndo_open = &ft1000_open,
2108 .ndo_stop = &ft1000_close,
2109 .ndo_start_xmit = &ft1000_start_xmit,
2110 .ndo_get_stats = &ft1000_stats,
2111 };
2112
2113 DEBUG(1, "ft1000_hw: init_ft1000_card()\n");
Marek Beliskoc331e762011-01-10 13:14:28 +01002114 DEBUG(1, "ft1000_hw: irq = %d\n", link->irq);
2115 DEBUG(1, "ft1000_hw: port = 0x%04x\n", link->resource[0]->start);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002116
2117 flarion_ft1000_cnt++;
2118
2119 if (flarion_ft1000_cnt > 1) {
2120 flarion_ft1000_cnt--;
2121
2122 printk(KERN_INFO
2123 "ft1000: This driver can not support more than one instance\n");
2124 return NULL;
2125 }
2126
Ondrej Zaryd3706552011-07-01 00:03:42 +02002127 dev = alloc_etherdev(sizeof(struct ft1000_info));
Marek Beliskof7c1be02010-09-22 07:56:27 +02002128 if (!dev) {
2129 printk(KERN_ERR "ft1000: failed to allocate etherdev\n");
2130 return NULL;
2131 }
2132
Marek Beliskoc331e762011-01-10 13:14:28 +01002133 SET_NETDEV_DEV(dev, &link->dev);
Joe Perchese33196e2010-11-15 13:12:32 -08002134 info = netdev_priv(dev);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002135
Ondrej Zaryd3706552011-07-01 00:03:42 +02002136 memset(info, 0, sizeof(struct ft1000_info));
Marek Beliskof7c1be02010-09-22 07:56:27 +02002137
2138 DEBUG(1, "address of dev = 0x%8x\n", (u32) dev);
2139 DEBUG(1, "address of dev info = 0x%8x\n", (u32) info);
2140 DEBUG(0, "device name = %s\n", dev->name);
2141
2142 memset(&info->stats, 0, sizeof(struct net_device_stats));
2143
2144 spin_lock_init(&info->dpram_lock);
2145 info->DrvErrNum = 0;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002146 info->registered = 1;
2147 info->link = link;
2148 info->ft1000_reset = ft1000_reset;
2149 info->mediastate = 0;
2150 info->fifo_cnt = 0;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002151 info->CardReady = 0;
2152 info->DSP_TIME[0] = 0;
2153 info->DSP_TIME[1] = 0;
2154 info->DSP_TIME[2] = 0;
2155 info->DSP_TIME[3] = 0;
2156 flarion_ft1000_cnt = 0;
2157
2158 INIT_LIST_HEAD(&info->prov_list);
2159
2160 info->squeseqnum = 0;
2161
2162// dev->hard_start_xmit = &ft1000_start_xmit;
2163// dev->get_stats = &ft1000_stats;
2164// dev->open = &ft1000_open;
2165// dev->stop = &ft1000_close;
2166
2167 dev->netdev_ops = &ft1000ops; // Slavius 21.10.2009 due to kernel changes
2168
2169 DEBUG(0, "device name = %s\n", dev->name);
2170
Marek Beliskoc331e762011-01-10 13:14:28 +01002171 dev->irq = link->irq;
2172 dev->base_addr = link->resource[0]->start;
2173 if (pcmcia_get_mac_from_cis(link, dev)) {
2174 printk(KERN_ERR "ft1000: Could not read mac address\n");
2175 goto err_dev;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002176 }
2177
Marek Beliskof7c1be02010-09-22 07:56:27 +02002178 if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name, dev)) {
2179 printk(KERN_ERR "ft1000: Could not request_irq\n");
Vasiliy Kulikovc95aef42010-09-28 21:49:35 +04002180 goto err_dev;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002181 }
2182
Vasiliy Kulikovc95aef42010-09-28 21:49:35 +04002183 if (request_region(dev->base_addr, 256, dev->name) == NULL) {
2184 printk(KERN_ERR "ft1000: Could not request_region\n");
2185 goto err_irq;
2186 }
Marek Beliskof7c1be02010-09-22 07:56:27 +02002187
2188 if (register_netdev(dev) != 0) {
2189 DEBUG(0, "ft1000: Could not register netdev");
Vasiliy Kulikovc95aef42010-09-28 21:49:35 +04002190 goto err_reg;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002191 }
2192
2193 info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
2194 if (info->AsicID == ELECTRABUZZ_ID) {
2195 DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n");
Marek Beliskoc331e762011-01-10 13:14:28 +01002196 if (request_firmware(&fw_entry, "ft1000.img", &link->dev) != 0) {
Marek Beliskof7c1be02010-09-22 07:56:27 +02002197 printk(KERN_INFO "ft1000: Could not open ft1000.img\n");
Vasiliy Kulikovc95aef42010-09-28 21:49:35 +04002198 goto err_unreg;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002199 }
2200 } else {
2201 DEBUG(0, "ft1000_hw: MAGNEMITE ASIC\n");
Marek Beliskoc331e762011-01-10 13:14:28 +01002202 if (request_firmware(&fw_entry, "ft2000.img", &link->dev) != 0) {
Marek Beliskof7c1be02010-09-22 07:56:27 +02002203 printk(KERN_INFO "ft1000: Could not open ft2000.img\n");
Vasiliy Kulikovc95aef42010-09-28 21:49:35 +04002204 goto err_unreg;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002205 }
2206 }
2207
2208 ft1000_enable_interrupts(dev);
2209
2210 ft1000InitProc(dev);
2211 ft1000_card_present = 1;
2212 SET_ETHTOOL_OPS(dev, &ops);
Danny Kukawka3274ce72012-02-24 14:46:01 +01002213 printk(KERN_INFO "ft1000: %s: addr 0x%04lx irq %d, MAC addr %pM\n",
2214 dev->name, dev->base_addr, dev->irq, dev->dev_addr);
Marek Beliskof7c1be02010-09-22 07:56:27 +02002215 return dev;
Vasiliy Kulikovc95aef42010-09-28 21:49:35 +04002216
2217err_unreg:
2218 unregister_netdev(dev);
2219err_reg:
2220 release_region(dev->base_addr, 256);
2221err_irq:
2222 free_irq(dev->irq, dev);
2223err_dev:
2224 free_netdev(dev);
2225 return NULL;
Marek Beliskof7c1be02010-09-22 07:56:27 +02002226}