📄 sk_g16.c
字号:
for (i = 0; i < RMDNUM; i++) /* Init all RMD's */ { rmdp = p->rmdhead + i; writel((unsigned long) p->rmdbufs[i], rmdp->u.buffer); /* assign buffer */ /* * LANCE must be owner at beginning so that he can fill in * receiving packets, set status and release RMD */ writeb(RX_OWN, rmdp->u.s.status); writew(-PKT_BUF_SZ, rmdp->blen); /* Buffer Size (two's complement) */ writeb(0, rmdp->mlen); /* init message length */ } /* Fill LANCE Initialize Block */ writew(mode, (p->ram)->ib.mode); /* Set operation mode */ for (i = 0; i < ETH_ALEN; i++) /* Set physical address */ { writeb(dev->dev_addr[i], (p->ram)->ib.paddr[i]); } for (i = 0; i < 8; i++) /* Set multicast, logical address */ { writeb(0, (p->ram)->ib.laddr[i]); /* We do not use logical addressing */ } /* Set ring descriptor pointers and set number of descriptors */ writel((int)p->rmdhead | RMDNUMMASK, (p->ram)->ib.rdrp); writel((int)p->tmdhead | TMDNUMMASK, (p->ram)->ib.tdrp); /* Prepare LANCE Control and Status Registers */ save_flags(flags); cli(); SK_write_reg(CSR3, CSR3_ACON); /* Ale Control !!!THIS MUST BE SET!!!! */ /* * LANCE addresses the RAM from 0x0000 to 0x3fbf and has no access to * PC Memory locations. * * In structure SK_ram is defined that the first thing in ram * is the initialization block. So his address is for LANCE always * 0x0000 * * CSR1 contains low order bits 15:0 of initialization block address * CSR2 is built of: * 7:0 High order bits 23:16 of initialization block address * 15:8 reserved, must be 0 */ /* Set initialization block address (must be on word boundary) */ SK_write_reg(CSR1, 0); /* Set low order bits 15:0 */ SK_write_reg(CSR2, 0); /* Set high order bits 23:16 */ PRINTK(("## %s: After setting CSR1-3. CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0))); /* Initialize LANCE */ /* * INIT = Initialize, when set, causes the LANCE to begin the * initialization procedure and access the Init Block. */ SK_write_reg(CSR0, CSR0_INIT); restore_flags(flags); /* Wait until LANCE finished initialization */ SK_set_RAP(CSR0); /* Register Address Pointer to CSR0 */ for (i = 0; (i < 100) && !(SK_rread_reg() & CSR0_IDON); i++) ; /* Wait until init done or go ahead if problems (i>=100) */ if (i >= 100) /* Something is wrong ! */ { printk("%s: can't init am7990, status: %04x " "init_block: %#08x\n", dev->name, (int) SK_read_reg(CSR0), (unsigned int) &(p->ram)->ib);#ifdef SK_DEBUG SK_print_pos(dev, "LANCE INIT failed"); SK_print_dev(dev,"Device Structure:");#endif return -1; /* LANCE init failed */ } PRINTK(("## %s: init done after %d ticks\n", SK_NAME, i)); /* Clear Initialize done, enable Interrupts, start LANCE */ SK_write_reg(CSR0, CSR0_IDON | CSR0_INEA | CSR0_STRT); PRINTK(("## %s: LANCE started. CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0))); return 0; /* LANCE is up and running */} /* End of SK_lance_init() *//*- * Function : SK_send_packet * Author : Patrick J.D. Weichmann * Date Created : 94/05/27 * * Description : Writes an socket buffer into a transmit descriptor * and starts transmission. * * Parameters : I : struct sk_buff *skb - packet to transfer * I : struct device *dev - SK_G16 device structure * Return Value : 0 - OK * 1 - Could not transmit (dev_queue_xmit will queue it) * and try to sent it later * Globals : None * Side Effects : None * Update History : * YY/MM/DD uid Description-*/static int SK_send_packet(struct sk_buff *skb, struct device *dev){ struct priv *p = (struct priv *) dev->priv; struct tmd *tmdp; if (dev->tbusy) { /* if Transmitter more than 150ms busy -> time_out */ int tickssofar = jiffies - dev->trans_start; if (tickssofar < 15) { return 1; /* We have to try transmit later */ } printk("%s: xmitter timed out, try to restart!\n", dev->name); SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */ dev->tbusy = 0; /* Clear Transmitter flag */ dev->trans_start = jiffies; /* Mark Start of transmission */ } PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n", SK_NAME, SK_read_reg(CSR0))); /* * Block a timer-based transmit from overlapping. * This means check if we are already in. */ if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) /* dev->tbusy already set ? */ { printk("%s: Transmitter access conflict.\n", dev->name); } else { /* Evaluate Packet length */ short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; tmdp = p->tmdhead + p->tmdnum; /* Which descriptor for transmitting */ /* Fill in Transmit Message Descriptor */ /* Copy data into dual ported ram */ memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len); writew(-len, tmdp->blen); /* set length to transmit */ /* * Packet start and end is always set because we use the maximum * packet length as buffer length. * Relinquish ownership to LANCE */ writeb(TX_OWN | TX_STP | TX_ENP, tmdp->u.s.status); /* Start Demand Transmission */ SK_write_reg(CSR0, CSR0_TDMD | CSR0_INEA); dev->trans_start = jiffies; /* Mark start of transmission */ /* Set pointer to next transmit buffer */ p->tmdnum++; p->tmdnum &= TMDNUM-1; /* Do we own the next transmit buffer ? */ if (! (readb((p->tmdhead + p->tmdnum)->u.s.status) & TX_OWN) ) { /* * We own next buffer and are ready to transmit, so * clear busy flag */ dev->tbusy = 0; } p->stats.tx_bytes += skb->len; } dev_kfree_skb(skb); return 0; } /* End of SK_send_packet *//*- * Function : SK_interrupt * Author : Patrick J.D. Weichmann * Date Created : 94/05/27 * * Description : SK_G16 interrupt handler which checks for LANCE * Errors, handles transmit and receive interrupts * * Parameters : I : int irq, void *dev_id, struct pt_regs * regs - * Return Value : None * Errors : None * Globals : None * Side Effects : None * Update History : * YY/MM/DD uid Description-*/static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs){ int csr0; struct device *dev = dev_id; struct priv *p = (struct priv *) dev->priv; PRINTK2(("## %s: SK_interrupt(). status: %#06x\n", SK_NAME, SK_read_reg(CSR0))); if (dev == NULL) { printk("SK_interrupt(): IRQ %d for unknown device.\n", irq); } if (dev->interrupt) { printk("%s: Re-entering the interrupt handler.\n", dev->name); } csr0 = SK_read_reg(CSR0); /* store register for checking */ dev->interrupt = 1; /* We are handling an interrupt */ /* * Acknowledge all of the current interrupt sources, disable * Interrupts (INEA = 0) */ SK_write_reg(CSR0, csr0 & CSR0_CLRALL); if (csr0 & CSR0_ERR) /* LANCE Error */ { printk("%s: error: %04x\n", dev->name, csr0); if (csr0 & CSR0_MISS) /* No place to store packet ? */ { p->stats.rx_dropped++; } } if (csr0 & CSR0_RINT) /* Receive Interrupt (packet arrived) */ { SK_rxintr(dev); } if (csr0 & CSR0_TINT) /* Transmit interrupt (packet sent) */ { SK_txintr(dev); } SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */ dev->interrupt = 0; /* We are out */} /* End of SK_interrupt() */ /*- * Function : SK_txintr * Author : Patrick J.D. Weichmann * Date Created : 94/05/27 * * Description : After sending a packet we check status, update * statistics and relinquish ownership of transmit * descriptor ring. * * Parameters : I : struct device *dev - SK_G16 device structure * Return Value : None * Errors : None * Globals : None * Update History : * YY/MM/DD uid Description-*/static void SK_txintr(struct device *dev){ int tmdstat; struct tmd *tmdp; struct priv *p = (struct priv *) dev->priv; PRINTK2(("## %s: SK_txintr() status: %#06x\n", SK_NAME, SK_read_reg(CSR0))); tmdp = p->tmdhead + p->tmdlast; /* Which buffer we sent at last ? */ /* Set next buffer */ p->tmdlast++; p->tmdlast &= TMDNUM-1; tmdstat = readb(tmdp->u.s.status); /* * We check status of transmitted packet. * see LANCE data-sheet for error explanation */ if (tmdstat & TX_ERR) /* Error occurred */ { int stat2 = readw(tmdp->status2); printk("%s: TX error: %04x %04x\n", dev->name, tmdstat, stat2); if (stat2 & TX_TDR) /* TDR problems? */ { printk("%s: tdr-problems \n", dev->name); } if (stat2 & TX_RTRY) /* Failed in 16 attempts to transmit ? */ p->stats.tx_aborted_errors++; if (stat2 & TX_LCOL) /* Late collision ? */ p->stats.tx_window_errors++; if (stat2 & TX_LCAR) /* Loss of Carrier ? */ p->stats.tx_carrier_errors++; if (stat2 & TX_UFLO) /* Underflow error ? */ { p->stats.tx_fifo_errors++; /* * If UFLO error occurs it will turn transmitter of. * So we must reinit LANCE */ SK_lance_init(dev, MODE_NORMAL); } p->stats.tx_errors++; writew(0, tmdp->status2); /* Clear error flags */ } else if (tmdstat & TX_MORE) /* Collisions occurred ? */ { /* * Here I have a problem. * I only know that there must be one or up to 15 collisions. * That's why TX_MORE is set, because after 16 attempts TX_RTRY * will be set which means couldn't send packet aborted transfer. * * First I did not have this in but then I thought at minimum * we see that something was not ok. * If anyone knows something better than this to handle this * please report it. */ p->stats.collisions++; } else /* Packet sent without any problems */ { p->stats.tx_packets++; } /* * We mark transmitter not busy anymore, because now we have a free * transmit descriptor which can be filled by SK_send_packet and * afterwards sent by the LANCE */ dev->tbusy = 0; /* * mark_bh(NET_BH); * This will cause net_bh() to run after this interrupt handler. * * The function which do handle slow IRQ parts is do_bottom_half() * which runs at normal kernel priority, that means all interrupt are * enabled. (see kernel/irq.c) * * net_bh does something like this: * - check if already in net_bh * - try to transmit something from the send queue * - if something is in the receive queue send it up to higher * levels if it is a known protocol * - try to transmit something from the send queue */ mark_bh(NET_BH); } /* End of SK_txintr() *//*- * Function : SK_rxintr * Author : Patrick J.D. Weichmann * Date Created : 94/05/27 * * Description : Buffer sent, check for errors, relinquish ownership * of the receive message descriptor. * * Parameters : I : SK_G16 device structure * Return Value : None * Globals : None * Update History : * YY/MM/DD uid Description-*/static void SK_rxintr(struct device *dev){ struct rmd *rmdp; int rmdstat; struct priv *p = (struct priv *) dev->priv; PRINTK2(("## %s: SK_rxintr(). CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0))); rmdp = p->rmdhead + p->rmdnum; /* As long as we own the next entry, check status and send * it up to higher layer */ while (!( (rmdstat = readb(rmdp->u.s.status)) & RX_OWN)) { /* * Start and end of packet must be set, because we use * the ethernet maximum packet length (1518) as buffer size. * * Because our buffers are at maximum OFLO and BUFF errors are * not to be concerned (see Data sheet) */ if ((rmdstat & (RX_STP | RX_ENP)) != (RX_STP | RX_ENP)) { /* Start of a frame > 1518 Bytes ? */ if (rmdstat & RX_STP) { p->stats.rx_errors++; /* bad packet received */ p->stats.rx_length_errors++; /* packet too long */ printk("%s: packet too long\n", dev->name); } /* * All other packets will be ignored until a new frame with * start (RX_STP) set follows. * * What we do is just give descriptor free for new incoming * packets. */ writeb(RX_OWN, rmdp->u.s.status); /* Relinquish ownership to LANCE */ } else if (rmdstat & RX_ERR) /* Receive Error ? */ { printk("%s: RX error: %04x\n", dev->name, (int) rmdstat); p->stats.rx_errors++; if (rmdstat & RX_FRAM) p->stats.rx_frame_errors++; if (rmdstat & RX_CRC) p->stats.rx_crc_errors++; writeb(RX_OWN, rmdp->u.s.status); /* Relinquish ownership to LANCE */ } else /* We have a packet which can be queued for the upper layers */ { int len = readw(rmdp->mlen) & 0x0fff; /* extract message length from receive buffer */ struct sk_buff *skb; skb = dev_alloc_skb(len+2); /* allocate socket buffer */ if (skb == NULL) /* Could not get mem ? */ { /* * Couldn't allocate sk_buffer so we give descriptor back * to Lance, update statistics and go ahead. */ writeb(RX_OWN, rmdp->u.s.status); /* Relinquish ownership to LANCE */ printk("%s: Couldn't allocate sk_buff, deferring packet.\n", dev->name); p->stats.rx_dropped++; break; /* Jump out */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -