📄 pmcmspeth.c
字号:
int i; printk("print_eth(%08x)\n", (unsigned int) add); for (i = 0; i < 6; i++) printk(" %2.2X", (unsigned char) add[i + 6]); printk(" =>"); for (i = 0; i < 6; i++) printk(" %2.2X", (unsigned char) add[i]); printk(" : %2.2X%2.2X\n", (unsigned char) add[12], (unsigned char) add[13]);}/* Used mainly for debugging unusual conditions signalled by a * fatal error interrupt (eg, IntBLEx). This function stops the transmit * and receive in an attempt to capture the true state of the queues * at the time of the interrupt. */#undef MSPETH_DUMP_QUEUES#define MSPETH_DUMP_QUEUES #ifdef MSPETH_DUMP_QUEUES/* Catalog the received buffers numbers */static int rx_bdnums[2][RX_BUF_NUM << 2];static int rx_bdnums_ind[2] = {0, 0};static inline void catalog_rx_bdnum(int hwnum, int bdnum){ rx_bdnums_ind[hwnum] = (rx_bdnums_ind[hwnum] + 1) & ((RX_BUF_NUM<<2)-1); rx_bdnums[hwnum][rx_bdnums_ind[hwnum]] = bdnum;}static void mspeth_dump_queues(struct net_device *dev){ struct mspeth_local *lp = (struct mspeth_local *) dev->priv; struct mspeth_regs *tr = (struct mspeth_regs *) dev->base_addr; int unit = lp->unit; int i; /* Halt Xmit and Recv to preserve the state of queues */ /* write_mspreg (MAC_HaltReq, &tr->MAC_Ctl); */ write_mspreg(read_mspreg(&tr->Rx_Ctl) & ~Rx_RxEn, &tr->Rx_Ctl); write_mspreg(read_mspreg(&tr->Tx_Ctl) & ~Tx_En, &tr->Tx_Ctl); /* Print receive queue */ printk("Receive Queue\n"); printk("=============\n\n"); printk("rxfd_base = 0x%08x\n", (unsigned long) lp->rxfd_base); printk("rxfd_curr = 0x%08x\n", (unsigned long) lp->rxfd_curr); for (i = 0; i < RX_BUF_NUM; i++) { printk("%d:", i); dump_qdesc((struct Q_Desc *) &lp->rxfd_base[i]); } /* Print transmit queue */ printk("\nTransmit Queue\n"); printk("==============\n"); printk("txfd_base = 0x%08x\n", (unsigned long) lp->txfd_base); printk("tx_head = %d, tx_tail = %d\n", lp->tx_head, lp->tx_tail); for (i = 0; i < TX_BUF_NUM; i++) { printk("%d:", i); dump_qdesc((struct Q_Desc *) &lp->txfd_base[i]); } /* Print the free buffer list */ printk("\nFree Buffer List\n"); printk("================\n"); printk("blfd_ptr = 0x%08x\n", (unsigned long) lp->blfd_ptr); dump_blist(lp->blfd_ptr); /* Finally print the bdnum history and current index as a reference */ printk("\nbdnum history\n"); printk("=============\n"); for (i = 0; i < RX_BUF_NUM; i++) { printk("\t%d\t%d\t%d\t%d\n", rx_bdnums[unit][4*i], rx_bdnums[unit][4*i+1], rx_bdnums[unit][4*i+2], rx_bdnums[unit][4*i+3]); } printk("Current bdnum index: %d\n", rx_bdnums_ind[unit]); /* Re-enable Xmit/Recv */ write_mspreg(read_mspreg(&tr->Rx_Ctl) | Rx_RxEn, &tr->Rx_Ctl); write_mspreg(read_mspreg(&tr->Tx_Ctl) | Tx_En, &tr->Tx_Ctl);}static void mspeth_dump_stats(struct net_device *dev){ struct mspeth_local *lp = (struct mspeth_local *) dev->priv; printk("Interface stats:\n"); printk("\ttx_ints: %d\n", lp->lstats.tx_ints); printk("\trx_ints: %d\n", lp->lstats.rx_ints); printk("\ttx_full: %d\n", lp->lstats.tx_full); printk("\tfd_exha: %d\n", lp->lstats.fd_exha);}#else#define mspeth_dump_stats(a) do {} while (0)#define mspeth_dump_queues(a) do {} while (0)#define catalog_rx_bdnum(a,b) do {} while (0)#endif /* MSPETH_DUMP_QUEUES *///sxj add testvoidwan_pro_tasklet (unsigned long data){ struct net_device *dev,*first; struct sdata *vp = (struct sdata *) data; int i=0; read_lock(&dev_base_lock); while(1) { if(vp->nFlag[nrCur]==1) {/*if(vp->skb[nrCur]->len==1518){ vp->skb[nrCur]->len-=4;// for(i=0;i<vp->skb[nrCur]->len;i++)// printk("%02x " ,vp->skb[nrCur]->data[i]);// printk("\n");}*/ for(dev=dev_base;dev!=NULL;dev=dev->next) { if(vp->flag[nrCur]==0) { if(strcmp(dev->name,"eth1")==0) { first=dev; break; } } if(vp->flag[nrCur]==1) { if(strcmp(dev->name,"eth0")==0) { first=dev; break; } } } if(first!=NULL) { vp->skb[nrCur]->dev=first;//printk("send packet is %d\n",vp->skb[nrCur]->len); first->hard_start_xmit(vp->skb[nrCur],first); } else dev_kfree_skb(vp->skb[nrCur]); vp->nFlag[nrCur]=0; nrCur++; if(nrCur>=64) nrCur=0; } else break; } }/*############################################################################### ## Actual functions used in the driver are defined here. They should ## all start with mspeth ## ###############################################################################*//************************************************************************** * Check for an mspeth ethernet device and return 0 if there is one. Also * a good time to fill out some of the device fields and do some preliminary * initialization. The mspeth resources are statically allocated. */int __init mspeth_probe(struct net_device *dev){ int unit, hwunit; int i, irqval; u8 macaddr[20]; struct mspeth_local *lp; struct mspeth_regs *tr; //sxj add unsigned int sxj=0; //sxj add end /* determine what interface we think we are */ if (sscanf(dev->name, "eth%d", &unit) != 1) return -ENODEV; /* scan the hardware list and associate a logical unit with a hardware unit * it's important to keep these two straight. hwunit is used for accessing * the prom and all hardware. unit is used when parsing the commandline and * any other uses that might refer to *all* eth devices (not just mspeth devices) * in the system */ for (i = 0, hwunit = 0; hwunit < MSPETH_MAX_UNITS; hwunit++) { if (identify_enet(hwunit) != FEATURE_NOEXIST) { if (i++ == unit) break; } } /* hughesan 7/22/2005 - I should add some testing code to make sure that we don't * attempt to find/initialize the same device twice */ if (unit < 0 || hwunit >= MSPETH_MAX_UNITS) return -ENODEV; mspeth_debug = MSPETH_DEBUG;#ifdef CONFIG_PMC_STEIN /* make sure that macB is in reset and that we don't identify it */ if (hwunit == 1) { *(volatile unsigned int *) RST_SET_REG = STEIN_MAC1_RST; return -ENODEV; }#endif /* Retrieve the mac address from the PROM */ if (get_ethernet_addr(macname[hwunit], macaddr)) { printk(KERN_INFO " No Mac addr specified for eth%d %s\n", unit, macname[hwunit]); return -ENODEV; } if (macaddr[0] & 0x01) { printk(KERN_INFO "Bad Multicast Mac addr specified for eth%d " "%s %02x:%02x:%02x:%02x:%02x:%02x\n", unit, macname[hwunit], macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); return -ENODEV; } /* * The ethernet MACS have fixed interrupts and address spaces. Allocate * the interrupt vector now and reserve the address space. There is no * point in waiting since no other device can use the resources, and this * marks the irq as busy. Jumpered interrupts are typically not reported * by the boards. MAC 0 is fixed at IRQ 10, MAC 1 is fixed IRQ11 etc */ /* base address for register accesses */ dev->base_addr = MacBases[hwunit]; if (check_mem_region(dev->base_addr, MSPEthExtent)) return -ENODEV; if (!request_mem_region(dev->base_addr, MSPEthExtent, cardname)) { printk(KERN_WARNING "%s: unable to get memory/io address region %lx\n", dev->name, dev->base_addr); return -ENODEV; } /* IRQ reservation */ dev->irq = MacIRQs[hwunit]; irqval = request_irq(dev->irq, &mspeth_interrupt, SA_SAMPLE_RANDOM, cardname, dev); if (irqval) { printk(KERN_WARNING "%s: unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, irqval); return -ENODEV; } /* MAC address */ dev->addr_len = ETH_ALEN; for (i = 0; i < dev->addr_len; i++) dev->dev_addr[i] = macaddr[i]; /* perform the "once only* tasks like creating the proc entry and probing the phys */ if (root_mspeth_dev == NULL) { proc_net_create("pmcmspeth", 0, mspeth_proc_info); mspeth_phyprobe(); } /* do the default ethernet setup and then customize */ ether_setup(dev); /* Create & initialize the local device structure */ if (dev->priv == NULL) { dev->priv = kmalloc(sizeof(struct mspeth_local), GFP_KERNEL); if (dev->priv == NULL) return -ENODEV; } lp = (struct mspeth_local *) dev->priv; tr = (struct mspeth_regs *) dev->base_addr; /* zero out the local structure and start initializing */ memset(lp, 0, sizeof(struct mspeth_local)); lp->next_module = root_mspeth_dev; root_mspeth_dev = dev; /* set the logical and hardware units */ lp->unit = unit; lp->hwunit = hwunit; /* parse the environment and command line */ mspeth_init_cmdline(dev); mspeth_init_phyaddr(dev); /* determine speed and duplex settings */ if (lp->option & MSP_OPT_10M) { lp->speed = 10; } else { lp->speed = 100; } if (lp->option & MSP_OPT_FDUP) { lp->fullduplex = true; } else { lp->fullduplex = false; } /* configure the BRCTL RII registers if we're an RMII device */ if (identify_enet(hwunit) == ENET_RMII) { u32 brctl = read_mspreg(&tr->BCTRL_Reg) & ~RMII_Reset; if (identify_enetTxD(hwunit) == ENETTXD_RISING) brctl |= RMII_ClkRising; if (identify_enetTxD(hwunit) == ENETTXD_FALLING) brctl &= ~RMII_ClkRising; if (lp->speed == 10) brctl |= RMII_10MBIT; else brctl &= ~RMII_10MBIT; write_mspreg(brctl, &tr->BCTRL_Reg); } /* set the various call back functions */ dev->open = mspeth_open; dev->stop = mspeth_close; dev->tx_timeout = mspeth_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT * HZ; dev->hard_start_xmit = mspeth_send_packet; dev->get_stats = mspeth_get_stats; dev->set_multicast_list = mspeth_set_multicast_list; dev->do_ioctl = mspeth_do_ioctl; /* set some device structure parameters */ dev->tx_queue_len = TX_BUF_NUM; /* allocate and initialize the tasklets */ tasklet_init(&lp->rx_tasklet, mspeth_rx, (u32) dev); tasklet_init(&lp->tx_tasklet, mspeth_txdone, (u32) dev); /* hammtrev, 2005/12/08: * Adding a new BH handler to reset the device in response to BLEx. */ tasklet_init(&lp->hard_restart_tasklet, mspeth_hard_restart_bh, (u32) dev); /* debugging output */#ifndef MODULE { static u8 printed_version; if (!printed_version++) { printk(KERN_INFO "%s: %s, %s\n", drv_file, drv_version, drv_reldate); printk(KERN_INFO "%s: PMC-Sierra, www.pmc-sierra.com\n", drv_file); } }#endif /* !MODULE */ /* debugging output */ printk(KERN_INFO "MSPETH (probe) %s: found at address %lx, irq %d\n", dev->name, dev->base_addr, dev->irq); printk(KERN_INFO "MSPETH (probe) %s: assigned MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); if (mspeth_debug > 1) { printk(KERN_INFO "MSPETH (probe) %s: associated with hardware unit %d, %s\n", dev->name, hwunit, macname[hwunit]); printk(KERN_INFO "MSPETH (probe) %s: assigned MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); printk(KERN_INFO "MSPETH (probe) %s: phytype %c, phyclk %c, phyindex %d\n", dev->name, identify_enet(hwunit), identify_enetTxD(hwunit), lp->phyindex); } //sxj add sxj = read_mspphyreg(21, 22); sxj|=0x0001; write_mspphyreg(sxj, 21, 22); sxj = read_mspphyreg(21, 22); //add test port 0 is bridge for(sxj=0;sxj<4;sxj++) { nFlag[sxj+1]=0; tempdata[sxj]=0; } //sxj use test/* nFlag[2]=1; nFlag[4]=1;*/ nrCur=0; nwCur=0; tasklet_init(&wan_tasklet, wan_pro_tasklet, (unsigned long)&data) ; //sxj add end return 0;}/************************************************************************** * Scan the environment and fill the phyaddresses */static void __init mspeth_init_phyaddr(struct net_device *dev){ struct mspeth_local *lp = (struct mspeth_local *) dev->priv; int hwindex; int phyindex; int phyaddr; char *phystr; char name[80]; /* default phy index */ lp->phyindex = 0; /* new style enviroment scan to determine the phy addresses */ sprintf(name, "phyaddr%d", lp->hwunit); phystr = prom_getenv(name); if (mspeth_debug > 0) { printk( "MSPETH (init_phyaddr) %s: hwunit = %d, phystr prom = \"%s\"\n", dev->name, lp->hwunit, phystr); } if (phystr != NULL && sscanf(phystr, "%d:%d", &hwindex, &phyaddr) == 2 && hwindex < MSPETH_MAX_UNITS && (phyaddr < MD_MAX_PHY || phyaddr == MD_DYNAMIC_PHY)) { /* look through the phylist and find a phy that matches the PROM settings */ for (phyindex = 0; phyindex < MSPETH_MAX_UNITS; phyindex++) { if (phy_ctrl[phyindex].hwindex == hwindex && phy_ctrl[phyindex].phyaddr == phyaddr) { if (phy_ctrl[phyindex].assigned) { printk(KERN_WARNING "MSPETH (init_phyaddr) %s: PROM phyaddress is already in use!\ phystr prom = \"%s\"\n", dev->name, phystr); } else { lp->phyindex = phyindex; phy_ctrl[phyindex].assigned = true; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -