staging: ft1000: Fix private data pointer usage.
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / ft1000 / ft1000-usb / ft1000_chdev.c
blob8b735e4898782afe79acbadde825daad6919d8dd
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 //---------------------------------------------------------------------------
18 // File: ft1000_chdev.c
20 // Description: Custom character device dispatch routines.
22 // History:
23 // 8/29/02 Whc Ported to Linux.
24 // 6/05/06 Whc Porting to Linux 2.6.9
26 //---------------------------------------------------------------------------
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/signal.h>
31 #include <linux/errno.h>
32 #include <linux/poll.h>
33 #include <linux/netdevice.h>
34 #include <linux/delay.h>
36 #include <linux/fs.h>
37 #include <linux/kmod.h>
38 #include <linux/ioctl.h>
39 #include <linux/unistd.h>
40 #include <linux/debugfs.h>
41 #include "ft1000_usb.h"
42 //#include "ft1000_ioctl.h"
44 static int ft1000_flarion_cnt = 0;
46 //need to looking usage of ft1000Handle
48 static int ft1000_ChOpen (struct inode *Inode, struct file *File);
49 static unsigned int ft1000_ChPoll(struct file *file, poll_table *wait);
50 static long ft1000_ChIoctl(struct file *File, unsigned int Command,
51 unsigned long Argument);
52 static int ft1000_ChRelease (struct inode *Inode, struct file *File);
54 // Global pointer to device object
55 static struct ft1000_device *pdevobj[MAX_NUM_CARDS + 2];
56 //static devfs_handle_t ft1000Handle[MAX_NUM_CARDS];
58 // List to free receive command buffer pool
59 struct list_head freercvpool;
61 // lock to arbitrate free buffer list for receive command data
62 spinlock_t free_buff_lock;
64 int numofmsgbuf = 0;
66 // Global variable to indicate that all provisioning data is sent to DSP
67 //bool fProvComplete;
70 // Table of entry-point routines for char device
72 static struct file_operations ft1000fops =
74 .unlocked_ioctl = ft1000_ChIoctl,
75 .poll = ft1000_ChPoll,
76 .open = ft1000_ChOpen,
77 .release = ft1000_ChRelease,
78 .llseek = no_llseek,
81 //---------------------------------------------------------------------------
82 // Function: ft1000_get_buffer
84 // Parameters:
86 // Returns:
88 // Description:
90 // Notes:
92 //---------------------------------------------------------------------------
93 struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist)
95 unsigned long flags;
96 struct dpram_blk *ptr;
98 spin_lock_irqsave(&free_buff_lock, flags);
99 // Check if buffer is available
100 if ( list_empty(bufflist) ) {
101 DEBUG("ft1000_get_buffer: No more buffer - %d\n", numofmsgbuf);
102 ptr = NULL;
104 else {
105 numofmsgbuf--;
106 ptr = list_entry(bufflist->next, struct dpram_blk, list);
107 list_del(&ptr->list);
108 //DEBUG("ft1000_get_buffer: number of free msg buffers = %d\n", numofmsgbuf);
110 spin_unlock_irqrestore(&free_buff_lock, flags);
112 return ptr;
118 //---------------------------------------------------------------------------
119 // Function: ft1000_free_buffer
121 // Parameters:
123 // Returns:
125 // Description:
127 // Notes:
129 //---------------------------------------------------------------------------
130 void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist)
132 unsigned long flags;
134 spin_lock_irqsave(&free_buff_lock, flags);
135 // Put memory back to list
136 list_add_tail(&pdpram_blk->list, plist);
137 numofmsgbuf++;
138 //DEBUG("ft1000_free_buffer: number of free msg buffers = %d\n", numofmsgbuf);
139 spin_unlock_irqrestore(&free_buff_lock, flags);
142 //---------------------------------------------------------------------------
143 // Function: ft1000_CreateDevice
145 // Parameters: dev - pointer to adapter object
147 // Returns: 0 if successful
149 // Description: Creates a private char device.
151 // Notes: Only called by init_module().
153 //---------------------------------------------------------------------------
154 int ft1000_CreateDevice(struct ft1000_device *dev)
156 struct ft1000_info *info = netdev_priv(dev->net);
157 int result;
158 int i;
159 struct dentry *dir, *file;
160 struct ft1000_debug_dirs *tmp;
162 // make a new device name
163 sprintf(info->DeviceName, "%s%d", "FT1000_", info->CardNumber);
165 DEBUG("ft1000_CreateDevice: number of instance = %d\n", ft1000_flarion_cnt);
166 DEBUG("DeviceCreated = %x\n", info->DeviceCreated);
168 //save the device info to global array
169 pdevobj[info->CardNumber] = dev;
171 DEBUG("ft1000_CreateDevice: ******SAVED pdevobj[%d]=%p\n", info->CardNumber, pdevobj[info->CardNumber]); //aelias [+] reason:up
173 if (info->DeviceCreated)
175 DEBUG("ft1000_CreateDevice: \"%s\" already registered\n", info->DeviceName);
176 return -EIO;
180 // register the device
181 DEBUG("ft1000_CreateDevice: \"%s\" device registration\n", info->DeviceName);
182 info->DeviceMajor = 0;
184 tmp = kmalloc(sizeof(struct ft1000_debug_dirs), GFP_KERNEL);
185 if (tmp == NULL) {
186 result = -1;
187 goto fail;
190 dir = debugfs_create_dir(info->DeviceName, 0);
191 if (IS_ERR(dir)) {
192 result = PTR_ERR(dir);
193 goto debug_dir_fail;
196 file = debugfs_create_file("device", S_IRUGO | S_IWUGO, dir,
197 NULL, &ft1000fops);
198 if (IS_ERR(file)) {
199 result = PTR_ERR(file);
200 goto debug_file_fail;
203 tmp->dent = dir;
204 tmp->file = file;
205 tmp->int_number = info->CardNumber;
206 list_add(&(tmp->list), &(info->nodes.list));
208 DEBUG("ft1000_CreateDevice: registered char device \"%s\"\n", info->DeviceName);
210 // initialize application information
212 // if (ft1000_flarion_cnt == 0) {
214 // DEBUG("Initialize free_buff_lock and freercvpool\n");
215 // spin_lock_init(&free_buff_lock);
217 // // initialize a list of buffers to be use for queuing up receive command data
218 // INIT_LIST_HEAD (&freercvpool);
220 // // create list of free buffers
221 // for (i=0; i<NUM_OF_FREE_BUFFERS; i++) {
222 // // Get memory for DPRAM_DATA link list
223 // pdpram_blk = kmalloc ( sizeof(struct dpram_blk), GFP_KERNEL );
224 // // Get a block of memory to store command data
225 // pdpram_blk->pbuffer = kmalloc ( MAX_CMD_SQSIZE, GFP_KERNEL );
226 // // link provisioning data
227 // list_add_tail (&pdpram_blk->list, &freercvpool);
228 // }
229 // numofmsgbuf = NUM_OF_FREE_BUFFERS;
230 // }
233 // initialize application information
234 info->appcnt = 0;
235 for (i=0; i<MAX_NUM_APP; i++) {
236 info->app_info[i].nTxMsg = 0;
237 info->app_info[i].nRxMsg = 0;
238 info->app_info[i].nTxMsgReject = 0;
239 info->app_info[i].nRxMsgMiss = 0;
240 info->app_info[i].fileobject = NULL;
241 info->app_info[i].app_id = i+1;
242 info->app_info[i].DspBCMsgFlag = 0;
243 info->app_info[i].NumOfMsg = 0;
244 init_waitqueue_head(&info->app_info[i].wait_dpram_msg);
245 INIT_LIST_HEAD (&info->app_info[i].app_sqlist);
251 // ft1000Handle[info->CardNumber] = devfs_register(NULL, info->DeviceName, DEVFS_FL_AUTO_DEVNUM, 0, 0,
252 // S_IFCHR | S_IRUGO | S_IWUGO, &ft1000fops, NULL);
255 info->DeviceCreated = TRUE;
256 ft1000_flarion_cnt++;
258 return 0;
260 debug_file_fail:
261 debugfs_remove(dir);
262 debug_dir_fail:
263 kfree(tmp);
264 fail:
265 return result;
268 //---------------------------------------------------------------------------
269 // Function: ft1000_DestroyDeviceDEBUG
271 // Parameters: dev - pointer to adapter object
273 // Description: Destroys a private char device.
275 // Notes: Only called by cleanup_module().
277 //---------------------------------------------------------------------------
278 void ft1000_DestroyDevice(struct net_device *dev)
280 struct ft1000_info *info = netdev_priv(dev);
281 int i;
282 struct dpram_blk *pdpram_blk;
283 struct dpram_blk *ptr;
284 struct list_head *pos, *q;
285 struct ft1000_debug_dirs *dir;
287 DEBUG("ft1000_chdev:ft1000_DestroyDevice called\n");
291 if (info->DeviceCreated)
293 ft1000_flarion_cnt--;
294 list_for_each_safe(pos, q, &info->nodes.list) {
295 dir = list_entry(pos, struct ft1000_debug_dirs, list);
296 if (dir->int_number == info->CardNumber) {
297 debugfs_remove(dir->file);
298 debugfs_remove(dir->dent);
299 list_del(pos);
300 kfree(dir);
303 DEBUG("ft1000_DestroyDevice: unregistered device \"%s\"\n",
304 info->DeviceName);
306 // Make sure we free any memory reserve for slow Queue
307 for (i=0; i<MAX_NUM_APP; i++) {
308 while (list_empty(&info->app_info[i].app_sqlist) == 0) {
309 pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, struct dpram_blk, list);
310 list_del(&pdpram_blk->list);
311 ft1000_free_buffer(pdpram_blk, &freercvpool);
314 wake_up_interruptible(&info->app_info[i].wait_dpram_msg);
317 // Remove buffer allocated for receive command data
318 if (ft1000_flarion_cnt == 0) {
319 while (list_empty(&freercvpool) == 0) {
320 ptr = list_entry(freercvpool.next, struct dpram_blk, list);
321 list_del(&ptr->list);
322 kfree(ptr->pbuffer);
323 kfree(ptr);
327 // devfs_unregister(ft1000Handle[info->CardNumber]);
329 info->DeviceCreated = FALSE;
331 pdevobj[info->CardNumber] = NULL;
337 //---------------------------------------------------------------------------
338 // Function: ft1000_ChOpen
340 // Parameters:
342 // Description:
344 // Notes:
346 //---------------------------------------------------------------------------
347 static int ft1000_ChOpen (struct inode *Inode, struct file *File)
349 struct ft1000_info *info;
350 struct ft1000_device *dev = (struct ft1000_device *)Inode->i_private;
351 int i,num;
353 DEBUG("ft1000_ChOpen called\n");
354 num = (MINOR(Inode->i_rdev) & 0xf);
355 DEBUG("ft1000_ChOpen: minor number=%d\n", num);
357 info = File->private_data = netdev_priv(dev->net);
359 for (i=0; i<5; i++)
360 DEBUG("pdevobj[%d]=%p\n", i, pdevobj[i]); //aelias [+] reason: down
362 if ( pdevobj[num] != NULL )
363 //info = (struct ft1000_info *)(pdevobj[num]->net->priv);
364 info = netdev_priv(pdevobj[num]->net);
365 else
367 DEBUG("ft1000_ChOpen: can not find device object %d\n", num);
368 return -1;
371 DEBUG("f_owner = %p number of application = %d\n", (&File->f_owner), info->appcnt );
373 // Check if maximum number of application exceeded
374 if (info->appcnt > MAX_NUM_APP) {
375 DEBUG("Maximum number of application exceeded\n");
376 return -EACCES;
379 // Search for available application info block
380 for (i=0; i<MAX_NUM_APP; i++) {
381 if ( (info->app_info[i].fileobject == NULL) ) {
382 break;
386 // Fail due to lack of application info block
387 if (i == MAX_NUM_APP) {
388 DEBUG("Could not find an application info block\n");
389 return -EACCES;
392 info->appcnt++;
393 info->app_info[i].fileobject = &File->f_owner;
394 info->app_info[i].nTxMsg = 0;
395 info->app_info[i].nRxMsg = 0;
396 info->app_info[i].nTxMsgReject = 0;
397 info->app_info[i].nRxMsgMiss = 0;
399 nonseekable_open(Inode, File);
400 return 0;
404 //---------------------------------------------------------------------------
405 // Function: ft1000_ChPoll
407 // Parameters:
409 // Description:
411 // Notes:
413 //---------------------------------------------------------------------------
415 static unsigned int ft1000_ChPoll(struct file *file, poll_table *wait)
417 struct net_device *dev = file->private_data;
418 struct ft1000_info *info;
419 int i;
421 //DEBUG("ft1000_ChPoll called\n");
422 if (ft1000_flarion_cnt == 0) {
423 DEBUG("FT1000:ft1000_ChPoll called when ft1000_flarion_cnt is zero\n");
424 return (-EBADF);
427 info = netdev_priv(dev);
429 // Search for matching file object
430 for (i=0; i<MAX_NUM_APP; i++) {
431 if ( info->app_info[i].fileobject == &file->f_owner) {
432 //DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id);
433 break;
437 // Could not find application info block
438 if (i == MAX_NUM_APP) {
439 DEBUG("FT1000:ft1000_ChIoctl:Could not find application info block\n");
440 return ( -EACCES );
443 if (list_empty(&info->app_info[i].app_sqlist) == 0) {
444 DEBUG("FT1000:ft1000_ChPoll:Message detected in slow queue\n");
445 return(POLLIN | POLLRDNORM | POLLPRI);
448 poll_wait (file, &info->app_info[i].wait_dpram_msg, wait);
449 //DEBUG("FT1000:ft1000_ChPoll:Polling for data from DSP\n");
451 return (0);
454 //---------------------------------------------------------------------------
455 // Function: ft1000_ChIoctl
457 // Parameters:
459 // Description:
461 // Notes:
463 //---------------------------------------------------------------------------
464 static long ft1000_ChIoctl (struct file *File, unsigned int Command,
465 unsigned long Argument)
467 void __user *argp = (void __user *)Argument;
468 struct net_device *dev;
469 struct ft1000_info *info;
470 struct ft1000_device *ft1000dev;
471 int result=0;
472 int cmd;
473 int i;
474 u16 tempword;
475 unsigned long flags;
476 struct timeval tv;
477 IOCTL_GET_VER get_ver_data;
478 IOCTL_GET_DSP_STAT get_stat_data;
479 u8 ConnectionMsg[] = {0x00,0x44,0x10,0x20,0x80,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x93,0x64,
480 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0a,
481 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
482 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
483 0x00,0x00,0x02,0x37,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x7f,0x00,
484 0x00,0x01,0x00,0x00};
486 unsigned short ledStat=0;
487 unsigned short conStat=0;
489 //DEBUG("ft1000_ChIoctl called\n");
491 if (ft1000_flarion_cnt == 0) {
492 DEBUG("FT1000:ft1000_ChIoctl called when ft1000_flarion_cnt is zero\n");
493 return (-EBADF);
496 //DEBUG("FT1000:ft1000_ChIoctl:Command = 0x%x Argument = 0x%8x\n", Command, (u32)Argument);
498 dev = File->private_data;
499 info = netdev_priv(dev);
500 ft1000dev = info->pFt1000Dev;
501 cmd = _IOC_NR(Command);
502 //DEBUG("FT1000:ft1000_ChIoctl:cmd = 0x%x\n", cmd);
504 // process the command
505 switch (cmd) {
506 case IOCTL_REGISTER_CMD:
507 DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_REGISTER called\n");
508 result = get_user(tempword, (__u16 __user*)argp);
509 if (result) {
510 DEBUG("result = %d failed to get_user\n", result);
511 break;
513 if (tempword == DSPBCMSGID) {
514 // Search for matching file object
515 for (i=0; i<MAX_NUM_APP; i++) {
516 if ( info->app_info[i].fileobject == &File->f_owner) {
517 info->app_info[i].DspBCMsgFlag = 1;
518 DEBUG("FT1000:ft1000_ChIoctl:Registered for broadcast messages\n");
519 break;
523 break;
525 case IOCTL_GET_VER_CMD:
526 DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_VER called\n");
528 get_ver_data.drv_ver = FT1000_DRV_VER;
530 if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data)) ) {
531 DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
532 result = -EFAULT;
533 break;
536 DEBUG("FT1000:ft1000_ChIoctl:driver version = 0x%x\n",(unsigned int)get_ver_data.drv_ver);
538 break;
539 case IOCTL_CONNECT:
540 // Connect Message
541 DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_CONNECT\n");
542 ConnectionMsg[79] = 0xfc;
543 CardSendCommand(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
545 break;
546 case IOCTL_DISCONNECT:
547 // Disconnect Message
548 DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_DISCONNECT\n");
549 ConnectionMsg[79] = 0xfd;
550 CardSendCommand(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
551 break;
552 case IOCTL_GET_DSP_STAT_CMD:
553 //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DSP_STAT called\n");
554 memset(&get_stat_data, 0, sizeof(get_stat_data));
555 memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
556 memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
557 memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
558 memcpy(get_stat_data.eui64, info->eui64, EUISZ);
560 if (info->ProgConStat != 0xFF) {
561 ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
562 get_stat_data.LedStat = ntohs(ledStat);
563 DEBUG("FT1000:ft1000_ChIoctl: LedStat = 0x%x\n", get_stat_data.LedStat);
564 ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
565 get_stat_data.ConStat = ntohs(conStat);
566 DEBUG("FT1000:ft1000_ChIoctl: ConStat = 0x%x\n", get_stat_data.ConStat);
568 else {
569 get_stat_data.ConStat = 0x0f;
573 get_stat_data.nTxPkts = info->stats.tx_packets;
574 get_stat_data.nRxPkts = info->stats.rx_packets;
575 get_stat_data.nTxBytes = info->stats.tx_bytes;
576 get_stat_data.nRxBytes = info->stats.rx_bytes;
577 do_gettimeofday ( &tv );
578 get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
579 DEBUG("Connection Time = %d\n", (int)get_stat_data.ConTm);
580 if (copy_to_user(argp, &get_stat_data, sizeof(get_stat_data)) ) {
581 DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
582 result = -EFAULT;
583 break;
585 DEBUG("ft1000_chioctl: GET_DSP_STAT succeed\n");
586 break;
587 case IOCTL_SET_DPRAM_CMD:
589 IOCTL_DPRAM_BLK *dpram_data = NULL;
590 //IOCTL_DPRAM_COMMAND dpram_command;
591 u16 qtype;
592 u16 msgsz;
593 struct pseudo_hdr *ppseudo_hdr;
594 u16 *pmsg;
595 u16 total_len;
596 u16 app_index;
597 u16 status;
599 //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_SET_DPRAM called\n");
602 if (ft1000_flarion_cnt == 0) {
603 return (-EBADF);
606 if (info->DrvMsgPend) {
607 return (-ENOTTY);
610 if ( (info->DspAsicReset) || (info->fProvComplete == 0) ) {
611 return (-EACCES);
614 info->fAppMsgPend = 1;
616 if (info->CardReady) {
618 //DEBUG("FT1000:ft1000_ChIoctl: try to SET_DPRAM \n");
620 // Get the length field to see how many bytes to copy
621 result = get_user(msgsz, (__u16 __user *)argp);
622 msgsz = ntohs (msgsz);
623 //DEBUG("FT1000:ft1000_ChIoctl: length of message = %d\n", msgsz);
625 if (msgsz > MAX_CMD_SQSIZE) {
626 DEBUG("FT1000:ft1000_ChIoctl: bad message length = %d\n", msgsz);
627 result = -EINVAL;
628 break;
631 result = -ENOMEM;
632 dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
633 if (!dpram_data)
634 break;
636 //if ( copy_from_user(&(dpram_command.dpram_blk), (PIOCTL_DPRAM_BLK)Argument, msgsz+2) ) {
637 if ( copy_from_user(dpram_data, argp, msgsz+2) ) {
638 DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
639 result = -EFAULT;
641 else {
642 #if 0
643 // whc - for debugging only
644 ptr = (char *)&dpram_data;
645 for (i=0; i<msgsz; i++) {
646 DEBUG(1,"FT1000:ft1000_ChIoctl: data %d = 0x%x\n", i, *ptr++);
648 #endif
649 // Check if this message came from a registered application
650 for (i=0; i<MAX_NUM_APP; i++) {
651 if ( info->app_info[i].fileobject == &File->f_owner) {
652 break;
655 if (i==MAX_NUM_APP) {
656 DEBUG("FT1000:No matching application fileobject\n");
657 result = -EINVAL;
658 kfree(dpram_data);
659 break;
661 app_index = i;
663 // Check message qtype type which is the lower byte within qos_class
664 //qtype = ntohs(dpram_command.dpram_blk.pseudohdr.qos_class) & 0xff;
665 qtype = ntohs(dpram_data->pseudohdr.qos_class) & 0xff;
666 //DEBUG("FT1000_ft1000_ChIoctl: qtype = %d\n", qtype);
667 if (qtype) {
669 else {
670 // Put message into Slow Queue
671 // Only put a message into the DPRAM if msg doorbell is available
672 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
673 //DEBUG("FT1000_ft1000_ChIoctl: READ REGISTER tempword=%x\n", tempword);
674 if (tempword & FT1000_DB_DPRAM_TX) {
675 // Suspend for 2ms and try again due to DSP doorbell busy
676 mdelay(2);
677 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
678 if (tempword & FT1000_DB_DPRAM_TX) {
679 // Suspend for 1ms and try again due to DSP doorbell busy
680 mdelay(1);
681 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
682 if (tempword & FT1000_DB_DPRAM_TX) {
683 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
684 if (tempword & FT1000_DB_DPRAM_TX) {
685 // Suspend for 3ms and try again due to DSP doorbell busy
686 mdelay(3);
687 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
688 if (tempword & FT1000_DB_DPRAM_TX) {
689 DEBUG("FT1000:ft1000_ChIoctl:Doorbell not available\n");
690 result = -ENOTTY;
691 kfree(dpram_data);
692 break;
699 //DEBUG("FT1000_ft1000_ChIoctl: finished reading register\n");
701 // Make sure we are within the limits of the slow queue memory limitation
702 if ( (msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ) ) {
703 // Need to put sequence number plus new checksum for message
704 //pmsg = (u16 *)&dpram_command.dpram_blk.pseudohdr;
705 pmsg = (u16 *)&dpram_data->pseudohdr;
706 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
707 total_len = msgsz+2;
708 if (total_len & 0x1) {
709 total_len++;
712 // Insert slow queue sequence number
713 ppseudo_hdr->seq_num = info->squeseqnum++;
714 ppseudo_hdr->portsrc = info->app_info[app_index].app_id;
715 // Calculate new checksum
716 ppseudo_hdr->checksum = *pmsg++;
717 //DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum);
718 for (i=1; i<7; i++) {
719 ppseudo_hdr->checksum ^= *pmsg++;
720 //DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum);
722 pmsg++;
723 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
724 #if 0
725 ptr = dpram_data;
726 DEBUG("FT1000:ft1000_ChIoctl: Command Send\n");
727 for (i=0; i<total_len; i++) {
728 DEBUG("FT1000:ft1000_ChIoctl: data %d = 0x%x\n", i, *ptr++);
730 #endif
731 //dpram_command.extra = 0;
733 //CardSendCommand(ft1000dev,(unsigned char*)&dpram_command,total_len+2);
734 CardSendCommand(ft1000dev,(unsigned short*)dpram_data,total_len+2);
737 info->app_info[app_index].nTxMsg++;
739 else {
740 result = -EINVAL;
745 else {
746 DEBUG("FT1000:ft1000_ChIoctl: Card not ready take messages\n");
747 result = -EACCES;
749 kfree(dpram_data);
752 break;
753 case IOCTL_GET_DPRAM_CMD:
755 struct dpram_blk *pdpram_blk;
756 IOCTL_DPRAM_BLK __user *pioctl_dpram;
757 int msglen;
759 //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DPRAM called\n");
761 if (ft1000_flarion_cnt == 0) {
762 return (-EBADF);
765 // Search for matching file object
766 for (i=0; i<MAX_NUM_APP; i++) {
767 if ( info->app_info[i].fileobject == &File->f_owner) {
768 //DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id);
769 break;
773 // Could not find application info block
774 if (i == MAX_NUM_APP) {
775 DEBUG("FT1000:ft1000_ChIoctl:Could not find application info block\n");
776 result = -EBADF;
777 break;
780 result = 0;
781 pioctl_dpram = argp;
782 if (list_empty(&info->app_info[i].app_sqlist) == 0) {
783 //DEBUG("FT1000:ft1000_ChIoctl:Message detected in slow queue\n");
784 spin_lock_irqsave(&free_buff_lock, flags);
785 pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, struct dpram_blk, list);
786 list_del(&pdpram_blk->list);
787 info->app_info[i].NumOfMsg--;
788 //DEBUG("FT1000:ft1000_ChIoctl:NumOfMsg for app %d = %d\n", i, info->app_info[i].NumOfMsg);
789 spin_unlock_irqrestore(&free_buff_lock, flags);
790 msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
791 result = get_user(msglen, &pioctl_dpram->total_len);
792 if (result)
793 break;
794 msglen = htons(msglen);
795 //DEBUG("FT1000:ft1000_ChIoctl:msg length = %x\n", msglen);
796 if(copy_to_user (&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen))
798 DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
799 result = -EFAULT;
800 break;
803 ft1000_free_buffer(pdpram_blk, &freercvpool);
804 result = msglen;
806 //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_GET_DPRAM no message\n");
808 break;
810 default:
811 DEBUG("FT1000:ft1000_ChIoctl:unknown command: 0x%x\n", Command);
812 result = -ENOTTY;
813 break;
815 info->fAppMsgPend = 0;
816 return result;
819 //---------------------------------------------------------------------------
820 // Function: ft1000_ChRelease
822 // Parameters:
824 // Description:
826 // Notes:
828 //---------------------------------------------------------------------------
829 static int ft1000_ChRelease (struct inode *Inode, struct file *File)
831 struct ft1000_info *info;
832 struct net_device *dev;
833 int i;
834 struct dpram_blk *pdpram_blk;
836 DEBUG("ft1000_ChRelease called\n");
838 dev = File->private_data;
839 info = netdev_priv(dev);
841 if (ft1000_flarion_cnt == 0) {
842 info->appcnt--;
843 return (-EBADF);
846 // Search for matching file object
847 for (i=0; i<MAX_NUM_APP; i++) {
848 if ( info->app_info[i].fileobject == &File->f_owner) {
849 //DEBUG("FT1000:ft1000_ChIoctl: Message is for AppId = %d\n", info->app_info[i].app_id);
850 break;
854 if (i==MAX_NUM_APP)
855 return 0;
857 while (list_empty(&info->app_info[i].app_sqlist) == 0) {
858 DEBUG("Remove and free memory queue up on slow queue\n");
859 pdpram_blk = list_entry(info->app_info[i].app_sqlist.next, struct dpram_blk, list);
860 list_del(&pdpram_blk->list);
861 ft1000_free_buffer(pdpram_blk, &freercvpool);
864 // initialize application information
865 info->appcnt--;
866 DEBUG("ft1000_chdev:%s:appcnt = %d\n", __FUNCTION__, info->appcnt);
867 info->app_info[i].fileobject = NULL;
869 return 0;