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 *---------------------------------------------------------------------------
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/sched.h>
35 #include <linux/errno.h>
36 #include <linux/poll.h>
37 #include <linux/netdevice.h>
38 #include <linux/delay.h>
40 #include <linux/ioctl.h>
41 #include <linux/debugfs.h>
42 #include "ft1000_usb.h"
44 static int ft1000_flarion_cnt;
46 static int ft1000_open(struct inode *inode, struct file *file);
47 static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait);
48 static long ft1000_ioctl(struct file *file, unsigned int command,
49 unsigned long argument);
50 static int ft1000_release(struct inode *inode, struct file *file);
52 /* List to free receive command buffer pool */
53 struct list_head freercvpool;
55 /* lock to arbitrate free buffer list for receive command data */
56 spinlock_t free_buff_lock;
61 * Table of entry-point routines for char device
63 static const struct file_operations ft1000fops = {
64 .unlocked_ioctl = ft1000_ioctl,
65 .poll = ft1000_poll_dev,
67 .release = ft1000_release,
72 ---------------------------------------------------------------------------
73 * Function: ft1000_get_buffer
83 *---------------------------------------------------------------------------
85 struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist)
88 struct dpram_blk *ptr;
90 spin_lock_irqsave(&free_buff_lock, flags);
91 /* Check if buffer is available */
92 if (list_empty(bufflist)) {
93 pr_debug("No more buffer - %d\n", numofmsgbuf);
97 ptr = list_entry(bufflist->next, struct dpram_blk, list);
99 /* pr_debug("number of free msg buffers = %d\n", numofmsgbuf); */
101 spin_unlock_irqrestore(&free_buff_lock, flags);
110 *---------------------------------------------------------------------------
111 * Function: ft1000_free_buffer
121 *---------------------------------------------------------------------------
123 void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist)
127 spin_lock_irqsave(&free_buff_lock, flags);
128 /* Put memory back to list */
129 list_add_tail(&pdpram_blk->list, plist);
131 /*pr_debug("number of free msg buffers = %d\n", numofmsgbuf); */
132 spin_unlock_irqrestore(&free_buff_lock, flags);
136 *---------------------------------------------------------------------------
137 * Function: ft1000_CreateDevice
139 * Parameters: dev - pointer to adapter object
141 * Returns: 0 if successful
143 * Description: Creates a private char device.
145 * Notes: Only called by init_module().
147 *---------------------------------------------------------------------------
149 int ft1000_create_dev(struct ft1000_usb *dev)
153 struct dentry *dir, *file;
154 struct ft1000_debug_dirs *tmp;
156 /* make a new device name */
157 sprintf(dev->DeviceName, "%s%d", "FT1000_", dev->CardNumber);
159 pr_debug("number of instance = %d\n", ft1000_flarion_cnt);
160 pr_debug("DeviceCreated = %x\n", dev->DeviceCreated);
162 if (dev->DeviceCreated) {
163 pr_debug("\"%s\" already registered\n", dev->DeviceName);
168 /* register the device */
169 pr_debug("\"%s\" debugfs device registration\n", dev->DeviceName);
171 tmp = kmalloc(sizeof(struct ft1000_debug_dirs), GFP_KERNEL);
177 dir = debugfs_create_dir(dev->DeviceName, NULL);
179 result = PTR_ERR(dir);
183 file = debugfs_create_file("device", S_IRUGO | S_IWUSR, dir,
186 result = PTR_ERR(file);
187 goto debug_file_fail;
192 tmp->int_number = dev->CardNumber;
193 list_add(&tmp->list, &dev->nodes.list);
195 pr_debug("registered debugfs directory \"%s\"\n", dev->DeviceName);
197 /* initialize application information */
199 for (i = 0; i < MAX_NUM_APP; i++) {
200 dev->app_info[i].nTxMsg = 0;
201 dev->app_info[i].nRxMsg = 0;
202 dev->app_info[i].nTxMsgReject = 0;
203 dev->app_info[i].nRxMsgMiss = 0;
204 dev->app_info[i].fileobject = NULL;
205 dev->app_info[i].app_id = i+1;
206 dev->app_info[i].DspBCMsgFlag = 0;
207 dev->app_info[i].NumOfMsg = 0;
208 init_waitqueue_head(&dev->app_info[i].wait_dpram_msg);
209 INIT_LIST_HEAD(&dev->app_info[i].app_sqlist);
212 dev->DeviceCreated = TRUE;
213 ft1000_flarion_cnt++;
226 *---------------------------------------------------------------------------
227 * Function: ft1000_DestroyDeviceDEBUG
229 * Parameters: dev - pointer to adapter object
231 * Description: Destroys a private char device.
233 * Notes: Only called by cleanup_module().
235 *---------------------------------------------------------------------------
237 void ft1000_destroy_dev(struct net_device *netdev)
239 struct ft1000_info *info = netdev_priv(netdev);
240 struct ft1000_usb *dev = info->priv;
242 struct dpram_blk *pdpram_blk;
243 struct dpram_blk *ptr;
244 struct list_head *pos, *q;
245 struct ft1000_debug_dirs *dir;
247 if (dev->DeviceCreated) {
248 ft1000_flarion_cnt--;
249 list_for_each_safe(pos, q, &dev->nodes.list) {
250 dir = list_entry(pos, struct ft1000_debug_dirs, list);
251 if (dir->int_number == dev->CardNumber) {
252 debugfs_remove(dir->file);
253 debugfs_remove(dir->dent);
258 pr_debug("unregistered device \"%s\"\n", dev->DeviceName);
260 /* Make sure we free any memory reserve for slow Queue */
261 for (i = 0; i < MAX_NUM_APP; i++) {
262 while (list_empty(&dev->app_info[i].app_sqlist) == 0) {
263 pdpram_blk = list_entry(dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
264 list_del(&pdpram_blk->list);
265 ft1000_free_buffer(pdpram_blk, &freercvpool);
268 wake_up_interruptible(&dev->app_info[i].wait_dpram_msg);
271 /* Remove buffer allocated for receive command data */
272 if (ft1000_flarion_cnt == 0) {
273 while (list_empty(&freercvpool) == 0) {
274 ptr = list_entry(freercvpool.next, struct dpram_blk, list);
275 list_del(&ptr->list);
280 dev->DeviceCreated = FALSE;
287 *---------------------------------------------------------------------------
288 * Function: ft1000_open
296 *---------------------------------------------------------------------------
298 static int ft1000_open(struct inode *inode, struct file *file)
300 struct ft1000_info *info;
301 struct ft1000_usb *dev = (struct ft1000_usb *)inode->i_private;
304 num = MINOR(inode->i_rdev) & 0xf;
305 pr_debug("minor number=%d\n", num);
307 info = file->private_data = netdev_priv(dev->net);
309 pr_debug("f_owner = %p number of application = %d\n",
310 &file->f_owner, dev->appcnt);
312 /* Check if maximum number of application exceeded */
313 if (dev->appcnt > MAX_NUM_APP) {
314 pr_debug("Maximum number of application exceeded\n");
318 /* Search for available application info block */
319 for (i = 0; i < MAX_NUM_APP; i++) {
320 if ((dev->app_info[i].fileobject == NULL))
324 /* Fail due to lack of application info block */
325 if (i == MAX_NUM_APP) {
326 pr_debug("Could not find an application info block\n");
331 dev->app_info[i].fileobject = &file->f_owner;
332 dev->app_info[i].nTxMsg = 0;
333 dev->app_info[i].nRxMsg = 0;
334 dev->app_info[i].nTxMsgReject = 0;
335 dev->app_info[i].nRxMsgMiss = 0;
337 nonseekable_open(inode, file);
343 *---------------------------------------------------------------------------
344 * Function: ft1000_poll_dev
352 *---------------------------------------------------------------------------
355 static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait)
357 struct net_device *netdev = file->private_data;
358 struct ft1000_info *info = netdev_priv(netdev);
359 struct ft1000_usb *dev = info->priv;
362 if (ft1000_flarion_cnt == 0) {
363 pr_debug("called with ft1000_flarion_cnt value zero\n");
367 /* Search for matching file object */
368 for (i = 0; i < MAX_NUM_APP; i++) {
369 if (dev->app_info[i].fileobject == &file->f_owner) {
370 /* pr_debug("Message is for AppId = %d\n", dev->app_info[i].app_id); */
375 /* Could not find application info block */
376 if (i == MAX_NUM_APP) {
377 pr_debug("Could not find application info block\n");
381 if (list_empty(&dev->app_info[i].app_sqlist) == 0) {
382 pr_debug("Message detected in slow queue\n");
383 return(POLLIN | POLLRDNORM | POLLPRI);
386 poll_wait(file, &dev->app_info[i].wait_dpram_msg, wait);
387 /* pr_debug("Polling for data from DSP\n"); */
393 *---------------------------------------------------------------------------
394 * Function: ft1000_ioctl
402 *---------------------------------------------------------------------------
404 static long ft1000_ioctl(struct file *file, unsigned int command,
405 unsigned long argument)
407 void __user *argp = (void __user *)argument;
408 struct ft1000_info *info;
409 struct ft1000_usb *ft1000dev;
416 struct IOCTL_GET_VER get_ver_data;
417 struct IOCTL_GET_DSP_STAT get_stat_data;
418 u8 ConnectionMsg[] = {0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
419 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
423 0x00, 0x01, 0x00, 0x00};
425 unsigned short ledStat = 0;
426 unsigned short conStat = 0;
428 if (ft1000_flarion_cnt == 0) {
429 pr_debug("called with ft1000_flarion_cnt of zero\n");
433 /* pr_debug("command = 0x%x argument = 0x%8x\n", command, (u32)argument); */
435 info = file->private_data;
436 ft1000dev = info->priv;
437 cmd = _IOC_NR(command);
438 /* pr_debug("cmd = 0x%x\n", cmd); */
440 /* process the command */
442 case IOCTL_REGISTER_CMD:
443 pr_debug("IOCTL_FT1000_REGISTER called\n");
444 result = get_user(tempword, (__u16 __user *)argp);
446 pr_debug("result = %d failed to get_user\n", result);
449 if (tempword == DSPBCMSGID) {
450 /* Search for matching file object */
451 for (i = 0; i < MAX_NUM_APP; i++) {
452 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
453 ft1000dev->app_info[i].DspBCMsgFlag = 1;
454 pr_debug("Registered for broadcast messages\n");
461 case IOCTL_GET_VER_CMD:
462 pr_debug("IOCTL_FT1000_GET_VER called\n");
464 get_ver_data.drv_ver = FT1000_DRV_VER;
466 if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data))) {
467 pr_debug("copy fault occurred\n");
472 pr_debug("driver version = 0x%x\n",
473 (unsigned int)get_ver_data.drv_ver);
477 /* Connect Message */
478 pr_debug("IOCTL_FT1000_CONNECT\n");
479 ConnectionMsg[79] = 0xfc;
480 result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
483 case IOCTL_DISCONNECT:
484 /* Disconnect Message */
485 pr_debug("IOCTL_FT1000_DISCONNECT\n");
486 ConnectionMsg[79] = 0xfd;
487 result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
489 case IOCTL_GET_DSP_STAT_CMD:
490 /* pr_debug("IOCTL_FT1000_GET_DSP_STAT\n"); */
491 memset(&get_stat_data, 0, sizeof(get_stat_data));
492 memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
493 memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
494 memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
495 memcpy(get_stat_data.eui64, info->eui64, EUISZ);
497 if (info->ProgConStat != 0xFF) {
498 ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
499 get_stat_data.LedStat = ntohs(ledStat);
500 pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
501 ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
502 get_stat_data.ConStat = ntohs(conStat);
503 pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
505 get_stat_data.ConStat = 0x0f;
509 get_stat_data.nTxPkts = info->stats.tx_packets;
510 get_stat_data.nRxPkts = info->stats.rx_packets;
511 get_stat_data.nTxBytes = info->stats.tx_bytes;
512 get_stat_data.nRxBytes = info->stats.rx_bytes;
513 do_gettimeofday(&tv);
514 get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
515 pr_debug("Connection Time = %d\n", (int)get_stat_data.ConTm);
516 if (copy_to_user(argp, &get_stat_data, sizeof(get_stat_data))) {
517 pr_debug("copy fault occurred\n");
521 pr_debug("GET_DSP_STAT succeed\n");
523 case IOCTL_SET_DPRAM_CMD:
525 struct IOCTL_DPRAM_BLK *dpram_data = NULL;
526 /* struct IOCTL_DPRAM_COMMAND dpram_command; */
529 struct pseudo_hdr *ppseudo_hdr;
535 /* pr_debug("IOCTL_FT1000_SET_DPRAM called\n");*/
538 if (ft1000_flarion_cnt == 0)
541 if (ft1000dev->DrvMsgPend)
544 if (ft1000dev->fProvComplete == 0)
547 ft1000dev->fAppMsgPend = true;
549 if (info->CardReady) {
551 /* pr_debug("try to SET_DPRAM\n"); */
553 /* Get the length field to see how many bytes to copy */
554 result = get_user(msgsz, (__u16 __user *)argp);
557 msgsz = ntohs(msgsz);
558 /* pr_debug("length of message = %d\n", msgsz); */
560 if (msgsz > MAX_CMD_SQSIZE) {
561 pr_debug("bad message length = %d\n", msgsz);
567 dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
571 if (copy_from_user(dpram_data, argp, msgsz+2)) {
572 pr_debug("copy fault occurred\n");
575 /* Check if this message came from a registered application */
576 for (i = 0; i < MAX_NUM_APP; i++) {
577 if (ft1000dev->app_info[i].fileobject == &file->f_owner)
580 if (i == MAX_NUM_APP) {
581 pr_debug("No matching application fileobject\n");
588 /* Check message qtype type which is the lower byte within qos_class */
589 qtype = ntohs(dpram_data->pseudohdr.qos_class) & 0xff;
590 /* pr_debug("qtype = %d\n", qtype); */
593 /* Put message into Slow Queue */
594 /* Only put a message into the DPRAM if msg doorbell is available */
595 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
596 /* pr_debug("READ REGISTER tempword=%x\n", tempword); */
597 if (tempword & FT1000_DB_DPRAM_TX) {
598 /* Suspend for 2ms and try again due to DSP doorbell busy */
600 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
601 if (tempword & FT1000_DB_DPRAM_TX) {
602 /* Suspend for 1ms and try again due to DSP doorbell busy */
604 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
605 if (tempword & FT1000_DB_DPRAM_TX) {
606 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
607 if (tempword & FT1000_DB_DPRAM_TX) {
608 /* Suspend for 3ms 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 pr_debug("Doorbell not available\n");
622 /*pr_debug("finished reading register\n"); */
624 /* Make sure we are within the limits of the slow queue memory limitation */
625 if ((msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ)) {
626 /* Need to put sequence number plus new checksum for message */
627 pmsg = (u16 *)&dpram_data->pseudohdr;
628 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
633 /* Insert slow queue sequence number */
634 ppseudo_hdr->seq_num = info->squeseqnum++;
635 ppseudo_hdr->portsrc = ft1000dev->app_info[app_index].app_id;
636 /* Calculate new checksum */
637 ppseudo_hdr->checksum = *pmsg++;
638 /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
639 for (i = 1; i < 7; i++) {
640 ppseudo_hdr->checksum ^= *pmsg++;
641 /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
644 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
645 result = card_send_command(ft1000dev, dpram_data, total_len+2);
648 ft1000dev->app_info[app_index].nTxMsg++;
655 pr_debug("Card not ready take messages\n");
662 case IOCTL_GET_DPRAM_CMD:
664 struct dpram_blk *pdpram_blk;
665 struct IOCTL_DPRAM_BLK __user *pioctl_dpram;
668 /* pr_debug("IOCTL_FT1000_GET_DPRAM called\n"); */
670 if (ft1000_flarion_cnt == 0)
673 /* Search for matching file object */
674 for (i = 0; i < MAX_NUM_APP; i++) {
675 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
676 /*pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
681 /* Could not find application info block */
682 if (i == MAX_NUM_APP) {
683 pr_debug("Could not find application info block\n");
690 if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
691 /* pr_debug("Message detected in slow queue\n"); */
692 spin_lock_irqsave(&free_buff_lock, flags);
693 pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
694 list_del(&pdpram_blk->list);
695 ft1000dev->app_info[i].NumOfMsg--;
696 /* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
697 spin_unlock_irqrestore(&free_buff_lock, flags);
698 msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
699 result = get_user(msglen, &pioctl_dpram->total_len);
702 msglen = htons(msglen);
703 /* pr_debug("msg length = %x\n", msglen); */
704 if (copy_to_user(&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen)) {
705 pr_debug("copy fault occurred\n");
710 ft1000_free_buffer(pdpram_blk, &freercvpool);
713 /* pr_debug("IOCTL_FT1000_GET_DPRAM no message\n"); */
718 pr_debug("unknown command: 0x%x\n", command);
722 ft1000dev->fAppMsgPend = false;
727 *---------------------------------------------------------------------------
728 * Function: ft1000_release
736 *---------------------------------------------------------------------------
738 static int ft1000_release(struct inode *inode, struct file *file)
740 struct ft1000_info *info;
741 struct net_device *dev;
742 struct ft1000_usb *ft1000dev;
744 struct dpram_blk *pdpram_blk;
745 struct dpram_blk *tmp;
747 dev = file->private_data;
748 info = netdev_priv(dev);
749 ft1000dev = info->priv;
751 if (ft1000_flarion_cnt == 0) {
756 /* Search for matching file object */
757 for (i = 0; i < MAX_NUM_APP; i++) {
758 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
759 /* pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
764 if (i == MAX_NUM_APP)
767 list_for_each_entry_safe(pdpram_blk, tmp, &ft1000dev->app_info[i].app_sqlist, list) {
768 pr_debug("Remove and free memory queue up on slow queue\n");
769 list_del(&pdpram_blk->list);
770 ft1000_free_buffer(pdpram_blk, &freercvpool);
773 /* initialize application information */
775 pr_debug("appcnt = %d\n", ft1000dev->appcnt);
776 ft1000dev->app_info[i].fileobject = NULL;