Here is what I currently have for my O2 ethernet driver. It still shows some weired behaviour sometimes, but works well enough to boot and run O2 over NFS.
Index: drivers/net/meth.c =================================================================== RCS file: /home/cvs/linux/drivers/net/meth.c,v retrieving revision 1.4 diff -u -r1.4 meth.c --- drivers/net/meth.c 1 Jul 2002 20:01:25 -0000 1.4 +++ drivers/net/meth.c 29 Jun 2003 22:55:44 -0000 @@ -55,10 +55,6 @@ MODULE_AUTHOR("Ilya Volynets"); MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver"); -/* This is a load-time options */ -/*static int eth = 0; -MODULE_PARM(eth, "i");*/ - #define HAVE_TX_TIMEOUT /* The maximum time waited (in jiffies) before assuming a Tx failed. (400ms) */ #define TX_TIMEOUT (400*HZ/1000) @@ -68,15 +64,13 @@ MODULE_PARM(timeout, "i"); #endif -int meth_eth; - /* * This structure is private to each device. It is used to pass * packets in and out, so there is place for a packet */ typedef struct meth_private { - struct net_device_stats stats; + struct net_device_stats stats; volatile struct meth_regs *regs; u64 mode; /* in-memory copy of MAC control register */ int phy_addr; /* address of phy, used by mdio_* functions, initialized in mdio_probe*/ @@ -92,12 +86,12 @@ dma_addr_t rx_ring_dmas[RX_RING_ENTRIES]; int rx_write; - spinlock_t meth_lock; + spinlock_t meth_lock; } meth_private; extern struct net_device meth_devs[]; void meth_tx_timeout (struct net_device *dev); -void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs); +irqreturn_t meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs); /* global, initialized in ip32-setup.c */ char o2meth_eaddr[8]={0,0,0,0,0,0,0,0}; @@ -109,14 +103,9 @@ DPRINTK("Loading MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", (int)o2meth_eaddr[0]&0xFF,(int)o2meth_eaddr[1]&0xFF,(int)o2meth_eaddr[2]&0xFF, (int)o2meth_eaddr[3]&0xFF,(int)o2meth_eaddr[4]&0xFF,(int)o2meth_eaddr[5]&0xFF); - //memcpy(dev->dev_addr,o2meth_eaddr+2,6); for (i=0; i<6; i++) dev->dev_addr[i]=o2meth_eaddr[i]; - regs->mac_addr= //dev->dev_addr[0]|(dev->dev_addr[1]<<8)| - //dev->dev_addr[2]<<16|(dev->dev_addr[3]<<24)| - //dev->dev_addr[4]<<32|(dev->dev_addr[5]<<40); - (*(u64*)o2meth_eaddr)>>16; - DPRINTK("MAC, finally is %0lx\n",regs->mac_addr); + regs->mac_addr=(*(u64*)o2meth_eaddr)>>16; } /* @@ -124,19 +113,19 @@ */ #define WAIT_FOR_PHY(___regs, ___rval) \ while((___rval=___regs->phy_data)&MDIO_BUSY){ \ - udelay(25); \ + udelay(25); \ } /*read phy register, return value read */ static int mdio_read(meth_private *priv,int phyreg) { volatile meth_regs* regs=priv->regs; volatile u32 rval; - WAIT_FOR_PHY(regs,rval) + WAIT_FOR_PHY(regs,rval); regs->phy_registers=(priv->phy_addr<<5)|(phyreg&0x1f); udelay(25); regs->phy_trans_go=1; udelay(25); - WAIT_FOR_PHY(regs,rval) + WAIT_FOR_PHY(regs,rval); return rval&MDIO_DATA_MASK; } @@ -145,14 +134,13 @@ { volatile meth_regs* regs=priv->regs; int rval; -/// DPRINTK("Trying to write value %i to reguster %i\n",val, pfyreg); - spin_lock_irq(&priv->meth_lock); - WAIT_FOR_PHY(regs,rval) + spin_lock(&priv->meth_lock); + WAIT_FOR_PHY(regs,rval); regs->phy_registers=(priv->phy_addr<<5)|(pfyreg&0x1f); regs->phy_data=val; udelay(25); - WAIT_FOR_PHY(regs,rval) - spin_unlock_irq(&priv->meth_lock); + WAIT_FOR_PHY(regs,rval); + spin_unlock(&priv->meth_lock); } /* Modify phy register using given mask and value */ @@ -165,11 +153,6 @@ mdio_write(priv,phyreg,rval); } -/* handle errata data on MDIO bus */ -//static void mdio_errata(meth_private *priv) -//{ - /* Hmmm... what the hell is phyerrata? does it come from sys init parameters in IRIX */ -//} static int mdio_probe(meth_private *priv) { int i, p2, p3; @@ -177,25 +160,25 @@ /* check if phy is detected already */ if(priv->phy_addr>=0&&priv->phy_addr<32) return 0; - spin_lock_irq(&priv->meth_lock); + spin_lock(&priv->meth_lock); for (i=0;i<32;++i){ priv->phy_addr=(char)i; p2=mdio_read(priv,2); #ifdef MFE_DEBUG p3=mdio_read(priv,3); switch ((p2<<12)|(p3>>4)){ - case PHY_QS6612X: - DPRINTK("PHY is QS6612X\n"); - break; - case PHY_ICS1889: - DPRINTK("PHY is ICS1889\n"); - break; - case PHY_ICS1890: - DPRINTK("PHY is ICS1890\n"); - break; - case PHY_DP83840: - DPRINTK("PHY is DP83840\n"); - break; + case PHY_QS6612X: + DPRINTK("PHY is QS6612X\n"); + break; + case PHY_ICS1889: + DPRINTK("PHY is ICS1889\n"); + break; + case PHY_ICS1890: + DPRINTK("PHY is ICS1890\n"); + break; + case PHY_DP83840: + DPRINTK("PHY is DP83840\n"); + break; } #endif if(p2!=0xffff&&p2!=0x0000){ @@ -203,7 +186,7 @@ break; } } - spin_unlock_irq(&priv->meth_lock); + spin_unlock(&priv->meth_lock); if(priv->phy_addr<32) { return 0; } @@ -269,15 +252,9 @@ static int meth_init_rx_ring(meth_private *priv) { int i; - DPRINTK("Initializing RX ring\n"); for(i=0;i<RX_RING_ENTRIES;i++){ - DPRINTK("\t1:\t%i\t",i); - /*if(!(priv->rx_ring[i]=get_free_page(GFP_KERNEL))) - return -ENOMEM; - DPRINTK("\t2:\t%i\n",i);*/ priv->rx_ring[i]=(rx_packet*)pci_alloc_consistent(NULL,METH_RX_BUFF_SIZE,&(priv->rx_ring_dmas[i])); /* I'll need to re-sync it after each RX */ - DPRINTK("\t%p\n",priv->rx_ring[i]); priv->regs->rx_fifo=priv->rx_ring_dmas[i]; } priv->rx_write = 0; @@ -290,8 +267,8 @@ /* Remove any pending skb */ for (i = 0; i < TX_RING_ENTRIES; i++) { - if (priv->tx_skbs[i]) - dev_kfree_skb(priv->tx_skbs[i]); + if (priv->tx_skbs[i]) + dev_kfree_skb(priv->tx_skbs[i]); priv->tx_skbs[i] = NULL; } pci_free_consistent(NULL, @@ -318,7 +295,6 @@ priv->regs->mac_ctrl = SGI_MAC_RESET; priv->regs->mac_ctrl = 0; udelay(25); - DPRINTK("MAC control after reset: %016lx\n", priv->regs->mac_ctrl); /* Load ethernet address */ load_eaddr(dev, priv->regs); @@ -341,7 +317,7 @@ /* Now set dma control, but don't enable DMA, yet */ priv->regs->dma_ctrl= (4 << METH_RX_OFFSET_SHIFT) | - (RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT); + (RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT); return(0); } @@ -356,9 +332,20 @@ { meth_private *priv=dev->priv; volatile meth_regs *regs=priv->regs; + int ret; - MOD_INC_USE_COUNT; + /* Initialize the hardware */ + if((ret=meth_reset(dev)) < 0) + return ret; + + /* Allocate the ring buffers */ + if((ret=meth_init_tx_ring(priv))<0||(ret=meth_init_rx_ring(priv))<0){ + meth_free_tx_ring(priv); + meth_free_rx_ring(priv); + return ret; + } + DPRINTK("Will set dma_ctl now\n"); /* Start DMA */ regs->dma_ctrl|= METH_DMA_TX_EN|/*METH_DMA_TX_INT_EN|*/ @@ -368,6 +355,7 @@ printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq); return -EAGAIN; } + DPRINTK("About to start queue\n"); netif_start_queue(dev); DPRINTK("Opened... DMA control=0x%08lx\n", regs->dma_ctrl); return 0; @@ -375,14 +363,16 @@ int meth_release(struct net_device *dev) { - netif_stop_queue(dev); /* can't transmit any more */ + meth_private *priv=dev->priv; + netif_stop_queue(dev); /* can't transmit any more */ /* shut down dma */ ((meth_private*)(dev->priv))->regs->dma_ctrl&= ~(METH_DMA_TX_EN|METH_DMA_TX_INT_EN| - METH_DMA_RX_EN|METH_DMA_RX_INT_EN); + METH_DMA_RX_EN|METH_DMA_RX_INT_EN); free_irq(dev->irq, dev); - MOD_DEC_USE_COUNT; - return 0; + meth_free_tx_ring(priv); + meth_free_rx_ring(priv); + return 0; } /* @@ -390,24 +380,24 @@ */ int meth_config(struct net_device *dev, struct ifmap *map) { - if (dev->flags & IFF_UP) /* can't act on a running interface */ - return -EBUSY; + if (dev->flags & IFF_UP) /* can't act on a running interface */ + return -EBUSY; - /* Don't allow changing the I/O address */ - if (map->base_addr != dev->base_addr) { - printk(KERN_WARNING "meth: Can't change I/O address\n"); - return -EOPNOTSUPP; - } - - /* Allow changing the IRQ */ - if (map->irq != dev->irq) { - printk(KERN_WARNING "meth: Can't change IRQ\n"); - return -EOPNOTSUPP; - } + /* Don't allow changing the I/O address */ + if (map->base_addr != dev->base_addr) { + printk(KERN_WARNING "meth: Can't change I/O address\n"); + return -EOPNOTSUPP; + } + + /* Don't allow changing the IRQ */ + if (map->irq != dev->irq) { + printk(KERN_WARNING "meth: Can't change IRQ\n"); + return -EOPNOTSUPP; + } DPRINTK("Configured\n"); - /* ignore other fields */ - return 0; + /* ignore other fields */ + return 0; } /* @@ -415,49 +405,62 @@ */ void meth_rx(struct net_device* dev) { - struct sk_buff *skb; - struct meth_private *priv = (struct meth_private *) dev->priv; + struct sk_buff *skb; + struct meth_private *priv = (struct meth_private *) dev->priv; rx_packet *rxb; - DPRINTK("RX...\n"); - // TEMP while((rxb=priv->rx_ring[priv->rx_write])->status.raw&0x8000000000000000){ - while((rxb=priv->rx_ring[priv->rx_write])->status.raw&0x8000000000000000){ - int len=rxb->status.parsed.rx_len - 4; /* omit CRC */ - DPRINTK("(%i)\n",priv->rx_write); + int twptr=priv->rx_write; + u64 status; + spin_lock(&(priv->meth_lock)); + while ((status=(rxb=priv->rx_ring[priv->rx_write])->status.raw)&0x8000000000000000) + { + int len=(status&0xFFFF) - 4; /* omit CRC */ /* length sanity check */ if(len < 60 || len > 1518) { - printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x.\n", - dev->name, priv->rx_write, rxb->status.raw); - priv->stats.rx_errors++; - priv->stats.rx_length_errors++; + printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2lx.\n", + dev->name, priv->rx_write, rxb->status.raw); + priv->stats.rx_errors++; + priv->stats.rx_length_errors++; } - if(!(rxb->status.raw&METH_RX_STATUS_ERRORS)){ + if(!(status&METH_RX_STATUS_ERRORS)){ skb=alloc_skb(len+2,GFP_ATOMIC);/* Should be atomic -- we are in interrupt */ if(!skb){ /* Ouch! No memory! Drop packet on the floor */ - DPRINTK("!!!>>>Ouch! Not enough Memory for RX buffer!\n"); priv->stats.rx_dropped++; } else { skb_reserve(skb, 2); /* align IP on 16B boundary */ - memcpy(skb_put(skb, len), rxb->buf, len); - /* Write metadata, and then pass to the receive level */ - skb->dev = dev; - skb->protocol = eth_type_trans(skb, dev); - //skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ - - DPRINTK("passing packet\n"); - DPRINTK("len = %d rxb->status = %x\n", - len, rxb->status.raw); - netif_rx(skb); + memcpy(skb_put(skb, len), rxb->buf, len); + /* Write metadata, and then pass to the receive level */ + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + dev->last_rx = jiffies; priv->stats.rx_packets++; priv->stats.rx_bytes+=len; - DPRINTK("There we go... Whew...\n"); + netif_rx(skb); } + } else { + printk(KERN_WARNING "meth: RX error: status=0x%016lx\n",status); + if(status&METH_RX_ST_RCV_CODE_VIOLATION) + printk(KERN_WARNING "Receive Code Violation\n"); + if(status&METH_RX_ST_CRC_ERR) + printk(KERN_WARNING "CRC error\n"); + if(status&METH_RX_ST_INV_PREAMBLE_CTX) + printk(KERN_WARNING "Invalid Preamble Context\n"); + if(status&METH_RX_ST_LONG_EVT_SEEN) + printk(KERN_WARNING "Long Event Seen...\n"); + if(status&METH_RX_ST_BAD_PACKET) + printk(KERN_WARNING "Bad Packet\n"); + if(status&METH_RX_ST_CARRIER_EVT_SEEN) + printk(KERN_WARNING "Carrier Event Seen\n"); } + rxb->status.raw=0; priv->regs->rx_fifo=priv->rx_ring_dmas[priv->rx_write]; - rxb->status.raw=0; priv->rx_write=(priv->rx_write+1)&(RX_RING_ENTRIES-1); + if(priv->rx_write==twptr) { + DPRINTK("going rounds\n"); + } } + spin_unlock(&(priv->meth_lock)); } static int meth_tx_full(struct net_device *dev) @@ -505,20 +508,10 @@ /* * The typical interrupt entry point */ -void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs) +irqreturn_t meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs) { struct meth_private *priv; - union { - u32 reg; /*Whole status register */ - struct { - u32 : 2, - rx_seq : 5, - tx_read : 9, - - rx_read : 8, - int_mask: 8; - } parsed; - } status; + u32 status; /* * As usual, check the "device" pointer for shared handlers. * Then assign "struct device *dev" @@ -526,33 +519,44 @@ struct net_device *dev = (struct net_device *)dev_id; /* ... and check with hw if it's really ours */ - if (!dev /*paranoid*/ ) return; + if (!dev /*paranoid*/ ) return IRQ_HANDLED; - /* Lock the device */ priv = (struct meth_private *) dev->priv; - status.reg = priv->regs->int_flags; + status = priv->regs->int_flags; - DPRINTK("Interrupt, status %08x...\n",status.reg); - if (status.parsed.int_mask & METH_INT_RX_THRESHOLD) { + if (status & METH_INT_RX_THRESHOLD) { /* send it to meth_rx for handling */ meth_rx(dev); } - if (status.parsed.int_mask & (METH_INT_TX_EMPTY|METH_INT_TX_PKT)) { + if (status & (METH_INT_TX_EMPTY|METH_INT_TX_PKT)) { /* a transmission is over: free the skb */ - meth_tx_cleanup(dev, status.parsed.tx_read); + meth_tx_cleanup(dev, (priv->regs->tx_info&TX_INFO_RPTR)>>16); } /* check for errors too... */ - if (status.parsed.int_mask & (METH_INT_TX_LINK_FAIL)) + if (status & (METH_INT_TX_LINK_FAIL)) printk(KERN_WARNING "meth: link failure\n"); - if (status.parsed.int_mask & (METH_INT_MEM_ERROR)) + if (status & (METH_INT_MEM_ERROR)) printk(KERN_WARNING "meth: memory error\n"); - if (status.parsed.int_mask & (METH_INT_TX_ABORT)) + if (status & (METH_INT_TX_ABORT)) printk(KERN_WARNING "meth: aborted\n"); - DPRINTK("Interrupt handling done...\n"); - - priv->regs->int_flags=status.reg&0xff; /* clear interrupts */ + if (status & (METH_INT_RX_OVERFLOW)) + printk(KERN_WARNING "meth: RX overflow\n"); + if (status & (METH_INT_RX_UNDERFLOW)) + printk(KERN_WARNING "meth: RX underflow\n"); + +#define METH_INT_ERROR (METH_INT_TX_LINK_FAIL| \ + METH_INT_MEM_ERROR| \ + METH_INT_TX_ABORT| \ + METH_INT_RX_OVERFLOW| \ + METH_INT_RX_UNDERFLOW) + if( status & METH_INT_ERROR) { + printk(KERN_WARNING "meth: error status: 0x%08x\n",status); + netif_wake_queue(dev); + } + priv->regs->int_flags=status&0xff; /* clear interrupts */ + return IRQ_HANDLED; } /* @@ -563,13 +567,11 @@ tx_packet *desc=&priv->tx_ring[priv->tx_write]; int len = (skb->len<ETH_ZLEN)?ETH_ZLEN:skb->len; - DPRINTK("preparing short packet\n"); /* maybe I should set whole thing to 0 first... */ memcpy(desc->data.dt+(120-len),skb->data,skb->len); if(skb->len < len) memset(desc->data.dt+120-len+skb->len,0,len-skb->len); desc->header.raw=METH_TX_CMD_INT_EN|(len-1)|((128-len)<<16); - DPRINTK("desc=%016lx\n",desc->header.raw); } #define TX_CATBUF1 BIT(25) static void meth_tx_1page_prepare(meth_private* priv, struct sk_buff* skb) @@ -580,13 +582,6 @@ int buffer_len = skb->len - unaligned_len; dma_addr_t catbuf; - DPRINTK("preparing 1 page...\n"); - DPRINTK("length=%d data=%p\n", skb->len, skb->data); - DPRINTK("unaligned_len=%d\n", unaligned_len); - DPRINTK("buffer_data=%p buffer_len=%d\n", - buffer_data, - buffer_len); - desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|(skb->len-1); /* unaligned part */ @@ -601,11 +596,8 @@ buffer_data, buffer_len, PCI_DMA_TODEVICE); - DPRINTK("catbuf=%x\n", catbuf); desc->data.cat_buf[0].form.start_addr = catbuf >> 3; desc->data.cat_buf[0].form.len = buffer_len-1; - DPRINTK("desc=%016lx\n",desc->header.raw); - DPRINTK("cat_buf[0].raw=%016lx\n",desc->data.cat_buf[0].raw); } #define TX_CATBUF2 BIT(26) static void meth_tx_2page_prepare(meth_private* priv, struct sk_buff* skb) @@ -618,16 +610,6 @@ int buffer2_len = skb->len - buffer1_len - unaligned_len; dma_addr_t catbuf1, catbuf2; - DPRINTK("preparing 2 pages... \n"); - DPRINTK("length=%d data=%p\n", skb->len, skb->data); - DPRINTK("unaligned_len=%d\n", unaligned_len); - DPRINTK("buffer1_data=%p buffer1_len=%d\n", - buffer1_data, - buffer1_len); - DPRINTK("buffer2_data=%p buffer2_len=%d\n", - buffer2_data, - buffer2_len); - desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|TX_CATBUF2|(skb->len-1); /* unaligned part */ if(unaligned_len){ @@ -641,7 +623,6 @@ buffer1_data, buffer1_len, PCI_DMA_TODEVICE); - DPRINTK("catbuf1=%x\n", catbuf1); desc->data.cat_buf[0].form.start_addr = catbuf1 >> 3; desc->data.cat_buf[0].form.len = buffer1_len-1; /* second page */ @@ -649,18 +630,12 @@ buffer2_data, buffer2_len, PCI_DMA_TODEVICE); - DPRINTK("catbuf2=%x\n", catbuf2); desc->data.cat_buf[1].form.start_addr = catbuf2 >> 3; desc->data.cat_buf[1].form.len = buffer2_len-1; - DPRINTK("desc=%016lx\n",desc->header.raw); - DPRINTK("cat_buf[0].raw=%016lx\n",desc->data.cat_buf[0].raw); - DPRINTK("cat_buf[1].raw=%016lx\n",desc->data.cat_buf[1].raw); } - void meth_add_to_tx_ring(meth_private *priv, struct sk_buff* skb) { - DPRINTK("Transmitting data...\n"); if(skb->len <= 120) { /* Whole packet fits into descriptor */ meth_tx_short_prepare(priv,skb); @@ -676,7 +651,7 @@ /* Remember the skb, so we can free it at interrupt time */ priv->tx_skbs[priv->tx_write] = skb; priv->tx_write = (priv->tx_write+1) & (TX_RING_ENTRIES-1); - priv->regs->tx_info.wptr = priv->tx_write; + priv->regs->tx_info = priv->tx_write; priv->tx_count ++; /* Enable DMA transfer */ priv->regs->dma_ctrl |= METH_DMA_TX_INT_EN; @@ -689,18 +664,18 @@ { struct meth_private *priv = (struct meth_private *) dev->priv; - spin_lock_irq(&priv->meth_lock); + spin_lock(&priv->meth_lock); meth_add_to_tx_ring(priv, skb); dev->trans_start = jiffies; /* save the timestamp */ /* If TX ring is full, tell the upper layer to stop sending packets */ if (meth_tx_full(dev)) { - DPRINTK("TX full: stopping\n"); + printk("TX full: stopping\n"); netif_stop_queue(dev); } - spin_unlock_irq(&priv->meth_lock); + spin_unlock(&priv->meth_lock); return 0; } @@ -716,9 +691,9 @@ printk(KERN_WARNING "%s: transmit timed out\n", dev->name); /* Protect against concurrent rx interrupts */ - spin_lock_irq(&priv->meth_lock); + spin_lock(&priv->meth_lock); - /* Try to reset the adaptor. */ + /* Try to reset the interface. */ meth_reset(dev); priv->stats.tx_errors++; @@ -733,7 +708,7 @@ priv->regs->dma_ctrl|=METH_DMA_TX_EN|METH_DMA_RX_EN|METH_DMA_RX_INT_EN; /* Enable interrupt */ - spin_unlock_irq(&priv->meth_lock); + spin_unlock(&priv->meth_lock); dev->trans_start = jiffies; netif_wake_queue(dev); @@ -747,8 +722,8 @@ int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - DPRINTK("ioctl\n"); - return 0; + DPRINTK("ioctl\n"); + return 0; } /* @@ -756,8 +731,8 @@ */ struct net_device_stats *meth_stats(struct net_device *dev) { - struct meth_private *priv = (struct meth_private *) dev->priv; - return &priv->stats; + struct meth_private *priv = (struct meth_private *) dev->priv; + return &priv->stats; } /* @@ -767,7 +742,6 @@ int meth_init(struct net_device *dev) { meth_private *priv; - int ret; /* * Then, assign other fields in dev, using ether_setup() and some * hand assignments @@ -806,20 +780,9 @@ dev->base_addr=SGI_MFE; priv->phy_addr = -1; /* No phy is known yet... */ - /* Initialize the hardware */ - if((ret=meth_reset(dev)) < 0) - return ret; - - /* Allocate the ring buffers */ - if((ret=meth_init_tx_ring(priv))<0||(ret=meth_init_rx_ring(priv))<0){ - meth_free_tx_ring(priv); - meth_free_rx_ring(priv); - return ret; - } - printk("SGI O2 Fast Ethernet rev. %ld\n", priv->regs->mac_ctrl >> 29); - return 0; + return 0; } /* @@ -827,7 +790,7 @@ */ struct net_device meth_devs[1] = { - { init: meth_init, } /* init, nothing more */ + { init: meth_init, } /* init, nothing more */ }; /* @@ -844,18 +807,15 @@ printk("meth: error %i registering device \"%s\"\n", result, meth_devs->name); else device_present++; -#ifndef METH_DEBUG - EXPORT_NO_SYMBOLS; -#endif return device_present ? 0 : -ENODEV; } void meth_cleanup(void) { - kfree(meth_devs->priv); - unregister_netdev(meth_devs); - return; + kfree(meth_devs->priv); + unregister_netdev(meth_devs); + return; } module_init(meth_init_module); Index: drivers/net/meth.h =================================================================== RCS file: /home/cvs/linux/drivers/net/meth.h,v retrieving revision 1.2 diff -u -r1.2 meth.h --- drivers/net/meth.h 1 Jul 2002 20:01:25 -0000 1.2 +++ drivers/net/meth.h 29 Jun 2003 22:55:45 -0000 @@ -85,7 +85,7 @@ } tx_packet; typedef union rx_status_vector { - struct { + volatile struct { u64 pad1:1;/*fill it with ones*/ u64 pad2:15;/*fill with 0*/ u64 ip_chk_sum:16; @@ -103,7 +103,7 @@ u64 rx_code_violation:1; u64 rx_len:16; } parsed; - u64 raw; + volatile u64 raw; } rx_status_vector; typedef struct rx_packet { @@ -113,6 +113,8 @@ char buf[METH_RX_BUFF_SIZE-sizeof(rx_status_vector)-3*sizeof(u64)-sizeof(u16)];/* data */ } rx_packet; +#define TX_INFO_RPTR 0x00FF0000 +#define TX_INFO_WPTR 0x000000FF typedef struct meth_regs { u64 mac_ctrl; /*0x00,rw,31:0*/ u64 int_flags; /*0x08,rw,30:0*/ @@ -120,10 +122,7 @@ u64 timer; /*0x18,rw,5:0*/ u64 int_tx; /*0x20,wo,0:0*/ u64 int_rx; /*0x28,wo,9:4*/ - struct { - u32 tx_info_pad; - u32 rptr:16,wptr:16; - } tx_info; /*0x30,rw,31:0*/ + u64 tx_info; /*0x30,rw,31:0*/ u64 tx_info_al; /*0x38,rw,31:0*/ struct { u32 rx_buff_pad1;
Attachment:
pgp00298.pgp
Description: PGP signature