From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from outbound-mail-24.bluehost.com (outbound-mail-24.bluehost.com [69.89.21.19]) by ozlabs.org (Postfix) with SMTP id AFC85DDED9 for ; Sun, 18 May 2008 01:36:49 +1000 (EST) Message-ID: <482EFB8F.9090402@dlasys.net> Date: Sat, 17 May 2008 11:36:47 -0400 From: "David H. Lynch Jr." MIME-Version: 1.0 To: Yoshio Kashiwagi Subject: Re: Xilinx PowerPC References: <480BA36D.1080000@dlasys.net> <480BA821.2030109@dlasys.net> <480BD66B.90001@dlasys.net> In-Reply-To: Content-Type: text/plain; charset=ISO-2022-JP Cc: linuxppc-embedded Reply-To: dhlii@dlasys.net List-Id: Linux on Embedded PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , I was able to incorporate Yoshio's driver and make use of it. It is a single file, fairly short, easy to understand, mostly conforming to linux kernel programming style. While it needs some work fo NAPI and OF, it is usable as it is. I would be happy to see it form the starting point for a distribution LL TEMAC driver. If Yoshio does not wish to put together a patch, for it I can, however, I have made some name changes and restructing to compare to my older PLB TEMAC. Yoshio Kashiwagi wrote: > Hi, > > I am writing the Non-Xilinx XPS_LL_TEMAC driver. > Checksum offloading is incomplete although NAPI and KGDBOE are supported. > Basic operation is working on EDK9.2 and EDK10.1. > > Furthermore, although the simple Non-Interrupt version for u-boot is > also written, it is not known where I should post. > > Best Regards, > > Yoshio Kashiwagi - Nissin Systems > > /* > * > * Xilinx Gigabit System Referece Design Ethenet driver > * > * Driver for Xilinx Virtex-4FX Based Platform > * > * Author: Yoshio Kashiwagi > * > * Copyright (c) 2008 Nissin Systems Co.,Ltd. > * > * March 2008 created > * > * This program is free software; you can redistribute it and/or modify > it > * under the terms of the GNU General Public License as published by > the > * Free Software Foundation; either version 2 of the License, or (at > your > * option) any later version. > * > */ > > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > #include > > #define S_DMA_CTRL_BASEADDR XPAR_LLTEMAC_0_LLINK_CONNECTED_BASEADDR > #define XPS_LLTEMAC_BASEADDR XPAR_LLTEMAC_0_BASEADDR > > /* XPS_LL_TEMAC SDMA registers definition */ > > #define TX_NXTDESC_PTR 0x00 > #define TX_CURBUF_ADDR 0x04 > #define TX_CURBUF_LENGTH 0x08 > #define TX_CURDESC_PTR 0x0c > #define TX_TAILDESC_PTR 0x10 > #define TX_CHNL_CTRL 0x14 > #define TX_IRQ_REG 0x18 > #define TX_CHNL_STS 0x1c > > #define RX_NXTDESC_PTR 0x20 > #define RX_CURBUF_ADDR 0x24 > #define RX_CURBUF_LENGTH 0x28 > #define RX_CURDESC_PTR 0x2c > #define RX_TAILDESC_PTR 0x30 > #define RX_CHNL_CTRL 0x34 > #define RX_IRQ_REG 0x38 > #define RX_CHNL_STS 0x3c > > #define DMA_CONTROL_REG 0x40 > > /* XPS_LL_TEMAC direct registers definition */ > > #define TEMAC_RAF0 0x00 > #define TEMAC_TPF0 0x04 > #define TEMAC_IFGP0 0x08 > #define TEMAC_IS0 0x0c > #define TEMAC_IP0 0x10 > #define TEMAC_IE0 0x14 > > #define TEMAC_MSW0 0x20 > #define TEMAC_LSW0 0x24 > #define TEMAC_CTL0 0x28 > #define TEMAC_RDY0 0x2c > > #define XTE_RSE_MIIM_RR_MASK 0x0002 > #define XTE_RSE_MIIM_WR_MASK 0x0004 > #define XTE_RSE_CFG_RR_MASK 0x0020 > #define XTE_RSE_CFG_WR_MASK 0x0040 > > /* XPS_LL_TEMAC indirect registers offset definition */ > > #define RCW0 0x200 > #define RCW1 0x240 > #define TC 0x280 > #define FCC 0x2c0 > #define EMMC 0x300 > #define PHYC 0x320 > #define MC 0x340 > #define UAW0 0x380 > #define UAW1 0x384 > #define MAW0 0x388 > #define MAW1 0x38c > #define AFM 0x390 > #define TIS 0x3a0 > #define TIE 0x3a4 > #define MIIMWD 0x3b0 > #define MIIMAI 0x3b4 > > #define CNTLREG_WRITE_ENABLE_MASK 0x8000 > #define CNTLREG_EMAC1SEL_MASK 0x0400 > #define CNTLREG_ADDRESSCODE_MASK 0x03ff > > #define MDIO_ENABLE_MASK 0x40 > #define MDIO_CLOCK_DIV_MASK 0x3F > #define MDIO_CLOCK_DIV_100MHz 0x28 > > #define ETHER_MTU 1500 > #define EMAC_PHY_ID 7 > > /* CDMAC descriptor status bit definitions */ > > #define BDSTAT_ERROR_MASK 0x80000000 > #define BDSTAT_INT_ON_END_MASK 0x40000000 > #define BDSTAT_STOP_ON_END_MASK 0x20000000 > #define BDSTAT_COMPLETED_MASK 0x10000000 > #define BDSTAT_SOP_MASK 0x08000000 > #define BDSTAT_EOP_MASK 0x04000000 > #define BDSTAT_CHANBUSY_MASK 0x02000000 > #define BDSTAT_CHANRESET_MASK 0x01000000 > > #define TEMAC_MAC_ADDR_SIZE 6 > #define TEMAC_MTU 1500 > #define TEMAC_JUMBO_MTU 9000 > #define TEMAC_HDR_SIZE 14 > #define TEMAC_HDR_VLAN_SIZE 18 > #define TEMAC_TRL_SIZE 4 > #define TEMAC_MAX_FRAME_SIZE (TEMAC_MTU + TEMAC_HDR_SIZE + TEMAC_ > TRL_SIZE) > #define TEMAC_MAX_VLAN_FRAME_SIZE (TEMAC_MTU + TEMAC_HDR_VLAN_SIZE + > TEMAC_TRL_SIZE) > #define TEMAC_MAX_JUMBO_FRAME_SIZE (TEMAC_JUMBO_MTU + TEMAC_HDR_SIZE + > TEMAC_TRL_SIZE) > > #define TX_CONTROL_CALC_CSUM_MASK 1 > > #define SDMA_MASTER_IRQ (1 << 7) > #define SDMA_COA_IRQ (1) > #define SDMA_DLY_IRQ (1 << 1) > #define SDMA_ERR_IRQ (1 << 2) > > #define ALIGNMENT 32 > #define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT) > > #define MULTICAST_CAM_TABLE_NUM 4 > > #define TX_BD_NUM 64 > #define RX_BD_NUM 128 > > #define XEM_MAX_FRAME_SIZE TEMAC_MAX_JUMBO_FRAME_SIZE > > #define XILINX_GSRD3_NAPI > > #define sdma_reg_write(dev, offset, value) (*(unsigned int *)(dev-> > sdma_reg_base + offset) = value) > #define sdma_reg_read(dev, offset) (*(volatile unsigned int *)(dev-> > sdma_reg_base + offset)) > #define temac_reg_write(dev, offset, value) (*(unsigned int *)(dev-> > temac_reg_base + offset) = value) > #define temac_reg_read(dev, offset) (*(volatile unsigned int *)(dev-> > temac_reg_base + offset)) > > struct net_local { > struct net_device_stats stats; > struct net_device *next_dev; > int index; > unsigned int sdma_reg_base; > unsigned int temac_reg_base; > int tx_irq; > int rx_irq; > struct timer_list phy_timer; > }; > > typedef struct cdmac_bd_t { > struct cdmac_bd_t *next_p; > unsigned char *phys_buf_p; > unsigned long buf_len; > unsigned long app0; > unsigned long app1; > unsigned long app2; > unsigned long app3; > unsigned long app4; > } cdmac_bd ; > > typedef struct cdmac_tx_bd_t { > cdmac_bd tx_bd[TX_BD_NUM]; > } cdmac_tx_bd ; > > typedef struct cdmac_rx_bd_t { > cdmac_bd rx_bd[RX_BD_NUM]; > } cdmac_rx_bd ; > > static cdmac_tx_bd *cdmac_tx_bd_virt_p; > static cdmac_rx_bd *cdmac_rx_bd_virt_p; > static cdmac_tx_bd *cdmac_tx_bd_phys_p; > static cdmac_rx_bd *cdmac_rx_bd_phys_p; > > static struct sk_buff *rx_skb[RX_BD_NUM]; > > static volatile int cur_tx_bd = 0; > static volatile int next_tx_bd = 0; > static volatile int tail_tx_bd = 0; > static int cur_rx_bd = 0; > > static struct net_device *dev_list = NULL; > static spinlock_t dev_lock; > static spinlock_t rcv_lock; > static spinlock_t xmt_lock; > > static int xps_ll_temac_xmit(struct sk_buff *skb, struct net_device *dev) > ; > static struct net_device_stats *xps_ll_temac_get_stats(struct net_device > *dev); > > static void xps_ll_temac_hostif_set(struct net_device *dev, int emac, > int phy_addr, int reg_addr, int phy_data) > { > struct net_local *lp = (struct net_local *)dev->priv; > > temac_reg_write(lp, TEMAC_LSW0, phy_data); > temac_reg_write(lp, TEMAC_CTL0, CNTLREG_WRITE_ENABLE_MASK | MIIMWD); > temac_reg_write(lp, TEMAC_LSW0, ((phy_addr << 5) | (reg_addr))); > temac_reg_write(lp, TEMAC_CTL0, CNTLREG_WRITE_ENABLE_MASK | MIIMAI | > (emac << 10)); > while(!(temac_reg_read(lp, TEMAC_RDY0) & XTE_RSE_MIIM_WR_MASK)); > } > > static unsigned int xps_ll_temac_hostif_get(struct net_device *dev, int > emac, int phy_addr, int reg_addr) > { > struct net_local *lp = (struct net_local *)dev->priv; > > temac_reg_write(lp, TEMAC_LSW0, ((phy_addr << 5) | (reg_addr))); > temac_reg_write(lp, TEMAC_CTL0, MIIMAI | (emac << 10)); > > while(!(temac_reg_read(lp, TEMAC_RDY0) & XTE_RSE_MIIM_RR_MASK)); > return temac_reg_read(lp, TEMAC_LSW0); > } > > static void xps_ll_temac_indirect_set(struct net_device *dev, int emac, > int reg_offset, int reg_data) > { > struct net_local *lp = (struct net_local *)dev->priv; > > temac_reg_write(lp, TEMAC_LSW0, reg_data); > temac_reg_write(lp, TEMAC_CTL0, (CNTLREG_WRITE_ENABLE_MASK | (emac < > < 10) | reg_offset)); > > while(!(temac_reg_read(lp, TEMAC_RDY0) & XTE_RSE_CFG_WR_MASK)); > } > > static void xps_ll_temac_phy_ctrl(struct net_device *dev) > { > unsigned int result; > > result = xps_ll_temac_hostif_get(dev, 0, EMAC_PHY_ID, 10); > if((result & 0x0800) == 0x0800) { > xps_ll_temac_indirect_set(dev, 0, EMMC, 0x80000000); > printk("1000BASE-T/FD\n"); > return; > } > result = xps_ll_temac_hostif_get(dev, 0, EMAC_PHY_ID, 5); > if((result & 0x0100) == 0x0100) { > xps_ll_temac_indirect_set(dev, 0, EMMC, 0x40000000); > printk("100BASE-T/FD\n"); > } else if((result & 0x0040) == 0x0040) { > xps_ll_temac_indirect_set(dev, 0, EMMC, 0x00000000); > printk("10BASE-T/FD\n"); > } else { > printk("Half Duplex not supported\n"); > } > } > > static int xps_ll_temac_set_address(struct net_device *dev, void *p) > { > struct sockaddr *sa = p; > > memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); > > xps_ll_temac_indirect_set(dev, 0, UAW0, (dev->dev_addr[0] & > 0x000000ff) | > ((dev->dev_addr[1] << 8) & 0x0000ff00) | > ((dev->dev_addr[2] << 16)& 0x00ff0000) | > ((dev->dev_addr[3] << 24) & 0xff000000)); > xps_ll_temac_indirect_set(dev, 0, UAW1, (dev->dev_addr[4] & > 0x000000ff) | > ((dev->dev_addr[5] << 8) & 0x0000ff00)); > > return 0; > } > > static void __set_rx_mode (struct net_device *dev) > { > unsigned long waddr_msw, waddr_lsw; > int i; > > if(dev->flags & IFF_PROMISC) { > printk(KERN_NOTICE "%s: Promiscuos mode enabled.\n", dev->name); > > xps_ll_temac_indirect_set(dev, 0, AFM, 0x80000000); > } else { > struct dev_mc_list *mclist; > for(i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; > i++, mclist = mclist->next) { > > if(i >= MULTICAST_CAM_TABLE_NUM) break; > waddr_msw = ((mclist->dmi_addr[3] << 24) | (mclist->dmi_ > addr[2] << 16) | > (mclist->dmi_addr[1] << 8) | mclist->dmi_addr[0]); > xps_ll_temac_indirect_set(dev, 0, MAW0, waddr_msw); > waddr_lsw = ((mclist->dmi_addr[5] << 8) | mclist->dmi_addr[4] > ); > waddr_lsw |= (i << 16); > xps_ll_temac_indirect_set(dev, 0, MAW1, waddr_lsw); > } > } > } > > static void xps_ll_temac_set_rx_mode (struct net_device *dev) > { > spin_lock(&dev_lock); > __set_rx_mode(dev); > spin_unlock(&dev_lock); > } > > static int xps_ll_temac_xmit_done(struct net_device *dev) > { > struct net_local *lp = (struct net_local *)dev->priv; > cdmac_bd *cur_p; > unsigned int stat = 0; > unsigned int flags; > > spin_lock_irqsave(&xmt_lock, flags); > > cur_p = &cdmac_tx_bd_virt_p->tx_bd[cur_tx_bd]; > stat = cur_p->app0; > > while(stat & BDSTAT_COMPLETED_MASK) { > pci_unmap_single(NULL, (unsigned long)cur_p->phys_buf_p, > cur_p->buf_len, PCI_DMA_TODEVICE); > if (cur_p->app4) > dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); > cur_p->app0 = 0; > > lp->stats.tx_packets++; > lp->stats.tx_bytes += cur_p->buf_len; > > cur_tx_bd++; > if (cur_tx_bd >= TX_BD_NUM) cur_tx_bd = 0; > > cur_p = &cdmac_tx_bd_virt_p->tx_bd[cur_tx_bd]; > stat = cur_p->app0; > } > > spin_unlock_irqrestore(&xmt_lock, flags); > > if(netif_queue_stopped(dev)) { > netif_wake_queue(dev); > } > } > > static int xps_ll_temac_xmit(struct sk_buff *skb, struct net_device *dev) > { > struct net_local *lp = (struct net_local *)dev->priv; > cdmac_bd *cur_p, *start_p, *tail_p; > int i; > unsigned long num_frag; > skb_frag_t *frag; > > spin_lock(&xmt_lock); > > num_frag = skb_shinfo(skb)->nr_frags; > frag = &skb_shinfo(skb)->frags[0]; > start_p = &cdmac_tx_bd_phys_p->tx_bd[tail_tx_bd]; > cur_p = &cdmac_tx_bd_virt_p->tx_bd[tail_tx_bd]; > > if(cur_p->app0 & BDSTAT_COMPLETED_MASK) { > if(!netif_queue_stopped(dev)) { > netif_stop_queue(dev); > spin_unlock(&xmt_lock); > return NETDEV_TX_BUSY; > } > return NETDEV_TX_BUSY; > } > > cur_p->app0 = 0; > if(skb->ip_summed == CHECKSUM_PARTIAL) { > const struct iphdr *ip = skb->nh.iph; > int length, start, insert, headlen; > > switch(ip->protocol) { > case IPPROTO_TCP: > start = sizeof(struct iphdr) + ETH_HLEN; > insert = sizeof(struct iphdr) + ETH_HLEN + 16; > length = ip->tot_len - sizeof(struct iphdr); > headlen = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct > tcphdr); > break; > case IPPROTO_UDP: > start = sizeof(struct iphdr) + ETH_HLEN; > insert = sizeof(struct iphdr) + ETH_HLEN + 6; > length = ip->tot_len - sizeof(struct iphdr); > headlen = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct > udphdr); > break; > default: > break; > } > cur_p->app1 = ((start << 16) | insert); > cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr, > length, ip->protocol, 0); > skb->data[insert] = 0; > skb->data[insert + 1] = 0; > } > cur_p->app0 |= BDSTAT_SOP_MASK; > cur_p->buf_len = skb_headlen(skb); > cur_p->phys_buf_p = (unsigned char *)pci_map_single(NULL, skb->data, > skb->len, PCI_DMA_TODEVICE); > cur_p->app4 = (unsigned long)skb; > > for(i = 0;i < num_frag;i++) { > tail_tx_bd++; > if (tail_tx_bd >= TX_BD_NUM) tail_tx_bd = 0; > > cur_p = &cdmac_tx_bd_virt_p->tx_bd[tail_tx_bd]; > cur_p->phys_buf_p = (unsigned char *)pci_map_single(NULL, > (void *)page_address(frag->page) + frag->page_offset, frag-> > size, PCI_DMA_TODEVICE); > cur_p->buf_len = frag->size; > cur_p->app0 = 0; > frag++; > } > cur_p->app0 |= BDSTAT_EOP_MASK; > > tail_p = &cdmac_tx_bd_phys_p->tx_bd[tail_tx_bd]; > tail_tx_bd++; > if (tail_tx_bd >= TX_BD_NUM) tail_tx_bd = 0; > > if(!(sdma_reg_read(lp, TX_CHNL_STS) & 2)) { > sdma_reg_write(lp, TX_CURDESC_PTR, start_p); > sdma_reg_write(lp, TX_TAILDESC_PTR, tail_p); // DMA start > } else { > } > > spin_unlock(&xmt_lock); > > return 0; > } > > static int xps_ll_temac_poll(struct net_device *dev, int *budget) > { > struct net_local *lp = (struct net_local *)dev->priv; > struct sk_buff *skb, *new_skb; > unsigned int bdstat; > unsigned long align; > cdmac_bd *cur_p, *tail_p; > int length; > unsigned long skb_vaddr; > unsigned int flags; > > tail_p = &cdmac_rx_bd_phys_p->rx_bd[cur_rx_bd]; > cur_p = &cdmac_rx_bd_virt_p->rx_bd[cur_rx_bd]; > > bdstat = cur_p->app0; > while((bdstat & BDSTAT_COMPLETED_MASK) && *budget > 0) { > > skb = rx_skb[cur_rx_bd]; > length = cur_p->app4; > > skb_vaddr = virt_to_bus(skb->data); > pci_unmap_single(NULL, skb_vaddr, length, PCI_DMA_FROMDEVICE); > > skb_put(skb, length); > skb->dev = dev; > skb->protocol = eth_type_trans(skb, dev); > skb->ip_summed = CHECKSUM_NONE; > > netif_receive_skb(skb); > dev->last_rx = jiffies; > > lp->stats.rx_packets++; > lp->stats.rx_bytes += length; > > new_skb = alloc_skb(XEM_MAX_FRAME_SIZE + ALIGNMENT, GFP_ATOMIC); > if(new_skb == 0) { > printk("no memory for new sk_buff\n"); > spin_unlock_irqrestore(&rcv_lock, flags); > return -ENOMEM; > } > > align = BUFFER_ALIGN(new_skb->data); > if(align) skb_reserve(new_skb, align); > > cur_p->app0 = BDSTAT_INT_ON_END_MASK; > cur_p->phys_buf_p = (unsigned char *) > pci_map_single(NULL, new_skb->data, > XEM_MAX_FRAME_SIZE, > PCI_DMA_FROMDEVICE); > cur_p->buf_len = XEM_MAX_FRAME_SIZE; > rx_skb[cur_rx_bd] = new_skb; > > cur_rx_bd++; > if(cur_rx_bd >= RX_BD_NUM) cur_rx_bd = 0; > > cur_p = &cdmac_rx_bd_virt_p->rx_bd[cur_rx_bd]; > bdstat = cur_p->app0 ; > (*budget)--; > } > > netif_rx_complete(dev); > sdma_reg_write(lp, RX_CHNL_CTRL, > sdma_reg_read(lp, RX_CHNL_CTRL) | SDMA_MASTER_IRQ); > sdma_reg_write(lp, RX_TAILDESC_PTR, tail_p); > > return 0; > } > > static void xps_ll_temac_recv(struct net_device *dev) > { > struct net_local *lp = (struct net_local *)dev->priv; > struct sk_buff *skb, *new_skb; > unsigned int bdstat; > unsigned long align; > cdmac_bd *cur_p, *tail_p; > int length; > unsigned long skb_vaddr; > unsigned int flags; > > spin_lock_irqsave(&rcv_lock, flags); > > tail_p = &cdmac_rx_bd_phys_p->rx_bd[cur_rx_bd]; > cur_p = &cdmac_rx_bd_virt_p->rx_bd[cur_rx_bd]; > > bdstat = cur_p->app0; > while((bdstat & BDSTAT_COMPLETED_MASK)) { > > skb = rx_skb[cur_rx_bd]; > length = cur_p->app4; > > skb_vaddr = virt_to_bus(skb->data); > pci_unmap_single(NULL, skb_vaddr, length, PCI_DMA_FROMDEVICE); > > skb_put(skb, length); > skb->dev = dev; > skb->protocol = eth_type_trans(skb, dev); > skb->ip_summed = CHECKSUM_NONE; > > netif_rx(skb); > > lp->stats.rx_packets++; > lp->stats.rx_bytes += length; > > new_skb = alloc_skb(XEM_MAX_FRAME_SIZE + ALIGNMENT, GFP_ATOMIC); > if(new_skb == 0) { > printk("no memory for new sk_buff\n"); > spin_unlock_irqrestore(&rcv_lock, flags); > return; > } > > align = BUFFER_ALIGN(new_skb->data); > if(align) skb_reserve(new_skb, align); > > cur_p->app0 = BDSTAT_INT_ON_END_MASK; > cur_p->phys_buf_p = (unsigned char *) > pci_map_single(NULL, new_skb->data, > XEM_MAX_FRAME_SIZE, > PCI_DMA_FROMDEVICE); > cur_p->buf_len = XEM_MAX_FRAME_SIZE; > rx_skb[cur_rx_bd] = new_skb; > > cur_rx_bd++; > if(cur_rx_bd >= RX_BD_NUM) cur_rx_bd = 0; > > cur_p = &cdmac_rx_bd_virt_p->rx_bd[cur_rx_bd]; > bdstat = cur_p->app0; > } > sdma_reg_write(lp, RX_TAILDESC_PTR, tail_p); > > spin_unlock_irqrestore(&rcv_lock, flags); > } > > static irqreturn_t > xps_ll_temac_tx_int(int irq, void * dev_id, struct pt_regs *regs) > { > unsigned int status; > struct net_device *dev = (struct net_device *)dev_id; > struct net_local *lp = (struct net_local *)dev->priv; > > status = sdma_reg_read(lp, TX_IRQ_REG); > sdma_reg_write(lp, TX_IRQ_REG, status); > > if(status & 3) xps_ll_temac_xmit_done(dev); > if(status & 0x080) printk("DMA error 0x%x\n", status); > > return IRQ_HANDLED; > } > > static irqreturn_t > xps_ll_temac_rx_int(int irq, void * dev_id, struct pt_regs *regs) > { > unsigned int status; > struct net_device *dev = (struct net_device *)dev_id; > struct net_local *lp = (struct net_local *)dev->priv; > > status = sdma_reg_read(lp, RX_IRQ_REG); > sdma_reg_write(lp, RX_IRQ_REG, status); > > #ifdef XPS_LL_TEMAC_NAPI > if(status & 1) { > if(likely(netif_rx_schedule_prep(dev))) { > sdma_reg_write(lp, RX_CHNL_CTRL, > sdma_reg_read(lp, RX_CHNL_CTRL) & ~SDMA_MASTER_IRQ); > __netif_rx_schedule(dev); > } > } > #else > if(status & 3) xps_ll_temac_recv(dev); > #endif > > return IRQ_HANDLED; > } > > static void xps_ll_temac_netpoll(struct net_device *dev) > { > //struct net_local *lp = (struct net_local *)dev->priv; > > disable_irq(XPAR_XPS_INTC_0_DDR_SDRAM_SDMA2_TX_INTOUT_INTR); > disable_irq(XPAR_XPS_INTC_0_DDR_SDRAM_SDMA2_RX_INTOUT_INTR); > > xps_ll_temac_rx_int(XPAR_XPS_INTC_0_DDR_SDRAM_SDMA2_RX_INTOUT_INTR, > dev, 0); > xps_ll_temac_tx_int(XPAR_XPS_INTC_0_DDR_SDRAM_SDMA2_TX_INTOUT_INTR, > dev, 0); > > enable_irq(XPAR_XPS_INTC_0_DDR_SDRAM_SDMA2_TX_INTOUT_INTR); > enable_irq(XPAR_XPS_INTC_0_DDR_SDRAM_SDMA2_RX_INTOUT_INTR); > } > > static struct net_device_stats *xps_ll_temac_get_stats(struct net_device > *dev) > { > return netdev_priv(dev); > } > > static int xps_ll_temac_init_descriptor(void) > { > struct sk_buff *skb; > unsigned long align; > int i; > > cdmac_tx_bd_virt_p = dma_alloc_coherent(NULL, sizeof(struct cdmac_ > tx_bd_t), > (dma_addr_t *)&cdmac_tx_bd_phys_p, GFP_KERNEL); > cdmac_rx_bd_virt_p = dma_alloc_coherent(NULL, sizeof(struct cdmac_ > rx_bd_t), > (dma_addr_t *)&cdmac_rx_bd_phys_p, GFP_KERNEL); > > for(i = 0;i < TX_BD_NUM;i++) { > memset((char *)&cdmac_tx_bd_virt_p->tx_bd[i], 0, sizeof(struct > cdmac_bd_t)); > if(i == (TX_BD_NUM - 1)) { > cdmac_tx_bd_virt_p->tx_bd[i].next_p = > &cdmac_tx_bd_phys_p->tx_bd[0]; > } else { > cdmac_tx_bd_virt_p->tx_bd[i].next_p = > &cdmac_tx_bd_phys_p->tx_bd[i + 1]; > } > } > for(i = 0;i < RX_BD_NUM;i++) { > memset((char *)&cdmac_rx_bd_virt_p->rx_bd[i], 0, sizeof(struct > cdmac_bd_t)); > if(i == (RX_BD_NUM - 1)) { > cdmac_rx_bd_virt_p->rx_bd[i].next_p = > &cdmac_rx_bd_phys_p->rx_bd[0]; > } else { > cdmac_rx_bd_virt_p->rx_bd[i].next_p = > &cdmac_rx_bd_phys_p->rx_bd[i + 1]; > } > skb = alloc_skb(XEM_MAX_FRAME_SIZE + ALIGNMENT, GFP_ATOMIC); > if(skb == 0) { > printk("alloc_skb error %d\n", i); > return -1; > } > rx_skb[i] = skb; > align = BUFFER_ALIGN(skb->data); > if(align) skb_reserve(skb, align); > > cdmac_rx_bd_virt_p->rx_bd[i].phys_buf_p = > (unsigned char *)pci_map_single(NULL, > skb->data, XEM_MAX_FRAME_SIZE, > PCI_DMA_FROMDEVICE); > cdmac_rx_bd_virt_p->rx_bd[i].buf_len = XEM_MAX_FRAME_SIZE; > cdmac_rx_bd_virt_p->rx_bd[i].app0 = BDSTAT_INT_ON_END_MASK; > } > > return 0; > } > > static int xps_ll_temac_changemtu(struct net_device *dev, int newmtu) > { > printk("[xilinx_enet]new MTU %d\n", newmtu); > dev->mtu = newmtu; > > return 0; > } > > static int xps_ll_temac_open(struct net_device *dev) > { > > return 0; > } > > static int xps_ll_temac_close(struct net_device *dev) > { > > return 0; > } > > static struct net_device **xps_ll_temacs; > > static int __init xps_ll_temac_init_one(int index) > { > struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); > struct net_local *lp; > int err = 0; > > if (!dev) return -ENOMEM; > > sprintf(dev->name, "eth%d", index); > > /* Initialize the device structure. */ > dev->get_stats = xps_ll_temac_get_stats; > dev->hard_start_xmit = xps_ll_temac_xmit; > dev->open = xps_ll_temac_open; > dev->stop = xps_ll_temac_close; > #ifdef XPS_LL_TEMAC_NAPI > dev->poll = &xps_ll_temac_poll; > #endif > dev->weight = 64; > dev->set_multicast_list = &xps_ll_temac_set_rx_mode; > dev->set_mac_address = xps_ll_temac_set_address; > dev->poll_controller = xps_ll_temac_netpoll; > > SET_MODULE_OWNER(dev); > #if 1 > // dev->features = NETIF_F_SG | NETIF_F_FRAGLIST > // | NETIF_F_IP_CSUM; > dev->features = NETIF_F_SG | NETIF_F_FRAGLIST; > #else > dev->features = NETIF_F_SG | NETIF_F_FRAGLIST > | NETIF_F_TSO | NETIF_F_IP_CSUM; > #endif > > ether_setup(dev); > > lp = (struct net_local *)dev->priv; > memset(lp, 0, sizeof(struct net_local)); > lp->index = index; > > lp->next_dev = dev_list; > lp->sdma_reg_base = ioremap(S_DMA_CTRL_BASEADDR, 128); > lp->temac_reg_base = ioremap(XPS_LLTEMAC_BASEADDR, 128); > > dev_list = dev; > > dev->tx_queue_len = 0; > dev->change_mtu = xps_ll_temac_changemtu; > > sdma_reg_write(lp, DMA_CONTROL_REG, 1); > > printk(KERN_INFO "%s: Xilinx Embedded Tri-Mode Ethernet MAC\n", dev- > >> name); >> > xps_ll_temac_init_descriptor(); > > dev->dev_addr[0] = 0x00; > dev->dev_addr[1] = 0x80; > dev->dev_addr[2] = 0x49; > dev->dev_addr[3] = 0x00; > dev->dev_addr[4] = 0x00; > dev->dev_addr[5] = 0x00; > > request_irq(XPAR_XPS_INTC_0_DDR_SDRAM_SDMA2_TX_INTOUT_INTR, > &xps_ll_temac_tx_int, 0, dev->name, dev); > request_irq(XPAR_XPS_INTC_0_DDR_SDRAM_SDMA2_RX_INTOUT_INTR, > &xps_ll_temac_rx_int, 0, dev->name, dev); > > xps_ll_temac_indirect_set(dev, 0, MC, MDIO_ENABLE_MASK | MDIO_CLOCK_ > DIV_100MHz); > > xps_ll_temac_indirect_set(dev, 0, RCW1, 0x10000000); // Enable > Receiver > xps_ll_temac_indirect_set(dev, 0, TC, 0x10000000); // Enable > Transmitter > xps_ll_temac_indirect_set(dev, 0, EMMC, 0x84000000); > > xps_ll_temac_indirect_set(dev, 0, UAW0, (dev->dev_addr[0] & > 0x000000ff) | > ((dev->dev_addr[1] << 8) & 0x0000ff00) | > ((dev->dev_addr[2] << 16)& 0x00ff0000) | > ((dev->dev_addr[3] << 24) & 0xff000000)); > xps_ll_temac_indirect_set(dev, 0, UAW1, (dev->dev_addr[4] & > 0x000000ff) | > ((dev->dev_addr[5] << 8) & 0x0000ff00)); > > xps_ll_temac_indirect_set(dev, 0, AFM, 0x00000000); > > xps_ll_temac_phy_ctrl(dev); > > sdma_reg_write(lp, TX_CHNL_CTRL, 0x10220483); > //sdma_reg_write(lp, TX_CHNL_CTRL, 0x00100483); > sdma_reg_write(lp, RX_CHNL_CTRL, 0xff010283); > > sdma_reg_write(lp, RX_CURDESC_PTR, (unsigned int)&cdmac_rx_bd_phys_ > p->rx_bd[0]); > sdma_reg_write(lp, RX_TAILDESC_PTR, (unsigned int)&cdmac_rx_bd_phys_ > p->rx_bd[RX_BD_NUM - 1]); > > if ((err = register_netdev(dev))) { > free_netdev(dev); > dev = NULL; > } else { > xps_ll_temacs[index] = dev; > } > > return 0; > } > > static void xps_ll_temac_free_one(int index) > { > unregister_netdev(xps_ll_temacs[index]); > free_netdev(xps_ll_temacs[index]); > } > > static int __init xps_ll_temac_init_module(void) > { > int err = 0; > > xps_ll_temacs = kmalloc(sizeof(void *), GFP_KERNEL); > > if (!xps_ll_temacs) return -ENOMEM; > > spin_lock_init(&dev_lock); > spin_lock_init(&rcv_lock); > spin_lock_init(&xmt_lock); > > if((err = xps_ll_temac_init_one(0))) xps_ll_temac_free_one(0); > > return err; > } > > static void __exit xps_ll_temac_cleanup_module(void) > { > xps_ll_temac_free_one(0); > kfree(xps_ll_temacs); > } > > module_init(xps_ll_temac_init_module); > module_exit(xps_ll_temac_cleanup_module); > MODULE_LICENSE("GPL"); > > > >> Thanks, >> >> I have alot of work to do on our stuff, I might as well see if I >> > can > >> move to the powerpc tree at the same time. >> >> BTW is there even the beginings of a non-xilinx lltemac driver out >> there ? There were hints on the list, but I have not seen anything. >> >> I would be happy to help advance the ball on anything anyone has >> started. >> >> >> >> Grant Likely wrote: >> >>> On Sun, Apr 20, 2008 at 2:31 PM, David H. Lynch Jr. >> >> wrote: >> >>> >>> >>>> Thanks. >>>> >>>> I am running linus's 2.6.25-rc9, but I can pull the Xilinx tree >>>> > or > >>>> yours - when your server is up. >>>> >>>> I can not find any Xilinx powerpc configs in arch/powerpc/ >>>> > config > >>>> Do I just need to do a >>>> make ARCH=powerpc menuconfig and create one from scratch ? >>>> >>>> >>> That's right; I haven't merged any defconfigs. Roll your own. >>> >>> >>> >>>> Is simpleboot in your tree or the xilinx tree, if can not find >>>> > it > >>>> in Linus's ? >>>> >>>> >>> If you want to use the "simpleboot" wrapper; then you'll need to >>> > pull > >>> paulus' tree (Linus hasn't yet pulled his tree; but he probably will >>> any moment now). >>> >>> Cheers, >>> g. >>> >>> >>> >> -- >> Dave Lynch DLA Systems >> Software Development: Embedded Linux >> 717.627.3770 dhlii@dlasys.net http://www.dlasys.net >> fax: 1.253.369.9244 Cell: 1.717.587.7774 >> Over 25 years' experience in platforms, languages, and technologies >> > too numerous to list. > >> "Any intelligent fool can make things bigger and more complex... It >> > takes a touch of genius - and a lot of courage to move in the opposite > direction." > >> Albert Einstein >> >> _______________________________________________ >> Linuxppc-embedded mailing list >> Linuxppc-embedded@ozlabs.org >> https://ozlabs.org/mailman/listinfo/linuxppc-embedded >> >> > ※ 4月から所属・部署が変更になりました > ------------------------------------------------------------------ > 柏木良夫 > 株式会社日新システムズ 東日本営業部 > > 本 社 〒600-8482 京都市下京区堀川通四条下ル東側 堀川四条ビル > TEL 075-344-7977 FAX 075-344-7887 > 東京事務所 〒101-0024 東京都千代田区神田和泉町1番地 神田和泉町ビル > TEL 03-5825-2081 FAX 03-5821-1259 > E-Mail kashiwagi@co-nss.co.jp HTTP http://www.co-nss.co.jp/ > ------------------------------------------------------------------ > > -- Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 dhlii@dlasys.net http://www.dlasys.net fax: 1.253.369.9244 Cell: 1.717.587.7774 Over 25 years' experience in platforms, languages, and technologies too numerous to list. "Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction." Albert Einstein