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

📄 cb20_cb.c

📁 vt6656驱动代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  rsp->rsp1 = cb20in(cb_info, V_RESP1);  rsp->rsp2 = cb20in(cb_info, V_RESP2);  if (cb20in(cb_info, V_COMMAND) & COMMAND_BUSY) {    cb20out(cb_info, V_EVACK, EV_CLEARCOMMANDBUSY);  }  /* acknowledge command */  cb20out(cb_info, V_EVACK, EV_CMD);  cb_info->macstatus = 1;  spin_unlock_irqrestore(&cb_info->cmd_lock, flags);  return rc;}/*  * Non busywait sleep  */static void schednap(int jifs){  set_current_state(TASK_INTERRUPTIBLE);  schedule_timeout(jifs);}    #if !defined(CONFIG_NET_PCMCIA)static void cb20_suspend(dev_node_t *dnp){  printk(KERN_ALERT "Suspend called! devnod=%p\n",dnp);}static  void cb20_resume(dev_node_t *dnp){  printk(KERN_ALERT "Resume called! devnod=%p\n",dnp);}/*  * ********* external pcmcia-cs  attach/detach/probe functions. *********************** * @attach */static  dev_node_t *cb20_attach(dev_locator_t *loc){  u_char bus, devfn;  struct pci_dev *pdev=0;  dev_node_t *node;  struct cb20_info *v_info ;  struct net_device *vdev;  cb20_reap();  MOD_INC_USE_COUNT;    node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);  if (!node){#ifdef DEBUG_CB    printk(KERN_CRIT "Cannot allocate device node!\n");#endif    MOD_DEC_USE_COUNT;    return 0;  }  if (loc->bus != LOC_PCI){#ifdef DEBUG_CB    printk(KERN_ERR "Dev locator is not PCI!\n");#endif    MOD_DEC_USE_COUNT;    kfree(node);    return 0;  }  bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;  schednap(10);      pdev = pci_find_slot(bus,devfn);  if((vdev=cb20_probe(pdev))!=0){    add_cb20(vdev);	    v_info = vdev->priv;    /*     * Create top level /proc/cb20/devname device directory     */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))    v_info->device = create_proc_entry(vdev->name,S_IFDIR|0555,cb20_entry);#else    memset(&v_info->proc_entry,0,sizeof(v_info->proc_entry));    v_info->proc_entry.namelen = strlen(vdev->name);    v_info->proc_entry.name = vdev->name;    v_info->proc_entry.mode = S_IFDIR|0555;    v_info->proc_entry.nlink = 2;    v_info->proc_entry.ops = cb20_entry.ops;    proc_register( &cb20_entry,&v_info->proc_entry); #endif    procsetup(vdev);    sprintf(node->dev_name, vdev->name);    node->major = node->minor = 0;    node->next = NULL;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))    netif_device_attach(vdev);#endif    return node;  }  else    printk(KERN_CRIT "Init cb20 failed\n");  kfree(node);  MOD_DEC_USE_COUNT;  return NULL;}static  void cb20_detach(dev_node_t *node){  struct net_device *dev;  struct cb20_info *v_info;   if(!(dev=loc_cb20(node->dev_name))){      printk(KERN_ERR "Cant find device %s\n",node->dev_name);      return;  }  v_info = (struct cb20_info *)dev->priv;#ifdef DEBUG_CB  printk(KERN_DEBUG "cb20_detach: node=0x%p\n", node);#endif  cb20out(v_info,CB_INTENABLE,0); /* no ints */  if(node ) {    #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))    netif_device_detach(dev);#endif    cb20_cleanup(dev);    kfree(node);    MOD_DEC_USE_COUNT;  }}static  void cb20_cleanup(struct net_device *dev){  struct cb20_info *v_info;    printk(KERN_DEBUG "Cleanup call\n");  if(dev){    v_info = (struct cb20_info *)dev->priv;    v_info->flags |= NOCARD;    del_proc_entry(dev,dev->priv);    stop_cb20_card(dev);    del_cb20(dev);  }}/* * @stop Stop CB20 device for external pcmcia-cs turn on REAP bit * for this device. Don't call unregister here as this is in  * interupt context so we cannot call unregister_netdev as he  * may sleep (BAD). Just mark it. */static int stop_cb20_card( struct net_device *vdev){  struct cb20_info *v_info = (struct cb20_info*)vdev->priv;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))  struct sk_buff    *skb=0;#endif  int status;  /* device has been freed   * already bail   */  if(vdev == 0)    return -1;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))  netif_device_detach(vdev);#endif  cb20out(v_info,CB_INTENABLE,0); /* disable cardbus ints */  /* Turn off mac (disable card ) before freeing stuff or (boom) make sure card   * is still there though   */	  if(cb20in(v_info,V_COMMAND)!=0xffff){    mac_disable(v_info);    cb20out(v_info,V_EVINTEN,0);  }    #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))  /* Clean out tx queue    */  if(skb_queue_len(&v_info->txq)> 0 )    for(;(skb = skb_dequeue(&v_info->txq));)      dev_kfree_skb(skb);#endif  pci_free_consistent(v_info->pcip,SHAREDMEMSIZE,v_info->SharedRegion,v_info->SharedBusaddr);  if(cb20in(v_info,V_COMMAND)!=0xffff){    iounmap(v_info->auxregmembase);  }  if((status=pci_proc_detach_device(v_info->pcip))!=0){    printk(KERN_WARNING "Can't detach now err %d\n",status);    return 1;  }  v_info->flags |= REAP ;  return 0;}#endifstatic  struct net_device  *cb20_probe(struct pci_dev *pci){  int status;  struct net_device *vdev;  if((vdev = init_cb20_card(pci))==0){    printk(KERN_CRIT "K350: init_cb20! returns 0\n");    status = -1;  }  else    status =0;  if(vdev){    status = start_cb20(vdev);  }  else{    printk(KERN_CRIT "could not init CB20 null!\n");    return NULL;  }  if(status ){    printk(KERN_ERR "[ERROR] START STATUS = %x\n",status);    unregister_netdev(vdev);    kfree(vdev);    return NULL;   }      return vdev;}/* * Proc setup for pcmcia or kernel pcmcia * Called after the device is initialized  * and running. Contains proc nodes for dev * @procsetup */static void procsetup(struct net_device *targetdev){  struct cb20_info *v_info ;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))  struct   proc_dir_entry *entry;#endif  v_info = targetdev->priv;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))  entry = create_proc_entry("SSID",S_IFREG|S_IRUGO,v_info->device);  entry->data = targetdev;  entry->proc_fops = &proc_ssid_ops;      entry = create_proc_entry("Status",S_IFREG|S_IRUGO,v_info->device);  entry->data = targetdev;	  entry->proc_fops = &proc_status_ops;#else  /* SSID */  memcpy( &v_info->proc_ssid_entry, &ssid_entry,sizeof( ssid_entry ) );  v_info->proc_ssid_entry.data = targetdev;    proc_register(&v_info->proc_entry,&v_info->proc_ssid_entry);  /* STATUS */  memcpy(&v_info->proc_status_entry,&status_entry,sizeof(status_entry));  v_info->proc_status_entry.data = targetdev;  proc_register(&v_info->proc_entry,&v_info->proc_status_entry);#endif}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))/* * Tickle TX ring if needed  for unwedging tx */static  void cb20txtmo(struct net_device *dev){  struct cb20_info *v_info ;  int    lasttx;  lasttx = jiffies - dev->trans_start;  v_info = (struct cb20_info *)dev->priv;  v_info->stats.tx_errors++;  /* RAW 8/13 for some reason the TXD's get lost and must be reclaimed.    * When they vanish, tx timouts happen and txreclaim gets called   * wich retries the transmit under 2.4. Under 2.2 the net_send_packet   * routine will detect device busy ,reclaim the txd and retry the    * transmission.   */  txreclaim(dev); }#endif/* * Reclaim any outstanding TX descriptor(s) due to  * a xmission error resulting in a tx timeout  */static  int txreclaim(struct net_device *dev){  struct       cb20_info *v_info  = (struct cb20_info*)dev->priv;  CARD_TX_DESC txd;  u16 irqstate;  memset((char *)&txd,0,sizeof(txd));  memcpy((char *)&txd,(char *)v_info->txfids[0].CardRamOff,sizeof(txd));  irqstate = cb20in(v_info,V_EVSTAT);  if(irqstate ){    printk(KERN_ERR "Missed irq %04x\n",irqstate);    cb20out(v_info,V_EVACK,irqstate);  }  if(!txd.valid ){    txd.valid = 1;    txd.eoc = 1;    memcpy((char *)v_info->txfids[0].CardRamOff,(char *)&txd,sizeof(txd));    v_info->txdfc = 1;    spin_unlock(&v_info->txd_lock);    return 1;  }#ifdef TX_DEBUG  printk(KERN_ERR "TXV!!\n");#endif#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,55 ))  send_packet(dev); /* Kick xmitter for 2.4 */#endif  return 0;}#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,55 ))/* * @net_send_packet * * Attempt to transmit a packet. Adapted from skeleton.c for 2.2 *  */static  int net_send_packet(struct sk_buff *skb,struct net_device *dev){  int      adhoc,i;  unsigned char *buffer;  s16      len,rlen,*payloadlen;  struct   cb20_info *v_info  = (struct cb20_info*)dev->priv;  u32      miclen;  u8       *sendbuf;  u32      dummy;  adhoc = 0;  if (dev->tbusy) {    int tickssofar = jiffies - dev->trans_start;    if (tickssofar < 5){      return 1;    }    printk(KERN_ERR "[TRANSMIT TIMEOUT], %s\n", dev->name);    v_info->stats.tx_errors++;    txreclaim(dev);    dev->tbusy=0;    dev->trans_start = jiffies;  }  /*   * Block a timer-based transmit from overlapping. This could better be   * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.   */  if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)    printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);  else     {      /*  send packet  */            len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;        buffer = skb->data;            v_info->txfids[0].TxDesc.Offset=  0;       v_info->txfids[0].TxDesc.valid =  1;      v_info->txfids[0].TxDesc.eoc   =  1;      v_info->txfids[0].TxDesc.length= len + sizeof(HDR_802_11);      /*       * Magic, the cards firmware needs a length count (2 bytes) in the host buffer        * right after  TXFID_HDR. The TXFID_HDR contains the status short so payloadlen        * is immediatly after it. ------------------------------------------------       *                         |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA|       *                         ------------------------------------------------       */      payloadlen = (s16 *)(v_info->txfids[0].VirtualHostAddress + sizeof(TXFID_HDR));      sendbuf = v_info->txfids[0].VirtualHostAddress + sizeof(TXFID_HDR) + 2;      /*       * Firmware automaticly puts 802 header on so       * we don't need to account for it in the length       */      miclen = rlen  = len;      *payloadlen = len - sizeof(HDR_802_3);      dev->trans_start = jiffies;            /* copy data into cb20 dma buffer */      memcpy(sendbuf ,buffer,len  );        /*        * ReadCacheline hack        */      for(i=0;i!=READLINE_DEL;i++)	dummy = *(u32 *)sendbuf;            /* Do the right thing (TM) for mic */            if(v_info->flags & MIC_CAPABLE){	adhoc = (v_info->flags & ADHOC) ? 1:0;	if(Encapsulate(v_info,(ETH_HEADER_STRUC *)sendbuf,&miclen , adhoc))  {	  v_info->txfids[0].TxDesc.length= miclen + sizeof(HDR_802_11);	  *payloadlen = (s16 ) (miclen - sizeof(HDR_802_3));	}	else	  {#ifdef DEBUG_MIC	    printk(KERN_DEBUG "Dumped tx packet\n");#endif	  goto dumptx;	  }            }    v_info->txdfc=0;        memcpy((char *)v_info->txfids[0].CardRamOff,	   (char *)&v_info->txfids[0].TxDesc, sizeof(CARD_TX_DESC));        cb20out(v_info,V_EVACK,EV_XMIT);  /* Send packet */        } dumptx:  dev_kfree_skb(skb);  return 0;}#else/* * @send_packet * * Attempt to transmit a packet. Can be called from interrupt  * or transmit . return number of packets we tried to send  */static  int send_packet(struct net_device *dev){  struct   sk_buff *skb;  int      npacks,adhoc,i;  unsigned char *buffer;  s16      len,rlen,*payloadlen;  struct   cb20_info *v_info  = (struct cb20_info*)dev->priv;  u32      miclen,dummy;  u8       *sendbuf;  CARD_TX_DESC txd;  adhoc = 0;  npacks = skb_queue_len(&v_info->txq);  if(!npacks){    v_info->flags &= ~(TXBUSY);    return 0;  }  /* check for txd available. TXCPY event   * will free them.    */  if(v_info->txdfc <= 0  ){#if TXD_DEBUG    printk(KERN_WARNING "No TXD's in send_packet txdfx=%x\n",v_info->txdfc);#endif    return 0;  }  /* get packet to send */  if((skb = skb_dequeue(&v_info->txq))==0){    printk(KERN_ERR "Dequeue'd zero in send_packet !!!!\n");    return 0;  }  len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;    buffer = skb->data;  memset((char *)&txd,0,sizeof(txd));  memcpy((char *)&txd,(char *)v_info->txfids[0].CardRamOff,sizeof(txd));  txd.Offset=  0;   txd.valid = 1;  txd.eoc=1 ;  txd.length = len + sizeof(HDR_802_11);  /*   * Magic, the cards firmware needs a length count (2 bytes) in the host buffer    * right after  TXFID_HDR. The TXFID_HDR contains the status short so payloadlen    * is immediatly after it. ------------------------------------------------   *                         |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA|   *                         ------------------------------------------------   */  payloadlen = (s16 *)(v_info->txfids[0].VirtualHostAddress + sizeof(TXFID_HDR));  sendbuf = v_info->txfids[0].VirtualHostAddress + sizeof(TXFID_HDR) + 2;  /*   * Firmware automaticly puts 802 header on so   * we don't need to account for it in the length   */  miclen = rlen  = len;  *payloadlen = len - sizeof(HDR_802_3);  dev->trans_start = jiffies;  /* copy data into cb20 dma buffer */  memcpy(sendbuf ,buffer,len  );    /*    * ReadCacheline hack 

⌨️ 快捷键说明

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