📄 pmcmspeth.c
字号:
netif_carrier_on(dev); } } /* reschedule the timer */ lp->link_timer.expires = jiffies + HZ / LINK_DELAY_DIV; add_timer(&lp->link_timer);}/************************************************************************** * Reset the hardware and restore defaults. Queues etc must be * cleared afterwards, although we don't change the pointers so they don't * need to be reallocated. */static void mspeth_mac_reset(struct net_device *dev){ struct mspeth_local *lp = (struct mspeth_local *) dev->priv; struct mspeth_regs *tr = (struct mspeth_regs *) dev->base_addr; int i; /* software reset the MAC -- why do we have to do both? But it seems to work better this * way so ..... */ write_mspreg(MAC_Reset, &tr->MAC_Ctl); /* hardware reset */ write_mspreg(MacRSTBases[lp->hwunit], RST_SET_REG); mdelay(100); write_mspreg(MacRSTBases[lp->hwunit], RST_CLR_REG); /* Wait for the MAC to come out of reset */ for (i = 0; i < 10; i++) { if ((read_mspreg(SYS_RST_REG) & MacRSTBases[lp->hwunit]) == 0) break; ndelay(100); } /* initialize registers to default value */ write_mspreg(0, &tr->MAC_Ctl); write_mspreg(0, &tr->DMA_Ctl); write_mspreg(0, &tr->TxThrsh); write_mspreg(0, &tr->TxPollCtr); write_mspreg(0, &tr->RxFragSize); write_mspreg(0, &tr->Int_En); write_mspreg(0, &tr->FDA_Bas); write_mspreg(0, &tr->FDA_Lim); write_mspreg(0xffffffff, &tr->Int_Src); /* Write 1 to clear */ write_mspreg(0, &tr->ARC_Ctl); write_mspreg(0, &tr->Tx_Ctl); write_mspreg(0, &tr->Rx_Ctl); write_mspreg(0, &tr->ARC_Ena); (void) read_mspreg(&tr->Miss_Cnt); /* Read to clear */}/************************************************************************** * initialize the hardware and start the DMA/MAC RX/TX. The queues must * be setup before this is called. */static void mspeth_mac_init(struct net_device *dev){ struct mspeth_local *lp = (struct mspeth_local *) dev->priv; struct mspeth_regs *tr = (struct mspeth_regs *) dev->base_addr; int flags; /* do not interrupt me while I'm configuring the MAC */ local_irq_save(flags); /* load station address to ARC */ mspeth_set_arc_entry(tr, ARC_ENTRY_SOURCE, dev->dev_addr); /* Enable ARC (broadcast and unicast) */ write_mspreg(ARC_Ena_Bit(ARC_ENTRY_SOURCE), &tr->ARC_Ena); write_mspreg(ARC_CompEn | ARC_BroadAcc, &tr->ARC_Ctl); /* configure DMA */ write_mspreg(DMA_CTL_CMD, &tr->DMA_Ctl); /* configure the RX/TX mac */ write_mspreg(0, &tr->RxFragSize); write_mspreg(TX_POLL_CNT, &tr->TxPollCtr); write_mspreg(TX_THRESHOLD, &tr->TxThrsh); /* zero and enable the interrupts */ lp->fatal_icnt = 0; write_mspreg(INT_EN_CMD, &tr->Int_En); /* set queues */ /* NOTE: This needs to be checked against the documentation: * How much does (RX_BUF_NUM-1) need to be shifted over. * Andrew thinks 5, used to be 4. */ /* hammtrev, 2005-11-25: * Using the formula used in the old brecis driver, which gives a * little bit less than (RX_BUF_NUM-1)<<5, allowing for more * buffer descriptors attached to a frame descriptor. */ write_mspreg(lp->rxfd_base, &tr->FDA_Bas); write_mspreg((RX_BUF_NUM - 1) << 5, &tr->FDA_Lim); /* * Activation method: * First, enable the MAC Transmitter and the DMA Receive circuits. * Then enable the DMA Transmitter and the MAC Receive circuits. */ write_mspreg(lp->blfd_ptr, &tr->BLFrmPtr); /* start DMA receiver */ write_mspreg(RX_CTL_CMD, &tr->Rx_Ctl); /* start MAC receiver */ write_mspreg(lp->txfd_base, &tr->TxFrmPtr); /* start the DMA transmitter */ write_mspreg(TX_CTL_CMD, &tr->Tx_Ctl); /* start the MAC transmitter */ /* turn the interrupts back on */ local_irq_restore(flags);}/************************************************************************** * start the Address Recognition circuit. It must be initialized with * address of the device (which can be changed in the PROM). */static voidmspeth_set_arc_entry(struct mspeth_regs *tr, int index, unsigned char *addr){ int arc_index = index * 6; unsigned long arc_data; unsigned long saved_addr; saved_addr = read_mspreg(&tr->ARC_Adr); if (mspeth_debug > 1) { int i; printk(KERN_DEBUG "%s: arc %d:", cardname, index); for (i = 0; i < 6; i++) printk(" %02x", addr[i]); printk("\n"); } if (index & 1) { /* read modify write */ write_mspreg(arc_index - 2, &tr->ARC_Adr); arc_data = read_mspreg(&tr->ARC_Data) & 0xffff0000; arc_data |= addr[0] << 8 | addr[1]; write_mspreg(arc_data, &tr->ARC_Data); /* write whole word */ write_mspreg(arc_index + 2, &tr->ARC_Adr); arc_data = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; write_mspreg(arc_data, &tr->ARC_Data); } else { /* write whole word */ write_mspreg(arc_index, &tr->ARC_Adr); arc_data = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3]; write_mspreg(arc_data, &tr->ARC_Data); /* read modify write */ write_mspreg(arc_index + 4, &tr->ARC_Adr); arc_data = read_mspreg(&tr->ARC_Data) & 0x0000ffff; arc_data |= addr[4] << 24 | (addr[5] << 16); write_mspreg(arc_data, &tr->ARC_Data); } if (mspeth_debug > 2) { int i; for (i = arc_index / 4; i < arc_index / 4 + 2; i++) { write_mspreg(i * 4, &tr->ARC_Adr); printk("arc 0x%x: %08x\n", i * 4, read_mspreg(&tr->ARC_Data)); } } write_mspreg(saved_addr, &tr->ARC_Adr);}/************************************************************************** * Initialize the RX/TX queues and the free buffer list. This routine * allocates memory and care must be taken to free the memory when it * is no longer required */static bool mspeth_queue_init(struct net_device *dev){ struct mspeth_local *lp = (struct mspeth_local *) dev->priv; int i, size = 0; u32 tmp_addr; struct sk_buff *skb; /* The queue structure allocates individual buffers large enough to hold an entire * packet. There is no packing so each FD requires a single BD. There is one * Q_Desc (an FD and a BD, 16-byte aligned) for each packet recieved and the same * for each packet to transmit. The list of free buffers has one FD and an arbitrary number * of BDs following it (but even). There is one BD for each RX buffer */ /* need to add some error checking here for reentry into this routine */ /* test for allocation requirements */ if (lp->FD_base == NULL) { /* descriptors for the rx/tx buffers and the buffer list */ size = (RX_BUF_NUM + TX_BUF_NUM) * sizeof(struct Q_Desc) + sizeof(struct BL_Desc); /* add enough margin to align to 16-byte boundary */ lp->FD_base = kmalloc(size + 15, GFP_KERNEL); if (lp->FD_base == NULL) { printk(KERN_ERR "Cannot allocate space for MSPETH descriptors!\n"); return false; } /* Move frame descriptors to uncached addresses. This prevents spurious IntBLEx interrupts. */ lp->FD_base = KSEG1ADDR(lp->FD_base); memset(lp->FD_base, 0, size + 15); if (mspeth_debug > 1) printk(KERN_INFO "MSPETH (queue_init) %s:FD_base = %p\n", dev->name, lp->FD_base); } /* Align to a 16 byte boundary */ tmp_addr = (u32) (lp->FD_base+15) & ~15; /* allocate the rx queue (aka free descriptor area) */ lp->rxfd_base = (struct Q_Desc *) tmp_addr; lp->rxfd_curr = lp->rxfd_base; tmp_addr += RX_BUF_NUM * sizeof(struct Q_Desc); /* initialize the receive queue (these values are mostly overwritten by the MAC) */ for (i = 0; i < RX_BUF_NUM; i++) { lp->rxfd_base[i].fd0.FDNext = 0x00000000; lp->rxfd_base[i].fd0.FDSystem = 0x00000000; lp->rxfd_base[i].fd0.FDStat = 0x00000000; lp->rxfd_base[i].fd0.FDCtl = FD_CownsFD; lp->rxfd_base[i].fd1.FDNext = 0x00000000; lp->rxfd_base[i].fd1.FDSystem = 0x00000000; lp->rxfd_base[i].fd1.FDStat = 0x00000000; lp->rxfd_base[i].fd1.FDCtl = FD_CownsFD; } /* allocate the tx queue */ lp->txfd_base = (struct Q_Desc *) tmp_addr; lp->tx_head = lp->tx_tail = 0; tmp_addr += TX_BUF_NUM * sizeof(struct Q_Desc); /* initialize the transmit queue */ for (i = 0; i < TX_BUF_NUM; i++) { lp->txfd_base[i].fd.FDNext = (u32) (&lp->txfd_base[i + 1]); lp->txfd_base[i].fd.FDSystem = 0x00000000; lp->txfd_base[i].fd.FDStat = 0x00000000; lp->txfd_base[i].fd.FDCtl = 0x00000000; } lp->txfd_base[TX_BUF_NUM - 1].fd.FDNext = (u32) (&lp->txfd_base[0]); /* initialize the buffer list FD */ lp->blfd_ptr = (struct BL_Desc *) tmp_addr; lp->blfd_ptr->fd.FDNext = (u32) lp->blfd_ptr; lp->blfd_ptr->fd.FDCtl = (RX_BUF_NUM << 1 | FD_CownsFD); /* allocate the array of sk_buff pointers */ if (lp->rx_skbp == NULL) { lp->rx_skbp = (struct sk_buff **) kmalloc(((RX_BUF_NUM << 1) * sizeof(struct sk_buff *)), GFP_KERNEL); for (i = 0; i < RX_BUF_NUM << 1; i++) lp->rx_skbp[i] = NULL; } /* allocate and initialize the actual sk_buffs proper */ for (i = 0; i < RX_BUF_NUM << 1; i++) { /* free up old sk_buffs */ if (lp->rx_skbp[i] != NULL) { dev_kfree_skb_any(lp->rx_skbp[i]); lp->rx_skbp[i] = NULL; } /* allocate and align the skb */ skb = mspeth_alloc_skb(dev); lp->rx_skbp[i] = skb; /* initialize the buffer list entries * reserving 2 bytes in the skb results in a 16-byte aligned * IP header, but also puts the skb->data at a 16-bit * boundary. The hardware requires a 32-bit aligned buffer. * So we round back two bytes and then instruct the hardware * to skip forward 2 bytes into the buffer. */ lp->blfd_ptr->bd[i].BuffData = (u32) skb->data & ~15; lp->blfd_ptr->bd[i].BDCtl = (BD_CownsBD | (i << BD_RxBDID_SHIFT) | MSP_END_BUFSIZE); } /* configure the queue length and return */ atomic_set(&lp->tx_qspc, TX_BUF_NUM); return true;}/************************************************************************** * Clear the queues of any outstanding packet. This *will* cause packet * loss, so it's a recovery mechanism. */static void mspeth_clear_queues(struct net_device *dev){ struct mspeth_local *lp = (struct mspeth_local *) dev->priv; int i; struct sk_buff *skb; if (lp->txfd_base != NULL) { for (i = 0; i < TX_BUF_NUM; i++) { if (lp->txfd_base[i].fd.FDSystem != 0x00000000) { skb = (struct sk_buff *) lp->txfd_base[i].fd. FDSystem; dev_kfree_skb_any(skb); } lp->txfd_base[i].fd.FDSystem = (0x00000000); } } mspeth_queue_init(dev);}/************************************************************************** * converse of the mspeth_init_queues routine. This frees all the memory * associated with the queues. It must be called when closing the device. */static void mspeth_free_queues(struct net_device *dev){ struct mspeth_local *lp = (struct mspeth_local *) dev->priv; struct sk_buff *skb; int i; /* free up any TX buffers */ if (lp->txfd_base != NULL) { for (i = 0; i < TX_BUF_NUM; i++) { if (lp->txfd_base[i].fd.FDSystem != 0x00000000) { skb = (struct sk_buff *) lp->txfd_base[i].fd. FDSystem; dev_kfree_skb_any(skb); } lp->txfd_base[i].fd.FDSystem = 0x00000000; } } /* free up the buffer list */ if (lp->rx_skbp != NULL) { for (i = 0; i < RX_BUF_NUM << 1; i++) { skb = lp->rx_skbp[i]; if (skb != NULL) dev_kfree_skb_any(skb); } kfree(lp->rx_skbp); } /* free the descriptor area. Move FD_base back to KSEG0 before freeing it. */ if (lp->FD_base != NULL) kfree(KSEG0ADDR(lp->FD_base)); /* nullify all the pointers and zero out the queue space */ lp->FD_base = NULL; lp->rxfd_base = NULL; lp->rxfd_curr = NULL; lp->txfd_base = NULL; lp->blfd_ptr = NULL; lp->rx_skbp = NULL; lp->tx_head = lp->tx_tail = 0; atomic_set(&lp->tx_qspc, 0);}/************************************************************************** * Do a safe soft restart of the device. This *will* cause packet loss, so * it's only used as a recovery mechanism */static void mspeth_soft_restart(struct net_device *dev){ int flags; struct mspeth_local *lp = (struct mspeth_local *) dev->priv; printk("MSPETH (soft_restart) %s: Soft device restart\n", dev->name); netif_stop_queue(dev); /* please don't interrupt me while I'm resetting everything */ local_irq_save(flags); /* Try to restart the adaptor. */ mspeth_mac_reset(dev); mspeth_clear_queues(dev); mspeth_mac_init(dev); //if (!(lp->option & MSP_OPT_SWITCH)) mspeth_phy_init(dev); /* turn back on the interrupts */ local_irq_restore(flags); /* and start up the queue! We should be fixed .... */ dev->trans_start = jiffies; netif_wake_queue(dev);}/************************************************************************** * Do a *hard* restart of the device. This *will* cause packet loss, so * it's only used as a recovery mechanism */static void mspeth_hard_restart(struct net_device *dev){ int flags; struct mspeth_local *lp = (struct mspeth_local *) dev->priv; printk("MSPETH (hard_restart) %s: Hard device restart\n", dev->name); netif_stop_queue(dev); /* please don't interrupt me while I'm resetting everything */ local_irq_save(flags); /* Try to restart the adaptor. */ mspeth_mac_reset(dev); if (!(lp->option & MSP_OPT_SWITCH)) mspeth_phy_reset(dev); mspeth_free_queues(dev); mspeth_queue_init(dev); mspeth_mac_init(dev); //if (!(lp->option & MSP_OPT_SWITCH)) mspeth_phy_init(dev); /* turn back on the interrupts */ local_irq_restore(flags); /* and start up the queue! We should be fixed .... */ dev->trans_start = jiffies; netif_wake_queue(dev);}static void time_out(){ int i=0;//added by Shi -> int j = 0;//added by Shi <- //macTimer_on = 0; //del_timer(&macTimer); if(jiffies-stime>=TIME_OUT) { for(i=0;i<MAX_COUNT;i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -