From: ? <uns...@us...> - 2002-05-28 18:41:46
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv10694 Modified Files: vaxsgec.c vaxsgec.h Log Message: Many SGEC driver changes and fixes from Christoph's vaxsgec.cvs-diff.2002-05-27 Now it can sometimes send packets, but is not yet consistently working. Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- vaxsgec.c 26 May 2002 07:58:36 -0000 1.7 +++ vaxsgec.c 28 May 2002 18:41:37 -0000 1.8 @@ -30,16 +30,17 @@ /* use #undef to turn these off */ #define VAX_SGEC_DEBUG +#undef VAX_SGEC_DEBUG_LVL2 #define VAX_SGEC_DEBUG_BUFFERS #define VAX_SGEC_AUTOPROBE_IRQ + #include "vaxsgec.h" #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ lp->tx_old+TX_RING_MASK-lp->tx_new:\ lp->tx_old - lp->tx_new-1) - static inline void writereg(volatile unsigned long *regptr, unsigned long value) { *regptr = value; @@ -53,17 +54,7 @@ static inline void sgec_stop(volatile struct sgec_regs *regs) { writecsr6(regs, regs->sg_nicsr6 & ~(SG_NICSR6_ST|SG_NICSR6_SR)); - udelay(100); /* allow card to change */ -} - -/* Load the CSR registers */ -static void load_csrs(struct sgec_private *lp) -{ - volatile struct sgec_regs *regs = lp->regs; - - writereg(®s->sg_nicsr3, virt_to_phys(lp->rx_ring)); - writereg(®s->sg_nicsr4, virt_to_phys(lp->tx_ring)); - writecsr6(regs, SG_NICSR6_MBO|SG_NICSR6_IE|SG_NICSR6_BL_8|SG_NICSR6_ST|SG_NICSR6_SR|SG_NICSR6_DC); + udelay(100); /* allow card to change and to "dropping out" interrupts */ } static inline void cp_to_buf(void *to, const void *from, __kernel_size_t len) @@ -85,12 +76,11 @@ /* Lock out other processes while setting up hardware */ netif_stop_queue(dev); - lp->rx_new = lp->tx_new = 0; - lp->rx_old = lp->tx_old = 0; + lp->rx_new = lp->rx_old = 0; + lp->tx_new = lp->tx_old = 0; - /* clear all descriptors */ - memset((void *)lp->rx_ring, 0, sizeof(lp->rx_ring)); - memset((void *)lp->tx_ring, 0, sizeof(lp->tx_ring)); + /* clear all buffers and descriptors */ + memset ((void *) lp->card_mem, 0x00, sizeof (struct sgec_shared_mem)); /* Setup the Tx ring entries */ for (i = 0; i < TX_RING_SIZE; i++) { @@ -101,15 +91,16 @@ lp->tx_ring[i].bufaddr = leptr; #ifdef VAX_SGEC_DEBUG if (i < 3) - printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, (int) lp->card_mem->tx_buf[i]); + printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, + (int) lp->card_mem->tx_buf[i]); #endif } i = TX_RING_SIZE; /* one after last for chaining ! */ /* normal fill already done, now we define the ring */ - lp->tx_ring[i].tx_err = SG_TDR_OWN; + lp->tx_ring[i].tx_err = SG_TDR_OWN; lp->tx_ring[i].flags1 = SG_TD1_CA; /* chain to ring */ lp->tx_ring[i].bufsize = 0; - lp->tx_ring[i].bufaddr = virt_to_phys (lp->tx_ring); + lp->tx_ring[i].bufaddr = virt_to_phys (& lp->tx_ring [0]) & 0xffffff; /* Setup the Rx ring entries */ #ifdef VAX_SGEC_DEBUG @@ -120,9 +111,11 @@ lp->rx_ring[i].framelen = SG_FR_OWN; lp->rx_ring[i].bufsize = RX_BUFF_SIZE; lp->rx_ring[i].bufaddr = leptr; + #ifdef VAX_SGEC_DEBUG if (i < 3) - printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, (int) lp->card_mem->rx_buf[i]); + printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, + (int) lp->card_mem->rx_buf[i]); #endif } /* take one after last element for ring chaining */ @@ -130,59 +123,205 @@ lp->rx_ring[i].framelen = SG_FR_OWN; lp->rx_ring[i].flags1 = SG_R1_CAD; lp->rx_ring[i].bufsize = RX_BUFF_SIZE; - lp->rx_ring[i].bufaddr = virt_to_phys (lp->rx_ring); + lp->rx_ring[i].bufaddr = virt_to_phys (& lp->rx_ring [0]) & 0xffffff; + } -static void kick_sgec(volatile struct sgec_regs *regs) +static void kick_sgec(volatile struct sgec_private * lp) { - if((regs->sg_nicsr5 & SG_NICSR5_TS) != SG_NICSR5_TS_RUN) - writereg(®s->sg_nicsr1,SG_NICSR1_TXPD); + volatile struct sgec_regs *regs = lp->regs; + + if ((regs->sg_nicsr5 & SG_NICSR5_TS) != SG_NICSR5_TS_RUN) + { + writereg(®s->sg_nicsr1,SG_NICSR1_TXPD); +#ifdef VAX_SGEC_DEBUG + printk ("%s: retrigger CSR1 (CSR5 is %ld)\n", + __FUNCTION__, (regs->sg_nicsr5 & SG_NICSR5_TS) >> 24); +#endif + } } -static int init_restart_sgec(struct sgec_private *lp) +static int reset_sgec (struct net_device *dev) { + struct sgec_private *lp = (struct sgec_private *) dev->priv; volatile struct sgec_regs *regs = lp->regs; + unsigned long v; int i; - int oldvect; #ifdef VAX_SGEC_DEBUG - printk("init_restart_sgec\n"); + printk("%s: entry\n", __FUNCTION__); #endif udelay(100); - oldvect = regs->sg_nicsr6; - writecsr6(regs, SG_NICSR6_RE); /* reset card */ - + /* do chip reset */ + writecsr6 (regs, SG_NICSR6_RE); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10 /* ms */ * HZ) / 1000); + /* Wait for the sgec to complete initialization */ for (i = 0; (i < 100) && !(regs->sg_nicsr5 & SG_NICSR5_ID); i++) { #ifdef VAX_SGEC_DEBUG - printk("SGEC restarted maybe %d\n", i); + printk("SGEC restarted, loop %d\n", i); #endif - udelay(10); + udelay(1000); } if(regs->sg_nicsr5 & SG_NICSR5_SF) { - printk("SGEC selftest failed after %d ticks, csr5=%4.4lx.\n", i, regs->sg_nicsr5); + printk("SGEC selftest failed after %d ticks, csr5=%4.4lx.\n", + i, regs->sg_nicsr5); return -1; } if (i == 100) { -#ifdef VAX_SGEC_DEBUG - printk("SGEC unopened after %d ticks, csr5=%4.4lx.\n", i, regs->sg_nicsr5); -#endif + printk("SGEC unopened after %d ticks, csr5=%4.4lx.\n", + i, regs->sg_nicsr5); return -1; } #ifdef VAX_SGEC_DEBUG printk("SGEC restarted\n"); #endif + /* + * IRQ setup + */ + v = SG_NICSR0_IPL14 | + (dev->irq & SG_NICSR0_IV_MASK) | SG_NICSR0_MBO; + i = 10; + do + { + if (i-- == 0) + { + printk ("Failing setting CSR0 (0x%08lx)!\n", + regs->sg_nicsr0); + /* further ignore error here XXX CP */ + } + writereg (& regs->sg_nicsr0, v); + } while (v != regs->sg_nicsr0); + if (i == 0) + { + printk ("SGEC: CSR0 IRQ setup FAILED !\n"); + return -1; + } + + writereg(®s->sg_nicsr3, + virt_to_phys(& lp->rx_ring [0]) & 0xffffff); + writereg(®s->sg_nicsr4, + virt_to_phys(& lp->tx_ring [0]) & 0xffffff); + +#ifdef VAX_SGEC_DEBUG + printk ("%s: done well\n", __FUNCTION__); +#endif + + return 0; +} + +static int setup_csr6 (struct net_device *dev) +{ + struct sgec_private *lp = (struct sgec_private *) dev->priv; + volatile struct sgec_regs *regs = lp->regs; + unsigned long csr6; + +#ifdef VAX_SGEC_DEBUG + printk ("%s: entry\n", __FUNCTION__); +#endif + /* for changes of the SG_NICSR6_AF_xxx stop RX */ + writecsr6(regs, regs->sg_nicsr6 & ~SG_NICSR6_SR); + udelay (20); + + /* generate fix CSR6 part */ + csr6 = SG_NICSR6_MBO | SG_NICSR6_IE | SG_NICSR6_BL_8 | + SG_NICSR6_ST | SG_NICSR6_SR | SG_NICSR6_DC; + + /* generate flags dependent part */ + if (dev->flags & IFF_PROMISC) + csr6 |= SG_NICSR6_AF_PROM; + + /* update CSR6 */ + writecsr6(regs, csr6); - writecsr6(regs, SG_NICSR6_IE | SG_NICSR6_BL_8|SG_NICSR6_ST|SG_NICSR6_SR|SG_NICSR6_DC); - kick_sgec(regs); return 0; } +static int setup_sgec (struct net_device *dev) +{ + struct sgec_private *lp = (struct sgec_private *)dev->priv; + u_int8_t buf_setup [128]; + int entry; + unsigned long flags; + +#ifdef VAX_SGEC_DEBUG + printk ("\n\n< SETUP >\n%s: entry\n", __FUNCTION__); +#endif + + spin_lock_irqsave (&lp->lock, flags); + + if (TX_BUFFS_AVAIL <= 0) + { + netif_stop_queue(dev); + + /* no buffers free, how to handle .... */ + spin_unlock_irqrestore (&lp->lock, flags); + return 1; + } + + /* create setup buffer */ + memset (buf_setup, 0xffu, sizeof (buf_setup)); + memcpy (buf_setup, dev->dev_addr, 6); + + /* TODO: add other multicast mac addresses or filters */ + + entry = lp->tx_new; + + cp_to_buf ((char *) lp->card_mem->tx_buf[entry], + buf_setup, sizeof (buf_setup)); + lp->tx_ring[entry].bufsize = sizeof (buf_setup); + lp->tx_ring[entry].flags1 = SG_TD1_DT_SETUP | SG_TD1_IC; + +#ifdef VAX_SGEC_DEBUG_BUFFERS + { + int i; + + printk("rx["); + for (i=0; i < RX_RING_SIZE; i++){ + if (i == lp->rx_new) + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? + "_" : "X"); + else + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? + "." : "1"); + } + printk("]\n"); + printk("tx["); + for (i=0; i < TX_RING_SIZE; i++){ + if (i == lp->tx_new) + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "_" : "X"); + else + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "." : "1"); + } + printk("]\n"); + } +#endif + + lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; + + if (TX_BUFFS_AVAIL <= 0) + netif_stop_queue(dev); + + /* Now pass frame to transmitter */ + lp->tx_ring[entry].tx_err = SG_TDR_OWN; + + /* Kick the SGEC: transmit now */ + kick_sgec (lp); + + spin_unlock_irqrestore (&lp->lock, flags); + + dev->trans_start = jiffies; + return 0; +} static int sgec_rx(struct net_device *dev) { @@ -191,63 +330,75 @@ unsigned char bits; int len = 0; struct sk_buff *skb = 0; - int i; #ifdef VAX_SGEC_DEBUG printk("sgec_rx\n"); #endif #ifdef VAX_SGEC_DEBUG_BUFFERS - printk("["); - for (i=0; i < RX_RING_SIZE; i++){ - if (i == lp->rx_new) - printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "_" : "X"); - else - printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "." : "1"); + { + int i; + + printk(" rx["); + for (i=0; i < RX_RING_SIZE; i++){ + if (i == lp->rx_new) + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "_" : "X"); + else + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "." : "1"); + } + printk("]\n"); } - printk("]"); #endif - for (rd=&lp->rx_ring[lp->rx_new]; - !((bits = rd->framelen) & SG_FR_OWN); - rd=&lp->rx_ring[lp->rx_new]){ - - /* check for incomplete frame */ - if ((bits & SG_R0_POK) == 0) { - lp->stats.rx_over_errors++; - lp->stats.rx_errors++; - } - else if (bits & SG_R0_ERR) { - /* only count last frame as the error */ + while (! (lp->rx_ring [lp->rx_new].framelen & SG_FR_OWN)) + { + rd = & lp->rx_ring[lp->rx_new]; + bits = rd->flags0; + /* + * check for incomplete frame + */ + if (bits & SG_R0_ERR) { + /* only count last frame as the error */ if (bits & SG_R0_FFO) lp->stats.rx_fifo_errors++; /* was _BUF */ if (bits & SG_R0_CRC) lp->stats.rx_crc_errors++; if (bits & SG_R0_OFL) lp->stats.rx_over_errors++; if (bits & SG_R0_FRA) lp->stats.rx_frame_errors++; if (bits & SG_R0_LNG) lp->stats.rx_errors++; /* was _EOP */ +#ifdef VAX_SGEC_DEBUG + printk (" SG_R0_ERR (0x%04x)\n", bits); +#endif } else { len = rd->framelen; skb = dev_alloc_skb((unsigned int)len + 2); if (skb == 0) { - printk("%s: SGEC Deferring Packet\n", dev->name); + printk(" %s: SGEC Deferring Packet\n", dev->name); lp->stats.rx_dropped++; - //rd->mblength = 0; rd->framelen = SG_FR_OWN; - lp->rx_new =(lp->rx_new+1) & RX_RING_MASK; + lp->rx_new = (lp->rx_new + 1) & RX_RING_MASK; return 0; - } + } +#ifdef VAX_SGEC_DEBUG + printk (" fetching frame from ring buffer (len = %d)\n", len); +#endif lp->stats.rx_bytes += len; skb->dev = dev; - skb_reserve(skb,2); /*16 byte align */ + skb_reserve(skb,2); /* 16 byte align */ skb_put(skb, len); /* make room */ cp_from_buf(skb->data, (char *) lp->card_mem->rx_buf[lp->rx_new], len); skb->protocol = eth_type_trans(skb,dev); +#ifdef VAX_SGEC_DEBUG_LVL2 + printk (" passing up to linux\n", __FUNCTION__); +#endif netif_rx(skb); dev->last_rx=jiffies; lp->stats.rx_packets++; } +#ifdef VAX_SGEC_DEBUG_LVL2 + printk (" freeing rx frame\n", __FUNCTION__); +#endif rd->framelen = SG_FR_OWN; lp->rx_new = (lp->rx_new + 1) & RX_RING_MASK; } @@ -257,79 +408,106 @@ static void sgec_tx(struct net_device *dev) { struct sgec_private *lp = (struct sgec_private *) dev->priv; - volatile struct sgec_regs *regs = lp->regs; - volatile struct sgec_tx_desc *td; - int i, j; - j = lp->tx_old; #ifdef VAX_SGEC_DEBUG - printk ("sgec_tx\n"); + printk ("sgec_tx: "); #endif spin_lock(&lp->lock); - for (i = j; i != lp->tx_new; i = j) { - td = &lp->tx_ring[i]; #ifdef VAX_SGEC_DEBUG - printk ("sgec_tx: td->flags1 = %d\n",td->flags1); + printk ("%d (tx_err=0x%04x, flags0=0x%04x, flags1=0x%04x, size=%d)\n", + lp->tx_old, + lp->tx_ring [lp->tx_old].tx_err, + lp->tx_ring [lp->tx_old].flags0, + lp->tx_ring [lp->tx_old].flags1, + lp->tx_ring [lp->tx_old].bufsize); #endif - /* If we hit a packet not owned by us, stop */ - if (!(td->flags1 & SG_FR_OWN)) - break; - /* if (td->tmd1_bits & SG_T0_ERR) { - status = td->misc; - lp->stats.tx_errors++; - if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++; - if (status & LE_T3_LCOL) lp->stats.tx_window_errors++; - if (status & LE_T3_CLOS) { - lp->stats.tx_carrier_errors++; - printk("%s: Carrier Lost", dev->name); - sgec_stop(regs); - sgec_init_ring(dev); - load_csrs(lp); - init_restart_sgec(lp); - goto out; +#ifdef VAX_SGEC_DEBUG_BUFFERS + { + int i; + + printk(" tx["); + for (i=0; i < TX_RING_SIZE; i++){ + if (i == lp->tx_new) + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "_" : "X"); + else + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "." : "1"); } - */ - /* Buffer errors and underflows turn off the - * transmitter, restart the adapter. - */ - /* if (status & (LE_T3_BUF | LE_T3_UFL)) { - lp->stats.tx_fifo_errors++; - printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", dev->name); - sgec_stop(regs); - sgec_init_ring(dev); - load_csrs(lp); - init_restart_sgec(lp); - goto out; + printk("]\n"); + } +#endif + + /* + * for the TX problems work with this + */ + /* do TX cleaning */ + if (lp->tx_ring [lp->tx_old].tx_err & SG_TDR_OWN) + { +#if 1 /* def VAX_SGEC_DEBUG */ + printk (" **** cleaning ...\n"); +#endif + lp->tx_ring [lp->tx_old].tx_err = 0; + } + + while (! (lp->tx_ring [lp->tx_old].tx_err & SG_TDR_OWN)) + { + if (lp->tx_old == lp->tx_new) + { +#ifdef VAX_SGEC_DEBUG + printk (" old == new\n"); +#endif + break; } - } else - */ - if ((td->flags1 & SG_TD1_POK) == SG_TD1_POK) { + +#ifdef VAX_SGEC_DEBUG + printk (" tx_err=0x%04x, flags0=0x%04x, flags1=0x%04x\n", + lp->tx_ring [lp->tx_old].tx_err, + lp->tx_ring [lp->tx_old].flags0, + lp->tx_ring [lp->tx_old].flags1); +#endif + if ((lp->tx_ring [lp->tx_old].flags1 & SG_TD1_DT) == SG_TD1_DT_SETUP) + { + /* do nothing */ + } + else if (lp->tx_ring [lp->tx_old].flags1 & SG_TD1_LS) { /* * So we don't count the packet more than once. */ - td->flags1 &= ~(SG_TD1_POK); - - /* * One collision before packet was sent. - if (td->flags1 & SG_T1_EONE) +#if 0 /* + * no collision detection in this first driver steps + * further flags are not correct and SG_TD1_CC provides a number + * of collisions + */ + + /* One collision before packet was sent. */ + if (td->flags0 & SG_T0_LC) lp->stats.collisions++; - * More than one collision, be optimistic. - * sgec can tell us exactly how many... - if (td->tmd1_bits & LE_T1_EMORE) - lp->stats.collisions += 2; - */ + /* More than one collision, be optimistic. */ + /* sgec can tell us exactly how many... */ + if (td->flags0 & SG_T0_EC) + lp->stats.collisions += 2; /* TODO: use _CC */ +#endif lp->stats.tx_packets++; } - j = (j + 1) & TX_RING_MASK; + lp->tx_old = (lp->tx_old + 1) & TX_RING_MASK; } - lp->tx_old = j; - out: - if (netif_queue_stopped(dev) && - TX_BUFFS_AVAIL > 0) - netif_wake_queue(dev); + + if (TX_BUFFS_AVAIL > 0) + netif_wake_queue (dev); + /* rekick the TX, if there are unsent frames in buffer */ + if (lp->tx_new != lp->tx_old) + { +#ifdef VAX_SGEC_DEBUG + printk (" start kick_sgec()\n"); +#endif + kick_sgec (lp); + } + spin_unlock(&lp->lock); } @@ -341,19 +519,24 @@ unsigned long csr5; #ifdef VAX_SGEC_DEBUG - printk("sgec: interrupt!\n"); + printk("sgec: interrupt ... "); #endif csr5 = sg_regs->sg_nicsr5; - +#ifdef VAX_SGEC_DEBUG + printk ("csr5=0x%08lx ... ", csr5); +#endif if ((csr5 & SG_NICSR5_IS) == 0) { /* Hmmm, not for us... */ +#ifdef VAX_SGEC_DEBUG + printk ("forget it!\n"); +#endif return; } writereg(&sg_regs->sg_nicsr5, csr5); /* clear interrupt */ #ifdef VAX_SGEC_DEBUG - printk("sgec: ... And it's for us!\n"); + printk("for us!\n"); #endif #ifdef CONFIG_VSBUS @@ -364,38 +547,6 @@ if (csr5 & SG_NICSR5_TI) sgec_tx(dev); } -struct net_device *last_dev = 0; - -static void make_setup_frame(struct net_device *dev) -{ - struct sgec_private *lp = (struct sgec_private *) dev->priv; - - memset((void *)lp->card_mem->setup_frame,0xff,sizeof(lp->card_mem->setup_frame)); - memcpy((void *)lp->card_mem->setup_frame,dev->dev_addr,6); - - /* we should load the rest of the frame with multicast addresses */ - -#if 0 - entry = lp->tx_new & TX_RING_MASK; - ib->tx_ring[entry].flags1 = len; - cp_to_buf((char *) lp->sgec_mem->tx_buf[entry], skb->data, skblen); - ib->tx_ring[entry].flags1 = SG_TDR_OWN | SG_TD1_POK; /* (LE_T1_POK | LE_T1_OWN);*/ - lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; - if (TX_BUFFS_AVAIL <= 0) - netif_stop_queue(dev); - kick_sgec(regs); /* we don't need to TXPD if it's already going, right? */ - - /* from tulip */ - tp->tx_buffers[0].skb = NULL; - tp->tx_buffers[0].mapping = mapping; - /* Put the setup frame on the Tx list. */ - tp->tx_ring[0].length = cpu_to_le32(0x08000000 | 192); - tp->tx_ring[0].buffer1 = cpu_to_le32(mapping); - tp->tx_ring[0].status = cpu_to_le32(DescOwned); - tp->cur_tx++; - -#endif -} static int sgec_open(struct net_device *dev) { @@ -404,11 +555,9 @@ int status = 0; #ifdef VAX_SGEC_DEBUG - printk("sgec_open\n"); + printk("sgec_open (irq=0x%02x)\n", dev->irq); #endif - last_dev = dev; - /* Associate IRQ with sgec_interrupt */ if (request_irq(dev->irq, &sgec_interrupt, 0, lp->name, dev)) { printk("SGEC: Can't get irq %d\n", dev->irq); @@ -430,21 +579,22 @@ lp->filter[3] = 0; sgec_init_ring(dev); - /*load_csrs(lp);*/ - make_setup_frame(dev); - - /* put packet in queue */ - netif_start_queue(dev); + status = reset_sgec (dev); - load_csrs(lp); - status = init_restart_sgec(lp); + setup_csr6 (dev); + setup_sgec (dev); - /* - * if (!status) - * MOD_INC_USE_COUNT; - */ + /* put packet in queue */ + netif_start_queue(dev); +#if 0 /* no module support at the moment */ + if (!status) + MOD_INC_USE_COUNT; +#endif +#ifdef VAX_SGEC_DEBUG + printk ("return code of %s() = %d\n", __FUNCTION__, status); +#endif return status; } @@ -458,37 +608,18 @@ #endif netif_stop_queue(dev); +#if 0 /* XXX CP, perhaps removable */ del_timer_sync(&lp->multicast_timer); +#endif /* 0 */ sgec_stop(regs); free_irq(dev->irq, (void *) dev); - /* - MOD_DEC_USE_COUNT; - */ - return 0; -} - -static inline int sgec_reset(struct net_device *dev) -{ - struct sgec_private *lp = (struct sgec_private *) dev->priv; - volatile struct sgec_regs *regs = lp->regs; - int status; -#ifdef VAX_SGEC_DEBUG - printk("sgec_reset\n"); -#endif - - sgec_stop(regs); - - sgec_init_ring(dev); - load_csrs(lp); - dev->trans_start = jiffies; - status = init_restart_sgec(lp); -#ifdef VAX_SGEC_DEBUG - printk("SGEC restart=%d\n", status); +#if 0 /* no module support at the moment */ + MOD_DEC_USE_COUNT; #endif - return status; + return 0; } static void sgec_tx_timeout(struct net_device *dev) @@ -498,73 +629,78 @@ printk(KERN_ERR "%s: transmit timed out, status %04lx, reset\n", dev->name, regs->sg_nicsr6); - sgec_reset(dev); + sgec_stop(regs); + + sgec_init_ring(dev); + reset_sgec (dev); + setup_csr6 (dev); + + setup_sgec (dev); + netif_wake_queue(dev); } static int sgec_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct sgec_private *lp = (struct sgec_private *) dev->priv; - volatile struct sgec_regs *regs = lp->regs; int skblen = skb->len; int len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; int entry; + unsigned long flags; #ifdef VAX_SGEC_DEBUG_BUFFERS int i; #endif #ifdef VAX_SGEC_DEBUG - printk ("sgec_start_xmit: data length %d\n",len); + printk ("\n\n< SEND >\nsgec_start_xmit: data length %d\n", len); #endif - skblen = skb->len; - len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; - - spin_lock_irq(&lp->lock); + spin_lock_irqsave(&lp->lock, flags); lp->stats.tx_bytes += len; - entry = lp->tx_new & TX_RING_MASK; + entry = lp->tx_new; cp_to_buf((char *) lp->card_mem->tx_buf[entry], skb->data, skblen); lp->tx_ring[entry].bufsize = len; lp->tx_ring[entry].flags1 = SG_TD1_POK | SG_TD1_IC; - - /* Clear the slack of the packet, do I need this? */ - /* For a firewall its a good idea - AC */ -/* - if (len != skblen) - memset ((char *) &ib->tx_buf [entry][skblen], 0, (len - skblen) << 1); - */ - /* Now, give the packet to the card */ - lp->tx_ring[entry].tx_err = SG_TDR_OWN; - lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; - - if (TX_BUFFS_AVAIL <= 0) - netif_stop_queue(dev); + /* do we need to clear the slack of the packet? */ + #ifdef VAX_SGEC_DEBUG_BUFFERS printk("rx["); for (i=0; i < RX_RING_SIZE; i++){ if (i == lp->rx_new) - printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "_" : "X"); + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? + "_" : "X"); else - printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "." : "1"); + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? + "." : "1"); } printk("]\n"); printk("tx["); for (i=0; i < TX_RING_SIZE; i++){ if (i == lp->tx_new) - printk("%s",lp->tx_ring[i].flags1 & SG_TDR_OWN ? "_" : "X"); + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "_" : "X"); else - printk("%s",lp->tx_ring[i].flags1 & SG_TDR_OWN ? "." : "1"); + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "." : "1"); } printk("]\n"); #endif + lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; + + if (TX_BUFFS_AVAIL <= 0) + netif_stop_queue(dev); + + /* Now, give the packet to the card */ + lp->tx_ring[entry].tx_err = SG_TDR_OWN; + /* Kick the SGEC: transmit now */ - kick_sgec(regs); + kick_sgec(lp); - spin_unlock_irq(&lp->lock); + spin_unlock_irqrestore (&lp->lock, flags); dev->trans_start = jiffies; dev_kfree_skb(skb); @@ -636,8 +772,6 @@ static void sgec_set_multicast(struct net_device *dev) { - struct sgec_private *lp = (struct sgec_private *) dev->priv; - volatile struct sgec_regs *regs = lp->regs; #ifdef VAX_SGEC_DEBUG printk("sgec_set_multicast\n"); @@ -646,37 +780,28 @@ if (!netif_running(dev)) return; +#if 0 /* XXX CP: REMOVABLE CODE, TX queue needs not to be empty ! */ if (lp->tx_old != lp->tx_new) { mod_timer(&lp->multicast_timer, jiffies + 4); netif_wake_queue(dev); return; } +#endif netif_stop_queue(dev); - sgec_stop(regs); - - sgec_init_ring(dev); +#if 0 /* for test do not use multicast + TODO: setup flags, load multicast, etc..... + */ +#endif - if (dev->flags & IFF_PROMISC) { - lp->mode |= SG_NICSR6_AF_PROM; - } else { - lp->mode &= ~SG_NICSR6_AF_PROM; - sgec_load_multicast(dev); - } - load_csrs(lp); - init_restart_sgec(lp); - writecsr6(regs, regs->sg_nicsr6 & lp->mode); /* turn on-off multicast */ + /* no reset csr6 with the new flag dependent stuff ! */ + setup_csr6 (dev); + setup_sgec (dev); + netif_wake_queue(dev); } -static void sgec_set_multicast_retry(unsigned long _opaque) -{ - struct net_device *dev = (struct net_device *) _opaque; - - sgec_set_multicast(dev); -} - static int read_esar(unsigned char dev_addr[]) { unsigned int *esar; @@ -709,13 +834,7 @@ struct sgec_private *lp; volatile struct sgec_regs *regs; int ret; - unsigned long sgec_phys_addr; - - if(!strcmp(mv->cpu_type_str(),"VXT2000")) { /* erm */ - sgec_phys_addr=VXT_SGECADDR; - } else { - sgec_phys_addr=SGECADDR; - } + unsigned long sgec_phys_addr=SGECADDR; if (version_printed++ == 0) printk(version); @@ -742,15 +861,18 @@ each (plus 128 bytes).. over 128KB */ /* At present, until we figure out the address extension * parity control bit, ask for memory in the DMA zone */ + /* 2^6 = 64x4KB = 256KB */ - dev->mem_start = __get_free_pages(GFP_DMA, /*4*/ 6); + dev->mem_start = __get_free_pages(GFP_DMA, 6); if (!dev->mem_start) { /* Shouldn't we free dev->priv here if dev was non-NULL on entry? */ return -ENOMEM; } dev->mem_end = dev->mem_start + sizeof (struct sgec_shared_mem); lp->card_mem = (volatile struct sgec_shared_mem *)(dev->mem_start); - + lp->rx_ring = (struct sgec_rx_desc *) & lp->card_mem->rx_ring_mem [0]; + lp->tx_ring = (struct sgec_tx_desc *) & lp->card_mem->tx_ring_mem [0]; + regs = (struct sgec_regs *) ioremap(sgec_phys_addr, 0x20 /* 0x8 */); dev->base_addr = (unsigned long) regs; if(dev->base_addr == 0) @@ -778,6 +900,8 @@ sgec_stop(regs); + dev->irq = 0; + #ifndef VAX_SGEC_AUTOPROBE_IRQ dev->irq=SGECVEC; printk("Using hardcoded SGEC interrupt vector %d\n", dev->irq); @@ -787,18 +911,13 @@ printk("Autoprobing SGEC interrupt vector..."); autoirq_setup(0); + #ifdef CONFIG_VSBUS vsbus_probe_irq_on(); #endif /* CONFIG_VSBUS */ #endif /* VAX_SGEC_AUTOPROBE_IRQ */ -#if 0 - sgec_init_ring(dev); - load_csrs(lp); - make_setup_frame(dev); - kick_sgec(regs); - udelay(1000); -#endif + /* should do something here to cause an interrupt */ #ifdef VAX_SGEC_AUTOPROBE_IRQ #ifdef CONFIG_VSBUS @@ -814,22 +933,15 @@ printk(" probed IRQ %d, vsbus %d\n", dev->irq, lp->vsbus_int); } else { dev->irq=SGECVEC; - dev->irq=0x80; - printk(" failed to detect IRQ line - assuming 0x%x.\n", dev->irq); + /* 0x80 is probably not the best vector but it's where the sgec + is ending up after we reset it, so force it there for now */ + dev->irq = 0x80; + printk(" failed to detect IRQ line - assuming 0x%x.\n", + dev->irq); } #endif /* VAX_SGEC_AUTOPROBE_IRQ */ ether_setup(dev); - - /* does anyone know what this really is supposed to do? */ - /* We cannot sleep if the chip is busy during a - * multicast list update event, because such events - * can occur from interrupts (ex. IPv6). So we - * use a timer to try again later when necessary. -DaveM - */ - init_timer(&lp->multicast_timer); - lp->multicast_timer.data = (unsigned long) dev; - lp->multicast_timer.function = &sgec_set_multicast_retry; #ifdef MODULE /* Index: vaxsgec.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- vaxsgec.h 26 May 2002 07:58:37 -0000 1.3 +++ vaxsgec.h 28 May 2002 18:41:37 -0000 1.4 @@ -162,7 +162,6 @@ */ /* The registers. */ #define SGECADDR 0x20008000 -#define VXT_SGECADDR 0x20000000 /* 20008000 would probably work too due to address aliasing, but 20000000 is probably more "right" */ /* The IDPROM. */ #define QBUS_NISA_ROM 0x20084000 /* 3100/85 */ #define VSBUS_NISA_ROM 0x27800000 /* 3100/90 (?) */ @@ -249,9 +248,14 @@ /* This is how our shared memory block is laid out */ struct sgec_shared_mem { + struct sgec_rx_desc rx_ring_mem [RX_RING_SIZE + 2]; /* desc in DMA mem */ + struct sgec_tx_desc tx_ring_mem [TX_RING_SIZE + 2]; /* desc in DMA mem */ + /* padding */ + char __padding [PAGE_SIZE - + (sizeof (struct sgec_rx_desc) * (RX_RING_SIZE + 2) + + sizeof (struct sgec_tx_desc) * (TX_RING_SIZE + 2))]; char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE]; /* packet storage */ char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE]; /* packet storage */ - u_int8_t setup_frame[128]; /* setup frame/packet */ }; struct sgec_private { @@ -264,8 +268,8 @@ unsigned short rx_len; /* receive len and high addr */ unsigned short tx_ptr; /* transmit descriptor addr */ unsigned short tx_len; /* transmit len and high addr */ - struct sgec_rx_desc rx_ring[RX_RING_SIZE]; - struct sgec_tx_desc tx_ring[TX_RING_SIZE]; + struct sgec_rx_desc * rx_ring; + struct sgec_tx_desc * tx_ring; volatile struct sgec_shared_mem *card_mem; /* virtual addr of shared memory block */ unsigned char vsbus_int; spinlock_t lock; @@ -274,5 +278,4 @@ struct net_device_stats stats; struct net_device *dev; /* Backpointer */ struct sgec_private *next_module; - struct timer_list multicast_timer; }; |