/home/hillier_g/checkout/most4linux/most-kernel/most-sync-m.c

Go to the documentation of this file.
00001 /*
00002  *  Copyright(c) Siemens AG, Muenchen, Germany, 2005, 2006, 2007
00003  *                           Bernhard Walle <bernhard.walle@gmx.de>
00004  *                           Gernot Hillier <gernot.hillier@siemens.com>
00005  *
00006  * ----------------------------------------------------------------------------
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License version 2 as 
00009  * published by the Free Software Foundation;
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  * ----------------------------------------------------------------------------
00020  */
00021 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config/config.h"
00031 #endif
00032 #include <linux/module.h>
00033 #include <linux/fs.h>
00034 #include <linux/dma-mapping.h>
00035 #include <linux/timer.h>
00036 #include <asm/msr.h>
00037 #include <asm/atomic.h>
00038 #include <asm/system.h>
00039 #include <asm/semaphore.h>
00040 #include <asm/uaccess.h>
00041 #include <linux/rwsem.h>
00042 
00043 #include "most-constants.h"
00044 #include "most-base.h"
00045 #include "most-sync.h"
00046 #include "most-measurements.h"
00047 #include "most-sync-common.h"
00048 
00052 #define DRIVER_NAME                     "most-sync"
00053 
00057 #define PR                              DRIVER_NAME       ": "
00058 
00062 static char *version = "$Rev: 639 $";
00063 
00064 /* general static data elements -------------------------------------------- */
00065 
00069 struct most_sync_dev *most_sync_devices[MOST_DEVICE_NUMBER];
00070 
00071 /* forward declarations ---------------------------------------------------- */
00072 
00073 static int        most_sync_probe       (struct most_dev *);
00074 static int        most_sync_remove      (struct most_dev *);
00075 static void       most_sync_int_handler (struct most_dev *, unsigned int);
00076 static int        most_sync_do_open     (struct inode *, struct file *);
00077 static int        most_sync_do_release  (struct inode *, struct file *);
00078 static ssize_t    most_sync_do_read     (struct file *, char __user *, 
00079                                          size_t, loff_t *);
00080 static ssize_t    most_sync_do_write    (struct file *, const char __user *, 
00081                                          size_t, loff_t *);
00082 static int        most_sync_do_ioctl    (struct inode *, struct file *,
00083                                          unsigned int, unsigned long);
00084 static inline int most_sync_do_setup_tx (struct file *, unsigned long);
00085 static inline int most_sync_do_setup_rx (struct file *, unsigned long);
00086 
00087 /* module parameters ------------------------------------------------------- */
00088 
00089 /*
00090  * see header
00091  */
00092 long sw_rx_buffer_size = STD_MOST_FRAMES_PER_SEC; /* 1 s */
00093 
00094 /*
00095  * see header
00096  */
00097 long sw_tx_buffer_size = STD_MOST_FRAMES_PER_SEC; /* 1 s */
00098 
00099 /*
00100  * see header
00101  */
00102 long hw_rx_buffer_size = 44; /* 1 ms */
00103 
00104 /*
00105  * see header
00106  */
00107 long hw_tx_buffer_size = 44; /* 1 ms */
00108 
00109 #ifndef DOXYGEN
00110 module_param(sw_rx_buffer_size, long, S_IRUGO);
00111 MODULE_PARM_DESC(sw_rx_buffer_size, 
00112         "Size of the software receive buffer in frame parts "
00113         "(default: " __MODULE_STRING(STD_MOST_FRAMES_PER_SEC) ")");
00114 
00115 module_param(sw_tx_buffer_size, long, S_IRUGO);
00116 MODULE_PARM_DESC(sw_tx_buffer_size, 
00117         "Size of the software transmit buffer in frame parts "
00118         "(default: " __MODULE_STRING(STD_MOST_FRAMES_PER_SEC) ")");
00119 
00120 module_param(hw_rx_buffer_size, long, S_IRUGO);
00121 MODULE_PARM_DESC(hw_rx_buffer_size,
00122         "Size of the hardware receive buffer in frame parts "
00123         "(default: " __MODULE_STRING(44) ")");
00124 
00125 module_param(hw_tx_buffer_size, long, S_IRUGO);
00126 MODULE_PARM_DESC(hw_tx_buffer_size, 
00127         "Size of the hardware transmit buffer in frame parts "
00128         "(default: " __MODULE_STRING(44) ")");
00129 #endif
00130 
00131 
00135 static struct file_operations most_sync_file_operations = {
00136     .owner   = THIS_MODULE,
00137     .open    = most_sync_do_open,
00138     .ioctl   = most_sync_do_ioctl,
00139     .release = most_sync_do_release,
00140     .read    = most_sync_do_read,
00141     .write   = most_sync_do_write
00142 };
00143 
00144 #ifdef DEBUG
00145 
00150 static inline void most_sync_print_devices(struct most_sync_file *file)
00151 {
00152     struct list_head        *ptr;
00153     struct most_sync_file   *entry;
00154     struct most_sync_dev    *sync_dev = file->sync_dev;
00155     int                     i         = 0;
00156     
00157     list_for_each(ptr, &sync_dev->file_list) {
00158         entry = list_entry(ptr, struct most_sync_file, list);
00159 
00160         rtnrt_debug(PR "-------------------------- %d -----------\n", i);
00161         rtnrt_debug(PR "Number of quadlets RX   : %d\n", entry->part_rx.count);
00162         rtnrt_debug(PR "Offset of quadlets RX   : %d\n", entry->part_rx.offset);
00163         rtnrt_debug(PR "Number of quadlets TX   : %d\n", entry->part_tx.count);
00164         rtnrt_debug(PR "Offset of quadlets TX   : %d\n", entry->part_tx.offset);
00165         rtnrt_debug(PR "RX running              : %d\n", entry->rx_running);
00166         rtnrt_debug(PR "TX running              : %d\n", entry->tx_running);
00167         rtnrt_debug(PR "Reader index            : %d\n", entry->reader_index);
00168         rtnrt_debug(PR "Writer index            : %d\n", entry->writer_index);
00169 
00170         i++;
00171     }
00172 }
00173 #endif
00174 
00175 
00182 static int most_sync_probe(struct most_dev *most_dev)
00183 {
00184     int                   number = MOST_DEV_CARDNUMBER(most_dev);
00185     dev_t                 devno  = MKDEV(MOST_DEV_MAJOR(most_dev),
00186                                          number + MOST_SYNC_MINOR_OFFSET);
00187     int                   err    = 0;
00188     struct most_sync_dev  *sync_dev;
00189     char                  buffer[10];
00190 
00191     return_value_if_fails_dbg(number < MOST_DEVICE_NUMBER, -EINVAL);
00192 
00193     print_dev_t(buffer, devno);
00194     pr_sync_debug(PR "most_sync_probe called, registering %s", buffer);
00195 
00196     /* create a new device structure */
00197     sync_dev = (struct most_sync_dev *)kmalloc(sizeof(struct most_sync_dev), GFP_KERNEL);
00198     if (unlikely(sync_dev == NULL)) {
00199         rtnrt_warn(PR "Allocation of private data structure failed\n");
00200         err = -ENOMEM;
00201         goto out;
00202     }
00203     memset(sync_dev, 0, sizeof(struct most_sync_dev));
00204 
00205     /* initialize some members */
00206     sync_dev->most_dev = most_dev;
00207     INIT_LIST_HEAD(&sync_dev->file_list);
00208     init_waitqueue_head(&sync_dev->rx_queue);
00209     init_waitqueue_head(&sync_dev->tx_queue);
00210     init_rwsem(&sync_dev->config_lock_rx);
00211     init_rwsem(&sync_dev->config_lock_tx);
00212     atomic_set(&sync_dev->receiver_count, 0);
00213     atomic_set(&sync_dev->transmitter_count, 0);
00214     atomic_set(&sync_dev->open_count, -MOST_SYNC_OPENS);
00215 
00216     /* register the new character device */
00217     cdev_init(&sync_dev->cdev, &most_sync_file_operations);
00218     sync_dev->cdev.owner = THIS_MODULE;
00219     err = cdev_add(&sync_dev->cdev, devno, 1);
00220     if (unlikely(err)) {
00221         rtnrt_warn(PR "cdev_add failed\n");
00222         goto out_free;
00223     }
00224 
00225     /* put the device in the global list of devices */
00226     most_sync_devices[number] = sync_dev;
00227 
00228     return 0;
00229 
00230 out_free:
00231     kfree(sync_dev);
00232 out:
00233     return err;
00234 }
00235 
00242 static int most_sync_remove(struct most_dev *dev)
00243 {
00244     int                  number    = MOST_DEV_CARDNUMBER(dev);
00245     struct most_sync_dev *sync_dev = most_sync_devices[number];
00246 
00247     pr_sync_debug(PR "most_sync_remove called, number = %d\n", number);
00248 
00249     /* delete device */
00250     cdev_del(&sync_dev->cdev);
00251 
00252     /* free memory and remove from the global device list */
00253     most_sync_devices[number] = NULL;
00254     kfree(sync_dev);
00255 
00256     return 0;
00257 }
00258 
00265 static void most_sync_int_handler(struct most_dev        *dev,
00266                                   unsigned int           intstatus)
00267 {
00268     int                   card = MOST_DEV_CARDNUMBER(dev);
00269     struct most_sync_dev  *sync_dev = most_sync_devices[card];
00270     u32                   val;
00271     int                   err;
00272     int                   current_page;
00273 
00274     assert(sync_dev != NULL);
00275 
00276     if (intstatus & ISSRX) {
00277         void          *dma_start;
00278         size_t        siz;
00279         
00280         pr_irq_debug(PR "RX INT\n");
00281 
00282         val = most_readreg(sync_dev->most_dev, MOST_PCI_SRXCTRL_REG);
00283         dma_start = sync_dev->hw_receive_buf.addr_virt;
00284         siz = sync_dev->hw_receive_buf.size / 2;
00285 
00286         /* 
00287          * current page == 0 
00288          * -> increase address (because then we must read out page 1!!!!)
00289          */
00290         if (!(val & SRXPP)) {
00291             dma_start += siz;
00292         }
00293 
00294         measuring_receive_isr_start(sync_dev->sw_receive_buf);
00295         err = rxbuf_put(sync_dev->sw_receive_buf, dma_start, siz);
00296         if (unlikely(err < 0)) {
00297             rtnrt_warn(PR "rxbuf_put in most_pci_int_handler returned %d\n", err);
00298         } else {
00299             memset(dma_start, 0, siz);
00300             measuring_receive_isr_wakeup();
00301             wake_up_interruptible(&sync_dev->rx_queue);
00302         }
00303 
00304         current_page = (val & SRXPP) ? 1 : 2;
00305         if ((sync_dev->rx_current_page != 0) 
00306                 && (sync_dev->rx_current_page == current_page)) {
00307             rtnrt_warn(PR "sync_dev->rx_current_page == current_page\n");
00308         }
00309         sync_dev->rx_current_page = current_page;
00310     }
00311     
00312     if (intstatus & ISSTX) {
00313         void          *dma_start;
00314         ssize_t       read;
00315         size_t        siz;
00316         unsigned int  *ptr;
00317 
00318         pr_irq_debug(PR "TX INT\n");
00319 
00320         val = most_readreg(sync_dev->most_dev, MOST_PCI_STXCTRL_REG);
00321         dma_start = sync_dev->hw_transmit_buf.addr_virt;
00322         siz = sync_dev->hw_transmit_buf.size / 2;
00323 
00324         /* 
00325          * current page == 0 
00326          * -> increase address (because then we must read out page 1!!!!)
00327          */
00328         if (!(val & STXPP)) {
00329             dma_start += siz;
00330         }
00331 
00332         ptr = dma_start;
00333 
00334         memset(dma_start, 0, siz);
00335         read = txbuf_get(sync_dev->sw_transmit_buf, dma_start, siz);
00336         if (unlikely(read < 0)) {
00337             rtnrt_warn(PR "txbuf_get in most_pci_int_handler returned %d\n", read);
00338         } else {
00339             wake_up_interruptible(&sync_dev->tx_queue);
00340         }
00341 
00342         current_page = (val & STXPP) ? 1 : 2;
00343         if ((sync_dev->tx_current_page != 0) && (sync_dev->tx_current_page == current_page)) {
00344             rtnrt_warn(PR "TX: sync_dev->tx_current_page == current_page\n");
00345         }
00346         sync_dev->tx_current_page = current_page;
00347     }
00348 }
00349 
00356 static inline void most_sync_stop_rx(struct most_sync_file *file)
00357 {
00358     most_sync_stop_rx_common(file->sync_dev, file);
00359 }
00360 
00367 static inline void most_sync_stop_tx(struct most_sync_file *file)
00368 {
00369     most_sync_stop_tx_common(file->sync_dev, file);
00370 }
00371 
00376 static struct most_high_driver most_sync_high_driver = {
00377     .name               = "most-sync",
00378     .sema_list          = LIST_HEAD_INIT(most_sync_high_driver.sema_list),
00379     .spin_list          = LIST_HEAD_INIT(most_sync_high_driver.spin_list),
00380     .probe              = most_sync_probe,
00381     .remove             = most_sync_remove,
00382     .int_handler        = most_sync_int_handler,
00383     .interrupt_mask     = (IESTX | IESRX)
00384 };
00385 
00395 static int most_sync_do_open(struct inode *inode, struct file *filp)
00396 {
00397     unsigned long            flags;
00398     struct most_sync_dev     *sync_dev;
00399     struct most_sync_file    *file;
00400 
00401     sync_dev = container_of(inode->i_cdev, struct most_sync_dev, cdev);
00402 
00403     pr_sync_debug(PR "most_sync_do_open called for PCI card %d\n",
00404                                 MOST_DEV_CARDNUMBER(sync_dev->most_dev));
00405     most_manage_usage(sync_dev->most_dev, 1);
00406 
00407     /* 
00408      * create the private data structure, this is not the device because each
00409      * device can be opened by more than one process
00410      */
00411     file = kmalloc(sizeof(struct most_sync_file), GFP_KERNEL);
00412     if (unlikely(!file)) {
00413         return -ENOMEM;
00414     }
00415 
00416     /* 
00417      * initializes quadlet_count_rx, quadlet_count_tx, state_rx, state_tx in a
00418      * sensible way
00419      */
00420     memset(file, 0, sizeof(struct most_sync_file));
00421     file->sync_dev = sync_dev;
00422     INIT_LIST_HEAD(&file->list);
00423 
00424     /* and register the structure */
00425     filp->private_data = file;
00426 
00427     /* check and increase the counter */
00428     if (atomic_inc_and_test(&sync_dev->open_count)) {
00429         rtnrt_err(PR "Too much open (%d) for a MOST device, only %d allowed\n",
00430                atomic_read(&sync_dev->open_count), MOST_SYNC_OPENS);
00431         goto out_dec;
00432     }
00433 
00434     /* add the file to the list */
00435     spin_lock_irqsave(&sync_dev->most_dev->lock, flags);
00436     list_add_tail(&file->list, &sync_dev->file_list);
00437     spin_unlock_irqrestore(&sync_dev->most_dev->lock, flags);
00438 
00439     return 0;
00440 
00441 out_dec:
00442     atomic_dec(&sync_dev->open_count);
00443     most_manage_usage(sync_dev->most_dev, -1);
00444     kfree(file);
00445     return -EBUSY;
00446 }
00447 
00456 static int most_sync_do_release(struct inode *inode, struct file *filp)
00457 {
00458     unsigned long         flags;
00459     struct most_sync_file *file      = filp->private_data;
00460     struct most_sync_dev  *sync_dev  = file->sync_dev;
00461 
00462     pr_sync_debug(PR "most_sync_do_release called for PCI card %d\n",
00463             MOST_DEV_CARDNUMBER(sync_dev->most_dev));
00464 
00465     /* remove the device from the list */
00466     spin_lock_irqsave(&sync_dev->most_dev->lock, flags);
00467     list_del(&file->list);
00468     spin_unlock_irqrestore(&sync_dev->most_dev->lock, flags);
00469 
00470     /* check if it's the last reader */
00471     if (file->rx_running && atomic_dec_and_test(&sync_dev->receiver_count)) {
00472         pr_sync_debug(PR "Last Reader\n");
00473         down_write(&sync_dev->config_lock_rx);
00474         most_sync_last_closed_rx(sync_dev, file, most_sync_stop_rx);
00475         up_write(&sync_dev->config_lock_rx);
00476     }
00477 
00478     /* check if it's the last writer */
00479     if (file->tx_running && atomic_dec_and_test(&sync_dev->transmitter_count)) {
00480         pr_sync_debug(PR "Last Transmitter\n");
00481         down_write(&sync_dev->config_lock_tx);
00482         most_sync_last_closed_tx(sync_dev, file, most_sync_stop_tx);
00483         up_write(&sync_dev->config_lock_tx);
00484     }
00485 
00486     /* free the memory */
00487     kfree(file);
00488     most_manage_usage(sync_dev->most_dev, -1);
00489     atomic_dec(&sync_dev->open_count);
00490 
00491     return 0;
00492 }
00493 
00494 /*
00495  * see header
00496  */
00497 ssize_t most_sync_read(struct file                  *filp,
00498                        void                         *buff,
00499                        size_t                       count,
00500                        struct rtnrt_memcopy_desc    *copy)
00501 {
00502     struct most_sync_file       *file = filp->private_data;
00503     struct most_sync_dev        *sync_dev = file->sync_dev;
00504     ssize_t                     copied = 0;
00505     int                         err;
00506 
00507     pr_sync_debug(PR "Entering most_sync_read %d, c=%d\n", 
00508             file->reader_index, count);
00509 
00510     /* optimisation */
00511     return_value_if_fails(count != 0, 0);
00512     
00513     /* check if we can read */
00514     if (!file->rx_running) {
00515         rtnrt_err(PR "Cannot read at this time\n");
00516         return -EBUSY;
00517     }
00518 
00519     down_read(&sync_dev->config_lock_rx);
00520 
00521     while (copied == 0) {
00522         copied = rxbuf_get(sync_dev->sw_receive_buf, file->reader_index, 
00523                 file->part_rx, buff, count, copy);
00524         if (unlikely(copied < 0)) {
00525             rtnrt_err(PR "Error in rxbuf_get: %d\n", copied);
00526             goto out_read;
00527         }
00528 
00529         if (copied == 0) {
00530             err = wait_event_interruptible(sync_dev->rx_queue, 
00531                     !rxbuf_is_empty(sync_dev->sw_receive_buf, file->reader_index) );
00532             if (err < 0) {
00533                 pr_sync_debug(PR "wait_event_interruptible "
00534                         " returned with %d\n", err);
00535                 copied = err;
00536                 goto out_read;
00537             }
00538         }
00539     }
00540 
00541 out_read:
00542     up_read(&sync_dev->config_lock_rx);
00543     pr_sync_debug(PR "Finishing most_sync_read %d with %d\n",
00544             file->reader_index, copied);
00545     
00546     return copied;
00547 }
00548 
00558 static ssize_t most_sync_do_read(struct file      *filp,
00559                                  char __user      *buff,
00560                                  size_t           count,
00561                                  loff_t           *offp)
00562 {
00563     struct rtnrt_memcopy_desc   copy = { rtnrt_copy_to_user, NULL };
00564     return most_sync_read(filp, buff, count, &copy);
00565 }
00566 
00567 /*
00568  * see header 
00569  */
00570 ssize_t most_sync_write(struct file                 *filp,
00571                         void                        *buff,
00572                         size_t                      count,
00573                         struct rtnrt_memcopy_desc   *copy)
00574 {
00575     struct most_sync_file       *file = filp->private_data;
00576     struct most_sync_dev        *sync_dev = file->sync_dev;
00577     size_t                      copied = 0;
00578     int                         err;
00579 
00580     pr_sync_debug(PR "Write called, count = %d\n", count);
00581 
00582     /* optimisation */
00583     return_value_if_fails(count != 0, 0);
00584 
00585     /* check if we can write */
00586     if (!file->tx_running) {
00587         rtnrt_err(PR "Cannot write at this time\n");
00588         return -EBUSY;
00589     }
00590 
00591     down_read(&sync_dev->config_lock_tx);
00592     
00593     while (copied != count) {
00594         err = txbuf_put(sync_dev->sw_transmit_buf, file->writer_index, 
00595                 file->part_tx, buff + copied, count - copied, copy);
00596         if (unlikely(err < 0)) {
00597             rtnrt_err(PR "Error in txbuf_put: %d\n", err);
00598             goto out_write;
00599         }
00600         
00601         copied += err;
00602         if (err == 0) {
00603             err = wait_event_interruptible(sync_dev->tx_queue, 
00604                      !txbuf_is_full(sync_dev->sw_transmit_buf, 
00605                          file->writer_index) );
00606             if (unlikely(err < 0)) {
00607                 pr_sync_debug(PR "wait_event_interruptible returned"
00608                         " with %d\n", err);
00609                 copied = err;
00610                 goto out_write;
00611             }
00612         }
00613     }
00614 
00615 out_write:
00616     up_read(&sync_dev->config_lock_tx);
00617     pr_sync_debug(PR "Finishing most_sync_do_write %d with %d\n",
00618             file->writer_index, copied);
00619 
00620     return copied;
00621 }
00622 
00632 static ssize_t most_sync_do_write(struct file         *filp,
00633                                   const char __user   *buff,
00634                                   size_t              count,
00635                                   loff_t              *offp)
00636 {
00637     struct rtnrt_memcopy_desc copy = { rtnrt_copy_from_user, NULL };
00638     return most_sync_write(filp, (void *)buff, count, &copy);
00639 }
00640 
00650 static int most_sync_do_ioctl(struct inode        *inode, 
00651                               struct file         *filp,
00652                               unsigned int        cmd,
00653                               unsigned long       arg)
00654 {
00655     int err  = 0;
00656 
00657     /*
00658      * extract the type and number bitfields, and don't decode
00659      * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
00660      */
00661     if (unlikely((_IOC_TYPE(cmd) != MOST_SYNC_IOCTL_MAGIC))) {
00662         return -ENOTTY;
00663     }
00664 
00665     /*
00666      * the direction is a bitmask, and VERIFY_WRITE catches R/W transfers.
00667      * Type is user-orignted, while access_ok is kernel-oriented, so the concept
00668      * of read and write is reversed
00669      */
00670     if (_IOC_DIR(cmd) & _IOC_READ) {
00671         err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
00672     } else if (_IOC_DIR(cmd) & _IOC_WRITE) {
00673         err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
00674     }
00675 
00676     /* check the rror */
00677     if (err) {
00678         return -EFAULT;
00679     }
00680 
00681     /* now do the command */
00682     switch (cmd) {
00683         case MOST_SYNC_SETUP_RX:
00684             return most_sync_do_setup_rx(filp, arg);
00685 
00686         case MOST_SYNC_SETUP_TX:
00687             return most_sync_do_setup_tx(filp, arg);
00688 
00689         default:
00690             return -ENOTTY;
00691     }
00692 
00693     return 0;
00694 }
00695 
00696 /*
00697  * see header
00698  */
00699 int most_sync_setup_rx(struct file              *filp, 
00700                        struct frame_part        *frame_part)
00701 {
00702     struct most_sync_file   *sync_file = (void *)filp->private_data;
00703     struct most_sync_dev    *sync_dev = sync_file->sync_dev;
00704     int                     err = 0;
00705 
00706     down_write(&sync_dev->config_lock_rx);
00707 
00708     /* if it's running, stop it*/
00709     if (sync_file->rx_running) {
00710         most_sync_stop_rx(sync_file);
00711     }
00712 
00713     most_sync_setup_rx_common(*frame_part, sync_file, sync_dev, hw_rx_buffer_size, 
00714                               sw_rx_buffer_size, err, most_sync_file);
00715 
00716     up_write(&sync_dev->config_lock_rx);
00717 
00718     return err;
00719 }
00720 
00727 static int most_sync_do_setup_rx(struct file        *filp,
00728                                  unsigned long      ioctl_arg)
00729 {
00730     struct frame_part       *arg = (struct frame_part __user *)ioctl_arg;
00731     int                     err = 0;
00732     struct frame_part       param;
00733 
00734     /* get the argument */
00735     err = __copy_from_user(&param, arg, sizeof(struct frame_part));
00736     if (unlikely(err != 0)) {
00737         return -EFAULT;
00738     }
00739 
00740     return most_sync_setup_rx(filp, &param);
00741 }
00742 
00743 /*
00744  * see header
00745  */
00746 int most_sync_setup_tx(struct file          *filp,
00747                        struct frame_part    *frame_part)
00748 {
00749     struct most_sync_file   *sync_file = (void *)filp->private_data;
00750     struct most_sync_dev    *sync_dev = sync_file->sync_dev;
00751     int                     err;
00752 
00753     down_write(&sync_dev->config_lock_tx);
00754 
00755     /* if it's running, stop it*/
00756     if (sync_file->tx_running) {
00757         most_sync_stop_tx(sync_file);
00758     }
00759 
00760     most_sync_setup_tx_common(*frame_part, sync_file, sync_dev, hw_tx_buffer_size, 
00761                               sw_tx_buffer_size, err, most_sync_file);
00762 
00763     up_write(&sync_dev->config_lock_tx);
00764 
00765     return 0;
00766 }
00767 
00774 static inline int most_sync_do_setup_tx(struct file *filp, unsigned long ioctl_arg)
00775 {
00776     struct frame_part       *arg         = (struct frame_part __user *)ioctl_arg;
00777     int                     err          = 0;
00778     struct frame_part       param;
00779 
00780     /* get the argument */
00781     err = __copy_from_user(&param, arg, sizeof(struct frame_part));
00782     if (unlikely(err != 0)) {
00783         return -EFAULT;
00784     }
00785 
00786     return most_sync_setup_tx(filp, &param);
00787 }
00788     
00794 static int __init most_sync_init(void)
00795 {
00796     int err;
00797 
00798     rtnrt_info("Loading module %s, version %s\n", DRIVER_NAME, version);
00799     print_measuring_warning();
00800 
00801     /* register driver */
00802     err = most_register_high_driver(&most_sync_high_driver);
00803     if (unlikely(err != 0)) {
00804         return err;
00805     }
00806 
00807     return 0;
00808 }
00809 
00813 static void __exit most_sync_exit(void)
00814 {
00815     most_deregister_high_driver(&most_sync_high_driver);
00816 
00817     rtnrt_info("Unloading module %s, version %s\n", DRIVER_NAME, version);
00818 }
00819 
00820 
00821 #ifndef DOXYGEN
00822 EXPORT_SYMBOL(hw_tx_buffer_size);
00823 EXPORT_SYMBOL(hw_rx_buffer_size);
00824 EXPORT_SYMBOL(sw_tx_buffer_size);
00825 EXPORT_SYMBOL(sw_rx_buffer_size);
00826 
00827 EXPORT_SYMBOL(most_sync_read);
00828 EXPORT_SYMBOL(most_sync_write);
00829 EXPORT_SYMBOL(most_sync_setup_rx);
00830 EXPORT_SYMBOL(most_sync_setup_tx);
00831 
00832 MODULE_LICENSE("GPL");
00833 MODULE_AUTHOR("Bernhard Walle");
00834 MODULE_VERSION("$Rev: 639 $");
00835 MODULE_DESCRIPTION("Driver for MOST Synchronous data.");
00836 module_init(most_sync_init);
00837 module_exit(most_sync_exit);
00838 #endif
00839 
00840 /* vim: set ts=4 et sw=4: */

Generated on Fri Mar 9 14:48:58 2007 for MOST Linux Drivers (Linux and RTAI) by  doxygen 1.5.0