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