#include <linux/fs.h>

#include "can.h"
#include "sja1000.h"

//-----------------------------------------------------------------------------
int can_open(struct inode *inode, struct file *filp)
{
	/* Реализация функции open */
	int dev, channel;
	struct can_rx_fifo_t *rx_fifo;
	unsigned long flags;
	struct private_data_t *private_data;

	dev = MINOR(inode->i_rdev) / CAN_NUM_CHANNEL;
	channel = MINOR(inode->i_rdev) % CAN_NUM_CHANNEL;

	/* Выделяем память */
	private_data = (struct private_data_t *)kmalloc(sizeof(struct private_data_t), GFP_KERNEL);
	if (NULL == private_data)
	{
		printk(KERN_ALERT "can200_open ERROR memory allocation.\n");
		return -ENOMEM;
	}

	/* Выделяем память */
	rx_fifo = (struct can_rx_fifo_t *)kmalloc(sizeof(struct can_rx_fifo_t), GFP_KERNEL);
	if (NULL == rx_fifo)
	{
		kfree(private_data);
		printk(KERN_ALERT "can200_open ERROR memory allocation.\n");
		return -ENOMEM;
	}
	rx_fifo->first = 0;
	rx_fifo->last = 0;
	atomic_set(&rx_fifo->len, 0);
	rx_fifo->overrun = 0;
	rx_fifo->next = NULL;

	private_data->num_dev = dev;
	private_data->num_channel = channel;
	private_data->len = 0;
	private_data->rx_fifo = rx_fifo;
	private_data->tx_fifo = NULL;
    private_data->status = CAN_TRANSMIT_COMPLETE;

	filp->private_data = (void *)(private_data);

	/* Захватываем спин и запрещаем локальные прерывания */
	spin_lock_irqsave(&can[dev].rx_fifo_lock[channel], flags);

	rx_fifo->next = can[dev].rx_fifo[channel];
	can[dev].rx_fifo[channel] = rx_fifo;

	/* Освобождаем спин и разрешаем локальные прерывания */
	spin_unlock_irqrestore(&can[dev].rx_fifo_lock[channel], flags);

	return 0;
}
