/home/hillier_g/checkout/most4linux/most-kernel/most-base.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 #ifdef HAVE_CONFIG_H
00022 #include "config/config.h"
00023 #endif
00024 #include <linux/module.h>
00025 #include <linux/pci.h>
00026 #include <linux/list.h>
00027 #include <linux/ioport.h>
00028 #include <linux/irq.h>
00029 #include <linux/moduleparam.h>
00030 #include <linux/rwsem.h>
00031 #include <linux/proc_fs.h>
00032 #include <asm/atomic.h>
00033 
00034 #include "most-constants.h"
00035 #include "most-base.h"
00036 #include "most-common.h"
00037 
00038 #ifdef RT_RTDM
00039 #   include <rtdm/rtdm_driver.h>
00040 #   include "most-common-rt.h"
00041 #endif
00042 
00052 #define DRIVER_NAME                     "most-base"
00053 
00057 #define PR                              DRIVER_NAME       ": "
00058 
00062 static char *version = "$Rev: 639 $";
00063 
00067 RWSEMA_LOCKED_LIST(most_base_low_drivers);
00068 
00072 RWSEMA_LOCKED_LIST(most_base_high_drivers_sema);
00073 
00077 SPIN_LOCKED_LIST(most_base_high_drivers_spin);
00078 
00082 static dev_t major_id = 0;
00083 
00087 static atomic_t device_count = ATOMIC_INIT(0);
00088 
00089 
00090 /*
00091  * Documentation: see header
00092  */
00093 int most_register_high_driver(struct most_high_driver *driver)
00094 {
00095     struct list_head            *cursor;
00096     struct most_low_driver      *low_driver;
00097     rtnrt_lockctx_t             flags;
00098 
00099     /* add the driver to the global list of drivers */
00100     down_write(&most_base_high_drivers_sema.lock);
00101     list_add_tail(&driver->sema_list, &most_base_high_drivers_sema.list);
00102     up_write(&most_base_high_drivers_sema.lock);
00103 
00104     /* add the driver to the global list of drivers */
00105     rtnrt_lock_get_irqsave(&most_base_high_drivers_spin.lock, flags);
00106     list_add_tail(&driver->spin_list, &most_base_high_drivers_spin.list);
00107     rtnrt_lock_put_irqrestore(&most_base_high_drivers_spin.lock, flags);
00108 
00109     /* 
00110      * now call each probe function if there are already PCI cards
00111      * available in the system
00112      */
00113     down_read(&most_base_low_drivers.lock);
00114     list_for_each(cursor, &most_base_low_drivers.list) {
00115         low_driver = list_entry(cursor, struct most_low_driver, list);
00116         low_driver->high_driver_registered(driver);
00117     }
00118     up_read(&most_base_low_drivers.lock);
00119 
00120     return 0;
00121 }
00122 
00123 
00124 /*
00125  * Documentation: see header
00126  */
00127 void most_deregister_high_driver(struct most_high_driver *driver)
00128 {
00129     struct list_head            *cursor_low_driver;
00130     struct most_low_driver      *low_driver;
00131     rtnrt_lockctx_t             flags;
00132 
00133     /* call each probe function */
00134     down_read(&most_base_low_drivers.lock);
00135     list_for_each(cursor_low_driver, &most_base_low_drivers.list) {
00136         low_driver = list_entry(cursor_low_driver, struct most_low_driver, list);
00137         low_driver->high_driver_deregistered(driver);
00138     }
00139     up_read(&most_base_low_drivers.lock);
00140     
00141     /* remove from the list */
00142     rtnrt_lock_get_irqsave(&most_base_high_drivers_spin.lock, flags);
00143     list_del(&driver->spin_list);
00144     rtnrt_lock_put_irqrestore(&most_base_high_drivers_spin.lock, flags);
00145 
00146     /* remove from the list */
00147     down_write(&most_base_high_drivers_sema.lock);
00148     list_del(&driver->sema_list);
00149     up_write(&most_base_high_drivers_sema.lock);
00150 }
00151 
00152 /*
00153  * Documentation: see header
00154  */
00155 void most_register_low_driver(struct most_low_driver *driver)
00156 {
00157     /* add the driver to the global list of drivers */
00158     down_write(&most_base_low_drivers.lock);
00159     list_add_tail(&driver->list, &most_base_low_drivers.list);
00160     up_write(&most_base_low_drivers.lock);
00161 }
00162 
00163 /*
00164  * Documentation: see header
00165  */
00166 void most_deregister_low_driver(struct most_low_driver *driver)
00167 {
00168     /* remove from the list */
00169     down_write(&most_base_low_drivers.lock);
00170     list_del(&driver->list);
00171     up_write(&most_base_low_drivers.lock);
00172 }
00173 
00174 
00175 /*
00176  * documentation: see header
00177  */
00178 struct most_dev *most_dev_new(void)
00179 {
00180     struct most_dev *ret;
00181     
00182     ret = kmalloc(sizeof(struct most_dev), GFP_KERNEL);
00183     if (!ret) {
00184         return NULL;
00185     }
00186 
00187     memset(ret, sizeof(struct most_dev), 0);
00188 
00189     spin_lock_init(&ret->lock);
00190     INIT_LIST_HEAD(&ret->list);
00191     ret->major_device_no = MAJOR(major_id);
00192     ret->card_number = atomic_read(&device_count);
00193 
00194     atomic_inc(&device_count);
00195     sprintf(ret->name, "most-%d", MOST_DEV_CARDNUMBER(ret));
00196     
00197     return ret;
00198 }
00199 
00200 /*
00201  * Documentation: see header
00202  */
00203 void most_dev_free(struct most_dev* dev)
00204 {
00205     atomic_dec(&device_count);
00206     if (dev->impl) {
00207         kfree(dev->impl);
00208     }
00209     kfree(dev);
00210 }
00211 
00220 static void *most_base_seq_start(struct seq_file *s, loff_t *pos)
00221 {
00222     return *pos == 0
00223         ? &version
00224         : NULL;
00225 }
00226 
00236 static void *most_base_seq_next(struct seq_file *s, void *v, loff_t *pos)
00237 {
00238     (*pos)++;
00239     return NULL;
00240 }
00241 
00249 static void most_base_seq_stop(struct seq_file *sfile, void *v)
00250 {}
00251 
00258 static int most_base_seq_show(struct seq_file *s, void *v)
00259 {
00260     struct list_head            *cursor_low_driver;
00261     struct most_low_driver      *low_driver;
00262     
00263     seq_printf(s, ">> MOST for Linux <<\n\n");
00264     seq_printf(s, "Devices:\n");
00265 
00266     /* now traverse the low drivers first */
00267     down_read(&most_base_low_drivers.lock);
00268     list_for_each(cursor_low_driver, &most_base_low_drivers.list) {
00269         low_driver = list_entry(cursor_low_driver, struct most_low_driver, list);
00270         if (low_driver->proc_show) {
00271             low_driver->proc_show(s);
00272         }
00273     }
00274     up_read(&most_base_low_drivers.lock);
00275 
00276     return 0;
00277 }
00278 
00282 static struct seq_operations most_base_seq_ops = {
00283     .start          = most_base_seq_start,
00284     .next           = most_base_seq_next,
00285     .stop           = most_base_seq_stop,
00286     .show           = most_base_seq_show
00287 };
00288 
00295 static int most_base_proc_open(struct inode *inode, struct file *file)
00296 {
00297     return seq_open(file, &most_base_seq_ops);
00298 }
00299 
00303 static struct file_operations most_base_proc_ops = {
00304     .owner          = THIS_MODULE,
00305     .open           = most_base_proc_open,
00306     .read           = seq_read,
00307     .llseek         = seq_lseek,
00308     .release        = seq_release
00309 };
00310 
00316 static int __init most_base_init(void)
00317 {
00318     int                   err;
00319     struct proc_dir_entry *entry;
00320 
00321     /* get a device id for all MOST drivers */
00322     err = alloc_chrdev_region(&major_id, 0, MOST_MINOR_IDS, DRIVER_NAME);
00323     if (unlikely(err != 0)) {
00324         rtnrt_err("Error in alloc_chrdev_region, err = %d\n", err);
00325         return err;
00326     }
00327     rtnrt_info("Registered major id %d\n", MAJOR(major_id));
00328 
00329     /* register proc */
00330     entry = create_proc_entry("most", 0, NULL);
00331     if (likely(entry)) {
00332         entry->proc_fops = &most_base_proc_ops;
00333     }
00334 
00335     return 0;
00336 }
00337 
00338 
00342 static void __exit most_base_exit(void)
00343 {
00344     rtnrt_info("Unloading module %s, version %s\n", DRIVER_NAME, version);
00345 
00346     /* unregistering id */
00347     unregister_chrdev_region(major_id, MOST_MINOR_IDS);
00348 
00349     /* unregistering proc */
00350     remove_proc_entry("most", NULL);
00351 }
00352 
00353 #ifndef DOXYGEN
00354 EXPORT_SYMBOL(most_register_high_driver);
00355 EXPORT_SYMBOL(most_deregister_high_driver);
00356 EXPORT_SYMBOL(most_register_low_driver);
00357 EXPORT_SYMBOL(most_deregister_low_driver);
00358 EXPORT_SYMBOL(most_base_high_drivers_sema);
00359 EXPORT_SYMBOL(most_base_high_drivers_spin);
00360 EXPORT_SYMBOL(most_dev_new);
00361 EXPORT_SYMBOL(most_dev_free);
00362 
00363 MODULE_LICENSE("GPL");
00364 MODULE_AUTHOR("Bernhard Walle");
00365 MODULE_VERSION("$Rev: 639 $");
00366 MODULE_DESCRIPTION("Base driver for the MOST devices from OASIS Silicon systems.");
00367 module_init(most_base_init);
00368 module_exit(most_base_exit);
00369 #endif
00370 
00371 /* vim: set ts=4 et sw=4: */

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