📄 sk_g16.c
字号:
for (i = 0; i < RMDNUM; i++) /* Init all RMD's */ { rmdp = p->rmdhead + i; rmdp->u.buffer = (unsigned long) p->rmdbufs[i]; /* assign buffer */ /* * LANCE must be owner at beginning so that he can fill in * receiving packets, set status and release RMD */ rmdp->u.s.status = RX_OWN; rmdp->blen = -PKT_BUF_SZ; /* Buffer Size in a two's complement */ rmdp->mlen = 0; /* init message length */ } /* Fill LANCE Initialize Block */ (p->ram)->ib.mode = mode; /* Set operation mode */ for (i = 0; i < ETH_ALEN; i++) /* Set physical address */ { (p->ram)->ib.paddr[i] = dev->dev_addr[i]; } for (i = 0; i < 8; i++) /* Set multicast, logical address */ { (p->ram)->ib.laddr[i] = 0; /* We do not use logical addressing */ } /* Set ring descriptor pointers and set number of descriptors */ (p->ram)->ib.rdrp = (int) p->rmdhead | RMDNUMMASK; (p->ram)->ib.tdrp = (int) p->tmdhead | TMDNUMMASK; /* Prepare LANCE Control and Status Registers */ 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); sti(); /* 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 */ } /* * If some upper Layer thinks we missed a transmit done interrupt * we are passed NULL. * (dev_queue_xmit net/inet/dev.c */ if (skb == NULL) { /* * Dequeue packets from transmit queue and send them. */ dev_tint(dev); return 0; } 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 (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((char *) (tmdp->u.buffer & 0x00ffffff), (char *)skb->data, skb->len); tmdp->blen = -len; /* 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 */ tmdp->u.s.status = TX_OWN | TX_STP | TX_ENP; /* 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 (! ((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; } } dev_kfree_skb(skb, FREE_WRITE); 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 = (struct device *) irq2dev_map[irq]; 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 = tmdp->u.s.status & 0xff00; /* filter out status bits 15:08 */ /* * We check status of transmitted packet. * see LANCE data-sheet for error explanation */ if (tmdstat & TX_ERR) /* Error occurred */ { printk("%s: TX error: %04x %04x\n", dev->name, (int) tmdstat, (int) tmdp->status2); if (tmdp->status2 & TX_TDR) /* TDR problems? */ { printk("%s: tdr-problems \n", dev->name); } if (tmdp->status2 & TX_RTRY) /* Failed in 16 attempts to transmit ? */ p->stats.tx_aborted_errors++; if (tmdp->status2 & TX_LCOL) /* Late collision ? */ p->stats.tx_window_errors++; if (tmdp->status2 & TX_LCAR) /* Loss of Carrier ? */ p->stats.tx_carrier_errors++; if (tmdp->status2 & 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++; tmdp->status2 = 0; /* 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. (see Email addresses in the README file) */ 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 = 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. */ rmdp->u.s.status = RX_OWN; /* 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++; rmdp->u.s.status = RX_OWN; /* Relinquish ownership to LANCE */ } else /* We have a packet which can be queued for the upper layers */ { int len = (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. */ rmdp->u.s.status = RX_OWN; /* Relinquish ownership to LANCE */ printk("%s: Couldn't allocate sk_buff, deferring packet.\n", dev->name); p->stats.rx_dropped++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -