⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iphase.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************         iphase.c: Device driver for Interphase ATM PCI adapter cards                     Author: Peter Wang  <pwang@iphase.com>                               Interphase Corporation  <www.iphase.com>                                          Version: 1.0                           *******************************************************************************            This software may be used and distributed according to the terms      of the GNU Public License (GPL), incorporated herein by reference.      Drivers based on this skeleton fall under the GPL and must retain      the authorship (implicit copyright) notice.      This program is distributed in the hope that it will be useful, but      WITHOUT ANY WARRANTY; without even the implied warranty of      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      General Public License for more details.            Modified from an incomplete driver for Interphase 5575 1KVC 1M card which       was originally written by Monalisa Agrawal at UNH. Now this driver       supports a variety of varients of Interphase ATM PCI (i)Chip adapter       card family (See www.iphase.com/products/ClassSheet.cfm?ClassID=ATM)       in terms of PHY type, the size of control memory and the size of       packet memory. The followings are the change log and history:               Bugfix the Mona's UBR driver.          Modify the basic memory allocation and dma logic.          Port the driver to the latest kernel from 2.0.46.          Complete the ABR logic of the driver, and added the ABR work-              around for the hardware anormalies.          Add the CBR support.	  Add the flow control logic to the driver to allow rate-limit VC.          Add 4K VC support to the board with 512K control memory.          Add the support of all the variants of the Interphase ATM PCI           (i)Chip adapter cards including x575 (155M OC3 and UTP155), x525          (25M UTP25) and x531 (DS3 and E3).          Add SMP support.      Support and updates available at: ftp://ftp.iphase.com/pub/atm*******************************************************************************/#ifdef IA_MODULE#define MODULE#endif#include <linux/version.h>#include <linux/module.h>  #include <linux/kernel.h>  #include <linux/mm.h>  #include <linux/pci.h>  #include <linux/errno.h>  #include <linux/atm.h>  #include <linux/atmdev.h>  #include <linux/sonet.h>  #include <linux/skbuff.h>  #include <linux/time.h>  #include <linux/sched.h> /* for xtime */  #include <linux/delay.h>  #include <linux/uio.h>  #include <linux/init.h>  #include <asm/system.h>  #include <asm/io.h>  #include <asm/atomic.h>  #include <asm/uaccess.h>  #include <asm/string.h>  #include <asm/byteorder.h>  #include <math.h>  #include <linux/vmalloc.h>  #include "iphase.h"		  #include "suni.h"		  #define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))  struct suni_priv {        struct k_sonet_stats sonet_stats; /* link diagnostics */        unsigned char loop_mode;        /* loopback mode */        struct atm_dev *dev;            /* device back-pointer */        struct suni_priv *next;         /* next SUNI */}; #define PRIV(dev) ((struct suni_priv *) dev->phy_data)static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr);static IADEV *ia_dev[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};static struct atm_dev *_ia_dev[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};static int iadev_count = 0;static void ia_led_timer(unsigned long arg);static struct timer_list ia_timer = { function: ia_led_timer };struct atm_vcc *vcc_close_que[100];static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ;static u32 IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER            |IF_IADBG_ABR | IF_IADBG_EVENT*/ 0; #ifdef MODULEMODULE_PARM(IA_TX_BUF, "i");MODULE_PARM(IA_TX_BUF_SZ, "i");MODULE_PARM(IA_RX_BUF, "i");MODULE_PARM(IA_RX_BUF_SZ, "i");MODULE_PARM(IADebugFlag, "i");#endif/**************************** IA_LIB **********************************/static void ia_init_rtn_q (IARTN_Q *que) {    que->next = NULL;    que->tail = NULL; }static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data) {   data->next = NULL;   if (que->next == NULL)       que->next = que->tail = data;   else {      data->next = que->next;      que->next = data;   }    return;}static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) {   IARTN_Q *entry;   entry = (IARTN_Q *)kmalloc(sizeof(IARTN_Q), GFP_KERNEL);   if (!entry) return -1;   entry->data = data;   entry->next = NULL;   if (que->next == NULL)       que->next = que->tail = entry;   else {      que->tail->next = entry;      que->tail = que->tail->next;   }         return 1;}static IARTN_Q * ia_deque_rtn_q (IARTN_Q *que) {   IARTN_Q *tmpdata;   if (que->next == NULL)      return NULL;   tmpdata = que->next;   if ( que->next == que->tail)        que->next = que->tail = NULL;   else       que->next = que->next->next;   return tmpdata;}static void ia_hack_tcq(IADEV *dev) {  u_short 		desc1;  u_short		tcq_wr;  struct ia_vcc         *iavcc_r = NULL;   extern void desc_dbg(IADEV *iadev);  tcq_wr = readl(dev->seg_reg+TCQ_WR_PTR) & 0xffff;  while (dev->host_tcq_wr != tcq_wr) {     desc1 = *(u_short *)(dev->seg_ram + dev->host_tcq_wr);     if (!desc1) ;     else if (!dev->desc_tbl[desc1 -1].timestamp) {        IF_ABR(printk(" Desc %d is reset at %ld\n", desc1 -1, jiffies);)        *(u_short *) (dev->seg_ram + dev->host_tcq_wr) = 0;     }                                      else if (dev->desc_tbl[desc1 -1].timestamp) {        if (!(iavcc_r = dev->desc_tbl[desc1 -1].iavcc)) {            printk("IA: Fatal err in get_desc\n");           continue;        }        iavcc_r->vc_desc_cnt--;        dev->desc_tbl[desc1 -1].timestamp = 0;        IF_EVENT(printk("ia_hack: return_q skb = 0x%x desc = %d\n",                                    (u32)dev->desc_tbl[desc1 -1].txskb, desc1);)        if (iavcc_r->pcr < dev->rate_limit) {           IA_SKB_STATE (dev->desc_tbl[desc1-1].txskb) |= IA_TX_DONE;           if (ia_enque_rtn_q(&dev->tx_return_q, dev->desc_tbl[desc1 -1]) < 0)              printk("ia_hack_tcq: No memory available\n");        }         dev->desc_tbl[desc1 -1].iavcc = NULL;        dev->desc_tbl[desc1 -1].txskb = NULL;     }     dev->host_tcq_wr += 2;     if (dev->host_tcq_wr > dev->ffL.tcq_ed)         dev->host_tcq_wr = dev->ffL.tcq_st;  }} /* ia_hack_tcq */static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {  u_short 		desc_num, i;  struct sk_buff        *skb;  struct ia_vcc         *iavcc_r = NULL;   unsigned long delta;  static unsigned long timer = 0;  int ltimeout;  extern void desc_dbg(IADEV *iadev);  ia_hack_tcq (dev);  if(((jiffies - timer)>50)||((dev->ffL.tcq_rd==dev->host_tcq_wr))){           timer = jiffies;      i=0;     while (i < dev->num_tx_desc) {        if (!dev->desc_tbl[i].timestamp) {           i++;           continue;        }        ltimeout = dev->desc_tbl[i].iavcc->ltimeout;         delta = jiffies - dev->desc_tbl[i].timestamp;        if (delta >= ltimeout) {           IF_ABR(printk("RECOVER run!! desc_tbl %d = %d  delta = %ld,                time = %ld\n", i,dev->desc_tbl[i].timestamp, delta, jiffies);)           if (dev->ffL.tcq_rd == dev->ffL.tcq_st)               dev->ffL.tcq_rd =  dev->ffL.tcq_ed;           else               dev->ffL.tcq_rd -= 2;           *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd) = i+1;           if (!(skb = dev->desc_tbl[i].txskb) ||                           !(iavcc_r = dev->desc_tbl[i].iavcc))              printk("Fatal err, desc table vcc or skb is NULL\n");           else               iavcc_r->vc_desc_cnt--;           dev->desc_tbl[i].timestamp = 0;           dev->desc_tbl[i].iavcc = NULL;           dev->desc_tbl[i].txskb = NULL;        }        i++;     } /* while */  }  if (dev->ffL.tcq_rd == dev->host_tcq_wr)      return 0xFFFF;      /* Get the next available descriptor number from TCQ */  desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);  while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) {     dev->ffL.tcq_rd += 2;     if (dev->ffL.tcq_rd > dev->ffL.tcq_ed)      dev->ffL.tcq_rd = dev->ffL.tcq_st;     if (dev->ffL.tcq_rd == dev->host_tcq_wr)         return 0xFFFF;      desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);  }  /* get system time */  dev->desc_tbl[desc_num -1].timestamp = jiffies;  return desc_num;}static void clear_lockup (struct atm_vcc *vcc, IADEV *dev) {  u_char          	foundLockUp;  vcstatus_t		*vcstatus;  u_short               *shd_tbl;  u_short               tempCellSlot, tempFract;  struct main_vc *abr_vc = (struct main_vc *)dev->MAIN_VC_TABLE_ADDR;  struct ext_vc *eabr_vc = (struct ext_vc *)dev->EXT_VC_TABLE_ADDR;  u_int  i;  if (vcc->qos.txtp.traffic_class == ATM_ABR) {     vcstatus = (vcstatus_t *) &(dev->testTable[vcc->vci]->vc_status);     vcstatus->cnt++;     foundLockUp = 0;     if( vcstatus->cnt == 0x05 ) {        abr_vc += vcc->vci;	eabr_vc += vcc->vci;	if( eabr_vc->last_desc ) {	   if( (abr_vc->status & 0x07) == ABR_STATE /* 0x2 */ ) {              /* Wait for 10 Micro sec */              udelay(10);	      if ((eabr_vc->last_desc)&&((abr_vc->status & 0x07)==ABR_STATE))		 foundLockUp = 1;           }	   else {	      tempCellSlot = abr_vc->last_cell_slot;              tempFract    = abr_vc->fraction;              if((tempCellSlot == dev->testTable[vcc->vci]->lastTime)                         && (tempFract == dev->testTable[vcc->vci]->fract))	         foundLockUp = 1; 		                  dev->testTable[vcc->vci]->lastTime = tempCellSlot;                 dev->testTable[vcc->vci]->fract = tempFract; 	   } 	            } /* last descriptor */	 	           vcstatus->cnt = 0;     	     } /* vcstatus->cnt */	     if (foundLockUp) {        IF_ABR(printk("LOCK UP found\n");) 	writew(0xFFFD, dev->seg_reg+MODE_REG_0);        /* Wait for 10 Micro sec */        udelay(10);         abr_vc->status &= 0xFFF8;        abr_vc->status |= 0x0001;  /* state is idle */	shd_tbl = (u_short *)dev->ABR_SCHED_TABLE_ADDR;                	for( i = 0; ((i < dev->num_vc) && (shd_tbl[i])); i++ );	if (i < dev->num_vc)           shd_tbl[i] = vcc->vci;        else           IF_ERR(printk("ABR Seg. may not continue on VC %x\n",vcc->vci);)        writew(T_ONLINE, dev->seg_reg+MODE_REG_0);        writew(~(TRANSMIT_DONE|TCQ_NOT_EMPTY), dev->seg_reg+SEG_MASK_REG);        writew(TRANSMIT_DONE, dev->seg_reg+SEG_INTR_STATUS_REG);       	vcstatus->cnt = 0;     } /* foundLockUp */  } /* if an ABR VC */} /*** Conversion of 24-bit cellrate (cells/sec) to 16-bit floating point format.****  +----+----+------------------+-------------------------------+**  |  R | NZ |  5-bit exponent  |        9-bit mantissa         |**  +----+----+------------------+-------------------------------+** **    R = reserverd (written as 0)**    NZ = 0 if 0 cells/sec; 1 otherwise****    if NZ = 1, rate = 1.mmmmmmmmm x 2^(eeeee) cells/sec*/static u16cellrate_to_float(u32 cr){#define	NZ 		0x4000#define	M_BITS		9		/* Number of bits in mantissa */#define	E_BITS		5		/* Number of bits in exponent */#define	M_MASK		0x1ff		#define	E_MASK		0x1f  u16   flot;  u32	tmp = cr & 0x00ffffff;  int 	i   = 0;  if (cr == 0)     return 0;  while (tmp != 1) {     tmp >>= 1;     i++;  }  if (i == M_BITS)     flot = NZ | (i << M_BITS) | (cr & M_MASK);  else if (i < M_BITS)     flot = NZ | (i << M_BITS) | ((cr << (M_BITS - i)) & M_MASK);  else     flot = NZ | (i << M_BITS) | ((cr >> (i - M_BITS)) & M_MASK);  return flot;}#if 0/*** Conversion of 16-bit floating point format to 24-bit cellrate (cells/sec).*/static u32float_to_cellrate(u16 rate){  u32   exp, mantissa, cps;  if ((rate & NZ) == 0)     return 0;  exp = (rate >> M_BITS) & E_MASK;  mantissa = rate & M_MASK;  if (exp == 0)     return 1;  cps = (1 << M_BITS) | mantissa;  if (exp == M_BITS)     cps = cps;  else if (exp > M_BITS)     cps <<= (exp - M_BITS);  else     cps >>= (M_BITS - exp);  return cps;}#endif static void init_abr_vc (IADEV *dev, srv_cls_param_t *srv_p) {  srv_p->class_type = ATM_ABR;  srv_p->pcr        = dev->LineRate;  srv_p->mcr        = 0;  srv_p->icr        = 0x055cb7;  srv_p->tbe        = 0xffffff;  srv_p->frtt       = 0x3a;  srv_p->rif        = 0xf;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -