]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
Merge tag 'mac80211-for-davem-2015-01-23' of git://git.kernel.org/pub/scm/linux/kerne...
[karo-tx-linux.git] / drivers / staging / ft1000 / ft1000-usb / ft1000_debug.c
1 /*
2  *---------------------------------------------------------------------------
3  * FT1000 driver for Flarion Flash OFDM NIC Device
4  *
5  * Copyright (C) 2006 Flarion Technologies, All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option) any
10  * later version. This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details. You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place -
16  * Suite 330, Boston, MA 02111-1307, USA.
17  *---------------------------------------------------------------------------
18  *
19  * File:         ft1000_chdev.c
20  *
21  * Description:  Custom character device dispatch routines.
22  *
23  * History:
24  * 8/29/02    Whc                Ported to Linux.
25  * 6/05/06    Whc                Porting to Linux 2.6.9
26  *
27  *---------------------------------------------------------------------------
28  */
29
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/sched.h>
35 #include <linux/errno.h>
36 #include <linux/poll.h>
37 #include <linux/netdevice.h>
38 #include <linux/delay.h>
39
40 #include <linux/ioctl.h>
41 #include <linux/debugfs.h>
42 #include "ft1000_usb.h"
43
44 static int ft1000_flarion_cnt;
45
46 static int ft1000_open(struct inode *inode, struct file *file);
47 static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait);
48 static long ft1000_ioctl(struct file *file, unsigned int command,
49                          unsigned long argument);
50 static int ft1000_release(struct inode *inode, struct file *file);
51
52 /* List to free receive command buffer pool */
53 struct list_head freercvpool;
54
55 /* lock to arbitrate free buffer list for receive command data */
56 spinlock_t free_buff_lock;
57
58 int numofmsgbuf = 0;
59
60 /*
61  * Table of entry-point routines for char device
62  */
63 static const struct file_operations ft1000fops = {
64         .unlocked_ioctl = ft1000_ioctl,
65         .poll           = ft1000_poll_dev,
66         .open           = ft1000_open,
67         .release        = ft1000_release,
68         .llseek         = no_llseek,
69 };
70
71 /*
72   ---------------------------------------------------------------------------
73   * Function:    ft1000_get_buffer
74   *
75   * Parameters:
76   *
77   * Returns:
78   *
79   * Description:
80   *
81   * Notes:
82   *
83   *---------------------------------------------------------------------------
84   */
85 struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist)
86 {
87         unsigned long flags;
88         struct dpram_blk *ptr;
89
90         spin_lock_irqsave(&free_buff_lock, flags);
91         /* Check if buffer is available */
92         if (list_empty(bufflist)) {
93                 pr_debug("No more buffer - %d\n", numofmsgbuf);
94                 ptr = NULL;
95         } else {
96                 numofmsgbuf--;
97                 ptr = list_entry(bufflist->next, struct dpram_blk, list);
98                 list_del(&ptr->list);
99                 /* pr_debug("number of free msg buffers = %d\n", numofmsgbuf); */
100         }
101         spin_unlock_irqrestore(&free_buff_lock, flags);
102
103         return ptr;
104 }
105
106
107
108
109 /*
110  *---------------------------------------------------------------------------
111  * Function:    ft1000_free_buffer
112  *
113  * Parameters:
114  *
115  * Returns:
116  *
117  * Description:
118  *
119  * Notes:
120  *
121  *---------------------------------------------------------------------------
122  */
123 void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist)
124 {
125         unsigned long flags;
126
127         spin_lock_irqsave(&free_buff_lock, flags);
128         /* Put memory back to list */
129         list_add_tail(&pdpram_blk->list, plist);
130         numofmsgbuf++;
131         /*pr_debug("number of free msg buffers = %d\n", numofmsgbuf); */
132         spin_unlock_irqrestore(&free_buff_lock, flags);
133 }
134
135 /*
136  *---------------------------------------------------------------------------
137  * Function:    ft1000_CreateDevice
138  *
139  * Parameters:  dev - pointer to adapter object
140  *
141  * Returns:     0 if successful
142  *
143  * Description: Creates a private char device.
144  *
145  * Notes:       Only called by init_module().
146  *
147  *---------------------------------------------------------------------------
148  */
149 int ft1000_create_dev(struct ft1000_usb *dev)
150 {
151         int result;
152         int i;
153         struct dentry *dir, *file;
154         struct ft1000_debug_dirs *tmp;
155
156         /* make a new device name */
157         sprintf(dev->DeviceName, "%s%d", "FT1000_", dev->CardNumber);
158
159         pr_debug("number of instance = %d\n", ft1000_flarion_cnt);
160         pr_debug("DeviceCreated = %x\n", dev->DeviceCreated);
161
162         if (dev->DeviceCreated) {
163                 pr_debug("\"%s\" already registered\n", dev->DeviceName);
164                 return -EIO;
165         }
166
167
168         /* register the device */
169         pr_debug("\"%s\" debugfs device registration\n", dev->DeviceName);
170
171         tmp = kmalloc(sizeof(struct ft1000_debug_dirs), GFP_KERNEL);
172         if (tmp == NULL) {
173                 result = -1;
174                 goto fail;
175         }
176
177         dir = debugfs_create_dir(dev->DeviceName, NULL);
178         if (IS_ERR(dir)) {
179                 result = PTR_ERR(dir);
180                 goto debug_dir_fail;
181         }
182
183         file = debugfs_create_file("device", S_IRUGO | S_IWUSR, dir,
184                                    dev, &ft1000fops);
185         if (IS_ERR(file)) {
186                 result = PTR_ERR(file);
187                 goto debug_file_fail;
188         }
189
190         tmp->dent = dir;
191         tmp->file = file;
192         tmp->int_number = dev->CardNumber;
193         list_add(&(tmp->list), &(dev->nodes.list));
194
195         pr_debug("registered debugfs directory \"%s\"\n", dev->DeviceName);
196
197         /* initialize application information */
198         dev->appcnt = 0;
199         for (i = 0; i < MAX_NUM_APP; i++) {
200                 dev->app_info[i].nTxMsg = 0;
201                 dev->app_info[i].nRxMsg = 0;
202                 dev->app_info[i].nTxMsgReject = 0;
203                 dev->app_info[i].nRxMsgMiss = 0;
204                 dev->app_info[i].fileobject = NULL;
205                 dev->app_info[i].app_id = i+1;
206                 dev->app_info[i].DspBCMsgFlag = 0;
207                 dev->app_info[i].NumOfMsg = 0;
208                 init_waitqueue_head(&dev->app_info[i].wait_dpram_msg);
209                 INIT_LIST_HEAD(&dev->app_info[i].app_sqlist);
210         }
211
212         dev->DeviceCreated = TRUE;
213         ft1000_flarion_cnt++;
214
215         return 0;
216
217 debug_file_fail:
218         debugfs_remove(dir);
219 debug_dir_fail:
220         kfree(tmp);
221 fail:
222         return result;
223 }
224
225 /*
226  *---------------------------------------------------------------------------
227  * Function:    ft1000_DestroyDeviceDEBUG
228  *
229  * Parameters:  dev - pointer to adapter object
230  *
231  * Description: Destroys a private char device.
232  *
233  * Notes:       Only called by cleanup_module().
234  *
235  *---------------------------------------------------------------------------
236  */
237 void ft1000_destroy_dev(struct net_device *netdev)
238 {
239         struct ft1000_info *info = netdev_priv(netdev);
240         struct ft1000_usb *dev = info->priv;
241         int i;
242         struct dpram_blk *pdpram_blk;
243         struct dpram_blk *ptr;
244         struct list_head *pos, *q;
245         struct ft1000_debug_dirs *dir;
246
247         if (dev->DeviceCreated) {
248                 ft1000_flarion_cnt--;
249                 list_for_each_safe(pos, q, &dev->nodes.list) {
250                         dir = list_entry(pos, struct ft1000_debug_dirs, list);
251                         if (dir->int_number == dev->CardNumber) {
252                                 debugfs_remove(dir->file);
253                                 debugfs_remove(dir->dent);
254                                 list_del(pos);
255                                 kfree(dir);
256                         }
257                 }
258                 pr_debug("unregistered device \"%s\"\n", dev->DeviceName);
259
260                 /* Make sure we free any memory reserve for slow Queue */
261                 for (i = 0; i < MAX_NUM_APP; i++) {
262                         while (list_empty(&dev->app_info[i].app_sqlist) == 0) {
263                                 pdpram_blk = list_entry(dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
264                                 list_del(&pdpram_blk->list);
265                                 ft1000_free_buffer(pdpram_blk, &freercvpool);
266
267                         }
268                         wake_up_interruptible(&dev->app_info[i].wait_dpram_msg);
269                 }
270
271                 /* Remove buffer allocated for receive command data */
272                 if (ft1000_flarion_cnt == 0) {
273                         while (list_empty(&freercvpool) == 0) {
274                                 ptr = list_entry(freercvpool.next, struct dpram_blk, list);
275                                 list_del(&ptr->list);
276                                 kfree(ptr->pbuffer);
277                                 kfree(ptr);
278                         }
279                 }
280                 dev->DeviceCreated = FALSE;
281         }
282
283
284 }
285
286 /*
287  *---------------------------------------------------------------------------
288  * Function:    ft1000_open
289  *
290  * Parameters:
291  *
292  * Description:
293  *
294  * Notes:
295  *
296  *---------------------------------------------------------------------------
297  */
298 static int ft1000_open(struct inode *inode, struct file *file)
299 {
300         struct ft1000_info *info;
301         struct ft1000_usb *dev = (struct ft1000_usb *)inode->i_private;
302         int i, num;
303
304         num = (MINOR(inode->i_rdev) & 0xf);
305         pr_debug("minor number=%d\n", num);
306
307         info = file->private_data = netdev_priv(dev->net);
308
309         pr_debug("f_owner = %p number of application = %d\n",
310                  &file->f_owner, dev->appcnt);
311
312         /* Check if maximum number of application exceeded */
313         if (dev->appcnt > MAX_NUM_APP) {
314                 pr_debug("Maximum number of application exceeded\n");
315                 return -EACCES;
316         }
317
318         /* Search for available application info block */
319         for (i = 0; i < MAX_NUM_APP; i++) {
320                 if ((dev->app_info[i].fileobject == NULL)) {
321                         break;
322                 }
323         }
324
325         /* Fail due to lack of application info block */
326         if (i == MAX_NUM_APP) {
327                 pr_debug("Could not find an application info block\n");
328                 return -EACCES;
329         }
330
331         dev->appcnt++;
332         dev->app_info[i].fileobject = &file->f_owner;
333         dev->app_info[i].nTxMsg = 0;
334         dev->app_info[i].nRxMsg = 0;
335         dev->app_info[i].nTxMsgReject = 0;
336         dev->app_info[i].nRxMsgMiss = 0;
337
338         nonseekable_open(inode, file);
339         return 0;
340 }
341
342
343 /*
344  *---------------------------------------------------------------------------
345  * Function:    ft1000_poll_dev
346  *
347  * Parameters:
348  *
349  * Description:
350  *
351  * Notes:
352  *
353  *---------------------------------------------------------------------------
354  */
355
356 static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait)
357 {
358         struct net_device *netdev = file->private_data;
359         struct ft1000_info *info = netdev_priv(netdev);
360         struct ft1000_usb *dev = info->priv;
361         int i;
362
363         if (ft1000_flarion_cnt == 0) {
364                 pr_debug("called with ft1000_flarion_cnt value zero\n");
365                 return -EBADF;
366         }
367
368         /* Search for matching file object */
369         for (i = 0; i < MAX_NUM_APP; i++) {
370                 if (dev->app_info[i].fileobject == &file->f_owner) {
371                         /* pr_debug("Message is for AppId = %d\n", dev->app_info[i].app_id); */
372                         break;
373                 }
374         }
375
376         /* Could not find application info block */
377         if (i == MAX_NUM_APP) {
378                 pr_debug("Could not find application info block\n");
379                 return -EACCES;
380         }
381
382         if (list_empty(&dev->app_info[i].app_sqlist) == 0) {
383                 pr_debug("Message detected in slow queue\n");
384                 return(POLLIN | POLLRDNORM | POLLPRI);
385         }
386
387         poll_wait(file, &dev->app_info[i].wait_dpram_msg, wait);
388         /* pr_debug("Polling for data from DSP\n"); */
389
390         return 0;
391 }
392
393 /*
394  *---------------------------------------------------------------------------
395  * Function:    ft1000_ioctl
396  *
397  * Parameters:
398  *
399  * Description:
400  *
401  * Notes:
402  *
403  *---------------------------------------------------------------------------
404  */
405 static long ft1000_ioctl(struct file *file, unsigned int command,
406                          unsigned long argument)
407 {
408         void __user *argp = (void __user *)argument;
409         struct ft1000_info *info;
410         struct ft1000_usb *ft1000dev;
411         int result = 0;
412         int cmd;
413         int i;
414         u16 tempword;
415         unsigned long flags;
416         struct timeval tv;
417         struct IOCTL_GET_VER get_ver_data;
418         struct IOCTL_GET_DSP_STAT get_stat_data;
419         u8 ConnectionMsg[] = {0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
420                               0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
421                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423                               0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
424                               0x00, 0x01, 0x00, 0x00};
425
426         unsigned short ledStat = 0;
427         unsigned short conStat = 0;
428
429         if (ft1000_flarion_cnt == 0) {
430                 pr_debug("called with ft1000_flarion_cnt of zero\n");
431                 return -EBADF;
432         }
433
434         /* pr_debug("command = 0x%x argument = 0x%8x\n", command, (u32)argument); */
435
436         info = file->private_data;
437         ft1000dev = info->priv;
438         cmd = _IOC_NR(command);
439         /* pr_debug("cmd = 0x%x\n", cmd); */
440
441         /* process the command */
442         switch (cmd) {
443         case IOCTL_REGISTER_CMD:
444                 pr_debug("IOCTL_FT1000_REGISTER called\n");
445                 result = get_user(tempword, (__u16 __user *)argp);
446                 if (result) {
447                         pr_debug("result = %d failed to get_user\n", result);
448                         break;
449                 }
450                 if (tempword == DSPBCMSGID) {
451                         /* Search for matching file object */
452                         for (i = 0; i < MAX_NUM_APP; i++) {
453                                 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
454                                         ft1000dev->app_info[i].DspBCMsgFlag = 1;
455                                         pr_debug("Registered for broadcast messages\n");
456                                         break;
457                                 }
458                         }
459                 }
460                 break;
461
462         case IOCTL_GET_VER_CMD:
463                 pr_debug("IOCTL_FT1000_GET_VER called\n");
464
465                 get_ver_data.drv_ver = FT1000_DRV_VER;
466
467                 if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data))) {
468                         pr_debug("copy fault occurred\n");
469                         result = -EFAULT;
470                         break;
471                 }
472
473                 pr_debug("driver version = 0x%x\n",
474                          (unsigned int)get_ver_data.drv_ver);
475
476                 break;
477         case IOCTL_CONNECT:
478                 /* Connect Message */
479                 pr_debug("IOCTL_FT1000_CONNECT\n");
480                 ConnectionMsg[79] = 0xfc;
481                 result = card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
482
483                 break;
484         case IOCTL_DISCONNECT:
485                 /* Disconnect Message */
486                 pr_debug("IOCTL_FT1000_DISCONNECT\n");
487                 ConnectionMsg[79] = 0xfd;
488                 result = card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
489                 break;
490         case IOCTL_GET_DSP_STAT_CMD:
491                 /* pr_debug("IOCTL_FT1000_GET_DSP_STAT\n"); */
492                 memset(&get_stat_data, 0, sizeof(get_stat_data));
493                 memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
494                 memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
495                 memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
496                 memcpy(get_stat_data.eui64, info->eui64, EUISZ);
497
498                 if (info->ProgConStat != 0xFF) {
499                         ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
500                         get_stat_data.LedStat = ntohs(ledStat);
501                         pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
502                         ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
503                         get_stat_data.ConStat = ntohs(conStat);
504                         pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
505                 } else {
506                         get_stat_data.ConStat = 0x0f;
507                 }
508
509
510                 get_stat_data.nTxPkts = info->stats.tx_packets;
511                 get_stat_data.nRxPkts = info->stats.rx_packets;
512                 get_stat_data.nTxBytes = info->stats.tx_bytes;
513                 get_stat_data.nRxBytes = info->stats.rx_bytes;
514                 do_gettimeofday(&tv);
515                 get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
516                 pr_debug("Connection Time = %d\n", (int)get_stat_data.ConTm);
517                 if (copy_to_user(argp, &get_stat_data, sizeof(get_stat_data))) {
518                         pr_debug("copy fault occurred\n");
519                         result = -EFAULT;
520                         break;
521                 }
522                 pr_debug("GET_DSP_STAT succeed\n");
523                 break;
524         case IOCTL_SET_DPRAM_CMD:
525         {
526                 struct IOCTL_DPRAM_BLK *dpram_data = NULL;
527                 /* struct IOCTL_DPRAM_COMMAND dpram_command; */
528                 u16 qtype;
529                 u16 msgsz;
530                 struct pseudo_hdr *ppseudo_hdr;
531                 u16 *pmsg;
532                 u16 total_len;
533                 u16 app_index;
534                 u16 status;
535
536                 /* pr_debug("IOCTL_FT1000_SET_DPRAM called\n");*/
537
538
539                 if (ft1000_flarion_cnt == 0)
540                         return -EBADF;
541
542                 if (ft1000dev->DrvMsgPend)
543                         return -ENOTTY;
544
545                 if (ft1000dev->fProvComplete == 0)
546                         return -EACCES;
547
548                 ft1000dev->fAppMsgPend = 1;
549
550                 if (info->CardReady) {
551
552                         /* pr_debug("try to SET_DPRAM\n"); */
553
554                         /* Get the length field to see how many bytes to copy */
555                         result = get_user(msgsz, (__u16 __user *)argp);
556                         if (result)
557                                 break;
558                         msgsz = ntohs(msgsz);
559                         /* pr_debug("length of message = %d\n", msgsz); */
560
561                         if (msgsz > MAX_CMD_SQSIZE) {
562                                 pr_debug("bad message length = %d\n", msgsz);
563                                 result = -EINVAL;
564                                 break;
565                         }
566
567                         result = -ENOMEM;
568                         dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
569                         if (!dpram_data)
570                                 break;
571
572                         if (copy_from_user(dpram_data, argp, msgsz+2)) {
573                                 pr_debug("copy fault occurred\n");
574                                 result = -EFAULT;
575                         } else {
576                                 /* Check if this message came from a registered application */
577                                 for (i = 0; i < MAX_NUM_APP; i++) {
578                                         if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
579                                                 break;
580                                         }
581                                 }
582                                 if (i == MAX_NUM_APP) {
583                                         pr_debug("No matching application fileobject\n");
584                                         result = -EINVAL;
585                                         kfree(dpram_data);
586                                         break;
587                                 }
588                                 app_index = i;
589
590                                 /* Check message qtype type which is the lower byte within qos_class */
591                                 qtype = ntohs(dpram_data->pseudohdr.qos_class) & 0xff;
592                                 /* pr_debug("qtype = %d\n", qtype); */
593                                 if (qtype) {
594                                 } else {
595                                         /* Put message into Slow Queue */
596                                         /* Only put a message into the DPRAM if msg doorbell is available */
597                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
598                                         /* pr_debug("READ REGISTER tempword=%x\n", tempword); */
599                                         if (tempword & FT1000_DB_DPRAM_TX) {
600                                                 /* Suspend for 2ms and try again due to DSP doorbell busy */
601                                                 mdelay(2);
602                                                 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
603                                                 if (tempword & FT1000_DB_DPRAM_TX) {
604                                                         /* Suspend for 1ms and try again due to DSP doorbell busy */
605                                                         mdelay(1);
606                                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
607                                                         if (tempword & FT1000_DB_DPRAM_TX) {
608                                                                 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
609                                                                 if (tempword & FT1000_DB_DPRAM_TX) {
610                                                                         /* Suspend for 3ms and try again due to DSP doorbell busy */
611                                                                         mdelay(3);
612                                                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
613                                                                         if (tempword & FT1000_DB_DPRAM_TX) {
614                                                                                 pr_debug("Doorbell not available\n");
615                                                                                 result = -ENOTTY;
616                                                                                 kfree(dpram_data);
617                                                                                 break;
618                                                                         }
619                                                                 }
620                                                         }
621                                                 }
622                                         }
623
624                                         /*pr_debug("finished reading register\n"); */
625
626                                         /* Make sure we are within the limits of the slow queue memory limitation */
627                                         if ((msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ)) {
628                                                 /* Need to put sequence number plus new checksum for message */
629                                                 pmsg = (u16 *)&dpram_data->pseudohdr;
630                                                 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
631                                                 total_len = msgsz+2;
632                                                 if (total_len & 0x1) {
633                                                         total_len++;
634                                                 }
635
636                                                 /* Insert slow queue sequence number */
637                                                 ppseudo_hdr->seq_num = info->squeseqnum++;
638                                                 ppseudo_hdr->portsrc = ft1000dev->app_info[app_index].app_id;
639                                                 /* Calculate new checksum */
640                                                 ppseudo_hdr->checksum = *pmsg++;
641                                                 /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
642                                                 for (i = 1; i < 7; i++) {
643                                                         ppseudo_hdr->checksum ^= *pmsg++;
644                                                         /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
645                                                 }
646                                                 pmsg++;
647                                                 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
648                                                 result = card_send_command(ft1000dev, (unsigned short *)dpram_data, total_len+2);
649
650
651                                                 ft1000dev->app_info[app_index].nTxMsg++;
652                                         } else {
653                                                 result = -EINVAL;
654                                         }
655                                 }
656                         }
657                 } else {
658                         pr_debug("Card not ready take messages\n");
659                         result = -EACCES;
660                 }
661                 kfree(dpram_data);
662
663         }
664         break;
665         case IOCTL_GET_DPRAM_CMD:
666         {
667                 struct dpram_blk *pdpram_blk;
668                 struct IOCTL_DPRAM_BLK __user *pioctl_dpram;
669                 int msglen;
670
671                 /* pr_debug("IOCTL_FT1000_GET_DPRAM called\n"); */
672
673                 if (ft1000_flarion_cnt == 0)
674                         return -EBADF;
675
676                 /* Search for matching file object */
677                 for (i = 0; i < MAX_NUM_APP; i++) {
678                         if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
679                                 /*pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
680                                 break;
681                         }
682                 }
683
684                 /* Could not find application info block */
685                 if (i == MAX_NUM_APP) {
686                         pr_debug("Could not find application info block\n");
687                         result = -EBADF;
688                         break;
689                 }
690
691                 result = 0;
692                 pioctl_dpram = argp;
693                 if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
694                         /* pr_debug("Message detected in slow queue\n"); */
695                         spin_lock_irqsave(&free_buff_lock, flags);
696                         pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
697                         list_del(&pdpram_blk->list);
698                         ft1000dev->app_info[i].NumOfMsg--;
699                         /* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
700                         spin_unlock_irqrestore(&free_buff_lock, flags);
701                         msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
702                         result = get_user(msglen, &pioctl_dpram->total_len);
703                         if (result)
704                                 break;
705                         msglen = htons(msglen);
706                         /* pr_debug("msg length = %x\n", msglen); */
707                         if (copy_to_user(&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen)) {
708                                 pr_debug("copy fault occurred\n");
709                                 result = -EFAULT;
710                                 break;
711                         }
712
713                         ft1000_free_buffer(pdpram_blk, &freercvpool);
714                         result = msglen;
715                 }
716                 /* pr_debug("IOCTL_FT1000_GET_DPRAM no message\n"); */
717         }
718         break;
719
720         default:
721                 pr_debug("unknown command: 0x%x\n", command);
722                 result = -ENOTTY;
723                 break;
724         }
725         ft1000dev->fAppMsgPend = 0;
726         return result;
727 }
728
729 /*
730  *---------------------------------------------------------------------------
731  * Function:    ft1000_release
732  *
733  * Parameters:
734  *
735  * Description:
736  *
737  * Notes:
738  *
739  *---------------------------------------------------------------------------
740  */
741 static int ft1000_release(struct inode *inode, struct file *file)
742 {
743         struct ft1000_info *info;
744         struct net_device *dev;
745         struct ft1000_usb *ft1000dev;
746         int i;
747         struct dpram_blk *pdpram_blk;
748
749         dev = file->private_data;
750         info = netdev_priv(dev);
751         ft1000dev = info->priv;
752
753         if (ft1000_flarion_cnt == 0) {
754                 ft1000dev->appcnt--;
755                 return -EBADF;
756         }
757
758         /* Search for matching file object */
759         for (i = 0; i < MAX_NUM_APP; i++) {
760                 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
761                         /* pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
762                         break;
763                 }
764         }
765
766         if (i == MAX_NUM_APP)
767                 return 0;
768
769         while (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
770                 pr_debug("Remove and free memory queue up on slow queue\n");
771                 pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
772                 list_del(&pdpram_blk->list);
773                 ft1000_free_buffer(pdpram_blk, &freercvpool);
774         }
775
776         /* initialize application information */
777         ft1000dev->appcnt--;
778         pr_debug("appcnt = %d\n", ft1000dev->appcnt);
779         ft1000dev->app_info[i].fileobject = NULL;
780
781         return 0;
782 }