OSDN Git Service

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