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

📄 ni52.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 3 页
字号:
        break;      size = 0x4000; /* check for 16K mem */      if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */        break;    }  }  dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */#endif  dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL);   if(dev->priv == NULL)  {    printk("%s: Ooops .. can't allocate private driver memory.\n",dev->name);    return -ENOMEM;  }                                  /* warning: we don't free it on errors */  memset((char *) dev->priv,0,sizeof(struct priv));    ((struct priv *) (dev->priv))->memtop = (char *) dev->mem_start + size;  ((struct priv *) (dev->priv))->base =  dev->mem_start + size - 0x01000000;  alloc586(dev);  /* set number of receive-buffs according to memsize */  if(size == 0x2000)    ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;  else    ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;  printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size);  if(dev->irq < 2)  {    autoirq_setup(0);    ni_reset586();    ni_attn586();    if(!(dev->irq = autoirq_report(2)))    {      printk("?autoirq, Failed to detect IRQ line!\n");       return 1;    }    printk("IRQ %d (autodetected).\n",dev->irq);  }  else  {    if(dev->irq == 2)      dev->irq = 9;    printk("IRQ %d (assigned and not checked!).\n",dev->irq);  }  dev->open            = &ni52_open;  dev->stop            = &ni52_close;  dev->get_stats       = &ni52_get_stats;  dev->hard_start_xmit = &ni52_send_packet;  dev->set_multicast_list = &set_multicast_list;  dev->if_port 	       = 0;  ether_setup(dev);  dev->tbusy = 0;  dev->interrupt = 0;  dev->start = 0;    return 0;}/**********************************************  * init the chip (ni52-interrupt should be disabled?!) * needs a correct 'allocated' memory */static int init586(struct device *dev){  void *ptr;  int i,result=0;  struct priv *p = (struct priv *) dev->priv;  volatile struct configure_cmd_struct  *cfg_cmd;  volatile struct iasetup_cmd_struct *ias_cmd;  volatile struct tdr_cmd_struct *tdr_cmd;  volatile struct mcsetup_cmd_struct *mc_cmd;  struct dev_mc_list *dmi=dev->mc_list;  int num_addrs=dev->mc_count;  ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));  cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */  cfg_cmd->cmd_status = 0;  cfg_cmd->cmd_cmd    = CMD_CONFIGURE | CMD_LAST;  cfg_cmd->cmd_link   = 0xffff;  cfg_cmd->byte_cnt   = 0x0a; /* number of cfg bytes */  cfg_cmd->fifo       = fifo; /* fifo-limit (8=tx:32/rx:64) */  cfg_cmd->sav_bf     = 0x40; /* hold or discard bad recv frames (bit 7) */  cfg_cmd->adr_len    = 0x2e; /* addr_len |!src_insert |pre-len |loopback */  cfg_cmd->priority   = 0x00;  cfg_cmd->ifs        = 0x60;  cfg_cmd->time_low   = 0x00;  cfg_cmd->time_high  = 0xf2;  cfg_cmd->promisc    = 0;  if(dev->flags & IFF_ALLMULTI) {    int len = ((char *) p->iscp - (char *) ptr - 8) / 6;    if(num_addrs > len)  {      printk("%s: switching to promisc. mode\n",dev->name);      dev->flags|=IFF_PROMISC;    }  }  if(dev->flags&IFF_PROMISC)  {       cfg_cmd->promisc=1;       dev->flags|=IFF_PROMISC;  }  cfg_cmd->carr_coll  = 0x00;   p->scb->cbl_offset = make16(cfg_cmd);  p->scb->cmd_ruc = 0;  p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */  ni_attn586();  WAIT_4_STAT_COMPL(cfg_cmd);  if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK))  {    printk("%s: configure command failed: %x\n",dev->name,cfg_cmd->cmd_status);    return 1;   }    /*     * individual address setup     */  ias_cmd = (struct iasetup_cmd_struct *)ptr;  ias_cmd->cmd_status = 0;  ias_cmd->cmd_cmd    = CMD_IASETUP | CMD_LAST;  ias_cmd->cmd_link   = 0xffff;  memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN);  p->scb->cbl_offset = make16(ias_cmd);  p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */  ni_attn586();  WAIT_4_STAT_COMPL(ias_cmd);  if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) {    printk("%s (ni52): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status);    return 1;   }   /*     * TDR, wire check .. e.g. no resistor e.t.c     */  tdr_cmd = (struct tdr_cmd_struct *)ptr;  tdr_cmd->cmd_status  = 0;  tdr_cmd->cmd_cmd     = CMD_TDR | CMD_LAST;  tdr_cmd->cmd_link    = 0xffff;  tdr_cmd->status      = 0;  p->scb->cbl_offset = make16(tdr_cmd);  p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */  ni_attn586();  WAIT_4_STAT_COMPL(tdr_cmd);  if(!(tdr_cmd->cmd_status & STAT_COMPL))  {    printk("%s: Problems while running the TDR.\n",dev->name);  }  else  {    DELAY_16(); /* wait for result */    result = tdr_cmd->status;    p->scb->cmd_cuc = p->scb->cus & STAT_MASK;    ni_attn586(); /* ack the interrupts */    if(result & TDR_LNK_OK)       ;    else if(result & TDR_XCVR_PRB)      printk("%s: TDR: Transceiver problem. Check the cable(s)!\n",dev->name);    else if(result & TDR_ET_OPN)      printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK);    else if(result & TDR_ET_SRT)     {      if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */        printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK);    }    else      printk("%s: TDR: Unknown status %04x\n",dev->name,result);  }  /*   * Multicast setup   */  if(num_addrs && !(dev->flags & IFF_PROMISC) )  {    mc_cmd = (struct mcsetup_cmd_struct *) ptr;    mc_cmd->cmd_status = 0;    mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;    mc_cmd->cmd_link = 0xffff;    mc_cmd->mc_cnt = num_addrs * 6;    for(i=0;i<num_addrs;i++,dmi=dmi->next)      memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6);    p->scb->cbl_offset = make16(mc_cmd);    p->scb->cmd_cuc = CUC_START;    ni_attn586();    WAIT_4_STAT_COMPL(mc_cmd);    if( (mc_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) )      printk("%s: Can't apply multicast-address-list.\n",dev->name);  }   /*    * alloc nop/xmit-cmds    */#if (NUM_XMIT_BUFFS == 1)  for(i=0;i<2;i++)  {    p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;    p->nop_cmds[i]->cmd_cmd    = CMD_NOP;    p->nop_cmds[i]->cmd_status = 0;    p->nop_cmds[i]->cmd_link   = make16((p->nop_cmds[i]));    ptr = (char *) ptr + sizeof(struct nop_cmd_struct);  }#else  for(i=0;i<NUM_XMIT_BUFFS;i++)  {    p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;    p->nop_cmds[i]->cmd_cmd    = CMD_NOP;    p->nop_cmds[i]->cmd_status = 0;    p->nop_cmds[i]->cmd_link   = make16((p->nop_cmds[i]));    ptr = (char *) ptr + sizeof(struct nop_cmd_struct);  }#endif  ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */   /*   * alloc xmit-buffs / init xmit_cmds   */  for(i=0;i<NUM_XMIT_BUFFS;i++)  {    p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/    ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);    p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */    ptr = (char *) ptr + XMIT_BUFF_SIZE;    p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */    ptr = (char *) ptr + sizeof(struct tbd_struct);    if((void *)ptr > (void *)p->iscp)     {      printk("%s: not enough shared-mem for your configuration!\n",dev->name);      return 1;    }       memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct));    memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct));    p->xmit_cmds[i]->cmd_link = make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]);    p->xmit_cmds[i]->cmd_status = STAT_COMPL;    p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;    p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));    p->xmit_buffs[i]->next = 0xffff;    p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));  }  p->xmit_count = 0;   p->xmit_last  = 0;#ifndef NO_NOPCOMMANDS  p->nop_point  = 0;#endif   /*    * 'start transmitter'    */#ifndef NO_NOPCOMMANDS  p->scb->cbl_offset = make16(p->nop_cmds[0]);  p->scb->cmd_cuc = CUC_START;  ni_attn586();  WAIT_4_SCB_CMD();#else  p->xmit_cmds[0]->cmd_link = make16(p->xmit_cmds[0]);  p->xmit_cmds[0]->cmd_cmd  = CMD_XMIT | CMD_SUSPEND | CMD_INT;#endif  /*   * ack. interrupts   */  p->scb->cmd_cuc = p->scb->cus & STAT_MASK;  ni_attn586();  DELAY_16();  ni_enaint();  return 0;}/****************************************************** * This is a helper routine for ni52_rnr_int() and init586().  * It sets up the Receive Frame Area (RFA). */static void *alloc_rfa(struct device *dev,void *ptr) {  volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr;  volatile struct rbd_struct *rbd;  int i;  struct priv *p = (struct priv *) dev->priv;  memset((char *) rfd,0,sizeof(struct rfd_struct)*(p->num_recv_buffs+rfdadd));  p->rfd_first = rfd;  for(i = 0; i < (p->num_recv_buffs+rfdadd); i++) {    rfd[i].next = make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd) );    rfd[i].rbd_offset = 0xffff;  }  rfd[p->num_recv_buffs-1+rfdadd].last = RFD_SUSP;   /* RU suspend */  ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd) );  rbd = (struct rbd_struct *) ptr;  ptr = (void *) (rbd + p->num_recv_buffs);   /* clr descriptors */  memset((char *) rbd,0,sizeof(struct rbd_struct)*(p->num_recv_buffs));  for(i=0;i<p->num_recv_buffs;i++)  {    rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs));    rbd[i].size = RECV_BUFF_SIZE;    rbd[i].buffer = make24(ptr);    ptr = (char *) ptr + RECV_BUFF_SIZE;  }  p->rfd_top  = p->rfd_first;  p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd);  p->scb->rfa_offset		= make16(p->rfd_first);  p->rfd_first->rbd_offset	= make16(rbd);  return ptr;}/************************************************** * Interrupt Handler ... */static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr){  struct device *dev = (struct device *) irq2dev_map[irq];  unsigned short stat;  int cnt=0;  struct priv *p;  if (!dev) {    printk ("ni5210-interrupt: irq %d for unknown device.\n",irq);    return;  }  p = (struct priv *) dev->priv;  if(debuglevel > 1)    printk("I");  dev->interrupt = 1;  WAIT_4_SCB_CMD(); /* wait for last command  */  while((stat=p->scb->cus & STAT_MASK))  {    p->scb->cmd_cuc = stat;    ni_attn586();    if(stat & STAT_FR)   /* received a frame */      ni52_rcv_int(dev);    if(stat & STAT_RNR) /* RU went 'not ready' */    {      printk("(R)");      if(p->scb->rus & RU_SUSPEND) /* special case: RU_SUSPEND */      {        WAIT_4_SCB_CMD();        p->scb->cmd_ruc = RUC_RESUME;        ni_attn586();        WAIT_4_SCB_CMD_RUC();      }      else      {        printk("%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->rus);        ni52_rnr_int(dev);       }    }    if(stat & STAT_CX)    /* command with I-bit set complete */       ni52_xmt_int(dev);#ifndef NO_NOPCOMMANDS    if(stat & STAT_CNA)  /* CU went 'not ready' */    {      if(dev->start)        printk("%s: oops! CU has left active state. stat: %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->cus);    }#endif    if(debuglevel > 1)      printk("%d",cnt++);    WAIT_4_SCB_CMD(); /* wait for ack. (ni52_xmt_int can be faster than ack!!) */    if(p->scb->cmd_cuc)   /* timed out? */    {      printk("%s: Acknowledge timed out.\n",dev->name);      ni_disint();      break;    }  }  if(debuglevel > 1)    printk("i");  dev->interrupt = 0;}/******************************************************* * receive-interrupt */static void ni52_rcv_int(struct device *dev){  int status,cnt=0;  unsigned short totlen;  struct sk_buff *skb;  struct rbd_struct *rbd;  struct priv *p = (struct priv *) dev->priv;  if(debuglevel > 0)    printk("R");  for(;(status = p->rfd_top->stat_high) & RFD_COMPL;)  {      rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);      if(status & RFD_OK) /* frame received without error? */      {        if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */        {          totlen &= RBD_MASK; /* length of this frame */          rbd->status = 0;          skb = (struct sk_buff *) dev_alloc_skb(totlen+2);          if(skb != NULL)          {            skb->dev = dev;            skb_reserve(skb,2);            skb_put(skb,totlen);            eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0);            skb->protocol=eth_type_trans(skb,dev);            netif_rx(skb);            p->stats.rx_packets++;          }          else            p->stats.rx_dropped++;        }        else

⌨️ 快捷键说明

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