Line 118... |
Line 118... |
struct pkt_map {
|
struct pkt_map {
|
int num;
|
int num;
|
int offset;
|
int offset;
|
};
|
};
|
|
|
typedef struct
|
typedef struct {
|
{
|
|
// fields related to the circular buffer
|
// fields related to the circular buffer
|
volatile int head;
|
volatile int head;
|
volatile int tail;
|
volatile int tail;
|
rwlock_t ptrs_lock; //Used to protect the head and tail pointers
|
rwlock_t ptrs_lock; //Used to protect the head and tail pointers
|
|
|
Line 250... |
Line 249... |
skb_reset_network_header(newskb);
|
skb_reset_network_header(newskb);
|
newskb->dev = sd->dev;
|
newskb->dev = sd->dev;
|
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 http://lxr.free-electrons.com/source/net/ipv4/arp.c?v=3.17#L608 it is shown how to build a packet!
|
// Here http://lxr.free-electrons.com/source/net/ipv4/arp.c?v=3.17#L608 it is shown how to build a packet!
|
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) {
|
{
|
|
mutex_unlock(&sd->usercmd_lock);
|
mutex_unlock(&sd->usercmd_lock);
|
kfree_skb(newskb);
|
kfree_skb(newskb);
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
//Put the protocol version id to the packet
|
//Put the protocol version id to the packet
|
Line 307... |
Line 305... |
skb_reset_network_header(newskb);
|
skb_reset_network_header(newskb);
|
newskb->dev = sd->dev;
|
newskb->dev = sd->dev;
|
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 http://lxr.free-electrons.com/source/net/ipv4/arp.c?v=3.17#L608 it is shown how to build a packet!
|
// Here http://lxr.free-electrons.com/source/net/ipv4/arp.c?v=3.17#L608 it is shown how to build a packet!
|
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) {
|
{
|
|
mutex_unlock(&sd->usercmd_lock);
|
mutex_unlock(&sd->usercmd_lock);
|
kfree_skb(newskb);
|
kfree_skb(newskb);
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
//Put the protocol version id to the packet
|
//Put the protocol version id to the packet
|
Line 333... |
Line 330... |
|
|
/* Function free_mac may be safely called even if the MAC was not taken
|
/* Function free_mac may be safely called even if the MAC was not taken
|
it checks sd->active to detect such situation
|
it checks sd->active to detect such situation
|
*/
|
*/
|
static inline
|
static inline
|
long free_mac(slave_data *sd) {
|
long free_mac(slave_data *sd)
|
|
{
|
write_lock_bh(&slave_table_lock);
|
write_lock_bh(&slave_table_lock);
|
if(sd->active) {
|
if(sd->active) {
|
/* Clear the MAC address */
|
/* Clear the MAC address */
|
sd->active = 0;
|
sd->active = 0;
|
memset(&sd->mac,0,ETH_ALEN);
|
memset(&sd->mac,0,ETH_ALEN);
|
Line 369... |
Line 367... |
write_unlock_bh(&sd->flags_lock);
|
write_unlock_bh(&sd->flags_lock);
|
return 0;
|
return 0;
|
case L3_V1_IOC_GETBUFLEN:
|
case L3_V1_IOC_GETBUFLEN:
|
/* Inform the user application about the length of the buffer */
|
/* Inform the user application about the length of the buffer */
|
return MY_BUF_LEN;
|
return MY_BUF_LEN;
|
case L3_V1_IOC_READPTRS:
|
case L3_V1_IOC_READPTRS: {
|
{
|
|
void * res = (void *) arg;
|
void * res = (void *) arg;
|
long res2;
|
long res2;
|
struct l3_v1_buf_pointers bp;
|
struct l3_v1_buf_pointers bp;
|
#if LINUX_VERSION_CODE >= 0x50000
|
#if LINUX_VERSION_CODE >= 0x50000
|
if (!access_ok(res,sizeof(bp))) {
|
if (!access_ok(res,sizeof(bp))) {
|
Line 411... |
Line 408... |
//We need to check if the amount of consumed data is correct
|
//We need to check if the amount of consumed data is correct
|
write_lock_bh(&sd->ptrs_lock);
|
write_lock_bh(&sd->ptrs_lock);
|
wptr = sd->head;
|
wptr = sd->head;
|
rptr = sd->tail;
|
rptr = sd->tail;
|
available_data = (wptr - rptr) & MY_BUF_LEN_MASK;
|
available_data = (wptr - rptr) & MY_BUF_LEN_MASK;
|
if (arg>available_data)
|
if (arg>available_data) {
|
{
|
|
write_unlock_bh(&sd->ptrs_lock);
|
write_unlock_bh(&sd->ptrs_lock);
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
//If the number of consumed bytes is correct, update the number of bytes
|
//If the number of consumed bytes is correct, update the number of bytes
|
sd->tail = (rptr + arg) & MY_BUF_LEN_MASK;
|
sd->tail = (rptr + arg) & MY_BUF_LEN_MASK;
|
write_unlock_bh(&sd->ptrs_lock);
|
write_unlock_bh(&sd->ptrs_lock);
|
return SUCCESS;
|
return SUCCESS;
|
}
|
}
|
case L3_V1_IOC_STARTMAC: //Open the slave
|
case L3_V1_IOC_STARTMAC: { //Open the slave
|
{
|
|
sd->stopped_flag = 0;
|
sd->stopped_flag = 0;
|
sd->eof_flag = 0;
|
sd->eof_flag = 0;
|
//We just send a request to start transmission and wait for confirmation
|
//We just send a request to start transmission and wait for confirmation
|
return send_cmd(sd,FCMD_START,0,NULL,100,2);
|
return send_cmd(sd,FCMD_START,0,NULL,100,2);
|
}
|
}
|
case L3_V1_IOC_STOPMAC: //Close the slave and reset it to stop transmission immediately
|
case L3_V1_IOC_STOPMAC: { //Close the slave and reset it to stop transmission immediately
|
{
|
|
return send_cmd(sd,FCMD_STOP,0,NULL,100,2);
|
return send_cmd(sd,FCMD_STOP,0,NULL,100,2);
|
}
|
}
|
case L3_V1_IOC_RESETMAC: //Reset MAC so, that it stops transmission immediately
|
case L3_V1_IOC_RESETMAC: { //Reset MAC so, that it stops transmission immediately
|
{
|
|
return send_reset(sd);
|
return send_reset(sd);
|
}
|
}
|
case L3_V1_IOC_GETMAC: //Open the slave
|
case L3_V1_IOC_GETMAC: { //Open the slave
|
{
|
|
void * source = (void *) arg;
|
void * source = (void *) arg;
|
struct l3_v1_slave sl;
|
struct l3_v1_slave sl;
|
struct net_device *dev = NULL;
|
struct net_device *dev = NULL;
|
long res2;
|
long res2;
|
#if LINUX_VERSION_CODE >= 0x50000
|
#if LINUX_VERSION_CODE >= 0x50000
|
Line 479... |
Line 471... |
dev = dev_get_by_name(&init_net,sl.devname);
|
dev = dev_get_by_name(&init_net,sl.devname);
|
if (!dev) return -ENODEV;
|
if (!dev) return -ENODEV;
|
sd->dev = dev;
|
sd->dev = dev;
|
return SUCCESS;
|
return SUCCESS;
|
}
|
}
|
case L3_V1_IOC_FREEMAC: //Close the slave and reset it to stop transmission immediately
|
case L3_V1_IOC_FREEMAC: { //Close the slave and reset it to stop transmission immediately
|
{
|
|
free_mac(sd);
|
free_mac(sd);
|
return SUCCESS;
|
return SUCCESS;
|
}
|
}
|
case L3_V1_IOC_USERCMD: //Perform the user command
|
case L3_V1_IOC_USERCMD: { //Perform the user command
|
{
|
|
void * source = (void *) arg;
|
void * source = (void *) arg;
|
long result = -EINVAL;
|
long result = -EINVAL;
|
struct l3_v1_usercmd ucmd;
|
struct l3_v1_usercmd ucmd;
|
//First copy command data
|
//First copy command data
|
result = __copy_from_user(&ucmd,source,sizeof(ucmd));
|
result = __copy_from_user(&ucmd,source,sizeof(ucmd));
|
Line 1025... |
Line 1015... |
unsigned long vsize = vma->vm_end - vma->vm_start;
|
unsigned long vsize = vma->vm_end - vma->vm_start;
|
unsigned long psize = MY_BUF_LEN;
|
unsigned long psize = MY_BUF_LEN;
|
if (vsize>psize)
|
if (vsize>psize)
|
return -EINVAL;
|
return -EINVAL;
|
remap_vmalloc_range(vma,sd->buffer, 0);
|
remap_vmalloc_range(vma,sd->buffer, 0);
|
if (vma->vm_ops)
|
|
return -EINVAL; //It should never happen...
|
|
vma->vm_ops = &my_proto1_vm_ops;
|
vma->vm_ops = &my_proto1_vm_ops;
|
my_proto1_vma_open(vma); //No open(vma) was called, we have called it ourselves
|
my_proto1_vma_open(vma); //No open(vma) was called, we have called it ourselves
|
return 0;
|
return 0;
|
}
|
}
|
|
|