fp@27: /****************************************************************************** fp@27: * fp@27: * ec_module.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@27: ******************************************************************************/ fp@27: fp@27: #include fp@27: #include fp@27: #include fp@27: fp@27: #include "ec_module.h" fp@27: fp@27: /******************************************************************************/ fp@27: fp@34: #define LITERAL(X) #X fp@34: #define STRINGIFY(X) LITERAL(X) fp@34: fp@34: #define COMPILE_INFO "Revision " STRINGIFY(EC_REV) \ fp@34: ", compiled by " STRINGIFY(EC_USER) \ fp@34: " at " STRINGIFY(EC_DATE) fp@34: fp@34: /******************************************************************************/ fp@27: fp@27: int ecat_master_count = 1; fp@27: EtherCAT_master_t *ecat_masters = NULL; fp@33: int *ecat_masters_reserved = NULL; fp@27: fp@27: /******************************************************************************/ fp@27: fp@27: MODULE_AUTHOR ("Wilhelm Hagemeister , Florian Pose "); fp@27: MODULE_DESCRIPTION ("EtherCAT master driver module"); fp@27: MODULE_LICENSE("GPL"); fp@34: MODULE_VERSION(COMPILE_INFO); fp@27: fp@27: module_param(ecat_master_count, int, 1); fp@27: MODULE_PARM_DESC(ecat_master_count, "Number of EtherCAT master to initialize."); fp@27: fp@27: module_init(ecat_init_module); fp@27: module_exit(ecat_cleanup_module); fp@27: fp@33: EXPORT_SYMBOL(EtherCAT_register_device); fp@33: EXPORT_SYMBOL(EtherCAT_unregister_device); fp@33: EXPORT_SYMBOL(EtherCAT_request); fp@33: EXPORT_SYMBOL(EtherCAT_release); fp@27: fp@27: /******************************************************************************/ fp@27: fp@27: /** fp@27: Init-Funktion des EtherCAT-Master-Treibermodules fp@27: fp@27: Initialisiert soviele Master, wie im Parameter ecat_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@27: oder zu wenig Speicher. fp@27: */ fp@27: fp@27: int __init ecat_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@27: if (ecat_master_count < 1) fp@27: { fp@27: printk(KERN_ERR "EtherCAT: Error - Illegal ecat_master_count: %i\n", fp@27: ecat_master_count); fp@27: return -1; fp@27: } fp@27: fp@27: printk(KERN_ERR "EtherCAT: Initializing %i EtherCAT master(s)...\n", fp@27: ecat_master_count); fp@27: fp@27: if ((ecat_masters = (EtherCAT_master_t *) kmalloc(sizeof(EtherCAT_master_t) fp@27: * ecat_master_count, fp@27: GFP_KERNEL)) == NULL) fp@27: { fp@27: printk(KERN_ERR "EtherCAT: Could not allocate memory for EtherCAT master(s)!\n"); fp@27: return -1; fp@27: } fp@27: fp@33: if ((ecat_masters_reserved = (int *) kmalloc(sizeof(int) * ecat_master_count, fp@33: GFP_KERNEL)) == NULL) fp@33: { fp@33: printk(KERN_ERR "EtherCAT: Could not allocate memory for reservation flags!\n"); fp@33: kfree(ecat_masters); fp@33: return -1; fp@33: } fp@33: fp@27: for (i = 0; i < ecat_master_count; i++) fp@27: { fp@27: EtherCAT_master_init(&ecat_masters[i]); fp@33: ecat_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@27: /******************************************************************************/ 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@27: void __exit ecat_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@27: if (ecat_masters) fp@27: { fp@27: for (i = 0; i < ecat_master_count; i++) fp@27: { fp@33: if (ecat_masters_reserved[i]) { fp@33: printk(KERN_WARNING "EtherCAT: Warning - Master %i is still in use!\n", i); fp@33: } fp@33: fp@27: EtherCAT_master_clear(&ecat_masters[i]); fp@27: } fp@27: fp@27: kfree(ecat_masters); fp@27: } fp@27: fp@27: printk(KERN_ERR "EtherCAT: Master driver cleaned up.\n"); fp@27: } fp@27: fp@33: /***************************************************************/ fp@33: fp@33: /** fp@33: Setzt das EtherCAT-Geraet, auf dem der Master arbeitet. fp@33: fp@33: Registriert das Geraet beim Master, der es daraufhin oeffnet. 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@33: < 0, wenn bereits ein Geraet registriert fp@33: oder das Geraet nicht geoeffnet werden konnte. fp@33: */ fp@33: fp@33: int EtherCAT_register_device(int index, EtherCAT_device_t *device) fp@33: { fp@33: if (index < 0 || index >= ecat_master_count) fp@33: { fp@33: printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index); fp@33: return -1; fp@33: } fp@33: fp@33: return EtherCAT_master_open(&ecat_masters[index], device); fp@33: } fp@33: fp@33: /***************************************************************/ 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@33: void EtherCAT_unregister_device(int index, EtherCAT_device_t *device) fp@33: { fp@33: if (index < 0 || index >= ecat_master_count) fp@33: { fp@33: printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n", index); fp@33: return; fp@33: } fp@33: fp@33: EtherCAT_master_close(&ecat_masters[index], device); fp@33: } fp@33: fp@33: /******************************************************************************/ 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@33: EtherCAT_master_t *EtherCAT_request(int index) fp@33: { fp@33: if (index < 0 || index >= ecat_master_count) { fp@27: printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index); fp@27: return NULL; fp@27: } fp@27: fp@33: if (ecat_masters_reserved[index]) { fp@33: printk(KERN_ERR "EtherCAT: Master %i already in use!\n", index); fp@33: return NULL; fp@33: } fp@33: fp@33: if (!ecat_masters[index].dev) { fp@33: printk(KERN_ERR "EtherCAT: Master %i has no device assigned yet!\n", index); fp@33: return NULL; fp@33: } fp@33: fp@33: if (!ecat_masters[index].dev->module) { fp@33: printk(KERN_ERR "EtherCAT: Master %i device module is not set!\n", index); fp@33: return NULL; fp@33: } fp@33: fp@33: if (!try_module_get(ecat_masters[index].dev->module)) { fp@33: printk(KERN_ERR "EtherCAT: Could not reserve device module!\n"); fp@33: return NULL; fp@33: } fp@33: fp@33: ecat_masters_reserved[index] = 1; fp@33: fp@33: printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index); fp@33: fp@27: return &ecat_masters[index]; fp@27: } fp@27: fp@27: /******************************************************************************/ fp@33: fp@33: /** fp@33: Gibt einen zuvor reservierten EtherCAT-Master wieder frei. fp@33: fp@33: @param master Zeiger auf den freizugebenden EtherCAT-Master. fp@33: */ fp@33: fp@33: void EtherCAT_release(EtherCAT_master_t *master) fp@33: { fp@33: unsigned int i; fp@33: fp@33: for (i = 0; i < ecat_master_count; i++) fp@33: { fp@33: if (&ecat_masters[i] == master) fp@33: { fp@33: if (!ecat_masters[i].dev) { 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@33: module_put(ecat_masters[i].dev->module); fp@33: ecat_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@33: printk(KERN_WARNING "EtherCAT: Master %X was never reserved!\n", fp@33: (unsigned int) master); fp@33: } fp@33: fp@33: /******************************************************************************/