2 *---------------------------------------------------------------------------
3 * FT1000 driver for Flarion Flash OFDM NIC Device
5 * Copyright (C) 2006 Flarion Technologies, All rights reserved.
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 *---------------------------------------------------------------------------
19 * File: ft1000_chdev.c
21 * Description: Custom character device dispatch routines.
24 * 8/29/02 Whc Ported to Linux.
25 * 6/05/06 Whc Porting to Linux 2.6.9
27 *---------------------------------------------------------------------------
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>
37 #include <linux/ioctl.h>
38 #include <linux/debugfs.h>
39 #include "ft1000_usb.h"
41 static int ft1000_flarion_cnt;
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);
49 /* List to free receive command buffer pool */
50 struct list_head freercvpool;
52 /* lock to arbitrate free buffer list for receive command data */
53 spinlock_t free_buff_lock;
58 * Table of entry-point routines for char device
60 static const struct file_operations ft1000fops = {
61 .unlocked_ioctl = ft1000_ioctl,
62 .poll = ft1000_poll_dev,
64 .release = ft1000_release,
69 ---------------------------------------------------------------------------
70 * Function: ft1000_get_buffer
80 *---------------------------------------------------------------------------
82 struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist)
85 struct dpram_blk *ptr;
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);
94 ptr = list_entry(bufflist->next, struct dpram_blk, list);
96 /* DEBUG("ft1000_get_buffer: number of free msg buffers = %d\n", numofmsgbuf); */
98 spin_unlock_irqrestore(&free_buff_lock, flags);
107 *---------------------------------------------------------------------------
108 * Function: ft1000_free_buffer
118 *---------------------------------------------------------------------------
120 void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist)
124 spin_lock_irqsave(&free_buff_lock, flags);
125 /* Put memory back to list */
126 list_add_tail(&pdpram_blk->list, plist);
128 /*DEBUG("ft1000_free_buffer: number of free msg buffers = %d\n", numofmsgbuf); */
129 spin_unlock_irqrestore(&free_buff_lock, flags);
133 *---------------------------------------------------------------------------
134 * Function: ft1000_CreateDevice
136 * Parameters: dev - pointer to adapter object
138 * Returns: 0 if successful
140 * Description: Creates a private char device.
142 * Notes: Only called by init_module().
144 *---------------------------------------------------------------------------
146 int ft1000_create_dev(struct ft1000_usb *dev)
150 struct dentry *dir, *file;
151 struct ft1000_debug_dirs *tmp;
153 /* make a new device name */
154 sprintf(dev->DeviceName, "%s%d", "FT1000_", dev->CardNumber);
156 DEBUG("%s: number of instance = %d\n", __func__, ft1000_flarion_cnt);
157 DEBUG("DeviceCreated = %x\n", dev->DeviceCreated);
159 if (dev->DeviceCreated) {
160 DEBUG("%s: \"%s\" already registered\n", __func__, dev->DeviceName);
165 /* register the device */
166 DEBUG("%s: \"%s\" debugfs device registration\n", __func__, dev->DeviceName);
168 tmp = kmalloc(sizeof(struct ft1000_debug_dirs), GFP_KERNEL);
174 dir = debugfs_create_dir(dev->DeviceName, NULL);
176 result = PTR_ERR(dir);
180 file = debugfs_create_file("device", S_IRUGO | S_IWUSR, dir,
183 result = PTR_ERR(file);
184 goto debug_file_fail;
189 tmp->int_number = dev->CardNumber;
190 list_add(&(tmp->list), &(dev->nodes.list));
192 DEBUG("%s: registered debugfs directory \"%s\"\n", __func__, dev->DeviceName);
194 /* initialize application information */
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);
209 dev->DeviceCreated = TRUE;
210 ft1000_flarion_cnt++;
223 *---------------------------------------------------------------------------
224 * Function: ft1000_DestroyDeviceDEBUG
226 * Parameters: dev - pointer to adapter object
228 * Description: Destroys a private char device.
230 * Notes: Only called by cleanup_module().
232 *---------------------------------------------------------------------------
234 void ft1000_destroy_dev(struct net_device *netdev)
236 struct ft1000_info *info = netdev_priv(netdev);
237 struct ft1000_usb *dev = info->priv;
239 struct dpram_blk *pdpram_blk;
240 struct dpram_blk *ptr;
241 struct list_head *pos, *q;
242 struct ft1000_debug_dirs *dir;
244 DEBUG("%s called\n", __func__);
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);
259 DEBUG("%s: unregistered device \"%s\"\n", __func__,
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);
270 wake_up_interruptible(&dev->app_info[i].wait_dpram_msg);
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);
282 dev->DeviceCreated = FALSE;
289 *---------------------------------------------------------------------------
290 * Function: ft1000_open
298 *---------------------------------------------------------------------------
300 static int ft1000_open(struct inode *inode, struct file *file)
302 struct ft1000_info *info;
303 struct ft1000_usb *dev = (struct ft1000_usb *)inode->i_private;
306 DEBUG("%s called\n", __func__);
307 num = (MINOR(inode->i_rdev) & 0xf);
308 DEBUG("ft1000_open: minor number=%d\n", num);
310 info = file->private_data = netdev_priv(dev->net);
312 DEBUG("f_owner = %p number of application = %d\n", (&file->f_owner), dev->appcnt);
314 /* Check if maximum number of application exceeded */
315 if (dev->appcnt > MAX_NUM_APP) {
316 DEBUG("Maximum number of application exceeded\n");
320 /* Search for available application info block */
321 for (i = 0; i < MAX_NUM_APP; i++) {
322 if ((dev->app_info[i].fileobject == NULL)) {
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");
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;
340 nonseekable_open(inode, file);
346 *---------------------------------------------------------------------------
347 * Function: ft1000_poll_dev
355 *---------------------------------------------------------------------------
358 static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait)
360 struct net_device *netdev = file->private_data;
361 struct ft1000_info *info = netdev_priv(netdev);
362 struct ft1000_usb *dev = info->priv;
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");
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); */
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");
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);
390 poll_wait(file, &dev->app_info[i].wait_dpram_msg, wait);
391 /* DEBUG("FT1000:ft1000_poll_dev:Polling for data from DSP\n"); */
397 *---------------------------------------------------------------------------
398 * Function: ft1000_ioctl
406 *---------------------------------------------------------------------------
408 static long ft1000_ioctl(struct file *file, unsigned int command,
409 unsigned long argument)
411 void __user *argp = (void __user *)argument;
412 struct ft1000_info *info;
413 struct ft1000_usb *ft1000dev;
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};
429 unsigned short ledStat = 0;
430 unsigned short conStat = 0;
432 /* DEBUG("ft1000_ioctl called\n"); */
434 if (ft1000_flarion_cnt == 0) {
435 DEBUG("FT1000:ft1000_ioctl called when ft1000_flarion_cnt is zero\n");
439 /* DEBUG("FT1000:ft1000_ioctl:command = 0x%x argument = 0x%8x\n", command, (u32)argument); */
441 info = file->private_data;
442 ft1000dev = info->priv;
443 cmd = _IOC_NR(command);
444 /* DEBUG("FT1000:ft1000_ioctl:cmd = 0x%x\n", cmd); */
446 /* process the command */
448 case IOCTL_REGISTER_CMD:
449 DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_REGISTER called\n");
450 result = get_user(tempword, (__u16 __user *)argp);
452 DEBUG("result = %d failed to get_user\n", result);
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");
467 case IOCTL_GET_VER_CMD:
468 DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_GET_VER called\n");
470 get_ver_data.drv_ver = FT1000_DRV_VER;
472 if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data))) {
473 DEBUG("FT1000:ft1000_ioctl: copy fault occurred\n");
478 DEBUG("FT1000:ft1000_ioctl:driver version = 0x%x\n", (unsigned int)get_ver_data.drv_ver);
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);
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);
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);
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);
510 get_stat_data.ConStat = 0x0f;
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");
526 DEBUG("ft1000_chioctl: GET_DSP_STAT succeed\n");
528 case IOCTL_SET_DPRAM_CMD:
530 struct IOCTL_DPRAM_BLK *dpram_data = NULL;
531 /* struct IOCTL_DPRAM_COMMAND dpram_command; */
534 struct pseudo_hdr *ppseudo_hdr;
540 /* DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_SET_DPRAM called\n");*/
543 if (ft1000_flarion_cnt == 0)
546 if (ft1000dev->DrvMsgPend)
549 if (ft1000dev->fProvComplete == 0)
552 ft1000dev->fAppMsgPend = 1;
554 if (info->CardReady) {
556 /* DEBUG("FT1000:ft1000_ioctl: try to SET_DPRAM \n"); */
558 /* Get the length field to see how many bytes to copy */
559 result = get_user(msgsz, (__u16 __user *)argp);
562 msgsz = ntohs(msgsz);
563 /* DEBUG("FT1000:ft1000_ioctl: length of message = %d\n", msgsz); */
565 if (msgsz > MAX_CMD_SQSIZE) {
566 DEBUG("FT1000:ft1000_ioctl: bad message length = %d\n", msgsz);
572 dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
576 if (copy_from_user(dpram_data, argp, msgsz+2)) {
577 DEBUG("FT1000:ft1000_ChIoctl: copy fault occurred\n");
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) {
586 if (i == MAX_NUM_APP) {
587 DEBUG("FT1000:No matching application fileobject\n");
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); */
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 */
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 */
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 */
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");
628 /*DEBUG("FT1000_ft1000_ioctl: finished reading register\n"); */
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;
636 if (total_len & 0x1) {
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); */
651 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
652 result = card_send_command(ft1000dev, (unsigned short *)dpram_data, total_len+2);
655 ft1000dev->app_info[app_index].nTxMsg++;
662 DEBUG("FT1000:ft1000_ioctl: Card not ready take messages\n");
669 case IOCTL_GET_DPRAM_CMD:
671 struct dpram_blk *pdpram_blk;
672 struct IOCTL_DPRAM_BLK __user *pioctl_dpram;
675 /* DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_GET_DPRAM called\n"); */
677 if (ft1000_flarion_cnt == 0)
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); */
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");
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);
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");
717 ft1000_free_buffer(pdpram_blk, &freercvpool);
720 /* DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_GET_DPRAM no message\n"); */
725 DEBUG("FT1000:ft1000_ioctl:unknown command: 0x%x\n", command);
729 ft1000dev->fAppMsgPend = 0;
734 *---------------------------------------------------------------------------
735 * Function: ft1000_release
743 *---------------------------------------------------------------------------
745 static int ft1000_release(struct inode *inode, struct file *file)
747 struct ft1000_info *info;
748 struct net_device *dev;
749 struct ft1000_usb *ft1000dev;
751 struct dpram_blk *pdpram_blk;
753 DEBUG("ft1000_release called\n");
755 dev = file->private_data;
756 info = netdev_priv(dev);
757 ft1000dev = info->priv;
759 if (ft1000_flarion_cnt == 0) {
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); */
772 if (i == MAX_NUM_APP)
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);
782 /* initialize application information */
784 DEBUG("ft1000_chdev:%s:appcnt = %d\n", __func__, ft1000dev->appcnt);
785 ft1000dev->app_info[i].fileobject = NULL;