fp@27: /****************************************************************************** fp@27: * fp@54: * m o d u l e . c fp@27: * fp@27: * EtherCAT-Master-Treiber fp@27: * fp@27: * Autoren: Wilhelm Hagemeister, Florian Pose fp@27: * fp@27: * $Id$ fp@27: * fp@27: * (C) Copyright IgH 2005 fp@27: * Ingenieurgemeinschaft IgH fp@27: * Heinz-Bäcker Str. 34 fp@27: * D-45356 Essen fp@27: * Tel.: +49 201/61 99 31 fp@27: * Fax.: +49 201/61 98 36 fp@27: * E-mail: sp@igh-essen.com fp@27: * fp@39: *****************************************************************************/ fp@27: fp@27: #include fp@27: #include fp@27: #include fp@27: fp@54: #include "master.h" fp@54: #include "device.h" fp@54: fp@54: /*****************************************************************************/ fp@54: fp@54: int __init ec_init_module(void); fp@54: void __exit ec_cleanup_module(void); fp@52: fp@39: /*****************************************************************************/ fp@39: fp@39: #define LIT(X) #X fp@39: #define STR(X) LIT(X) fp@39: fp@39: #define COMPILE_INFO "Revision " STR(EC_REV) \ fp@39: ", compiled by " STR(EC_USER) \ fp@39: " at " STR(EC_DATE) fp@39: fp@39: /*****************************************************************************/ fp@27: fp@54: int ec_master_count = 1; fp@54: ec_master_t *ec_masters = NULL; fp@54: int *ec_masters_reserved = NULL; fp@27: fp@39: /*****************************************************************************/ fp@39: fp@39: MODULE_AUTHOR ("Wilhelm Hagemeister ," fp@39: "Florian Pose "); fp@27: MODULE_DESCRIPTION ("EtherCAT master driver module"); fp@27: MODULE_LICENSE("GPL"); fp@34: MODULE_VERSION(COMPILE_INFO); fp@27: fp@54: module_param(ec_master_count, int, 1); fp@54: MODULE_PARM_DESC(ec_master_count, "Number of EtherCAT master to initialize."); fp@27: fp@39: /*****************************************************************************/ fp@27: fp@27: /** fp@27: Init-Funktion des EtherCAT-Master-Treibermodules fp@27: fp@54: Initialisiert soviele Master, wie im Parameter ec_master_count fp@27: angegeben wurde (Default ist 1). fp@27: fp@27: @returns 0, wenn alles o.k., -1 bei ungueltiger Anzahl Master fp@54: oder zu wenig Speicher. fp@54: */ fp@54: fp@54: int __init ec_init_module(void) fp@27: { fp@27: unsigned int i; fp@27: fp@34: printk(KERN_ERR "EtherCAT: Master driver, %s\n", COMPILE_INFO); fp@27: fp@54: if (ec_master_count < 1) { fp@39: printk(KERN_ERR "EtherCAT: Error - Illegal" fp@54: " ec_master_count: %i\n", ec_master_count); fp@27: return -1; fp@27: } fp@27: fp@27: printk(KERN_ERR "EtherCAT: Initializing %i EtherCAT master(s)...\n", fp@54: ec_master_count); fp@54: fp@54: if ((ec_masters = fp@54: (ec_master_t *) kmalloc(sizeof(ec_master_t) fp@54: * ec_master_count, fp@54: GFP_KERNEL)) == NULL) { fp@39: printk(KERN_ERR "EtherCAT: Could not allocate" fp@39: " memory for EtherCAT master(s)!\n"); fp@39: return -1; fp@39: } fp@39: fp@54: if ((ec_masters_reserved = fp@54: (int *) kmalloc(sizeof(int) * ec_master_count, fp@39: GFP_KERNEL)) == NULL) { fp@39: printk(KERN_ERR "EtherCAT: Could not allocate" fp@39: " memory for reservation flags!\n"); fp@54: kfree(ec_masters); fp@33: return -1; fp@33: } fp@33: fp@54: for (i = 0; i < ec_master_count; i++) fp@27: { fp@54: ec_master_init(&ec_masters[i]); fp@54: ec_masters_reserved[i] = 0; fp@27: } fp@27: fp@27: printk(KERN_ERR "EtherCAT: Master driver initialized.\n"); fp@27: fp@27: return 0; fp@27: } fp@27: fp@39: /*****************************************************************************/ fp@27: fp@27: /** fp@27: Cleanup-Funktion des EtherCAT-Master-Treibermoduls fp@27: fp@27: Entfernt alle Master-Instanzen. fp@27: */ fp@27: fp@54: void __exit ec_cleanup_module(void) fp@27: { fp@27: unsigned int i; fp@27: fp@27: printk(KERN_ERR "EtherCAT: Cleaning up master driver...\n"); fp@27: fp@54: if (ec_masters) fp@27: { fp@54: for (i = 0; i < ec_master_count; i++) fp@27: { fp@54: if (ec_masters_reserved[i]) { fp@39: printk(KERN_WARNING "EtherCAT: Warning -" fp@39: " Master %i is still in use!\n", i); fp@33: } fp@33: fp@54: ec_master_clear(&ec_masters[i]); fp@27: } fp@27: fp@54: kfree(ec_masters); fp@27: } fp@27: fp@27: printk(KERN_ERR "EtherCAT: Master driver cleaned up.\n"); fp@27: } fp@27: fp@54: /****************************************************************************** fp@54: * fp@54: * Treiberschnittstelle fp@54: * fp@54: *****************************************************************************/ fp@33: fp@33: /** fp@33: Setzt das EtherCAT-Geraet, auf dem der Master arbeitet. fp@33: fp@33: fp@33: @param master Der EtherCAT-Master fp@33: @param device Das EtherCAT-Geraet fp@33: @return 0, wenn alles o.k., fp@54: < 0, wenn bereits ein Geraet registriert fp@54: oder das Geraet nicht geoeffnet werden konnte. fp@54: */ fp@54: fp@54: ec_device_t *EtherCAT_dev_register(unsigned int master_index, fp@54: struct net_device *dev, fp@54: irqreturn_t (*isr)(int, void *, fp@54: struct pt_regs *), fp@54: struct module *module) fp@54: { fp@54: ec_device_t *ecd; fp@55: ec_master_t *master; fp@54: fp@54: if (master_index >= ec_master_count) { fp@54: printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", master_index); fp@54: return NULL; fp@54: } fp@54: fp@54: if (!dev) { fp@54: printk("EtherCAT: Device is NULL!\n"); fp@54: return NULL; fp@54: } fp@54: fp@55: master = ec_masters + master_index; fp@55: fp@55: if (master->device_registered) { fp@54: printk(KERN_ERR "EtherCAT: Master %i already has a device!\n", fp@54: master_index); fp@54: return NULL; fp@54: } fp@54: fp@55: ecd = &master->device; fp@54: fp@54: if (ec_device_init(ecd) < 0) { fp@54: return NULL; fp@54: } fp@54: fp@54: ecd->dev = dev; fp@54: ecd->tx_skb->dev = dev; fp@54: ecd->rx_skb->dev = dev; fp@54: ecd->isr = isr; fp@54: ecd->module = module; fp@54: fp@55: master->device_registered = 1; fp@55: fp@54: return ecd; fp@33: } fp@33: fp@39: /*****************************************************************************/ fp@33: fp@33: /** fp@33: Loescht das EtherCAT-Geraet, auf dem der Master arbeitet. fp@33: fp@33: @param master Der EtherCAT-Master fp@33: @param device Das EtherCAT-Geraet fp@33: */ fp@33: fp@55: void EtherCAT_dev_unregister(unsigned int master_index, ec_device_t *ecd) fp@55: { fp@55: ec_master_t *master; fp@55: fp@54: if (master_index >= ec_master_count) { fp@54: printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n", master_index); fp@33: return; fp@33: } fp@33: fp@55: master = ec_masters + master_index; fp@55: fp@55: if (!master->device_registered || &master->device != ecd) { fp@55: printk(KERN_ERR "EtherCAT: Unable to unregister device!\n"); fp@55: return; fp@55: } fp@55: fp@55: master->device_registered = 0; fp@55: ec_device_clear(ecd); fp@54: } fp@54: fp@54: /****************************************************************************** fp@54: * fp@54: * Echtzeitschnittstelle fp@54: * fp@54: *****************************************************************************/ fp@33: fp@33: /** fp@33: Reserviert einen bestimmten EtherCAT-Master und das zugehörige Gerät. fp@33: fp@33: Gibt einen Zeiger auf den reservierten EtherCAT-Master zurueck. fp@27: fp@27: @param index Index des gewuenschten Masters fp@27: @returns Zeiger auf EtherCAT-Master oder NULL, wenn Parameter ungueltig. fp@27: */ fp@27: fp@55: ec_master_t *EtherCAT_rt_request_master(unsigned int index) fp@54: { fp@54: ec_master_t *master; fp@54: fp@54: if (index < 0 || index >= ec_master_count) { fp@27: printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index); fp@54: goto req_return; fp@54: } fp@54: fp@54: if (ec_masters_reserved[index]) { fp@33: printk(KERN_ERR "EtherCAT: Master %i already in use!\n", index); fp@54: goto req_return; fp@54: } fp@54: fp@54: master = &ec_masters[index]; fp@54: fp@54: if (!master->device_registered) { fp@39: printk(KERN_ERR "EtherCAT: Master %i has no device assigned yet!\n", fp@39: index); fp@54: goto req_return; fp@54: } fp@54: fp@54: if (!try_module_get(master->device.module)) { fp@33: printk(KERN_ERR "EtherCAT: Could not reserve device module!\n"); fp@54: goto req_return; fp@54: } fp@54: fp@54: if (ec_master_open(master) < 0) { fp@54: printk(KERN_ERR "EtherCAT: Could not open device!\n"); fp@54: goto req_module_put; fp@54: } fp@54: fp@54: if (ec_scan_for_slaves(master) != 0) { fp@54: printk(KERN_ERR "EtherCAT: Could not scan for slaves!\n"); fp@54: goto req_close; fp@54: } fp@54: fp@54: ec_masters_reserved[index] = 1; fp@33: printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index); fp@33: fp@54: return master; fp@54: fp@54: req_close: fp@54: ec_master_close(master); fp@54: fp@54: req_module_put: fp@54: module_put(master->device.module); fp@54: fp@54: req_return: fp@54: return NULL; fp@27: } fp@27: fp@39: /*****************************************************************************/ fp@33: fp@33: /** fp@42: Gibt einen zuvor angeforderten EtherCAT-Master wieder frei. fp@33: fp@33: @param master Zeiger auf den freizugebenden EtherCAT-Master. fp@33: */ fp@33: fp@54: void EtherCAT_rt_release_master(ec_master_t *master) fp@33: { fp@33: unsigned int i; fp@33: fp@54: for (i = 0; i < ec_master_count; i++) fp@33: { fp@54: if (&ec_masters[i] == master) fp@33: { fp@54: if (!master->device_registered) { fp@33: printk(KERN_WARNING "EtherCAT: Could not release device" fp@33: "module because of no device!\n"); fp@33: return; fp@33: } fp@33: fp@54: ec_master_close(master); fp@56: ec_master_reset(master); fp@56: fp@54: module_put(master->device.module); fp@54: ec_masters_reserved[i] = 0; fp@33: fp@33: printk(KERN_INFO "EtherCAT: Released master %i.\n", i); fp@33: fp@33: return; fp@33: } fp@33: } fp@33: fp@42: printk(KERN_WARNING "EtherCAT: Master %X was never requested!\n", fp@33: (unsigned int) master); fp@33: } fp@33: fp@39: /*****************************************************************************/ fp@54: fp@54: module_init(ec_init_module); fp@54: module_exit(ec_cleanup_module); fp@54: fp@54: EXPORT_SYMBOL(EtherCAT_dev_register); fp@54: EXPORT_SYMBOL(EtherCAT_dev_unregister); fp@54: EXPORT_SYMBOL(EtherCAT_rt_request_master); fp@54: EXPORT_SYMBOL(EtherCAT_rt_release_master); fp@54: fp@54: /*****************************************************************************/ fp@55: fp@55: /* Emacs-Konfiguration fp@55: ;;; Local Variables: *** fp@55: ;;; c-basic-offset:2 *** fp@55: ;;; End: *** fp@55: */