Xilinx PowerPC
Subsystems (2)
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.
Quoted 27 lines · Grant Likely
Quoted 9 lines · David H. Lynch Jr.
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/configDo 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.
Quoted 3 lines
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.
Signature · 8 lines
Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 [email protected] 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
I have the start of a lltemac based on the new XPS_LL_TEMAC from EDK 9.2. I'm currently in the process of upgrading my design to 9.2. So I will be very much interested in the driver working ;).
I'll see what I can get cleaned up and posted somewhere, if you'd like to take a look at it.
-- Mike
(sorry for the double post, if it happens but it seems that my last e-mail was blank per my records.)=20
-----Original Message-----
From: David H. Lynch Jr. [mailto:[email protected]]=20
Sent: Sunday, April 20, 2008 7:49 PM
To: Grant Likely
Cc: linuxppc-embedded
Subject: Re: Xilinx PowerPC
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.
=20
Quoted 1 line · Grant Likely
On Sun, Apr 20, 2008 at 2:31 PM, David H. Lynch Jr. <[email protected]>
Quoted 18 lines · wrote:
=20
Quoted 9 lines
Thanks.
I am running linus's 2.6.25-rc9, but I can pull the Xilinx tree=20
or yours - when your server is up.I can not find any Xilinx powerpc configs in
arch/powerpc/configDo I just need to do a
make ARCH=3Dpowerpc menuconfig and create one from scratch ?
=20That's right; I haven't merged any defconfigs. Roll your own.
=20
Quoted 3 lines
Is simpleboot in your tree or the xilinx tree, if can not find=20
it in Linus's ?
=20
Quoted 8 lines
If you want to use the "simpleboot" wrapper; then you'll need to pull=20 paulus' tree (Linus hasn't yet pulled his tree; but he probably will=20 any moment now).
Cheers,
g.=20
--=20
Dave Lynch DLA Systems
Software Development: Embedded Linux
717.627.3770 [email protected] 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
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 <linux/autoconf.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/in.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <platforms/4xx/xparameters/xparameters.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <net/sock.h>
#include <net/checksum.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/percpu.h>
#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_txps_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_txps_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-Quoted 1 line
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");
Quoted 3 lines
Thanks,
I have alot of work to do on our stuff, I might as well see if I
can
Quoted 5 lines
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.
Quoted 12 lines
I would be happy to help advance the ball on anything anyone has
started.Quoted 1 line · Grant Likely
On Sun, Apr 20, 2008 at 2:31 PM, David H. Lynch Jr. <[email protected]
Quoted 4 lines · wrote:
Quoted 4 lines
Thanks.
I am running linus's 2.6.25-rc9, but I can pull the Xilinx tree
or
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
yours - when your server is up.
I can not find any Xilinx powerpc configs in
arch/powerpc/
config
Quoted 8 lines
Quoted 8 lines
Quoted 3 lines
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.
Quoted 1 line
Is simpleboot in your tree or the xilinx tree, if can not find
it
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines
in Linus's ?
If you want to use the "simpleboot" wrapper; then you'll need to
pull
Quoted 15 lines
Quoted 7 lines
paulus' tree (Linus hasn't yet pulled his tree; but he probably will any moment now).
Cheers,
g.Signature · 5 lines
Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 [email protected] 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.
Quoted 2 lines
"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."
Quoted 7 lines
Albert Einstein
_______________________________________________
Linuxppc-embedded mailing list
[email protected]
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 [email protected] HTTP http://www.co-nss.co.jp/
------------------------------------------------------------------
I would be ecstatic to look at/collaborate on what you have.
I do not care if you clean it up. It can not be harder to work with than my own code or the Xilinx code.
In the end I need Linux, GreenHills, as well as a lightweight stripped driver for a monitor and embedded mini-web server.
I have all the above for the older PLB TEMAC in FIFO mode, but we are moving to the LL TEMAC.
I started through the xilinx code and rapidly remembered how long it took to demacrofy the xilinx PLB TEMAC code down to a single source file with only
the code actually needed, and got depressed.
This is critical to us now, so I can put time into it.
If I can figure out how to bring up a git server on my hosting service I am willing to host work on this -
though one of the existing trees might be a better choice.
Quoted 70 lines · Mike (Mission Systems)
I have the start of a lltemac based on the new
XPS_LL_TEMACfrom EDK 9.2. I'm currently in the process of upgrading my design to 9.2. So I will be very much interested in the driver working ;).I'll see what I can get cleaned up and posted somewhere, if you'd like to take a look at it.
-- Mike
(sorry for the double post, if it happens but it seems that my last e-mail was blank per my records.)
-----Original Message-----
From: David H. Lynch Jr. [mailto:[email protected]]
Sent: Sunday, April 20, 2008 7:49 PM
To: Grant Likely
Cc: linuxppc-embedded
Subject: Re: Xilinx PowerPCThanks,
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.Quoted 2 lines · Grant Likely
On Sun, Apr 20, 2008 at 2:31 PM, David H. Lynch Jr. <[email protected]>
Quoted 29 lines · wrote:
Quoted 12 lines
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/configDo 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.
Quoted 4 lines
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.
Signature · 8 lines
Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 [email protected] 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
Thanks alot.
On quick review this looks great. I will see if I can get it working for me this weekend.
Quoted 12 lines · Yoshio Kashiwagi
Hi,
I am writing the Non-Xilinx
XPS_LL_TEMACdriver.
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
Signature · 8 lines
Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 [email protected] 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
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.
Quoted 989 lines · Yoshio Kashiwagi
Hi,
I am writing the Non-Xilinx
XPS_LL_TEMACdriver.
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 <
linux/autoconf.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/in.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <platforms/4xx/xparameters/xparameters.h>#include <
linux/inet.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <net/sock.h>
#include <net/checksum.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/percpu.h>#define
S_DMA_CTRL_BASEADDRXPAR_LLTEMAC_0_LLINK_CONNECTED_BASEADDR
#defineXPS_LLTEMAC_BASEADDRXPAR_LLTEMAC_0_BASEADDR/*
XPS_LL_TEMACSDMA 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_REG0x18
#defineTX_CHNL_STS0x1c#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_REG0x38
#defineRX_CHNL_STS0x3c#define
DMA_CONTROL_REG0x40/*
XPS_LL_TEMACdirect 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_TEMACindirect registers offset definition */#define RCW0
0x200
#define RCW10x240
#define TC0x280
#define FCC0x2c0
#define EMMC0x300
#define PHYC0x320
#define MC0x340#define UAW0 0x380 #define UAW1 0x384 #define MAW0 0x388 #define MAW1 0x38c#define AFM
0x390
#define TIS0x3a0
#define TIE0x3a4
#define MIIMWD0x3b0
#define MIIMAI0x3b4#define CNTLREG_WRITE_ENABLE_MASK 0x8000 #define CNTLREG_EMAC1SEL_MASK 0x0400 #define CNTLREG_ADDRESSCODE_MASK 0x03ff#define
MDIO_ENABLE_MASK0x40
#defineMDIO_CLOCK_DIV_MASK0x3F
#defineMDIO_CLOCK_DIV_100MHz0x28#define
ETHER_MTU1500
#defineEMAC_PHY_ID7/* CDMAC descriptor status bit definitions */
#define
BDSTAT_ERROR_MASK0x80000000
#defineBDSTAT_INT_ON_END_MASK0x40000000
#defineBDSTAT_STOP_ON_END_MASK0x20000000#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_SIZE6
#defineTEMAC_MTU1500
#defineTEMAC_JUMBO_MTU9000
#defineTEMAC_HDR_SIZE14
#defineTEMAC_HDR_VLAN_SIZE18
#defineTEMAC_TRL_SIZE4
#defineTEMAC_MAX_FRAME_SIZE(TEMAC_MTU+TEMAC_HDR_SIZE+TEMAC_TRL_SIZE)
#defineTEMAC_MAX_VLAN_FRAME_SIZE(TEMAC_MTU+TEMAC_HDR_VLAN_SIZE+TEMAC_TRL_SIZE)
#defineTEMAC_MAX_JUMBO_FRAME_SIZE(TEMAC_JUMBO_MTU+TEMAC_HDR_SIZE+TEMAC_TRL_SIZE)#define
TX_CONTROL_CALC_CSUM_MASK1#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
#defineBUFFER_ALIGN(adr)((ALIGNMENT - ((u32) adr)) % ALIGNMENT)#define
MULTICAST_CAM_TABLE_NUM4#define
TX_BD_NUM64
#defineRX_BD_NUM128#define
XEM_MAX_FRAME_SIZETEMAC_MAX_JUMBO_FRAME_SIZE#define
XILINX_GSRD3_NAPI#define
sdma_reg_write(dev, offset, value)(*(unsigned int *)(dev->sdma_reg_base+ offset) = value)
#definesdma_reg_read(dev, offset)(*(volatile unsigned int *)(dev->sdma_reg_base+ offset))
#definetemac_reg_write(dev, offset, value)(*(unsigned int *)(dev->temac_reg_base+ offset) = value)
#definetemac_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;
staticcdmac_rx_bd*cdmac_rx_bd_virt_p;
staticcdmac_tx_bd*cdmac_tx_bd_phys_p;
staticcdmac_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 intnext_tx_bd= 0;
static volatile inttail_tx_bd= 0;
static intcur_rx_bd= 0;static struct
net_device*dev_list= NULL;
staticspinlock_tdev_lock;
staticspinlock_trcv_lock;
staticspinlock_txmt_lock;static int
xps_ll_temac_xmit(struct sk_buff *skb, struct net_device *dev);
static structnet_device_stats*xps_ll_temac_get_stats(structnet_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(structnet_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(structnet_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_txps_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_txps_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(structnet_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(structcdmac_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
__initxps_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-Quoted 2 lines
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
__initxps_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
__exitxps_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");Quoted 4 lines
Thanks,
I have alot of work to do on our stuff, I might as well see if I
can
Quoted 10 lines
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.Quoted 12 lines
Quoted 2 lines · Grant Likely
On Sun, Apr 20, 2008 at 2:31 PM, David H. Lynch Jr. <[email protected]
Quoted 6 lines · wrote:
Quoted 6 lines
Thanks.
I am running linus's 2.6.25-rc9, but I can pull the Xilinx tree
or
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
yours - when your server is up.
I can not find any Xilinx powerpc configs in
arch/powerpc/config
Quoted 10 lines
Quoted 10 lines
Quoted 4 lines
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.
Quoted 2 lines
Is simpleboot in your tree or the xilinx tree, if can not find
it
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
in Linus's ?
If you want to use the "simpleboot" wrapper; then you'll need to
pull
Quoted 15 lines
Quoted 8 lines
paulus' tree (Linus hasn't yet pulled his tree; but he probably will any moment now).
Cheers,
g.Signature · 5 lines
Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 [email protected] http://www.dlasys.net fax: 1.253.369.9244 Cell: 1.717.587.7774 Over 25 years' experience in platforms, languages, and technologiestoo numerous to list.
Quoted 2 lines
"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."
Quoted 8 lines
Albert Einstein
_______________________________________________
Linuxppc-embedded mailing list
[email protected]
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 [email protected] HTTP http://www.co-nss.co.jp/
------------------------------------------------------------------
Signature · 8 lines
Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 [email protected] 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
David-san,
This driver must add some corrections, for example, Checksum-offloading is incomplete as you say it. As for me, it is very happy to obtain your cooperation. Let me know if I can be of any work for it.
Moreover, although I wrote the xps_ll_temac driver for u-boot of a very simple single SDMA descriptor, I have not got used and put in the contribution way.
Best Regards,
Yoshio Kashiwagi - Nissin Systems
Quoted 11 lines
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.
I am preparing my own version of Yoshio's driver. Since most of my changes are re-ordering, renaming, or other items of small consequence, I will leave Yoshio as the author - unless he prefers otherwise.
I hope to have it ready to submit as a patch in a few days. If Yoshio is unhappy with any of the changes I have made or chooses to submit his original code or some permutation I will withdrawl mine.
While adding OF checksum offloading, ... would be nice,
All I am looking to do is get something that can start its way into the kernel.
This driver is working for me - with very light testing so far.
If no one else is willing to Shepard something in, then I will try. Hints, clues, etc would be very much appreciated.
I presume that if this driver is acceptable here, the next step would be forwarding it to linux-netdev ?
Quoted 12 lines · Yoshio Kashiwagi
David-san,
This driver must add some corrections, for example, Checksum-offloading is incomplete as you say it. As for me, it is very happy to obtain your cooperation. Let me know if I can be of any work for it.
Moreover, although I wrote the
xps_ll_temacdriver for u-boot of a very simple single SDMA descriptor, I have not got used and put in the contribution way.Best Regards,
Yoshio Kashiwagi - Nissin Systems
Signature · 8 lines
Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 [email protected] 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
Quoted 13 lines · David H. Lynch Jr.
I am preparing my own version of Yoshio's driver. Since most of my changes are re-ordering, renaming, or other items of small consequence, I will leave Yoshio as the author - unless he prefers otherwise.
I hope to have it ready to submit as a patch in a few days. If Yoshio is unhappy with any of the changes I have made or chooses to submit his original code or some permutation I will withdrawl mine.
While adding OF checksum offloading, ... would be nice,
All I am looking to do is get something that can start its way into the kernel.
This driver is working for me - with very light testing so far.
Quoted 4 lines
If no one else is willing to Shepard something in, then I will try. Hints, clues, etc would be very much appreciated.
I presume that if this driver is acceptable here, the next step would be forwarding it to linux-netdev ?
When you have a patch ready, post it both to here (linuxppc-dev) and to netdev. I'll provide review and help. Most likely when it is ready it will go in through jgarzik's tree, but if Jeff prefers, it can go in via my Virtex tree. Make sure you're able to generate and send clean patches before you post it to the mailing lists (inline instead of attachment, no line wrapping, applies cleanly to head of tree). If you need help, email me directly, and you can even send test emails to me for me to check before posting to the list.
It doesn't have to be perfect before you submit, but you do need to be prepared to respond to comments quickly and expect to respin the patch several times.
Cheers,
g.
Quoted 26 lines
Quoted 6 lines · Yoshio Kashiwagi
David-san,
This driver must add some corrections, for example, Checksum-offloading is incomplete as you say it. As for me, it is very happy to obtain your cooperation. Let me know if I can be of any work for it.
Quoted 6 lines
Moreover, although I wrote the
xps_ll_temacdriver for u-boot of a very simple single SDMA descriptor, I have not got used and put in the contribution way.Best Regards,
Yoshio Kashiwagi - Nissin Systems--
Dave Lynch DLA Systems
Software Development: Embedded Linux
717.627.3770 [email protected] 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
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
David-san,
I posted this source code so that usage of SDMA could be shared. Probably this code will be able to be used also by Virtex-5 FXT. Since this source code is a reference level and start point as you say, it is happy that it is maintainable with people of this ML. I'll leave it in your hands about author.
Best Regards,
Yoshio Kashiwagi - Nissin Systems
Quoted 2 lines
I am preparing my own version of Yoshio's driver. Since most of my changes are re-ordering, renaming, or other items of small
consequence,
Quoted 8 lines
I will leave Yoshio as the author - unless he prefers otherwise.
I hope to have it ready to submit as a patch in a few days. If Yoshio is unhappy with any of the changes I have made or chooses to submit his original code or some permutation I will withdrawl mine.
While adding OF checksum offloading, ... would be nice, All I am looking to do is get something that can start its way into
the
Quoted 6 lines
kernel.
This driver is working for me - with very light testing so far.If no one else is willing to Shepard something in, then I will try. Hints, clues, etc would be very much appreciated.
I presume that if this driver is acceptable here, the next step would
be
Quoted 6 lines
forwarding it to linux-netdev ?
Quoted 3 lines · Yoshio Kashiwagi
David-san,
This driver must add some corrections, for example, Checksum-
offloading
Quoted 4 lines
Quoted 4 lines
is incomplete as you say it. As for me, it is very happy to obtain your cooperation. Let me know if I can be of any work for it.
Moreover, although I wrote the
xps_ll_temacdriver for u-boot of a
very
Quoted 12 lines
Quoted 5 lines
simple single SDMA descriptor, I have not got used and put in the contribution way.
Best Regards,
Yoshio Kashiwagi - Nissin SystemsSignature · 5 lines
Dave Lynch DLA Systems Software Development: Embedded Linux 717.627.3770 [email protected] 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.
Quoted 2 lines
"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."
Quoted 1 line
Albert Einstein
Quoted 7 lines · Yoshio Kashiwagi
David-san,
I posted this source code so that usage of SDMA could be shared. Probably this code will be able to be used also by Virtex-5 FXT. Since this source code is a reference level and start point as you say, it is happy that it is maintainable with people of this ML. I'll leave it in your hands about author.
It is probably appropriate for David to maintain your copyright notice at the top of the file. Also, you should provide your "signed-off-by" line to confirm that there are no legal issues with you contributing your code (see Documentation/SubmittingPatches for details). Email it to Dave, and he should preserve your signed-off-by line when he posts his modified patch.
Cheers,
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.