00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00065
00069 struct most_sync_dev *most_sync_devices[MOST_DEVICE_NUMBER];
00070
00071
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
00088
00089
00090
00091
00092 long sw_rx_buffer_size = STD_MOST_FRAMES_PER_SEC;
00093
00094
00095
00096
00097 long sw_tx_buffer_size = STD_MOST_FRAMES_PER_SEC;
00098
00099
00100
00101
00102 long hw_rx_buffer_size = 44;
00103
00104
00105
00106
00107 long hw_tx_buffer_size = 44;
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
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
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
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
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
00250 cdev_del(&sync_dev->cdev);
00251
00252
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
00288
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
00326
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
00409
00410
00411 file = kmalloc(sizeof(struct most_sync_file), GFP_KERNEL);
00412 if (unlikely(!file)) {
00413 return -ENOMEM;
00414 }
00415
00416
00417
00418
00419
00420 memset(file, 0, sizeof(struct most_sync_file));
00421 file->sync_dev = sync_dev;
00422 INIT_LIST_HEAD(&file->list);
00423
00424
00425 filp->private_data = file;
00426
00427
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
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
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
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
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
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
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
00511 return_value_if_fails(count != 0, 0);
00512
00513
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, ©);
00565 }
00566
00567
00568
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
00583 return_value_if_fails(count != 0, 0);
00584
00585
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, ©);
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
00659
00660
00661 if (unlikely((_IOC_TYPE(cmd) != MOST_SYNC_IOCTL_MAGIC))) {
00662 return -ENOTTY;
00663 }
00664
00665
00666
00667
00668
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
00677 if (err) {
00678 return -EFAULT;
00679 }
00680
00681
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
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
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
00735 err = __copy_from_user(¶m, arg, sizeof(struct frame_part));
00736 if (unlikely(err != 0)) {
00737 return -EFAULT;
00738 }
00739
00740 return most_sync_setup_rx(filp, ¶m);
00741 }
00742
00743
00744
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
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
00781 err = __copy_from_user(¶m, arg, sizeof(struct frame_part));
00782 if (unlikely(err != 0)) {
00783 return -EFAULT;
00784 }
00785
00786 return most_sync_setup_tx(filp, ¶m);
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
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