OSDN Git Service

Merge remote-tracking branch 'kselftest/next'
[uclinux-h8/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;
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,
264                                                         struct dpram_blk, list);
265                                 list_del(&pdpram_blk->list);
266                                 ft1000_free_buffer(pdpram_blk, &freercvpool);
267
268                         }
269                         wake_up_interruptible(&dev->app_info[i].wait_dpram_msg);
270                 }
271
272                 /* Remove buffer allocated for receive command data */
273                 if (ft1000_flarion_cnt == 0) {
274                         while (list_empty(&freercvpool) == 0) {
275                                 ptr = list_entry(freercvpool.next, struct dpram_blk, list);
276                                 list_del(&ptr->list);
277                                 kfree(ptr->pbuffer);
278                                 kfree(ptr);
279                         }
280                 }
281                 dev->DeviceCreated = FALSE;
282         }
283
284
285 }
286
287 /*
288  *---------------------------------------------------------------------------
289  * Function:    ft1000_open
290  *
291  * Parameters:
292  *
293  * Description:
294  *
295  * Notes:
296  *
297  *---------------------------------------------------------------------------
298  */
299 static int ft1000_open(struct inode *inode, struct file *file)
300 {
301         struct ft1000_info *info;
302         struct ft1000_usb *dev = (struct ft1000_usb *)inode->i_private;
303         int i, num;
304
305         num = MINOR(inode->i_rdev) & 0xf;
306         pr_debug("minor number=%d\n", num);
307
308         info = file->private_data = netdev_priv(dev->net);
309
310         pr_debug("f_owner = %p number of application = %d\n",
311                  &file->f_owner, dev->appcnt);
312
313         /* Check if maximum number of application exceeded */
314         if (dev->appcnt > MAX_NUM_APP) {
315                 pr_debug("Maximum number of application exceeded\n");
316                 return -EACCES;
317         }
318
319         /* Search for available application info block */
320         for (i = 0; i < MAX_NUM_APP; i++) {
321                 if (dev->app_info[i].fileobject == NULL)
322                         break;
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[] = {
420                 0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00,
421                 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
422                 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
423                 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
424                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
425                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
427                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428                 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08,
429                 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
430                 0x00, 0x01, 0x00, 0x00
431         };
432
433         unsigned short ledStat = 0;
434         unsigned short conStat = 0;
435
436         if (ft1000_flarion_cnt == 0) {
437                 pr_debug("called with ft1000_flarion_cnt of zero\n");
438                 return -EBADF;
439         }
440
441         /* pr_debug("command = 0x%x argument = 0x%8x\n", command, (u32)argument); */
442
443         info = file->private_data;
444         ft1000dev = info->priv;
445         cmd = _IOC_NR(command);
446         /* pr_debug("cmd = 0x%x\n", cmd); */
447
448         /* process the command */
449         switch (cmd) {
450         case IOCTL_REGISTER_CMD:
451                 pr_debug("IOCTL_FT1000_REGISTER called\n");
452                 result = get_user(tempword, (__u16 __user *)argp);
453                 if (result) {
454                         pr_debug("result = %d failed to get_user\n", result);
455                         break;
456                 }
457                 if (tempword == DSPBCMSGID) {
458                         /* Search for matching file object */
459                         for (i = 0; i < MAX_NUM_APP; i++) {
460                                 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
461                                         ft1000dev->app_info[i].DspBCMsgFlag = 1;
462                                         pr_debug("Registered for broadcast messages\n");
463                                         break;
464                                 }
465                         }
466                 }
467                 break;
468
469         case IOCTL_GET_VER_CMD:
470                 pr_debug("IOCTL_FT1000_GET_VER called\n");
471
472                 get_ver_data.drv_ver = FT1000_DRV_VER;
473
474                 if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data))) {
475                         pr_debug("copy fault occurred\n");
476                         result = -EFAULT;
477                         break;
478                 }
479
480                 pr_debug("driver version = 0x%x\n",
481                          (unsigned int)get_ver_data.drv_ver);
482
483                 break;
484         case IOCTL_CONNECT:
485                 /* Connect Message */
486                 pr_debug("IOCTL_FT1000_CONNECT\n");
487                 ConnectionMsg[79] = 0xfc;
488                 result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
489
490                 break;
491         case IOCTL_DISCONNECT:
492                 /* Disconnect Message */
493                 pr_debug("IOCTL_FT1000_DISCONNECT\n");
494                 ConnectionMsg[79] = 0xfd;
495                 result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
496                 break;
497         case IOCTL_GET_DSP_STAT_CMD:
498                 /* pr_debug("IOCTL_FT1000_GET_DSP_STAT\n"); */
499                 memset(&get_stat_data, 0, sizeof(get_stat_data));
500                 memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
501                 memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
502                 memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
503                 memcpy(get_stat_data.eui64, info->eui64, EUISZ);
504
505                 if (info->ProgConStat != 0xFF) {
506                         ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED,
507                                             (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
508                         get_stat_data.LedStat = ntohs(ledStat);
509                         pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
510                         ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE,
511                                             (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
512                         get_stat_data.ConStat = ntohs(conStat);
513                         pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
514                 } else {
515                         get_stat_data.ConStat = 0x0f;
516                 }
517
518
519                 get_stat_data.nTxPkts = info->stats.tx_packets;
520                 get_stat_data.nRxPkts = info->stats.rx_packets;
521                 get_stat_data.nTxBytes = info->stats.tx_bytes;
522                 get_stat_data.nRxBytes = info->stats.rx_bytes;
523                 do_gettimeofday(&tv);
524                 get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
525                 pr_debug("Connection Time = %d\n", (int)get_stat_data.ConTm);
526                 if (copy_to_user(argp, &get_stat_data, sizeof(get_stat_data))) {
527                         pr_debug("copy fault occurred\n");
528                         result = -EFAULT;
529                         break;
530                 }
531                 pr_debug("GET_DSP_STAT succeed\n");
532                 break;
533         case IOCTL_SET_DPRAM_CMD:
534         {
535                 struct IOCTL_DPRAM_BLK *dpram_data = NULL;
536                 /* struct IOCTL_DPRAM_COMMAND dpram_command; */
537                 u16 qtype;
538                 u16 msgsz;
539                 struct pseudo_hdr *ppseudo_hdr;
540                 u16 *pmsg;
541                 u16 total_len;
542                 u16 app_index;
543                 u16 status;
544
545                 /* pr_debug("IOCTL_FT1000_SET_DPRAM called\n");*/
546
547
548                 if (ft1000_flarion_cnt == 0)
549                         return -EBADF;
550
551                 if (ft1000dev->DrvMsgPend)
552                         return -ENOTTY;
553
554                 if (ft1000dev->fProvComplete == 0)
555                         return -EACCES;
556
557                 ft1000dev->fAppMsgPend = true;
558
559                 if (info->CardReady) {
560
561                         /* pr_debug("try to SET_DPRAM\n"); */
562
563                         /* Get the length field to see how many bytes to copy */
564                         result = get_user(msgsz, (__u16 __user *)argp);
565                         if (result)
566                                 break;
567                         msgsz = ntohs(msgsz);
568                         /* pr_debug("length of message = %d\n", msgsz); */
569
570                         if (msgsz > MAX_CMD_SQSIZE) {
571                                 pr_debug("bad message length = %d\n", msgsz);
572                                 result = -EINVAL;
573                                 break;
574                         }
575
576                         result = -ENOMEM;
577                         dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
578                         if (!dpram_data)
579                                 break;
580
581                         if (copy_from_user(dpram_data, argp, msgsz+2)) {
582                                 pr_debug("copy fault occurred\n");
583                                 result = -EFAULT;
584                         } else {
585                                 /* Check if this message came from a registered application */
586                                 for (i = 0; i < MAX_NUM_APP; i++) {
587                                         if (ft1000dev->app_info[i].fileobject == &file->f_owner)
588                                                 break;
589                                 }
590                                 if (i == MAX_NUM_APP) {
591                                         pr_debug("No matching application fileobject\n");
592                                         result = -EINVAL;
593                                         kfree(dpram_data);
594                                         break;
595                                 }
596                                 app_index = i;
597
598                                 /* Check message qtype type which is the lower byte within qos_class */
599                                 qtype = ntohs(dpram_data->pseudohdr.qos_class) & 0xff;
600                                 /* pr_debug("qtype = %d\n", qtype); */
601                                 if (!qtype) {
602                                         /* Put message into Slow Queue */
603                                         /* Only put a message into the DPRAM if msg doorbell is available */
604                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
605                                         /* pr_debug("READ REGISTER tempword=%x\n", tempword); */
606                                         if (tempword & FT1000_DB_DPRAM_TX) {
607                                                 /* Suspend for 2ms and try again due to DSP doorbell busy */
608                                                 mdelay(2);
609                                                 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
610                                                 if (tempword & FT1000_DB_DPRAM_TX) {
611                                                         /* Suspend for 1ms and try again due to DSP doorbell busy */
612                                                         mdelay(1);
613                                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
614                                                         if (tempword & FT1000_DB_DPRAM_TX) {
615                                                                 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
616                                                                 if (tempword & FT1000_DB_DPRAM_TX) {
617                                                                         /* Suspend for 3ms and try again due to DSP doorbell busy */
618                                                                         mdelay(3);
619                                                                         status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
620                                                                         if (tempword & FT1000_DB_DPRAM_TX) {
621                                                                                 pr_debug("Doorbell not available\n");
622                                                                                 result = -ENOTTY;
623                                                                                 kfree(dpram_data);
624                                                                                 break;
625                                                                         }
626                                                                 }
627                                                         }
628                                                 }
629                                         }
630
631                                         /*pr_debug("finished reading register\n"); */
632
633                                         /* Make sure we are within the limits of the slow queue memory limitation */
634                                         if ((msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ)) {
635                                                 /* Need to put sequence number plus new checksum for message */
636                                                 pmsg = (u16 *)&dpram_data->pseudohdr;
637                                                 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
638                                                 total_len = msgsz+2;
639                                                 if (total_len & 0x1)
640                                                         total_len++;
641
642                                                 /* Insert slow queue sequence number */
643                                                 ppseudo_hdr->seq_num = info->squeseqnum++;
644                                                 ppseudo_hdr->portsrc = ft1000dev->app_info[app_index].app_id;
645                                                 /* Calculate new checksum */
646                                                 ppseudo_hdr->checksum = *pmsg++;
647                                                 /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
648                                                 for (i = 1; i < 7; i++) {
649                                                         ppseudo_hdr->checksum ^= *pmsg++;
650                                                         /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
651                                                 }
652                                                 pmsg++;
653                                                 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
654                                                 result = card_send_command(ft1000dev, dpram_data, total_len+2);
655
656
657                                                 ft1000dev->app_info[app_index].nTxMsg++;
658                                         } else {
659                                                 result = -EINVAL;
660                                         }
661                                 }
662                         }
663                 } else {
664                         pr_debug("Card not ready take messages\n");
665                         result = -EACCES;
666                 }
667                 kfree(dpram_data);
668
669         }
670         break;
671         case IOCTL_GET_DPRAM_CMD:
672         {
673                 struct dpram_blk *pdpram_blk;
674                 struct IOCTL_DPRAM_BLK __user *pioctl_dpram;
675                 int msglen;
676
677                 /* pr_debug("IOCTL_FT1000_GET_DPRAM called\n"); */
678
679                 if (ft1000_flarion_cnt == 0)
680                         return -EBADF;
681
682                 /* Search for matching file object */
683                 for (i = 0; i < MAX_NUM_APP; i++) {
684                         if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
685                                 /*pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
686                                 break;
687                         }
688                 }
689
690                 /* Could not find application info block */
691                 if (i == MAX_NUM_APP) {
692                         pr_debug("Could not find application info block\n");
693                         result = -EBADF;
694                         break;
695                 }
696
697                 result = 0;
698                 pioctl_dpram = argp;
699                 if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
700                         /* pr_debug("Message detected in slow queue\n"); */
701                         spin_lock_irqsave(&free_buff_lock, flags);
702                         pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next,
703                                                 struct dpram_blk, list);
704                         list_del(&pdpram_blk->list);
705                         ft1000dev->app_info[i].NumOfMsg--;
706                         /* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
707                         spin_unlock_irqrestore(&free_buff_lock, flags);
708                         msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
709                         result = get_user(msglen, &pioctl_dpram->total_len);
710                         if (result)
711                                 break;
712                         msglen = htons(msglen);
713                         /* pr_debug("msg length = %x\n", msglen); */
714                         if (copy_to_user(&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen)) {
715                                 pr_debug("copy fault occurred\n");
716                                 result = -EFAULT;
717                                 break;
718                         }
719
720                         ft1000_free_buffer(pdpram_blk, &freercvpool);
721                         result = msglen;
722                 }
723                 /* pr_debug("IOCTL_FT1000_GET_DPRAM no message\n"); */
724         }
725         break;
726
727         default:
728                 pr_debug("unknown command: 0x%x\n", command);
729                 result = -ENOTTY;
730                 break;
731         }
732         ft1000dev->fAppMsgPend = false;
733         return result;
734 }
735
736 /*
737  *---------------------------------------------------------------------------
738  * Function:    ft1000_release
739  *
740  * Parameters:
741  *
742  * Description:
743  *
744  * Notes:
745  *
746  *---------------------------------------------------------------------------
747  */
748 static int ft1000_release(struct inode *inode, struct file *file)
749 {
750         struct ft1000_info *info;
751         struct net_device *dev;
752         struct ft1000_usb *ft1000dev;
753         int i;
754         struct dpram_blk *pdpram_blk;
755         struct dpram_blk *tmp;
756
757         dev = file->private_data;
758         info = netdev_priv(dev);
759         ft1000dev = info->priv;
760
761         if (ft1000_flarion_cnt == 0) {
762                 ft1000dev->appcnt--;
763                 return -EBADF;
764         }
765
766         /* Search for matching file object */
767         for (i = 0; i < MAX_NUM_APP; i++) {
768                 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
769                         /* pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
770                         break;
771                 }
772         }
773
774         if (i == MAX_NUM_APP)
775                 return 0;
776
777         list_for_each_entry_safe(pdpram_blk, tmp, &ft1000dev->app_info[i].app_sqlist, list) {
778                 pr_debug("Remove and free memory queue up on slow queue\n");
779                 list_del(&pdpram_blk->list);
780                 ft1000_free_buffer(pdpram_blk, &freercvpool);
781         }
782
783         /* initialize application information */
784         ft1000dev->appcnt--;
785         pr_debug("appcnt = %d\n", ft1000dev->appcnt);
786         ft1000dev->app_info[i].fileobject = NULL;
787
788         return 0;
789 }