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; }