www.pudn.com > 422.rar > write.c


/* write.c
 * Linux serial-bus device driver.
 * Written by wang song yue  email:wsy5228@sina.com
 * This software is released under the GPL-License.
 * Version 0.1  28 october 2005
 */

#include 
#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
#define MODVERSIONS
#endif

#if defined (MODVERSIONS)
#include 
#endif

#define __NO_VERSION__
#include 
#include 
#include 
#include 
#include 
#include 

#include "../include/main.h"


ssize_t serial_write(struct file *file, const char *buffer, size_t length, loff_t *offset)
{
	struct msgobj_t *obj;
	struct chip_t *chip;
	struct serialmsg_t *write_msg;
	struct canfifo_t *fifo;
	int ret = 0;
	int space = 0;
	int written = 0;
	int bytes_to_copy = 0;
	long can_timeout = 1;
//printk("i am in can_write!\n");
 if(MINOR_NR==0)
        {
                tts_io_addr=0xffd00000;
                
        }
        else if(MINOR_NR==1)
        {
                tts_io_addr=0xffd00008;
                
        }
                                                                                                               
        else if(MINOR_NR==2)
        {
                tts_io_addr=0xffd00010;
                                                                                                               
        }
                                                                                                               
       else if(MINOR_NR==3)
        {
                tts_io_addr=0xffd00018;
                                                                                                               
        }
                                                                                                               

 //printk("i am in serial_write minor=%d,tts_io_addr=0x%lx\n",MINOR_NR,tts_io_addr);
	if (length < sizeof(struct serialmsg_t)) {
		DEBUGMSG("Trying to write less bytes than a CAN message,\n");
		DEBUGMSG("this will always return 0 !\n");
		return 0;
	}
	if (length > 8 * sizeof(struct serialmsg_t)) {
		CANMSG("Trying to write more than is supported.\n");
		return -1;
	}
	if (length % sizeof(struct serialmsg_t)) {
		CANMSG("The number of bytes requested to be written is not a multiple of\n");
		CANMSG("'sizeof(struct serialmsg_t)', currently this is not allowed.\n");
		return -1;
	} 

	/* Initialize hardware pointers */
	if ( (obj = objects_p[MINOR_NR]) == NULL) {
		CANMSG("Could not assign buffer structure\n");
		return -1;
	}
	if ( (chip = obj->hostchip) == NULL) {
		CANMSG("Device is not correctly configured,\n");
		CANMSG("please reload the driver\n");
		return -1;
	}	if ( (fifo = obj->fifo) == NULL) {
		CANMSG("Could not assign buffer memory\n");
		return -1;
	}

	/* Initialize pointer to the first message to be sent */
	write_msg = fifo->tx_writep;

	/* Calculate free buffer space */
	cli();
	space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ? 
			((int)fifo->tx_readp - (int)fifo->tx_writep) : 
			((int)fifo->tx_readp - (int)fifo->tx_writep + 
						(int)fifo->tx_size);
   //     printk("interrupt 1111!\n");
//printk("space==========%d,write_msg.length===========%d\n",space,write_msg->length);
	sti();

	/* If the output buffer is full, return immediately in case O_NONBLOCK
	 * has been specified or loop until space becomes available.
	 */
	while (space < sizeof(struct serialmsg_t)) {
		DEBUGMSG("Buffer is full\n");
		if (file->f_flags & O_NONBLOCK)
			return -EAGAIN;
		can_timeout = interruptible_sleep_on_timeout(&fifo->writeq, 
								CANTIMEOUT);
//printk("can_write can_timeout=%d\n",can_timeout);
		if (signal_pending(current))
			return -EINTR;
		if (!can_timeout)
			return -EIO;
		cli();
//printk("inter 222!\n");
		space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ? 
			((int)fifo->tx_readp - (int)fifo->tx_writep) : 
			((int)fifo->tx_readp - (int)fifo->tx_writep + 
							(int)fifo->tx_size);
		sti();
	}

	/* There's space available in the kernel output buffer.
	 * Find out wich is smaller: 'length', the number of bytes requested to
	 * be written or 'space', the number of bytes available in the kernel 
	 * buffer. We copy the least of the two to kernel space.
	 */
//	space = space - (space % sizeof(struct serialmsg_t)); // round it
	bytes_to_copy = space < length ? space : length;
	copy_from_user(fifo->tx_writep, buffer, bytes_to_copy);
	written = bytes_to_copy;
//printk("written--bytes_to_copy=0x%x\n",written);
	while (bytes_to_copy > 0) {
		fifo->tx_writep++;
		if (fifo->tx_writep >= fifo->buf_tx_entry + MAX_BUF_LENGTH)            //maybe wrong   maybe mot >=  shoud be >!!!!
			fifo->tx_writep = fifo->buf_tx_entry;
		bytes_to_copy -= sizeof(struct serialmsg_t);
	}

	/* Copy the data to be transmitted into the output buffer */
/*	while ( (written < length) && (space >= sizeof(struct canmsg_t)) ) {
		copy_from_user(fifo->tx_writep,buffer, sizeof(struct canmsg_t));
		cli();
		fifo->tx_writep++;
		if (fifo->tx_writep >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
			fifo->tx_writep = fifo->buf_tx_entry;
		buffer += sizeof(struct canmsg_t);
		written += sizeof(struct canmsg_t);
		space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ?
			((int)fifo->tx_readp - (int)fifo->tx_writep) :
			((int)fifo->tx_readp - (int)fifo->tx_writep + 
							(int)fifo->tx_size);
		sti();
	} */

	/* Initiate transmission in case we are not already transmitting */
	cli();
//printk("interrupt 3333!\n");
	if (!fifo->tx_in_progress) {
		//fifo->tx_in_progress = 1;              //wang  zeng jia!!!!!!!!!!!
          	sti();
		if ( (ret = chip->chipspecops->pre_write_config(chip, obj, 
							write_msg)) < 0) {
			CANMSG("Error initializing hardware for sending\n");
			return -EIO;
		}
//printk("pre_write_config=0x%x\n",ret);
		obj->ret = 0;
//		if ( (ret = chip->chipspecops->send_msg(chip, obj, 
//							write_msg)) < 0) {
//			CANMSG("Error sending message\n");
//			return -EIO;
//		}

//printk("send_msg=0x%x\n",ret);
		/* If O_SYNC is specified wait for successfull transmission */
/*		while (1) {
			cli();
			if ( (!file->f_flags & O_SYNC) || 
						(!fifo->tx_in_progress)) {
				sti();
				if (obj->ret < 0)
					return obj->ret;
				else
					return written;
			}
			cli();
			if (fifo->tx_in_progress) {
				can_timeout = interruptible_sleep_on_timeout(
						&fifo->writeq, CANTIMEOUT);
			}
			sti();
			if (signal_pending(current))
				return -EINTR;
			if (!can_timeout)
				return -EIO;
		} */
	}
//printk("zeng  jia\n");        
  //  ret = chip->chipspecops->pre_write_config(chip, obj,write_msg);
    //        ret = chip->chipspecops->send_msg(chip,obj, write_msg);

	sti();
	
	//printk("go out write\n");

	return written;

}