📄 ni52.c
字号:
} else p->stats.rx_dropped++; } else { int rstat; /* free all RBD's until RBD_LAST is set */ totlen = 0; while(!((rstat=rbd->status) & RBD_LAST)) { totlen += rstat & RBD_MASK; if(!rstat) { printk("%s: Whoops .. no end mark in RBD list\n",dev->name); break; } rbd->status = 0; rbd = (struct rbd_struct *) make32(rbd->next); } totlen += rstat & RBD_MASK; rbd->status = 0; printk("%s: received oversized frame! length: %d\n",dev->name,totlen); p->stats.rx_dropped++; } } else /* frame !(ok), only with 'save-bad-frames' */ { printk("%s: oops! rfd-error-status: %04x\n",dev->name,status); p->stats.rx_errors++; } p->rfd_top->stat_high = 0; p->rfd_top->last = RFD_SUSP; /* maybe exchange by RFD_LAST */ p->rfd_top->rbd_offset = 0xffff; p->rfd_last->last = 0; /* delete RFD_SUSP */ p->rfd_last = p->rfd_top; p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */ p->scb->rfa_offset = make16(p->rfd_top); if(debuglevel > 0) printk("%d",cnt++); } if(automatic_resume) { WAIT_4_SCB_CMD(); p->scb->cmd_ruc = RUC_RESUME; ni_attn586(); WAIT_4_SCB_CMD_RUC(); }#ifdef WAIT_4_BUSY { int i; for(i=0;i<1024;i++) { if(p->rfd_top->status) break; DELAY_16(); if(i == 1023) printk("%s: RU hasn't fetched next RFD (not busy/complete)\n",dev->name); } }#endif#if 0 if(!at_least_one) { int i; volatile struct rfd_struct *rfds=p->rfd_top; volatile struct rbd_struct *rbds; printk("%s: received a FC intr. without having a frame: %04x %d\n",dev->name,status,old_at_least); for(i=0;i< (p->num_recv_buffs+4);i++) { rbds = (struct rbd_struct *) make32(rfds->rbd_offset); printk("%04x:%04x ",rfds->status,rbds->status); rfds = (struct rfd_struct *) make32(rfds->next); } printk("\nerrs: %04x %04x stat: %04x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->status); printk("\nerrs: %04x %04x rus: %02x, cus: %02x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->rus,(int)p->scb->cus); } old_at_least = at_least_one;#endif if(debuglevel > 0) printk("r");}/********************************************************** * handle 'Receiver went not ready'. */static void ni52_rnr_int(struct device *dev){ struct priv *p = (struct priv *) dev->priv; p->stats.rx_errors++; WAIT_4_SCB_CMD(); /* wait for the last cmd, WAIT_4_FULLSTAT?? */ p->scb->cmd_ruc = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */ ni_attn586(); WAIT_4_SCB_CMD_RUC(); /* wait for accept cmd. */ alloc_rfa(dev,(char *)p->rfd_first);/* maybe add a check here, before restarting the RU */ startrecv586(dev); /* restart RU */ printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->rus);}/********************************************************** * handle xmit - interrupt */static void ni52_xmt_int(struct device *dev){ int status; struct priv *p = (struct priv *) dev->priv; if(debuglevel > 0) printk("X"); status = p->xmit_cmds[p->xmit_last]->cmd_status; if(!(status & STAT_COMPL)) printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name); if(status & STAT_OK) { p->stats.tx_packets++; p->stats.collisions += (status & TCMD_MAXCOLLMASK); } else { p->stats.tx_errors++; if(status & TCMD_LATECOLL) { printk("%s: late collision detected.\n",dev->name); p->stats.collisions++; } else if(status & TCMD_NOCARRIER) { p->stats.tx_carrier_errors++; printk("%s: no carrier detected.\n",dev->name); } else if(status & TCMD_LOSTCTS) printk("%s: loss of CTS detected.\n",dev->name); else if(status & TCMD_UNDERRUN) { p->stats.tx_fifo_errors++; printk("%s: DMA underrun detected.\n",dev->name); } else if(status & TCMD_MAXCOLL) { printk("%s: Max. collisions exceeded.\n",dev->name); p->stats.collisions += 16; } }#if (NUM_XMIT_BUFFS > 1) if( (++p->xmit_last) == NUM_XMIT_BUFFS) p->xmit_last = 0;#endif dev->tbusy = 0; mark_bh(NET_BH);}/*********************************************************** * (re)start the receiver */static void startrecv586(struct device *dev){ struct priv *p = (struct priv *) dev->priv; WAIT_4_SCB_CMD(); WAIT_4_SCB_CMD_RUC(); p->scb->rfa_offset = make16(p->rfd_first); p->scb->cmd_ruc = RUC_START; ni_attn586(); /* start cmd. */ WAIT_4_SCB_CMD_RUC(); /* wait for accept cmd. (no timeout!!) */}/****************************************************** * send frame */static int ni52_send_packet(struct sk_buff *skb, struct device *dev){ int len,i;#ifndef NO_NOPCOMMANDS int next_nop;#endif struct priv *p = (struct priv *) dev->priv; if(dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1;#ifndef NO_NOPCOMMANDS if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */ { dev->tbusy = 0;#ifdef DEBUG printk("%s: strange ... timeout with CU active?!?\n",dev->name); printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point);#endif p->scb->cmd_cuc = CUC_ABORT; ni_attn586(); WAIT_4_SCB_CMD(); p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); p->scb->cmd_cuc = CUC_START; ni_attn586(); WAIT_4_SCB_CMD(); dev->trans_start = jiffies; return 0; } else#endif {#ifdef DEBUG printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus); printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); printk("%s: check, whether you set the right interrupt number!\n",dev->name);#endif ni52_close(dev); ni52_open(dev); } dev->trans_start = jiffies; return 0; } if(skb->len > XMIT_BUFF_SIZE) { printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len); return 0; } if (test_and_set_bit(0, (void*)&dev->tbusy)) { printk("%s: Transmitter access conflict.\n", dev->name); return 1; }#if(NUM_XMIT_BUFFS > 1) else if(test_and_set_bit(0,(void *) &p->lock)) { printk("%s: Queue was locked\n",dev->name); return 1; }#endif else { memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;#if (NUM_XMIT_BUFFS == 1)# ifdef NO_NOPCOMMANDS#ifdef DEBUG if(p->scb->cus & CU_ACTIVE) { printk("%s: Hmmm .. CU is still running and we wanna send a new packet.\n",dev->name); printk("%s: stat: %04x %04x\n",dev->name,p->scb->cus,p->xmit_cmds[0]->cmd_status); }#endif p->xmit_buffs[0]->size = TBD_LAST | len; for(i=0;i<16;i++) { p->xmit_cmds[0]->cmd_status = 0; WAIT_4_SCB_CMD(); if( (p->scb->cus & CU_STATUS) == CU_SUSPEND) p->scb->cmd_cuc = CUC_RESUME; else { p->scb->cbl_offset = make16(p->xmit_cmds[0]); p->scb->cmd_cuc = CUC_START; } ni_attn586(); dev->trans_start = jiffies; if(!i) dev_kfree_skb(skb); WAIT_4_SCB_CMD(); if( (p->scb->cus & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */ break; if(p->xmit_cmds[0]->cmd_status) break; if(i==15) printk("%s: Can't start transmit-command.\n",dev->name); }# else next_nop = (p->nop_point + 1) & 0x1; p->xmit_buffs[0]->size = TBD_LAST | len; p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); dev->trans_start = jiffies; p->nop_point = next_nop; dev_kfree_skb(skb);# endif#else p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) next_nop = 0; p->xmit_cmds[p->xmit_count]->cmd_status = 0; /* linkpointer of xmit-command already points to next nop cmd */ p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); dev->trans_start = jiffies; p->xmit_count = next_nop; { long flags; save_flags(flags); cli(); if(p->xmit_count != p->xmit_last) dev->tbusy = 0; p->lock = 0; restore_flags(flags); } dev_kfree_skb(skb);#endif } return 0;}/******************************************* * Someone wanna have the statistics */static struct net_device_stats *ni52_get_stats(struct device *dev){ struct priv *p = (struct priv *) dev->priv; unsigned short crc,aln,rsc,ovrn; crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */ p->scb->crc_errs = 0; aln = p->scb->aln_errs; p->scb->aln_errs = 0; rsc = p->scb->rsc_errs; p->scb->rsc_errs = 0; ovrn = p->scb->ovrn_errs; p->scb->ovrn_errs = 0; p->stats.rx_crc_errors += crc; p->stats.rx_fifo_errors += ovrn; p->stats.rx_frame_errors += aln; p->stats.rx_dropped += rsc; return &p->stats;}/******************************************************** * Set MC list .. */static void set_multicast_list(struct device *dev){ if(!dev->start) { printk("%s: Can't apply promiscuous/multicastmode to a not running interface.\n",dev->name); return; } dev->start = 0; ni_disint(); alloc586(dev); init586(dev); startrecv586(dev); ni_enaint(); dev->start = 1;}#ifdef MODULEstatic char devicename[9] = { 0, };static struct device dev_ni52 = { devicename, /* "ni5210": device name inserted by net_init.c */ 0, 0, 0, 0, 0x300, 9, /* I/O address, IRQ */ 0, 0, 0, NULL, ni52_probe };/* set: io,irq,memstart,memend or set it when calling insmod */int irq=9;int io=0x300;long memstart=0; /* e.g 0xd0000 */long memend=0; /* e.g 0xd4000 */MODULE_PARM(io, "i");MODULE_PARM(irq, "i");MODULE_PARM(memstart, "l");MODULE_PARM(memend, "l");int init_module(void){ if(io <= 0x0 || !memend || !memstart || irq < 2) { printk("ni52: Autoprobing not allowed for modules.\nni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n"); return -ENODEV; } dev_ni52.irq = irq; dev_ni52.base_addr = io; dev_ni52.mem_end = memend; dev_ni52.mem_start = memstart; if (register_netdev(&dev_ni52) != 0) return -EIO; return 0;}void cleanup_module(void){ release_region(dev_ni52.base_addr, NI52_TOTAL_SIZE); unregister_netdev(&dev_ni52); kfree(dev_ni52.priv); dev_ni52.priv = NULL;}#endif /* MODULE */#if 0/* * DUMP .. we expect a not running CMD unit and enough space */void ni52_dump(struct device *dev,void *ptr){ struct priv *p = (struct priv *) dev->priv; struct dump_cmd_struct *dump_cmd = (struct dump_cmd_struct *) ptr; int i; p->scb->cmd_cuc = CUC_ABORT; ni_attn586(); WAIT_4_SCB_CMD(); WAIT_4_SCB_CMD_RUC(); dump_cmd->cmd_status = 0; dump_cmd->cmd_cmd = CMD_DUMP | CMD_LAST; dump_cmd->dump_offset = make16((dump_cmd + 1)); dump_cmd->cmd_link = 0xffff; p->scb->cbl_offset = make16(dump_cmd); p->scb->cmd_cuc = CUC_START; ni_attn586(); WAIT_4_STAT_COMPL(dump_cmd); if( (dump_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) ) printk("%s: Can't get dump information.\n",dev->name); for(i=0;i<170;i++) { printk("%02x ",(int) ((unsigned char *) (dump_cmd + 1))[i]); if(i % 24 == 23) printk("\n"); } printk("\n");}#endif/* * END: linux/drivers/net/ni52.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -