📄 hydra.c
字号:
{ dev->interrupt = 0; return; } /* acknowledge all interrupts, by clearing the interrupt flag */ WRITE_REG(NIC_ISR, intbits); if((intbits & ISR_PTX) && !(intbits & ISR_TXE)) { dev->tbusy = 0; mark_bh(NET_BH); } if((intbits & ISR_PRX) && !(intbits & ISR_RXE))/* packet received OK */ hydra_rx(dev, priv, nicbase); if(intbits & ISR_TXE) priv->stats.tx_errors++; if(intbits & ISR_RXE) priv->stats.rx_errors++; if(intbits & ISR_CNT) { /* * read the tally counters and (currently) ignore the values * might be useful because of bugs of some versions of the 8390 NIC */#ifdef HYDRA_DEBUG printk("hydra_interrupt(): ISR_CNT\n");#endif (void)READ_REG(NIC_CNTR0); (void)READ_REG(NIC_CNTR1); (void)READ_REG(NIC_CNTR2); } if(intbits & ISR_OVW) {#ifdef HYDRA_DEBUG WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA);/* another one just too much for me to comprehend - basically this could *//* only occur because of invalid access to hydra ram, thus invalidating *//* the interrupt bits read - in average usage these do not occur at all */ printk("hydra_interrupt(): overwrite warning, NIC_ISR %02x, NIC_CURR %02x\n", intbits, READ_REG(NIC_CURR)); WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA);#endif /* overwrite warning occurred, stop NIC & check the BOUNDARY pointer */ /* FIXME - real overwrite handling needed !! */ printk("hydra_interrupt(): overwrite warning, resetting NIC\n"); WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_STOP); while(!(READ_REG(NIC_ISR) & ISR_RST)); /* wait for NIC to reset */ WRITE_REG(NIC_DCR, DCR_WTS | DCR_BOS | DCR_LS | DCR_FT0); WRITE_REG(NIC_RBCR0, 0); WRITE_REG(NIC_RBCR1, 0); WRITE_REG(NIC_RCR, NIC_RCRBITS); WRITE_REG(NIC_TCR, TCR_LB1); WRITE_REG(NIC_PSTART, priv->rx_page_start); WRITE_REG(NIC_PSTOP, priv->rx_page_stop); WRITE_REG(NIC_BNDRY, priv->rx_page_start); WRITE_REG(NIC_ISR, 0xff); WRITE_REG(NIC_IMR, NIC_INTS); /* currently this _won't_ reset my hydra, even though it is */ /* basically the same code as in the board init - any ideas? */ priv->next_pkt = priv->rx_page_start+1; /* init our s/w variable */ WRITE_REG(NIC_CURR, priv->next_pkt); /* set the next buf for current */ WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START); WRITE_REG(NIC_TCR, 0); } dev->interrupt = 0; return; }/* * packet transmit routine */static int hydra_start_xmit(struct sk_buff *skb, struct device *dev){ struct hydra_private *priv = (struct hydra_private *)dev->priv; volatile u8 *nicbase = priv->hydra_nic_base; int len, len1; /* Transmitter timeout, serious problems. */ if(dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if(tickssofar < 20) return(1); WRITE_REG(NIC_CR, CR_STOP); printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name, 0); priv->stats.tx_errors++; dev->tbusy = 0; dev->trans_start = jiffies; return(0); } len=skb->len; /* fill in a tx ring entry */ #ifdef HYDRA_DEBUG printk("TX pkt type 0x%04x from ", ((u16 *)skb->data)[6]); { int i; u8 *ptr = &((u8 *)skb->data)[6]; for (i = 0; i < 6; i++) printk("%02x", ptr[i]); } printk(" to "); { int i; u8 *ptr = (u8 *)skb->data; for (i = 0; i < 6; i++) printk("%02x", ptr[i]); } printk(" data 0x%08x len %d\n", (int)skb->data, len);#endif /* * make sure that the packet size is at least the minimum * allowed ethernet packet length. * (FIXME: Should also clear the unused space...) * note: minimum packet length is 64, including CRC */ len1 = len; if(len < (ETHER_MIN_LEN-4)) len = (ETHER_MIN_LEN-1); /* make sure we've got an even number of bytes to copy to hydra's mem */ if(len & 1) len++; if((u32)(priv->hydra_base + (priv->tx_page_start << 8)) < 0x80000000) printk("weirdness: memcpyw(txbuf, skbdata, len): txbuf = 0x%x\n", (u_int)(priv->hydra_base+(priv->tx_page_start<<8))); /* copy the packet data to the transmit buffer in the ethernet card RAM */ memcpyw((u16 *)(priv->hydra_base + (priv->tx_page_start << 8)), (u16 *)skb->data, len); /* clear the unused space */ for(; len1<len; len1++) (u16)*(priv->hydra_base + (priv->tx_page_start<<8) + len1) = 0; dev_kfree_skb(skb); priv->stats.tx_packets++; cli(); /* make sure we are on the correct page */ WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START); /* here we configure the transmit page start register etc */ /* notice that this code is hardwired to one transmit buffer */ WRITE_REG(NIC_TPSR, priv->tx_page_start); WRITE_REG(NIC_TBCR0, len & 0xff); WRITE_REG(NIC_TBCR1, len >> 8); /* commit the packet to the wire */ WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA | CR_TXP); sti(); dev->trans_start = jiffies; return(0);}static void __inline__ hydra_rx(struct device *dev, struct hydra_private *priv, volatile u8 *nicbase){ volatile u16 *board_ram_ptr; struct sk_buff *skb; int hdr_next_pkt, pkt_len, len1, boundary; /* remove packet(s) from the ring and commit them to TCP layer */ WRITE_REG(NIC_CR, CR_PAGE1 | CR_NODMA | CR_START); /* page 1 */ while(priv->next_pkt != READ_REG(NIC_CURR)) /* should read this only once? */ { board_ram_ptr = (u16 *)(priv->hydra_base + (priv->next_pkt << 8)); #ifdef HYDRA_DEBUG printk("next_pkt = 0x%x, board_ram_ptr = 0x%x\n", priv->next_pkt, board_ram_ptr);#endif /* the following must be done with two steps, or GCC optimizes it to a byte access to Hydra memory, which doesn't work... */ hdr_next_pkt = board_ram_ptr[0]; hdr_next_pkt >>= 8; pkt_len = board_ram_ptr[1]; pkt_len = ((pkt_len >> 8) | ((pkt_len & 0xff) << 8)); #ifdef HYDRA_DEBUG printk("hydra_interrupt(): hdr_next_pkt = 0x%02x, len = %d\n", hdr_next_pkt, pkt_len);#endif if(pkt_len >= ETHER_MIN_LEN && pkt_len <= ETHER_MAX_LEN) { /* note that board_ram_ptr is u16 */ /* CRC is not included in the packet length */ pkt_len -= 4; skb = dev_alloc_skb(pkt_len+2); if(skb == NULL) { printk(KERN_INFO "%s: memory squeeze, dropping packet.\n", dev->name); priv->stats.rx_dropped++; } else { skb->dev = dev; skb_reserve(skb, 2); if(hdr_next_pkt < priv->next_pkt && hdr_next_pkt != priv->rx_page_start) { /* here, the packet is wrapped */ len1 = ((priv->rx_page_stop - priv->next_pkt)<<8)-4; memcpyw((u16 *)skb_put(skb, len1), (u16 *)(board_ram_ptr+2), len1); memcpyw((u16 *)skb_put(skb, pkt_len-len1), (u16 *)(priv->hydra_base+(priv->rx_page_start<<8)), pkt_len-len1); #ifdef HYDRA_DEBUG printk("wrapped packet: %d/%d bytes\n", len1, pkt_len-len1);#endif } /* ... here, packet is not wrapped */ else memcpyw((u16 *) skb_put(skb, pkt_len), (u16 *)(board_ram_ptr+2), pkt_len); } } else { WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA); printk("hydra_interrupt(): invalid packet len: %d, NIC_CURR = %02x\n", pkt_len, READ_REG(NIC_CURR));/*this is the error i kept getting until i switched to 0.9.10. it still doesn'tmean that the bug would have gone away - so be alarmed. the packet is likelybeing fetched from a wrong memory location - but why - dunno note-for-v2.1: not really problem anymore. hasn't been for a long time.*/ WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA); /* should probably reset the NIC here ?? */ hydra_open(dev); /* FIXME - i shouldn't really be doing this. */ return; } /* now, update the next_pkt pointer */ if(hdr_next_pkt < priv->rx_page_stop) priv->next_pkt = hdr_next_pkt; else printk("hydra_interrupt(): invalid next_pkt pointer %d\n", hdr_next_pkt); /* update the boundary pointer */ boundary = priv->next_pkt - 1; if(boundary < priv->rx_page_start) boundary = priv->rx_page_stop - 1; /* set NIC to page 0 to update the NIC_BNDRY register */ WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA); WRITE_REG(NIC_BNDRY, boundary); /* select page1 to access the NIC_CURR register */ WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); priv->stats.rx_packets++; } return;} static struct net_device_stats *hydra_get_stats(struct device *dev){ struct hydra_private *priv = (struct hydra_private *)dev->priv;#if 0 u8 *board = priv->hydra_base; short saved_addr;#endif/* currently does nothing :) i'll finish this later */ return(&priv->stats);}#ifdef HAVE_MULTICASTstatic void set_multicast_list(struct device *dev, int num_addrs, void *addrs){ struct hydra_private *priv = (struct hydra_private *)dev->priv; u8 *board = priv->hydra_base; /* yes, this code is also waiting for someone to complete.. :) */ /* (personally i don't care about multicasts at all :) */ return;}#endif#ifdef MODULEstatic char devicename[9] = { 0, };static struct device hydra_dev ={ devicename, /* filled in by register_netdev() */ 0, 0, 0, 0, /* memory */ 0, 0, /* base, irq */ 0, 0, 0, NULL, hydra_probe,};int init_module(void){ int err; if ((err = register_netdev(&hydra_dev))) { if (err == -EIO) printk("No Hydra board found. Module not loaded.\n"); return(err); } return(0);}void cleanup_module(void){ struct hydra_private *priv = (struct hydra_private *)hydra_dev.priv; unregister_netdev(&hydra_dev); zorro_unconfig_board(priv->key, 0); kfree(priv);}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -