00001
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <linux/module.h>
00036 #include <linux/kernel.h>
00037 #include <linux/init.h>
00038 #include <linux/list.h>
00039 #include <linux/proc_fs.h>
00040 #include <linux/moduleparam.h>
00041
00042 #include "sim_if.h"
00043 #include "oq_kmod.h"
00044
00045
00046 MODULE_LICENSE("Dual BSD/GPL");
00047 MODULE_DESCRIPTION("OrbisQuartus Simulator Kernel Module");
00048 MODULE_AUTHOR("Sean M. Brennan");
00049
00050
00051 static int oq_test = 0;
00052 static char *oq_simd = OQ_SIMD_PATH;
00053 module_param(oq_test, bool, S_IRUGO);
00054 module_param(oq_simd, charp, S_IRUGO);
00055
00056
00057 char oq_simulation_daemon[PATH_MAX];
00058 struct proc_dir_entry *oq_dir;
00059 struct oq_dev *oq_device;
00060
00061
00062 static int oq_major;
00063 static int oq_minor = 0;
00064
00065 static struct file_operations oq_fops = {
00066 .owner = THIS_MODULE,
00067 .llseek = oq_llseek,
00068 .read = oq_read,
00069 .write = oq_write,
00070 .ioctl = oq_ioctl,
00071 .open = oq_open,
00072 .release = oq_release,
00073 };
00074
00075
00076
00077 static int __init orbisquartus_init(void)
00078 {
00079 int devnum, result = 0;
00080 struct proc_dir_entry *oqd_dir, *oq_log;
00081 dev_t dev = 0;
00082
00083 if ((result = alloc_chrdev_region(&dev, oq_minor, 1,
00084 "orbisquartus")) < 0) {
00085 printk(KERN_WARNING "orbisquartus: can't get major %d\n",
00086 MAJOR(dev));
00087 return result;
00088 }
00089 oq_major = MAJOR(dev);
00090
00091 oq_device = kmalloc(sizeof(struct oq_dev), GFP_KERNEL);
00092 if (!oq_device) {
00093 printk(KERN_ERR
00094 "orbisquartus: Couldn't create oq device\n");
00095 result = -ENOMEM;
00096 goto end;
00097 }
00098 memset(oq_device, 0, sizeof(struct oq_dev));
00099
00100 init_MUTEX(&oq_device->sem);
00101 cdev_init(&oq_device->cdev, &oq_fops);
00102 oq_device->cdev.owner = THIS_MODULE;
00103 oq_device->cdev.ops = &oq_fops;
00104
00105 devnum = MKDEV(oq_major, oq_minor);
00106 if ((result = cdev_add(&oq_device->cdev, devnum, 1)) != 0) {
00107 printk(KERN_ERR
00108 "orbisquartus: Error %d adding orbisquartus0\n",
00109 result);
00110 goto cleanup_dev;
00111 }
00112
00113 memset(oq_simulation_daemon, '\0', PATH_MAX);
00114 strncpy(oq_simulation_daemon, oq_simd, PATH_MAX);
00115
00116
00117 if ((oq_dir = proc_mkdir(OQ_PATH, &proc_root)) == NULL) {
00118 printk(KERN_ERR
00119 "orbisquartus: Couldn't create proc entry\n");
00120 result = -ENOMEM;
00121 goto cleanup_base;
00122 }
00123 oq_dir->owner = THIS_MODULE;
00124
00125
00126 if ((oqd_dir =
00127 proc_symlink("daemon", oq_dir, oq_simulation_daemon)) == NULL) {
00128 printk(KERN_ERR
00129 "orbisquartus: Couldn't create daemon symlink\n");
00130 result = -ENOMEM;
00131 goto cleanup_daemon;
00132 }
00133 oqd_dir->owner = THIS_MODULE;
00134
00135
00136 if ((oq_log = proc_symlink("oq.log", oq_dir, OQ_DEVICE)) == NULL) {
00137 printk(KERN_ERR
00138 "orbisquartus: Couldn't create log symlink\n");
00139 result = -ENOMEM;
00140 goto cleanup_log;
00141 }
00142 oq_log->owner = THIS_MODULE;
00143
00144 if ((result == init_simulator_iface(oq_test)) < 0) {
00145 printk(KERN_ERR
00146 "orbisquartus: Couldn't create simulator interface\n");
00147 goto cleanup_log;
00148 }
00149
00150 printk(KERN_INFO "orbisquartus: Module loaded\n");
00151 goto end;
00152
00153
00154 cleanup_log:
00155 remove_proc_entry("oq.log", oq_dir);
00156 cleanup_daemon:
00157 remove_proc_entry("daemon", oq_dir);
00158 cleanup_base:
00159 remove_proc_entry(OQ_PATH, &proc_root);
00160 cleanup_dev:
00161 unregister_chrdev_region(MKDEV(oq_major, oq_minor), 1);
00162 end:
00163 return result;
00164 }
00165
00166
00167 static void __exit orbisquartus_shutdown(void)
00168 {
00169 shutdown_simulator_iface();
00170
00171 remove_proc_entry("oq.log", oq_dir);
00172 remove_proc_entry("daemon", oq_dir);
00173 remove_proc_entry(OQ_PATH, &proc_root);
00174 oq_dir = NULL;
00175 unregister_chrdev_region(MKDEV(oq_major, oq_minor), 1);
00176 printk(KERN_INFO "orbisquartus: Module removed\n");
00177 }
00178
00179
00180 module_init(orbisquartus_init);
00181 module_exit(orbisquartus_shutdown);