00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028 #ifdef HAVE_CONFIG_H
00029 #include "config/config.h"
00030 #endif
00031
00032 #include <linux/module.h>
00033 #include <linux/fs.h>
00034 #include <linux/spinlock.h>
00035 #include <linux/interrupt.h>
00036 #include <linux/signal.h>
00037
00038 #include <asm/siginfo.h>
00039 #include <asm/uaccess.h>
00040 #include <asm/io.h>
00041
00042 #include "most-pci.h"
00043 #include "most-netservice.h"
00044 #include "most-constants.h"
00045 #include "most-base.h"
00046
00050 #define DRIVER_NAME "most-netservice"
00051
00055 #define PR DRIVER_NAME ": "
00056
00057
00061 static char *version = "$Rev: 641 $";
00062
00063
00064 static int most_nets_open (struct inode *, struct file *);
00065 static int most_nets_release (struct inode *inode, struct file *file);
00066 static int most_nets_ioctl (struct inode *, struct file *,
00067 unsigned int, unsigned long);
00068 static void process_sigsend_handler (unsigned long);
00069
00070
00071 static int ioctl_write_register (struct most_nets_dev *, unsigned long);
00072 static int ioctl_read_register (struct most_nets_dev *, unsigned long);
00073 static int ioctl_write_regblock (struct most_nets_dev *, unsigned long);
00074 static int ioctl_read_regblock (struct most_nets_dev *, unsigned long);
00075 static int ioctl_read_int (struct most_nets_dev *);
00076 static int ioctl_irq_set (struct most_nets_dev *, unsigned long);
00077 static int ioctl_irq_reset (struct most_nets_dev *, unsigned long);
00078 static int ioctl_reset (struct most_nets_dev *);
00079
00080
00081
00082
00086 struct most_nets_dev *most_nets_devices[MOST_DEVICE_NUMBER];
00087
00088
00092 static struct file_operations most_nets_file_operations = {
00093 .owner = THIS_MODULE,
00094 .open = most_nets_open,
00095 .ioctl = most_nets_ioctl,
00096 .release = most_nets_release
00097 };
00098
00104 static unsigned long cards_to_send_interrupt = 0;
00105
00110 static DECLARE_TASKLET(sigsend_tasklet, process_sigsend_handler, 0);
00111
00117 DEFINE_NRTSIG(nrt_signal);
00118
00119
00120
00129 static void process_sigsend_handler(unsigned long data)
00130 {
00131 int i;
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 for (i = 0; i < MOST_DEVICE_NUMBER; i++) {
00142 if (test_and_clear_bit(i, &cards_to_send_interrupt)) {
00143 struct most_nets_dev* nets_dev = most_nets_devices[i];
00144 int data = 0;
00145
00146 assert(nets_dev != NULL);
00147
00148 if (nets_dev->task == NULL) {
00149 continue;
00150 }
00151 if ((nets_dev->intstatus & ISMAINT) &&
00152 (nets_dev->signo_async != 0)) {
00153 data = MNS_AINT;
00154 }
00155 if ((nets_dev->intstatus & (ISMINT)) && nets_dev->signo != 0) {
00156 data = MNS_INT;
00157 }
00158
00159 assert(data != 0);
00160
00161
00162 most_kill(nets_dev->signo, nets_dev->task, data);
00163
00164 nets_dev->intstatus = 0;
00165 }
00166 }
00167 }
00168
00176 static int most_nets_open(struct inode *inode, struct file *filp)
00177 {
00178 int err = 0;
00179 struct most_nets_dev *dev;
00180
00181 dev = container_of(inode->i_cdev, struct most_nets_dev, cdev);
00182 most_manage_usage(dev->most_dev, 1);
00183
00184 pr_nets_debug(PR "most_nets_open called for PCI card %d\n",
00185 MOST_DEV_CARDNUMBER(dev->most_dev));
00186
00187
00188 filp->private_data = dev;
00189
00190
00191 if (!atomic_inc_and_test(&dev->open_count)) {
00192 rtnrt_info(PR "Only one device allowed to access "
00193 "MostNetService device.\n");
00194 err = -EBUSY;
00195 goto out_dec;
00196 }
00197
00198 return 0;
00199
00200 out_dec:
00201 atomic_dec(&dev->open_count);
00202 most_manage_usage(dev->most_dev, -1);
00203
00204 return err;
00205 }
00206
00207
00219 static int most_nets_ioctl(struct inode *inode,
00220 struct file *file,
00221 unsigned int cmd,
00222 unsigned long arg)
00223 {
00224 struct most_nets_dev *dev = (struct most_nets_dev *)file->private_data;
00225 int err = 0;
00226
00227
00228
00229
00230
00231 if ((_IOC_TYPE(cmd) != MOST_NETS_IOCTL_MAGIC) ||
00232 (_IOC_NR(cmd) > MOST_NETS_MAXIOCTL)) {
00233 return -ENOTTY;
00234 }
00235
00236
00237
00238
00239
00240
00241 if (_IOC_DIR(cmd) & _IOC_READ) {
00242 err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
00243 } else if (_IOC_DIR(cmd) & _IOC_WRITE) {
00244 err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
00245 }
00246
00247
00248 if (err) {
00249 return -EFAULT;
00250 }
00251
00252
00253 switch (cmd)
00254 {
00255 case MOST_NETS_WRITEREG:
00256 return ioctl_write_register(dev, arg);
00257
00258 case MOST_NETS_READREG:
00259 return ioctl_read_register(dev, arg);
00260
00261 case MOST_NETS_WRITEREG_BLOCK:
00262 return ioctl_write_regblock(dev, arg);
00263
00264 case MOST_NETS_READREG_BLOCK:
00265 return ioctl_read_regblock(dev, arg);
00266
00267 case MOST_NETS_READ_INT:
00268 return ioctl_read_int(dev);
00269
00270 case MOST_NETS_IRQ_SET:
00271 return ioctl_irq_set(dev, arg);
00272
00273 case MOST_NETS_IRQ_RESET:
00274 return ioctl_irq_reset(dev, arg);
00275
00276 case MOST_NETS_RESET:
00277 return ioctl_reset(dev);
00278
00279 default:
00280 return -ENOTTY;
00281 }
00282
00283 return 0;
00284 }
00285
00286
00294 static int most_nets_release(struct inode *inode, struct file *filp)
00295 {
00296 struct most_nets_dev *dev = (struct most_nets_dev *)filp->private_data;
00297
00298 pr_nets_debug(PR "most_nets_release called for PCI card %d\n",
00299 MOST_DEV_CARDNUMBER(dev->most_dev));
00300
00301
00302 atomic_dec(&dev->open_count);
00303 most_manage_usage(dev->most_dev, -1);
00304
00305 return 0;
00306 }
00307
00308
00316 static int ioctl_write_register(struct most_nets_dev *dev,
00317 unsigned long ioctl_arg)
00318 {
00319 int ret = 0;
00320 struct single_transfer_arg *arg = (void *)ioctl_arg;
00321 struct single_transfer_arg param;
00322
00323
00324 ret = __copy_from_user(¶m, arg, sizeof(struct single_transfer_arg));
00325 if (unlikely(ret != 0)) {
00326 return -EFAULT;
00327 }
00328
00329 pr_ioctl_debug(PR "MOST IOCTL WRITE 0x%x = 0x%x\n",
00330 param.address, param.value);
00331
00332 ret = most_writereg8104(dev->most_dev, ¶m.value, 1, param.address);
00333
00334 return 0;
00335 }
00336
00337
00345 static int ioctl_read_register(struct most_nets_dev *dev,
00346 unsigned long ioctl_arg)
00347 {
00348 int ret = 0;
00349 struct single_transfer_arg *arg = (void *)ioctl_arg;
00350 struct single_transfer_arg param;
00351
00352
00353 ret = __copy_from_user(¶m, arg, sizeof(struct single_transfer_arg));
00354 if (unlikely(ret != 0)) {
00355 return -EFAULT;
00356 }
00357
00358 ret = most_readreg8104(dev->most_dev, ¶m.value, 1, param.address);
00359 if (unlikely(ret < 0)) {
00360 return ret;
00361 }
00362
00363 pr_ioctl_debug(PR "MOST IOCTL READ 0x%x = 0x%x\n",
00364 param.address, param.value);
00365
00366 ret = __copy_to_user(arg, ¶m, sizeof(struct single_transfer_arg));
00367 if (unlikely(ret != 0)) {
00368 return -EFAULT;
00369 }
00370
00371 return 0;
00372 }
00373
00383 static int ioctl_read_regblock(struct most_nets_dev *dev,
00384 unsigned long ioctl_arg)
00385 {
00386 int ret = 0;
00387 struct block_transfer_arg *arg = (void *)ioctl_arg;
00388 struct block_transfer_arg param;
00389
00390
00391 ret = __copy_from_user(¶m, arg, sizeof(struct block_transfer_arg));
00392 if (unlikely(ret != 0)) {
00393 return -EFAULT;
00394 }
00395
00396
00397 ret = most_readreg8104(dev->most_dev, dev->buffer, param.count,
00398 param.address);
00399 if (ret < 0) {
00400 return ret;
00401 }
00402
00403
00404 ret = copy_to_user(param.data, dev->buffer, ret);
00405 if (ret < 0) {
00406 return -EFAULT;
00407 }
00408
00409 pr_ioctl_debug(PR "MOST READBLOCK 0x%x - 0x%x\n",
00410 param.address, param.address + param.count);
00411
00412 return param.count;
00413 }
00414
00415
00425 static int ioctl_write_regblock(struct most_nets_dev *dev,
00426 unsigned long ioctl_arg)
00427 {
00428 int ret = 0;
00429 struct block_transfer_arg *arg = (void *)ioctl_arg;
00430 struct block_transfer_arg param;
00431
00432
00433 ret = __copy_from_user(¶m, arg, sizeof(struct block_transfer_arg));
00434 if (unlikely(ret != 0)) {
00435 return -EFAULT;
00436 }
00437
00438
00439 ret = copy_from_user(dev->buffer, (unsigned char __user *)param.data,
00440 param.count);
00441
00442 #ifdef IOCTL_DEBUG
00443 {
00444 int i;
00445 for (i = 0; i < param.count; i++) {
00446 pr_ioctl_debug(PR "MOST WRITEBLOCK 0x%x = 0x%x\n",
00447 param.address + i, *(dev->buffer + i));
00448 }
00449 }
00450 #endif
00451
00452 ret = most_writereg8104(dev->most_dev, dev->buffer, param.count,
00453 param.address);
00454 if (ret < 0) {
00455 return -EFAULT;
00456 }
00457
00458 return param.count;
00459 }
00460
00461
00470 static int ioctl_read_int(struct most_nets_dev *dev)
00471 {
00472 int ret = 0;
00473
00474 ret = most_readreg(dev->most_dev, MOST_PCI_INTSTATUS_REG) & ISMINT;
00475
00476 if (ret < 0) {
00477 return -EFAULT;
00478 }
00479
00480 pr_ioctl_debug(PR "MOST IOCTL READ_INT = %d\n", ret ? true : false);
00481
00482 return ret ? true : false;
00483 }
00484
00496 static int ioctl_irq_set(struct most_nets_dev *dev,
00497 unsigned long ioctl_arg)
00498 {
00499 struct interrupt_set_arg param;
00500 struct interrupt_set_arg *arg = (void *)ioctl_arg;
00501 int ret = 0;
00502
00503
00504 ret = __copy_from_user(¶m, arg, sizeof(struct interrupt_set_arg));
00505 if (unlikely(ret != 0)) {
00506 return -EFAULT;
00507 }
00508
00509
00510 if ((param.signo != 0) && !is_between_excl(param.signo,
00511 SIGRTMIN, SIGRTMAX)) {
00512 rtnrt_err(PR "Signal number out of range: %d\n", param.signo);
00513 return -EINVAL;
00514 }
00515
00516 pr_ioctl_debug(PR "MOST IRQ SET %d\n", param.signo);
00517
00518 dev->task = param.sigmask == 0 ? NULL : current;
00519 dev->signo = param.signo;
00520
00521 dev->intmask = 0;
00522 if (param.sigmask & MNS_INT) {
00523 dev->intmask |= IEMINT;
00524 }
00525 if (param.sigmask & MNS_AINT) {
00526 dev->intmask |= IEMINT;
00527 }
00528
00529 most_intset(dev->most_dev, dev->intmask, IEMAINT | IEMINT, NULL);
00530
00531 return 0;
00532 }
00533
00545 static int ioctl_irq_reset(struct most_nets_dev *dev,
00546 unsigned long ioctl_arg)
00547 {
00548 int ret = 0;
00549 unsigned char mask;
00550
00551
00552 ret = __get_user(mask, (unsigned char __user *)ioctl_arg);
00553 if (unlikely(ret != 0)) {
00554 return -EFAULT;
00555 }
00556
00557
00558 ret = most_writereg8104(dev->most_dev, &mask, 1, MSGC);
00559 if (unlikely(ret != 1)) {
00560 return ret;
00561 }
00562
00563 pr_ioctl_debug(PR "MOST IRQ RESET\n");
00564
00565
00566 most_intset(dev->most_dev, dev->intmask, IEMAINT | IEMINT, NULL);
00567
00568 return 0;
00569 }
00570
00571
00577 static int ioctl_reset(struct most_nets_dev *dev)
00578 {
00579 most_reset(dev->most_dev);
00580 return 0;
00581 }
00582
00583
00590 static int nets_probe(struct most_dev *most_dev)
00591 {
00592 int number = MOST_DEV_CARDNUMBER(most_dev);
00593 struct most_nets_dev *dev;
00594 int err;
00595 dev_t devno = MKDEV(MOST_DEV_MAJOR(most_dev),
00596 number + MOST_NETS_MINOR_OFFSET);
00597 char buffer[10];
00598
00599 return_value_if_fails_dbg(number < MOST_DEVICE_NUMBER, -EINVAL);
00600
00601 print_dev_t(buffer, devno);
00602 pr_nets_debug(PR "nets_probe called, registering %s", buffer);
00603
00604
00605 dev = (struct most_nets_dev *)kmalloc(sizeof(struct most_nets_dev), GFP_KERNEL);
00606 if (unlikely(dev == NULL)) {
00607 printk(KERN_WARNING PR "Allocation of private data "
00608 "structure failed\n");
00609 err = -ENOMEM;
00610 goto out;
00611 }
00612 memset(dev, 0, sizeof(struct most_nets_dev));
00613
00614
00615 dev->most_dev = most_dev;
00616 atomic_set(&dev->open_count, -MAX_OPEN_PROCESSES);
00617 dev->task = NULL;
00618
00619
00620 cdev_init(&dev->cdev, &most_nets_file_operations);
00621 dev->cdev.owner = THIS_MODULE;
00622 err = cdev_add(&dev->cdev, devno, 1);
00623 if (unlikely(err)) {
00624 printk(KERN_WARNING PR "cdev_add failed\n");
00625 goto out_free;
00626 }
00627
00628
00629 most_nets_devices[number] = dev;
00630
00631 return 0;
00632
00633 out_free:
00634 kfree(dev);
00635 out:
00636 return err;
00637 }
00638
00639
00646 int nets_remove(struct most_dev *dev)
00647 {
00648 int number = MOST_DEV_CARDNUMBER(dev);
00649 struct most_nets_dev *nets_dev = most_nets_devices[number];
00650
00651 pr_nets_debug(PR "nets_remove called, number = %d\n", number);
00652
00653
00654 cdev_del(&nets_dev->cdev);
00655
00656
00657 most_nets_devices[number] = NULL;
00658 kfree(nets_dev);
00659
00660 return 0;
00661 }
00662
00670 static inline void nrtsig_handler(rtnrt_nrtsig_t nrt_sig)
00671 {
00672 tasklet_schedule(&sigsend_tasklet);
00673 }
00674
00685 static void nets_int_handler(struct most_dev *dev,
00686 unsigned int intstatus)
00687 {
00688 int card = MOST_DEV_CARDNUMBER(dev);
00689 struct most_nets_dev *nets_dev = most_nets_devices[card];
00690
00691 assert(nets_dev != NULL);
00692
00693
00694 set_bit(card, &cards_to_send_interrupt);
00695
00696
00697 nets_dev->intstatus |= intstatus;
00698
00699
00700 most_intset(dev, 0, IEMINT | IEMINT, NULL);
00701
00702
00703 rtnrt_nrtsig_action(&nrt_signal, nrtsig_handler);
00704 }
00705
00706
00711 static struct most_high_driver most_netservice_high_driver = {
00712 .name = "most-netservice",
00713 .sema_list = LIST_HEAD_INIT(most_netservice_high_driver.sema_list),
00714 .spin_list = LIST_HEAD_INIT(most_netservice_high_driver.spin_list),
00715 .probe = nets_probe,
00716 .remove = nets_remove,
00717 .int_handler = nets_int_handler,
00718 .interrupt_mask = (IEMAINT | IEMINT)
00719 };
00720
00721
00727 static int __init most_nets_init(void)
00728 {
00729 int err;
00730
00731 rtnrt_info("Loading module %s, version %s\n", DRIVER_NAME, version);
00732
00733
00734 err = most_register_high_driver(&most_netservice_high_driver);
00735 if (unlikely(err != 0)) {
00736 return err;
00737 }
00738
00739 return rtnrt_nrtsig_init(&nrt_signal, nrtsig_handler);
00740 }
00741
00742
00746 static void __exit most_nets_exit(void)
00747 {
00748 most_deregister_high_driver(&most_netservice_high_driver);
00749
00750 rtnrt_info("Unloading module %s, version %s\n", DRIVER_NAME, version);
00751
00752 rtnrt_nrtsig_destroy(&nrt_signal);
00753 }
00754
00755 #ifndef DOXYGEN
00756 MODULE_LICENSE("GPL");
00757 MODULE_AUTHOR("Bernhard Walle");
00758 MODULE_VERSION("$Rev: 641 $");
00759 MODULE_DESCRIPTION("Support driver for NetService library in userspace ");
00760 module_init(most_nets_init);
00761 module_exit(most_nets_exit);
00762 #endif
00763
00764
00765