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,
264 struct dpram_blk, list);
265 list_del(&pdpram_blk->list);
266 ft1000_free_buffer(pdpram_blk, &freercvpool);
269 wake_up_interruptible(&dev->app_info[i].wait_dpram_msg);
272 /* Remove buffer allocated for receive command data */
273 if (ft1000_flarion_cnt == 0) {
274 while (list_empty(&freercvpool) == 0) {
275 ptr = list_entry(freercvpool.next, struct dpram_blk, list);
276 list_del(&ptr->list);
281 dev->DeviceCreated = FALSE;
288 *---------------------------------------------------------------------------
289 * Function: ft1000_open
297 *---------------------------------------------------------------------------
299 static int ft1000_open(struct inode *inode, struct file *file)
301 struct ft1000_info *info;
302 struct ft1000_usb *dev = (struct ft1000_usb *)inode->i_private;
305 num = MINOR(inode->i_rdev) & 0xf;
306 pr_debug("minor number=%d\n", num);
308 info = file->private_data = netdev_priv(dev->net);
310 pr_debug("f_owner = %p number of application = %d\n",
311 &file->f_owner, dev->appcnt);
313 /* Check if maximum number of application exceeded */
314 if (dev->appcnt > MAX_NUM_APP) {
315 pr_debug("Maximum number of application exceeded\n");
319 /* Search for available application info block */
320 for (i = 0; i < MAX_NUM_APP; i++) {
321 if (dev->app_info[i].fileobject == NULL)
325 /* Fail due to lack of application info block */
326 if (i == MAX_NUM_APP) {
327 pr_debug("Could not find an application info block\n");
332 dev->app_info[i].fileobject = &file->f_owner;
333 dev->app_info[i].nTxMsg = 0;
334 dev->app_info[i].nRxMsg = 0;
335 dev->app_info[i].nTxMsgReject = 0;
336 dev->app_info[i].nRxMsgMiss = 0;
338 nonseekable_open(inode, file);
344 *---------------------------------------------------------------------------
345 * Function: ft1000_poll_dev
353 *---------------------------------------------------------------------------
356 static unsigned int ft1000_poll_dev(struct file *file, poll_table *wait)
358 struct net_device *netdev = file->private_data;
359 struct ft1000_info *info = netdev_priv(netdev);
360 struct ft1000_usb *dev = info->priv;
363 if (ft1000_flarion_cnt == 0) {
364 pr_debug("called with ft1000_flarion_cnt value zero\n");
368 /* Search for matching file object */
369 for (i = 0; i < MAX_NUM_APP; i++) {
370 if (dev->app_info[i].fileobject == &file->f_owner) {
371 /* pr_debug("Message is for AppId = %d\n", dev->app_info[i].app_id); */
376 /* Could not find application info block */
377 if (i == MAX_NUM_APP) {
378 pr_debug("Could not find application info block\n");
382 if (list_empty(&dev->app_info[i].app_sqlist) == 0) {
383 pr_debug("Message detected in slow queue\n");
384 return(POLLIN | POLLRDNORM | POLLPRI);
387 poll_wait(file, &dev->app_info[i].wait_dpram_msg, wait);
388 /* pr_debug("Polling for data from DSP\n"); */
394 *---------------------------------------------------------------------------
395 * Function: ft1000_ioctl
403 *---------------------------------------------------------------------------
405 static long ft1000_ioctl(struct file *file, unsigned int command,
406 unsigned long argument)
408 void __user *argp = (void __user *)argument;
409 struct ft1000_info *info;
410 struct ft1000_usb *ft1000dev;
417 struct IOCTL_GET_VER get_ver_data;
418 struct IOCTL_GET_DSP_STAT get_stat_data;
419 u8 ConnectionMsg[] = {
420 0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
422 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08,
429 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
430 0x00, 0x01, 0x00, 0x00
433 unsigned short ledStat = 0;
434 unsigned short conStat = 0;
436 if (ft1000_flarion_cnt == 0) {
437 pr_debug("called with ft1000_flarion_cnt of zero\n");
441 /* pr_debug("command = 0x%x argument = 0x%8x\n", command, (u32)argument); */
443 info = file->private_data;
444 ft1000dev = info->priv;
445 cmd = _IOC_NR(command);
446 /* pr_debug("cmd = 0x%x\n", cmd); */
448 /* process the command */
450 case IOCTL_REGISTER_CMD:
451 pr_debug("IOCTL_FT1000_REGISTER called\n");
452 result = get_user(tempword, (__u16 __user *)argp);
454 pr_debug("result = %d failed to get_user\n", result);
457 if (tempword == DSPBCMSGID) {
458 /* Search for matching file object */
459 for (i = 0; i < MAX_NUM_APP; i++) {
460 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
461 ft1000dev->app_info[i].DspBCMsgFlag = 1;
462 pr_debug("Registered for broadcast messages\n");
469 case IOCTL_GET_VER_CMD:
470 pr_debug("IOCTL_FT1000_GET_VER called\n");
472 get_ver_data.drv_ver = FT1000_DRV_VER;
474 if (copy_to_user(argp, &get_ver_data, sizeof(get_ver_data))) {
475 pr_debug("copy fault occurred\n");
480 pr_debug("driver version = 0x%x\n",
481 (unsigned int)get_ver_data.drv_ver);
485 /* Connect Message */
486 pr_debug("IOCTL_FT1000_CONNECT\n");
487 ConnectionMsg[79] = 0xfc;
488 result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
491 case IOCTL_DISCONNECT:
492 /* Disconnect Message */
493 pr_debug("IOCTL_FT1000_DISCONNECT\n");
494 ConnectionMsg[79] = 0xfd;
495 result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
497 case IOCTL_GET_DSP_STAT_CMD:
498 /* pr_debug("IOCTL_FT1000_GET_DSP_STAT\n"); */
499 memset(&get_stat_data, 0, sizeof(get_stat_data));
500 memcpy(get_stat_data.DspVer, info->DspVer, DSPVERSZ);
501 memcpy(get_stat_data.HwSerNum, info->HwSerNum, HWSERNUMSZ);
502 memcpy(get_stat_data.Sku, info->Sku, SKUSZ);
503 memcpy(get_stat_data.eui64, info->eui64, EUISZ);
505 if (info->ProgConStat != 0xFF) {
506 ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED,
507 (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
508 get_stat_data.LedStat = ntohs(ledStat);
509 pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
510 ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE,
511 (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
512 get_stat_data.ConStat = ntohs(conStat);
513 pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
515 get_stat_data.ConStat = 0x0f;
519 get_stat_data.nTxPkts = info->stats.tx_packets;
520 get_stat_data.nRxPkts = info->stats.rx_packets;
521 get_stat_data.nTxBytes = info->stats.tx_bytes;
522 get_stat_data.nRxBytes = info->stats.rx_bytes;
523 do_gettimeofday(&tv);
524 get_stat_data.ConTm = (u32)(tv.tv_sec - info->ConTm);
525 pr_debug("Connection Time = %d\n", (int)get_stat_data.ConTm);
526 if (copy_to_user(argp, &get_stat_data, sizeof(get_stat_data))) {
527 pr_debug("copy fault occurred\n");
531 pr_debug("GET_DSP_STAT succeed\n");
533 case IOCTL_SET_DPRAM_CMD:
535 struct IOCTL_DPRAM_BLK *dpram_data = NULL;
536 /* struct IOCTL_DPRAM_COMMAND dpram_command; */
539 struct pseudo_hdr *ppseudo_hdr;
545 /* pr_debug("IOCTL_FT1000_SET_DPRAM called\n");*/
548 if (ft1000_flarion_cnt == 0)
551 if (ft1000dev->DrvMsgPend)
554 if (ft1000dev->fProvComplete == 0)
557 ft1000dev->fAppMsgPend = true;
559 if (info->CardReady) {
561 /* pr_debug("try to SET_DPRAM\n"); */
563 /* Get the length field to see how many bytes to copy */
564 result = get_user(msgsz, (__u16 __user *)argp);
567 msgsz = ntohs(msgsz);
568 /* pr_debug("length of message = %d\n", msgsz); */
570 if (msgsz > MAX_CMD_SQSIZE) {
571 pr_debug("bad message length = %d\n", msgsz);
577 dpram_data = kmalloc(msgsz + 2, GFP_KERNEL);
581 if (copy_from_user(dpram_data, argp, msgsz+2)) {
582 pr_debug("copy fault occurred\n");
585 /* Check if this message came from a registered application */
586 for (i = 0; i < MAX_NUM_APP; i++) {
587 if (ft1000dev->app_info[i].fileobject == &file->f_owner)
590 if (i == MAX_NUM_APP) {
591 pr_debug("No matching application fileobject\n");
598 /* Check message qtype type which is the lower byte within qos_class */
599 qtype = ntohs(dpram_data->pseudohdr.qos_class) & 0xff;
600 /* pr_debug("qtype = %d\n", qtype); */
602 /* Put message into Slow Queue */
603 /* Only put a message into the DPRAM if msg doorbell is available */
604 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
605 /* pr_debug("READ REGISTER tempword=%x\n", tempword); */
606 if (tempword & FT1000_DB_DPRAM_TX) {
607 /* Suspend for 2ms and try again due to DSP doorbell busy */
609 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
610 if (tempword & FT1000_DB_DPRAM_TX) {
611 /* Suspend for 1ms and try again due to DSP doorbell busy */
613 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
614 if (tempword & FT1000_DB_DPRAM_TX) {
615 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
616 if (tempword & FT1000_DB_DPRAM_TX) {
617 /* Suspend for 3ms and try again due to DSP doorbell busy */
619 status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_DOORBELL);
620 if (tempword & FT1000_DB_DPRAM_TX) {
621 pr_debug("Doorbell not available\n");
631 /*pr_debug("finished reading register\n"); */
633 /* Make sure we are within the limits of the slow queue memory limitation */
634 if ((msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ)) {
635 /* Need to put sequence number plus new checksum for message */
636 pmsg = (u16 *)&dpram_data->pseudohdr;
637 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
642 /* Insert slow queue sequence number */
643 ppseudo_hdr->seq_num = info->squeseqnum++;
644 ppseudo_hdr->portsrc = ft1000dev->app_info[app_index].app_id;
645 /* Calculate new checksum */
646 ppseudo_hdr->checksum = *pmsg++;
647 /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
648 for (i = 1; i < 7; i++) {
649 ppseudo_hdr->checksum ^= *pmsg++;
650 /* pr_debug("checksum = 0x%x\n", ppseudo_hdr->checksum); */
653 ppseudo_hdr = (struct pseudo_hdr *)pmsg;
654 result = card_send_command(ft1000dev, dpram_data, total_len+2);
657 ft1000dev->app_info[app_index].nTxMsg++;
664 pr_debug("Card not ready take messages\n");
671 case IOCTL_GET_DPRAM_CMD:
673 struct dpram_blk *pdpram_blk;
674 struct IOCTL_DPRAM_BLK __user *pioctl_dpram;
677 /* pr_debug("IOCTL_FT1000_GET_DPRAM called\n"); */
679 if (ft1000_flarion_cnt == 0)
682 /* Search for matching file object */
683 for (i = 0; i < MAX_NUM_APP; i++) {
684 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
685 /*pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
690 /* Could not find application info block */
691 if (i == MAX_NUM_APP) {
692 pr_debug("Could not find application info block\n");
699 if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
700 /* pr_debug("Message detected in slow queue\n"); */
701 spin_lock_irqsave(&free_buff_lock, flags);
702 pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next,
703 struct dpram_blk, list);
704 list_del(&pdpram_blk->list);
705 ft1000dev->app_info[i].NumOfMsg--;
706 /* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
707 spin_unlock_irqrestore(&free_buff_lock, flags);
708 msglen = ntohs(*(u16 *)pdpram_blk->pbuffer) + PSEUDOSZ;
709 result = get_user(msglen, &pioctl_dpram->total_len);
712 msglen = htons(msglen);
713 /* pr_debug("msg length = %x\n", msglen); */
714 if (copy_to_user(&pioctl_dpram->pseudohdr, pdpram_blk->pbuffer, msglen)) {
715 pr_debug("copy fault occurred\n");
720 ft1000_free_buffer(pdpram_blk, &freercvpool);
723 /* pr_debug("IOCTL_FT1000_GET_DPRAM no message\n"); */
728 pr_debug("unknown command: 0x%x\n", command);
732 ft1000dev->fAppMsgPend = false;
737 *---------------------------------------------------------------------------
738 * Function: ft1000_release
746 *---------------------------------------------------------------------------
748 static int ft1000_release(struct inode *inode, struct file *file)
750 struct ft1000_info *info;
751 struct net_device *dev;
752 struct ft1000_usb *ft1000dev;
754 struct dpram_blk *pdpram_blk;
755 struct dpram_blk *tmp;
757 dev = file->private_data;
758 info = netdev_priv(dev);
759 ft1000dev = info->priv;
761 if (ft1000_flarion_cnt == 0) {
766 /* Search for matching file object */
767 for (i = 0; i < MAX_NUM_APP; i++) {
768 if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
769 /* pr_debug("Message is for AppId = %d\n", ft1000dev->app_info[i].app_id); */
774 if (i == MAX_NUM_APP)
777 list_for_each_entry_safe(pdpram_blk, tmp, &ft1000dev->app_info[i].app_sqlist, list) {
778 pr_debug("Remove and free memory queue up on slow queue\n");
779 list_del(&pdpram_blk->list);
780 ft1000_free_buffer(pdpram_blk, &freercvpool);
783 /* initialize application information */
785 pr_debug("appcnt = %d\n", ft1000dev->appcnt);
786 ft1000dev->app_info[i].fileobject = NULL;