Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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         /* Fail due to lack of application info block */
325         if (i == MAX_NUM_APP) {
326                 pr_debug("Could not find an application info block\n");
327                 return -EACCES;
328         }
329
330         dev->appcnt++;
331         dev->app_info[i].fileobject = &file->f_owner;
332         dev->app_info[i].nTxMsg = 0;
333         dev->app_info[i].nRxMsg = 0;
334         dev->app_info[i].nTxMsgReject = 0;
335         dev->app_info[i].nRxMsgMiss = 0;
336
337         nonseekable_open(inode, file);
338         return 0;
339 }
340
341
342 /*
343  *---------------------------------------------------------------------------
344  * Function:    ft1000_poll_dev
345  *
346  * Parameters:
347  *
348  * Description:
349  *
350  * Notes:
351  *
352  *---------------------------------------------------------------------------
353  */
354
355 static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait)
356 {
357         struct net_device *netdev = file->private_data;
358         struct ft1000_info *info = netdev_priv(netdev);
359         struct ft1000_usb *dev = info->priv;
360         int i;
361
362         if (ft1000_flarion_cnt == 0) {
363                 pr_debug("called with ft1000_flarion_cnt value zero\n");
364                 return -EBADF;
365         }
366
367         /* Search for matching file object */
368         for (i = 0; i < MAX_NUM_APP; i++) {
369                 if (dev->app_info[i].fileobject == &file->f_owner) {
370                         /* pr_debug("Message is for AppId = %d\n", dev->app_info[i].app_id); */
371                         break;
372                 }
373         }
374
375         /* Could not find application info block */
376         if (i == MAX_NUM_APP) {
377                 pr_debug("Could not find application info block\n");
378                 return -EACCES;
379         }
380
381         if (list_empty(&dev->app_info[i].app_sqlist) == 0) {
382                 pr_debug("Message detected in slow queue\n");
383                 return(POLLIN | POLLRDNORM | POLLPRI);
384         }
385
386         poll_wait(file, &dev->app_info[i].wait_dpram_msg, wait);
387         /* pr_debug("Polling for data from DSP\n"); */
388
389         return 0;
390 }
391
392 /*
393  *---------------------------------------------------------------------------
394  * Function:    ft1000_ioctl
395  *
396  * Parameters:
397  *
398  * Description:
399  *
400  * Notes:
401  *
402  *---------------------------------------------------------------------------
403  */
404 static long ft1000_ioctl(struct file *file, unsigned int command,
405                          unsigned long argument)
406 {
407         void __user *argp = (void __user *)argument;
408         struct ft1000_info *info;
409         struct ft1000_usb *ft1000dev;
410         int result = 0;
411         int cmd;
412         int i;
413         u16 tempword;
414         unsigned long flags;
415         struct timeval tv;
416         struct IOCTL_GET_VER get_ver_data;
417         struct IOCTL_GET_DSP_STAT get_stat_data;
418         u8 ConnectionMsg[] = {0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
419                               0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
420                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422                               0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
423                               0x00, 0x01, 0x00, 0x00};
424
425         unsigned short ledStat = 0;
426         unsigned short conStat = 0;
427
428         if (ft1000_flarion_cnt == 0) {
429                 pr_debug("called with ft1000_flarion_cnt of zero\n");
430                 return -EBADF;
431         }
432
433         /* pr_debug("command = 0x%x argument = 0x%8x\n", command, (u32)argument); */
434
435         info = file->private_data;
436         ft1000dev = info->priv;
437         cmd = _IOC_NR(command);
438         /* pr_debug("cmd = 0x%x\n", cmd); */
439
440         /* process the command */
441         switch (cmd) {
442         case IOCTL_REGISTER_CMD:
443                 pr_debug("IOCTL_FT1000_REGISTER called\n");
444                 result = get_user(tempword, (__u16 __user *)argp);
445                 if (result) {
446                         pr_debug("result = %d failed to get_user\n", result);
447                         break;
448                 }
449                 if (tempword == DSPBCMSGID) {
450                         /* Search for matching file object */
451                         for (i = 0; i < MAX_NUM_APP; i++) {
452                                 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
453                                         ft1000dev->app_info[i].DspBCMsgFlag = 1;
454                                         pr_debug("Registered for broadcast messages\n");
455                                         break;
456                                 }
457                         }
458                 }
459                 break;
460
461         case IOCTL_GET_VER_CMD:
462                 pr_debug("IOCTL_FT1000_GET_VER called\n");
463
464                 get_ver_data.drv_ver = FT1000_DRV_VER;
465
466                 if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data))) {
467                         pr_debug("copy fault occurred\n");
468                         result = -EFAULT;
469                         break;
470                 }
471
472                 pr_debug("driver version = 0x%x\n",
473                          (unsigned int)get_ver_data.drv_ver);
474
475                 break;
476         case IOCTL_CONNECT:
477                 /* Connect Message */
478                 pr_debug("IOCTL_FT1000_CONNECT\n");
479                 ConnectionMsg[79] = 0xfc;
480                 result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
481
482                 break;
483         case IOCTL_DISCONNECT:
484                 /* Disconnect Message */
485                 pr_debug("IOCTL_FT1000_DISCONNECT\n");
486                 ConnectionMsg[79] = 0xfd;
487                 result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
488                 break;
489         case IOCTL_GET_DSP_STAT_CMD:
490                 /* pr_debug("IOCTL_FT1000_GET_DSP_STAT\n"); */
491                 memset(&get_stat_data, 0, sizeof(get_stat_data));
492                 memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
493                 memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
494                 memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
495                 memcpy(get_stat_data.eui64, info->eui64, EUISZ);
496
497                 if (info->ProgConStat != 0xFF) {
498                         ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
499                         get_stat_data.LedStat = ntohs(ledStat);
500                         pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
501                         ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
502                         get_stat_data.ConStat = ntohs(conStat);
503                         pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
504                 } else {
505                         get_stat_data.ConStat = 0x0f;
506                 }
507
508
509                 get_stat_data.nTxPkts = info->stats.tx_packets;
510                 get_stat_data.nRxPkts = info->stats.rx_packets;
511                 get_stat_data.nTxBytes = info->stats.tx_bytes;
512                 get_stat_data.nRxBytes = info->stats.rx_bytes;
513                 do_gettimeofday(&tv);
514                 get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
515                 pr_debug("Connection Time = %d\n", (int)get_stat_data.ConTm);
516                 if (copy_to_user(argp, &get_stat_data, sizeof(get_stat_data))) {
517                         pr_debug("copy fault occurred\n");
518                         result = -EFAULT;
519                         break;
520                 }
521                 pr_debug("GET_DSP_STAT succeed\n");
522                 break;
523         case IOCTL_SET_DPRAM_CMD:
524         {
525                 struct IOCTL_DPRAM_BLK *dpram_data = NULL;
526                 /* struct IOCTL_DPRAM_COMMAND dpram_command; */
527                 u16 qtype;
528                 u16 msgsz;
529                 struct pseudo_hdr *ppseudo_hdr;
530                 u16 *pmsg;
531                 u16 total_len;
532                 u16 app_index;
533                 u16 status;
534
535                 /* pr_debug("IOCTL_FT1000_SET_DPRAM called\n");*/
536
537
538                 if (ft1000_flarion_cnt == 0)
539                         return -EBADF;
540
541                 if (ft1000dev->DrvMsgPend)
542                         return -ENOTTY;
543
544                 if (ft1000dev->fProvComplete == 0)
545                         return -EACCES;
546
547                 ft1000dev->fAppMsgPend = true;
548
549                 if (info->CardReady) {
550
551                         /* pr_debug("try to SET_DPRAM\n"); */
552
553                         /* Get the length field to see how many bytes to copy */
554                         result = get_user(msgsz, (__u16 __user *)argp);
555                         if (result)
556                                 break;
557                         msgsz = ntohs(msgsz);
558                         /* pr_debug("length of message = %d\n", msgsz); */
559
560                         if (msgsz > MAX_CMD_SQSIZE) {
561                                 pr_debug("bad message length = %d\n", msgsz);
562                                 result = -EINVAL;
563                                 break;
564                         }
565
566                         result = -ENOMEM;
567                         dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
568                         if (!dpram_data)
569                                 break;
570
571                         if (copy_from_user(dpram_data, argp, msgsz+2)) {
572                                 pr_debug("copy fault occurred\n");
573                                 result = -EFAULT;
574                         } else {
575                                 /* Check if this message came from a registered application */
576                                 for (i = 0; i < MAX_NUM_APP; i++) {
577                                         if (ft1000dev->app_info[i].fileobject == &file->f_owner)
578                                                 break;
579                                 }
580                                 if (i == MAX_NUM_APP) {
581                                         pr_debug("No matching application fileobject\n");
582                                         result = -EINVAL;
583                                         kfree(dpram_data);
584                                         break;
585                                 }
586                                 app_index = i;
587
588                                 /* Check message qtype type which is the lower byte within qos_class */
589                                 qtype = ntohs(dpram_data->pseudohdr.qos_class) & 0xff;
590                                 /* pr_debug("qtype = %d\n", qtype); */
591                                 if (qtype) {
592                                 } else {
593                                         /* Put message into Slow Queue */
594                                         /* Only put a message into the DPRAM if msg doorbell is available */
595                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
596                                         /* pr_debug("READ REGISTER tempword=%x\n", tempword); */
597                                         if (tempword & FT1000_DB_DPRAM_TX) {
598                                                 /* Suspend for 2ms and try again due to DSP doorbell busy */
599                                                 mdelay(2);
600                                                 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
601                                                 if (tempword & FT1000_DB_DPRAM_TX) {
602                                                         /* Suspend for 1ms and try again due to DSP doorbell busy */
603                                                         mdelay(1);
604                                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
605                                                         if (tempword & FT1000_DB_DPRAM_TX) {
606                                                                 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
607                                                                 if (tempword & FT1000_DB_DPRAM_TX) {
608                                                                         /* Suspend for 3ms and try again due to DSP doorbell busy */
609                                                                         mdelay(3);
610                                                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
611                                                                         if (tempword & FT1000_DB_DPRAM_TX) {
612                                                                                 pr_debug("Doorbell not available\n");
613                                                                                 result = -ENOTTY;
614                                                                                 kfree(dpram_data);
615                                                                                 break;
616                                                                         }
617                                                                 }
618                                                         }
619                                                 }
620                                         }
621
622                                         /*pr_debug("finished reading register\n"); */
623
624                                         /* Make sure we are within the limits of the slow queue memory limitation */
625                                         if ((msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ)) {
626                                                 /* Need to put sequence number plus new checksum for message */
627                                                 pmsg = (u16 *)&dpram_data->pseudohdr;
628                                                 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
629                                                 total_len = msgsz+2;
630                                                 if (total_len & 0x1)
631                                                         total_len++;
632
633                                                 /* Insert slow queue sequence number */
634                                                 ppseudo_hdr->seq_num = info->squeseqnum++;
635                                                 ppseudo_hdr->portsrc = ft1000dev->app_info[app_index].app_id;
636                                                 /* Calculate new checksum */
637                                                 ppseudo_hdr->checksum = *pmsg++;
638                                                 /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
639                                                 for (i = 1; i < 7; i++) {
640                                                         ppseudo_hdr->checksum ^= *pmsg++;
641                                                         /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
642                                                 }
643                                                 pmsg++;
644                                                 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
645                                                 result = card_send_command(ft1000dev, dpram_data, total_len+2);
646
647
648                                                 ft1000dev->app_info[app_index].nTxMsg++;
649                                         } else {
650                                                 result = -EINVAL;
651                                         }
652                                 }
653                         }
654                 } else {
655                         pr_debug("Card not ready take messages\n");
656                         result = -EACCES;
657                 }
658                 kfree(dpram_data);
659
660         }
661         break;
662         case IOCTL_GET_DPRAM_CMD:
663         {
664                 struct dpram_blk *pdpram_blk;
665                 struct IOCTL_DPRAM_BLK __user *pioctl_dpram;
666                 int msglen;
667
668                 /* pr_debug("IOCTL_FT1000_GET_DPRAM called\n"); */
669
670                 if (ft1000_flarion_cnt == 0)
671                         return -EBADF;
672
673                 /* Search for matching file object */
674                 for (i = 0; i < MAX_NUM_APP; i++) {
675                         if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
676                                 /*pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
677                                 break;
678                         }
679                 }
680
681                 /* Could not find application info block */
682                 if (i == MAX_NUM_APP) {
683                         pr_debug("Could not find application info block\n");
684                         result = -EBADF;
685                         break;
686                 }
687
688                 result = 0;
689                 pioctl_dpram = argp;
690                 if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
691                         /* pr_debug("Message detected in slow queue\n"); */
692                         spin_lock_irqsave(&free_buff_lock, flags);
693                         pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
694                         list_del(&pdpram_blk->list);
695                         ft1000dev->app_info[i].NumOfMsg--;
696                         /* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
697                         spin_unlock_irqrestore(&free_buff_lock, flags);
698                         msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
699                         result = get_user(msglen, &pioctl_dpram->total_len);
700                         if (result)
701                                 break;
702                         msglen = htons(msglen);
703                         /* pr_debug("msg length = %x\n", msglen); */
704                         if (copy_to_user(&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen)) {
705                                 pr_debug("copy fault occurred\n");
706                                 result = -EFAULT;
707                                 break;
708                         }
709
710                         ft1000_free_buffer(pdpram_blk, &freercvpool);
711                         result = msglen;
712                 }
713                 /* pr_debug("IOCTL_FT1000_GET_DPRAM no message\n"); */
714         }
715         break;
716
717         default:
718                 pr_debug("unknown command: 0x%x\n", command);
719                 result = -ENOTTY;
720                 break;
721         }
722         ft1000dev->fAppMsgPend = false;
723         return result;
724 }
725
726 /*
727  *---------------------------------------------------------------------------
728  * Function:    ft1000_release
729  *
730  * Parameters:
731  *
732  * Description:
733  *
734  * Notes:
735  *
736  *---------------------------------------------------------------------------
737  */
738 static int ft1000_release(struct inode *inode, struct file *file)
739 {
740         struct ft1000_info *info;
741         struct net_device *dev;
742         struct ft1000_usb *ft1000dev;
743         int i;
744         struct dpram_blk *pdpram_blk;
745         struct dpram_blk *tmp;
746
747         dev = file->private_data;
748         info = netdev_priv(dev);
749         ft1000dev = info->priv;
750
751         if (ft1000_flarion_cnt == 0) {
752                 ft1000dev->appcnt--;
753                 return -EBADF;
754         }
755
756         /* Search for matching file object */
757         for (i = 0; i < MAX_NUM_APP; i++) {
758                 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
759                         /* pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
760                         break;
761                 }
762         }
763
764         if (i == MAX_NUM_APP)
765                 return 0;
766
767         list_for_each_entry_safe(pdpram_blk, tmp, &ft1000dev->app_info[i].app_sqlist, list) {
768                 pr_debug("Remove and free memory queue up on slow queue\n");
769                 list_del(&pdpram_blk->list);
770                 ft1000_free_buffer(pdpram_blk, &freercvpool);
771         }
772
773         /* initialize application information */
774         ft1000dev->appcnt--;
775         pr_debug("appcnt = %d\n", ft1000dev->appcnt);
776         ft1000dev->app_info[i].fileobject = NULL;
777
778         return 0;
779 }