Line 141... |
Line 141... |
int rx_wakeup_thr;
|
int rx_wakeup_thr;
|
unsigned char mac[ETH_ALEN];
|
unsigned char mac[ETH_ALEN];
|
struct net_device * dev;
|
struct net_device * dev;
|
} slave_data;
|
} slave_data;
|
|
|
/*
|
/* Auxiliary inline functions */
|
* The array pkts holds the number of set, from which we expect the particulal packet
|
static inline uint16_t get_be_u16(char * buf)
|
* (so we can safely start with this array filled with zeroes).
|
{
|
* After the packet is sent and acknowledged, we increase the number corresponding
|
return be16_to_cpu(*(uint16_t *)buf);
|
* to this packet.
|
}
|
* At each moment this table may be filled with two different values - n, and n+1
|
|
* because we service two consecutive sets
|
static inline uint32_t get_be_u32(char * buf)
|
*/
|
{
|
|
return be32_to_cpu(*(uint32_t *)buf);
|
|
}
|
|
|
|
static inline uint64_t get_be_u64(char * buf)
|
|
{
|
|
return be64_to_cpu(*(uint64_t *)buf);
|
|
}
|
|
|
|
static inline void put_skb_u16(struct sk_buff * skb, uint16_t val)
|
|
{
|
|
char * data = skb_put(skb,sizeof(val));
|
|
* (uint16_t *) data = cpu_to_be16(val);
|
|
}
|
|
|
|
static inline void put_skb_u32(struct sk_buff * skb, uint32_t val)
|
|
{
|
|
char * data = skb_put(skb,sizeof(val));
|
|
* (uint32_t *) data = cpu_to_be32(val);
|
|
}
|
|
|
|
static inline void put_skb_u64(struct sk_buff * skb, uint64_t val)
|
|
{
|
|
char * data = skb_put(skb,sizeof(val));
|
|
* (uint64_t *) data = cpu_to_be64(val);
|
|
}
|
|
|
static slave_data * slave_table = NULL;
|
static slave_data * slave_table = NULL;
|
|
|
static int my_proto_rcv(struct sk_buff * skb, struct net_device * dev, struct packet_type * pt,
|
static int my_proto_rcv(struct sk_buff * skb, struct net_device * dev, struct packet_type * pt,
|
struct net_device * orig_dev);
|
struct net_device * orig_dev);
|
|
|
Line 266... |
Line 292... |
// Based on http://lxr.linux.no/#linux+v3.3.4/net/ipv4/arp.c#L586 !
|
// Based on http://lxr.linux.no/#linux+v3.3.4/net/ipv4/arp.c#L586 !
|
if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0) {
|
if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0) {
|
kfree_skb(newskb);
|
kfree_skb(newskb);
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
my_data = skb_put(newskb,4);
|
|
//Put the protocol version id to the packet
|
//Put the protocol version id to the packet
|
*(my_data++) = (MY_PROTO_VER>>8) & 0xff;
|
put_skb_u16(newskb,MY_PROTO_VER);
|
*(my_data++) = (MY_PROTO_VER & 0xff);
|
|
//Put the "start" command to the packet
|
//Put the "start" command to the packet
|
*(my_data++) = 0;
|
put_skb_u16(newskb,0x01);
|
*(my_data++) = 1;
|
|
my_data = skb_put(newskb,MY_ACK_LEN - 4);
|
my_data = skb_put(newskb,MY_ACK_LEN - 4);
|
memset(my_data,0xa5,MY_ACK_LEN - 4);
|
memset(my_data,0xa5,MY_ACK_LEN - 4);
|
#ifdef FADE_DEBUG
|
#ifdef FADE_DEBUG
|
printk(KERN_INFO "skb_nh: %x, skb_dt: %x, skb_nh2: %x, skb_t: %x\n tail: %d head: %d\n",(int)skb_network_header(newskb),(int)newskb->data,
|
printk(KERN_INFO "skb_nh: %x, skb_dt: %x, skb_nh2: %x, skb_t: %x\n tail: %d head: %d\n",(int)skb_network_header(newskb),(int)newskb->data,
|
(int)newskb->network_header,(int)newskb->tail, (int)sd->tail, (int)sd->head) ;
|
(int)newskb->network_header,(int)newskb->tail, (int)sd->tail, (int)sd->head) ;
|
Line 351... |
Line 374... |
// Based on http://lxr.linux.no/#linux+v3.3.4/net/ipv4/arp.c#L586 !
|
// Based on http://lxr.linux.no/#linux+v3.3.4/net/ipv4/arp.c#L586 !
|
if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0) {
|
if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0) {
|
kfree_skb(newskb);
|
kfree_skb(newskb);
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
my_data = skb_put(newskb,4);
|
|
//Put the protocol version id to the packet
|
//Put the protocol version id to the packet
|
*(my_data++) = (MY_PROTO_VER>>8) & 0xff;
|
put_skb_u16(newskb,MY_PROTO_VER);
|
*(my_data++) = (MY_PROTO_VER & 0xff);
|
|
//Put the "stop" command to the packet
|
//Put the "stop" command to the packet
|
*(my_data++) = 0;
|
put_skb_u16(newskb,0x05);
|
*(my_data++) = 5;
|
|
my_data = skb_put(newskb,MY_ACK_LEN - 4);
|
my_data = skb_put(newskb,MY_ACK_LEN - 4);
|
memset(my_data,0xa5,MY_ACK_LEN - 4);
|
memset(my_data,0xa5,MY_ACK_LEN - 4);
|
#ifdef FADE_DEBUG
|
#ifdef FADE_DEBUG
|
printk(KERN_INFO "skb_nh: %x, skb_dt: %x, skb_nh2: %x, skb_t: %x\n tail: %d head: %d\n",(int)skb_network_header(newskb),(int)newskb->data,
|
printk(KERN_INFO "skb_nh: %x, skb_dt: %x, skb_nh2: %x, skb_t: %x\n tail: %d head: %d\n",(int)skb_network_header(newskb),(int)newskb->data,
|
(int)newskb->network_header,(int)newskb->tail, (int)sd->tail, (int)sd->head) ;
|
(int)newskb->network_header,(int)newskb->tail, (int)sd->tail, (int)sd->head) ;
|
Line 407... |
Line 427... |
if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0)
|
if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0)
|
{
|
{
|
kfree_skb(newskb);
|
kfree_skb(newskb);
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
my_data = skb_put(newskb,10);
|
|
//Put the protocol version id to the packet
|
//Put the protocol version id to the packet
|
*(my_data++) = (MY_PROTO_VER>>8) & 0xff;
|
put_skb_u16(newskb,MY_PROTO_VER);
|
*(my_data++) = (MY_PROTO_VER & 0xff);
|
|
//Put the command code
|
//Put the command code
|
*(my_data++) = (ucmd.cmd>>8) & 0xff;
|
put_skb_u16(newskb,ucmd.cmd);
|
*(my_data++) = (ucmd.cmd & 0xff);
|
|
//Put the sequence number
|
//Put the sequence number
|
*(my_data++) = (sd->cmd_seq>>8) & 0xff;
|
put_skb_u16(newskb,sd->cmd_seq);
|
*(my_data++) = (sd->cmd_seq & 0xff);
|
|
//Put the argument
|
//Put the argument
|
*(my_data++) = (ucmd.arg>>24) & 0xff;
|
put_skb_u32(newskb,ucmd.arg);
|
*(my_data++) = (ucmd.arg>>16) & 0xff;
|
|
*(my_data++) = (ucmd.arg>>8) & 0xff;
|
|
*(my_data++) = (ucmd.arg & 0xff);
|
|
//Fill the packet
|
//Fill the packet
|
my_data = skb_put(newskb,MY_ACK_LEN-10);
|
my_data = skb_put(newskb,MY_ACK_LEN-10);
|
memset(my_data,0xa5,MY_ACK_LEN-10);
|
memset(my_data,0xa5,MY_ACK_LEN-10);
|
dev_queue_xmit(newskb);
|
dev_queue_xmit(newskb);
|
//Sleep with short timeout, waiting for response
|
//Sleep with short timeout, waiting for response
|
Line 643... |
Line 656... |
newskb->protocol = htons(MY_PROTO_ID);
|
newskb->protocol = htons(MY_PROTO_ID);
|
//Build the MAC header for the new packet
|
//Build the MAC header for the new packet
|
// Here is shown how to build a packet: http://lxr.linux.no/linux+*/net/ipv4/arp.c#L586
|
// Here is shown how to build a packet: http://lxr.linux.no/linux+*/net/ipv4/arp.c#L586
|
if (dev_hard_header(newskb,dev,MY_PROTO_ID,&rcv_hdr->h_source,&rcv_hdr->h_dest,MY_ACK_LEN+ETH_HLEN) < 0)
|
if (dev_hard_header(newskb,dev,MY_PROTO_ID,&rcv_hdr->h_source,&rcv_hdr->h_dest,MY_ACK_LEN+ETH_HLEN) < 0)
|
goto error;
|
goto error;
|
my_data = skb_put(newskb,4);
|
|
//Put the protocol version id to the packet
|
//Put the protocol version id to the packet
|
*(my_data++) = (MY_PROTO_VER>>8) & 0xff;
|
put_skb_u16(newskb,MY_PROTO_VER);
|
*(my_data++) = (MY_PROTO_VER & 0xff);
|
|
//Put the "restart" command to the packet
|
//Put the "restart" command to the packet
|
*(my_data++) = 0;
|
put_skb_u16(newskb,0x05);
|
*(my_data++) = 5;
|
|
my_data = skb_put(newskb,MY_ACK_LEN - 4);
|
my_data = skb_put(newskb,MY_ACK_LEN - 4);
|
memset(my_data,0xa5,MY_ACK_LEN - 4);
|
memset(my_data,0xa5,MY_ACK_LEN - 4);
|
dev_queue_xmit(newskb);
|
dev_queue_xmit(newskb);
|
kfree_skb(skb);
|
kfree_skb(skb);
|
return NET_RX_DROP;
|
return NET_RX_DROP;
|
Line 666... |
Line 676... |
//To avoid problems with scattered packets, we copy initial part of data to the buffer
|
//To avoid problems with scattered packets, we copy initial part of data to the buffer
|
//using the skb_copy_bits
|
//using the skb_copy_bits
|
skb_copy_bits(skb,0,tmp_buf,USER_HDR_LEN);
|
skb_copy_bits(skb,0,tmp_buf,USER_HDR_LEN);
|
/* We extract the information from the user header
|
/* We extract the information from the user header
|
* First we check if this is correct version of the protocol */
|
* First we check if this is correct version of the protocol */
|
if (unlikely((tmp_buf[0] != ((MY_PROTO_VER>>8) & 0xff)) ||
|
if (unlikely(get_be_u16(&tmp_buf[0]) != MY_PROTO_VER))
|
(tmp_buf[1] != (MY_PROTO_VER & 0xff)))) goto wrong_pkt_type_error;
|
goto wrong_pkt_type_error;
|
if (unlikely((tmp_buf[2] == 0xa5) &&
|
if (unlikely(get_be_u16(&tmp_buf[2]) == 0xa55a)) {
|
(tmp_buf[3] == 0x5a))) {
|
|
//This is a command response packet
|
//This is a command response packet
|
printk(KERN_INFO " received command response packet");
|
printk(KERN_INFO " received command response packet");
|
if(sd->cmd_ack==1) {
|
if(sd->cmd_ack==1) {
|
//We are waiting for response
|
//We are waiting for response
|
printk(KERN_INFO "we were waiting for command response packet");
|
printk(KERN_INFO "we were waiting for command response packet");
|
if ((tmp_buf[6] == ((sd->cmd_code >> 8) & 0xff)) &&
|
if ((get_be_u16(&tmp_buf[6]) == sd->cmd_code) &&
|
(tmp_buf[7] == (sd->cmd_code & 0xff)) &&
|
(get_be_u16(&tmp_buf[8]) == sd->cmd_seq)) {
|
(tmp_buf[8] == ((sd->cmd_seq >> 8) & 0xff)) &&
|
|
(tmp_buf[9] == (sd->cmd_seq & 0xff))) {
|
|
//This is a response for the right command
|
//This is a response for the right command
|
//copy the response to the slave data
|
//copy the response to the slave data
|
printk(KERN_INFO "It was response for the right command");
|
printk(KERN_INFO "It was response for the right command");
|
memcpy(&sd->cmd_resp,&tmp_buf[6],12);
|
memcpy(&sd->cmd_resp,&tmp_buf[6],12);
|
sd->cmd_ack=2;
|
sd->cmd_ack=2;
|
Line 691... |
Line 698... |
}
|
}
|
}
|
}
|
kfree_skb(skb);
|
kfree_skb(skb);
|
return NET_RX_SUCCESS;
|
return NET_RX_SUCCESS;
|
}
|
}
|
if (unlikely((tmp_buf[2] != 0xa5) ||
|
if (unlikely(get_be_u16(&tmp_buf[2]) != 0xa5a5)) {
|
(tmp_buf[3] != 0xa5))) {
|
|
//This is not a data packet
|
//This is not a data packet
|
goto wrong_pkt_type_error;
|
goto wrong_pkt_type_error;
|
}
|
}
|
/* Now we handle the data packet
|
/* Now we handle the data packet
|
PLEASE NOTE, THAT THIS MUST TIGHTLY CORRESPOND
|
PLEASE NOTE, THAT THIS MUST TIGHTLY CORRESPOND
|
TO YOUR FPGA IMPLEMENTATION! */
|
TO YOUR FPGA IMPLEMENTATION! */
|
//Check, if we need to read a command response
|
//Check, if we need to read a command response
|
if(sd->cmd_ack==1) {
|
if(sd->cmd_ack==1) {
|
//We are waiting for response
|
//We are waiting for response
|
if ((tmp_buf[14] == ((sd->cmd_code >> 8) & 0xff)) &&
|
if ((get_be_u16(&tmp_buf[14]) == sd->cmd_code) &&
|
(tmp_buf[15] == (sd->cmd_code & 0xff)) &&
|
(get_be_u16(&tmp_buf[16]) == sd->cmd_seq)) {
|
(tmp_buf[16] == ((sd->cmd_seq >> 8) & 0xff)) &&
|
|
(tmp_buf[17] == (sd->cmd_seq & 0xff))) {
|
|
//This is a response for the right command
|
//This is a response for the right command
|
//copy the response to the slave data
|
//copy the response to the slave data
|
memcpy(&sd->cmd_resp,&tmp_buf[14],12);
|
memcpy(&sd->cmd_resp,&tmp_buf[14],12);
|
sd->cmd_ack=2;
|
sd->cmd_ack=2;
|
//Wake up the waiting process
|
//Wake up the waiting process
|
wake_up_interruptible(&usercmd_queue);
|
wake_up_interruptible(&usercmd_queue);
|
}
|
}
|
}
|
}
|
packet_number = htonl(*((uint32_t *)&tmp_buf[6]));
|
packet_number = get_be_u32(&tmp_buf[6]);
|
#ifdef FADE_DEBUG
|
#ifdef FADE_DEBUG
|
printk(KERN_INFO "pkt=%d\n",(int)packet_number);
|
printk(KERN_INFO "pkt=%d\n",(int)packet_number);
|
#endif
|
#endif
|
/* To know if this is a new packet, we compare the packet number
|
/* To know if this is a new packet, we compare the packet number
|
* in the received packet with the number of the last unconfirmed packet,
|
* in the received packet with the number of the last unconfirmed packet,
|
Line 819... |
Line 823... |
newskb->protocol = htons(MY_PROTO_ID);
|
newskb->protocol = htons(MY_PROTO_ID);
|
//Build the MAC header for the new packet
|
//Build the MAC header for the new packet
|
// Tu http://lxr.linux.no/linux+*/net/ipv4/arp.c#L586 jest pokazane jak zbudować pakiet!
|
// Tu http://lxr.linux.no/linux+*/net/ipv4/arp.c#L586 jest pokazane jak zbudować pakiet!
|
if (dev_hard_header(newskb,dev,MY_PROTO_ID,&rcv_hdr->h_source,&rcv_hdr->h_dest,MY_ACK_LEN+ETH_HLEN) < 0)
|
if (dev_hard_header(newskb,dev,MY_PROTO_ID,&rcv_hdr->h_source,&rcv_hdr->h_dest,MY_ACK_LEN+ETH_HLEN) < 0)
|
goto error;
|
goto error;
|
my_data = skb_put(newskb,4);
|
|
//Put the protocol version id to the packet
|
//Put the protocol version id to the packet
|
*(my_data++) = (MY_PROTO_VER>>8) & 0xff;
|
put_skb_u16(newskb,MY_PROTO_VER);
|
*(my_data++) = (MY_PROTO_VER & 0xff);
|
|
//Put the "ACKNOWLEDGE" type
|
//Put the "ACKNOWLEDGE" type
|
*(my_data++) = 0;
|
put_skb_u16(newskb,0x03); //ACK!
|
*(my_data++) = 3; //ACK!
|
|
//Copy the begining of the received packet to the acknowledge packet
|
//Copy the begining of the received packet to the acknowledge packet
|
my_data = skb_put(newskb,MY_ACK_COPIED);
|
my_data = skb_put(newskb,MY_ACK_COPIED);
|
res = skb_copy_bits(skb,4,my_data,MY_ACK_COPIED);
|
res = skb_copy_bits(skb,4,my_data,MY_ACK_COPIED);
|
my_data = skb_put(newskb,MY_ACK_LEN -MY_ACK_COPIED-4);
|
my_data = skb_put(newskb,MY_ACK_LEN -MY_ACK_COPIED-4);
|
memset(my_data,0xa5,MY_ACK_LEN - MY_ACK_COPIED-4);
|
memset(my_data,0xa5,MY_ACK_LEN - MY_ACK_COPIED-4);
|