From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: <45B0E8BF.5090705@domain.hid> Date: Fri, 19 Jan 2007 16:50:23 +0100 From: Markus Franke MIME-Version: 1.0 Subject: Re: [Xenomai-help] problem inserting a kernel module References: <910933.20673.qm@domain.hid> In-Reply-To: <910933.20673.qm@domain.hid> Content-Type: multipart/mixed; boundary="------------030406080900010906050903" Reply-To: Markus.Franke@domain.hid List-Id: Help regarding installation and common use of Xenomai List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: mani bhatti Cc: xenomai@xenomai.org This is a multi-part message in MIME format. --------------030406080900010906050903 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Well, some symbols which are referenced by your module are not found in the kernel. A "dmesg()"-call should provide you some information about the missing symbols. Maybe you missed inserting the "RTDM"-kernel module? Regards, Markus mani bhatti wrote: > Hi all > i have a problem inserting the realtimedriver.ko module from captain.at > actually everything works well module is made with out any error from make file and user.c also compiles but when i try to insert following error appears > > insmod: error inserting './realtimedriver.ko': -1 Unknown symbol in module > > Is there any error inside module.Thanks. > i have attached all files.thanks > > > > > > --------------------------------- > Everyone is raving about the all-new Yahoo! Mail beta. > > > ------------------------------------------------------------------------ > > #include > #include > #include "inc.h" > > char dummy_buffer[BUFSIZE]; > int events; > int ioctlvalue; > > // our driver context struct: used for storing various information > struct demodrv_context { > rtdm_irq_t irq_handle; > rtdm_lock_t lock; > int dev_id; > u64 last_timestamp; > rtdm_event_t irq_event; > volatile unsigned long irq_event_lock; > volatile int irq_events; > int64_t timeout; > void *buf; > rtdm_user_info_t *mapped_user_info; > void *mapped_user_addr; > }; > > #ifdef USEMMAP > static void demo_vm_open(struct vm_area_struct *vma) > { > printk("opening %p, private_data = %p\n", vma, > vma->vm_private_data); > } > static void demo_vm_close(struct vm_area_struct *vma) > { > printk("releasing %p, private_data = %p\n", vma, > vma->vm_private_data); > } > static struct vm_operations_struct mmap_ops = { > .open = demo_vm_open, > .close = demo_vm_close, > }; > #endif > > /**********************************************************/ > /* INTERRUPT HANDLING */ > /**********************************************************/ > static int demo_interrupt(rtdm_irq_t *irq_context) > { > struct demodrv_context *ctx; > int dev_id; > // timestamp, if needed, can be obtained list this: > // u64 timestamp = rtdm_clock_read(); > int ret = RTDM_IRQ_HANDLED; // usual return value > > ctx = rtdm_irq_get_arg(irq_context, struct demodrv_context); > dev_id = ctx->dev_id; > > rtdm_lock_get(&ctx->lock); > > // do stuff > #ifdef TIMERINT > if (events > 100) { > rtdm_event_signal(&ctx->irq_event); > events = 0; > } > #else > rtdm_event_signal(&ctx->irq_event); > #endif > events++; > > rtdm_lock_put(&ctx->lock); > // those return values were dropped from the RTDM > // ret = RTDM_IRQ_ENABLE | RTDM_IRQ_PROPAGATE; > > #ifdef TIMERINT > // Only propagate the timer interrupt, so that linux sees it. > // Forwarding interrupts to the non-realtime domain is not a common > // use-case of realtime device drivers, so usually DON'T DO THIS. > // But here we grab the important timer interrupt, so we need to propagate it. > return XN_ISR_PROPAGATE; > #else > // signal interrupt is handled and don't propagate the interrupt to linux > return RTDM_IRQ_HANDLED; > #endif > } > > /**********************************************************/ > /* DRIVER OPEN */ > /**********************************************************/ > int demo_open_rt(struct rtdm_dev_context *context, > rtdm_user_info_t *user_info, > int oflags) > { > struct demodrv_context *my_context; > #ifdef USEMMAP > unsigned long vaddr; > #endif > int dev_id = context->device->device_id; > int ret; > > // get the context for our driver - used to store driver info > my_context = (struct demodrv_context *)context->dev_private; > > #ifdef USEMMAP > // allocate and prepare memory for our buffer > my_context->buf = kmalloc(BUFFER_SIZE, 0); > /* mark pages reserved so that remap_pfn_range works */ > for (vaddr = (unsigned long)my_context->buf; > vaddr < (unsigned long)my_context->buf + BUFFER_SIZE; > vaddr += PAGE_SIZE) > SetPageReserved(virt_to_page(vaddr)); > // write some test value to the start of our buffer > *(int *)my_context->buf = 1234; > > my_context->mapped_user_addr = NULL; > #endif > > // we also have an interrupt handler: > #ifdef TIMERINT > ret = rtdm_irq_request(&my_context->irq_handle, TIMER_INT, > demo_interrupt, > 0, context->device->proc_name, my_context); > #else > ret = rtdm_irq_request(&my_context->irq_handle, PAR_INT, > demo_interrupt, > 0, context->device->proc_name, my_context); > #endif > if (ret < 0) > return ret; > > /* IPC initialisation - cannot fail with used parameters */ > rtdm_lock_init(&my_context->lock); > rtdm_event_init(&my_context->irq_event, 0); > my_context->dev_id = dev_id; > > my_context->irq_events = 0; > my_context->irq_event_lock = 0; > my_context->timeout = 0; // wait INFINITE > > #ifndef TIMERINT > //set port to interrupt mode; pins are output > outb_p(0x10, BASEPORT + 2); > #endif > // enable interrupt in RTDM > rtdm_irq_enable(&my_context->irq_handle); > return 0; > } > > /**********************************************************/ > /* DRIVER CLOSE */ > /**********************************************************/ > int demo_close_rt(struct rtdm_dev_context *context, > rtdm_user_info_t *user_info) > { > struct demodrv_context *my_context; > rtdm_lockctx_t lock_ctx; > #ifdef USEMMAP > unsigned long vaddr; > #endif > // get the context > my_context = (struct demodrv_context *)context->dev_private; > > #ifdef USEMMAP > // printk some test value > printk("%d\n", *((int *)my_context->buf + 10)); > > // munmap our buffer > if (my_context->mapped_user_addr) { > int ret = rtdm_munmap(my_context->mapped_user_info, > my_context->mapped_user_addr, > BUFFER_SIZE); > printk("rtdm_munmap = %p, %d\n", my_context->mapped_user_info, > ret); > } > > /* clear pages reserved */ > for (vaddr = (unsigned long)my_context->buf; > vaddr < (unsigned long)my_context->buf + BUFFER_SIZE; > vaddr += PAGE_SIZE) > ClearPageReserved(virt_to_page(vaddr)); > > kfree(my_context->buf); > #endif > > // if we need to do some stuff with preemption disabled: > rtdm_lock_get_irqsave(&my_context->lock, lock_ctx); > // other stuff here > rtdm_lock_put_irqrestore(&my_context->lock, lock_ctx); > > // free irq in RTDM > rtdm_irq_free(&my_context->irq_handle); > // destroy our interrupt signal/event > rtdm_event_destroy(&my_context->irq_event); > return 0; > } > > /**********************************************************/ > /* DRIVER IOCTL */ > /**********************************************************/ > int demo_ioctl_rt(struct rtdm_dev_context *context, > rtdm_user_info_t *user_info, > int request, > void *arg) > { > struct demodrv_context *my_context; > #ifdef USEMMAP > int err; > #endif > int ret = 0; > my_context = (struct demodrv_context *)context->dev_private; > > switch (request) { > case MMAP: // set mmap pointer > #ifdef USEMMAP > printk("buf = %p:%x\n", my_context->buf, *(int*)my_context->buf); > > err = rtdm_mmap_to_user(user_info, my_context->buf,BUFFER_SIZE, PROT_READ|PROT_WRITE, (void **)arg,&mmap_ops,(void *)0x12345678); > if (!err) { > my_context->mapped_user_info = user_info; > my_context->mapped_user_addr = *(void **)arg; > } > printk("rtdm_mmap = %p %d\n", my_context->mapped_user_info,err); > #else > return -EPERM; > #endif > break; > case GETVALUE: // write "ioctlvalue" to user > if (user_info) { > if (!rtdm_rw_user_ok(user_info, arg, sizeof(int)) || > rtdm_copy_to_user(user_info, arg, &ioctlvalue, > sizeof(int))) > return -EFAULT; > } else > memcpy(arg, &ioctlvalue, sizeof(int)); > break; > case SETVALUE: // read "ioctlvalue" from user > if (user_info) { > if (!rtdm_read_user_ok(user_info, arg, sizeof(int)) || > rtdm_copy_from_user(user_info, &ioctlvalue, arg, > sizeof(int))) > return -EFAULT; > } > break; > default: > ret = -ENOTTY; > } > return ret; > } > > /**********************************************************/ > /* DRIVER READ */ > /**********************************************************/ > int demo_read_rt(struct rtdm_dev_context *context, > rtdm_user_info_t *user_info, void *buf, size_t nbyte) > { > struct demodrv_context *ctx; > int dev_id; > // rtdm_lockctx_t lock_ctx; > char *out_pos = (char *)buf; > rtdm_toseq_t timeout_seq; > int ret; > > // zero bytes requested ? return! > if (nbyte == 0) > return 0; > > // check if R/W actions to user-space are allowed > if (user_info && !rtdm_rw_user_ok(user_info, buf, nbyte)) > return -EFAULT; > > ctx = (struct demodrv_context *)context->dev_private; > dev_id = ctx->dev_id; > > // in case we need to check if reading is allowed (locking) > /* if (test_and_set_bit(0, &ctx->in_lock)) > return -EBUSY; > */ > /* // if we need to do some stuff with preemption disabled: > rtdm_lock_get_irqsave(&ctx->lock, lock_ctx); > // stuff here > rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx); > */ > > // wait: if ctx->timeout = 0, it will block infintely until > // rtdm_event_signal(&ctx->irq_event); is called from our > // interrupt routine > ret = rtdm_event_timedwait(&ctx->irq_event, ctx->timeout, > &timeout_seq); > > // now write the requested stuff to user-space > if (rtdm_copy_to_user(user_info, out_pos, > dummy_buffer, BUFSIZE) != 0) { > ret = -EFAULT; > } else { > ret = BUFSIZE; > } > return ret; > } > > /**********************************************************/ > /* DRIVER WRITE */ > /**********************************************************/ > int demo_write_rt(struct rtdm_dev_context *context, > rtdm_user_info_t *user_info, > const void *buf, size_t nbyte) > { > struct demodrv_context *ctx; > int dev_id; > char *in_pos = (char *)buf; > int ret; > > if (nbyte == 0) > return 0; > if (user_info && !rtdm_read_user_ok(user_info, buf, nbyte)) > return -EFAULT; > > ctx = (struct demodrv_context *)context->dev_private; > dev_id = ctx->dev_id; > > // make write operation atomic > /* ret = rtdm_mutex_timedlock(&ctx->out_lock, > ctx->config.rx_timeout, &timeout_seq); > if (ret) > return ret; */ > > /* // if we need to do some stuff with preemption disabled: > rtdm_lock_get_irqsave(&ctx->lock, lock_ctx); > // stuff here > rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx); > */ > > // now copy the stuff from user-space to our kernel dummy_buffer > if (rtdm_copy_from_user(user_info, dummy_buffer,in_pos, BUFSIZE) != 0) > { > ret = -EFAULT; > } else { > ret = BUFSIZE; > } > > // used when it is atomic > // rtdm_mutex_unlock(&ctx->out_lock); > return ret; > } > > /**********************************************************/ > /* DRIVER OPERATIONS */ > /**********************************************************/ > static struct rtdm_device demo_device = { > struct_version: RTDM_DEVICE_STRUCT_VER, > > device_flags: RTDM_NAMED_DEVICE, > context_size: sizeof(struct demodrv_context), > device_name: DEV_FILE, > > /* open and close functions are not real-time safe due kmalloc > and kfree. If you do not use kmalloc and kfree, and you made > sure that there is no syscall in the open/close handler, you > can declare the open_rt and close_rt handler. > */ > open_rt: NULL, > open_nrt: demo_open_rt, > > ops: { > close_rt: NULL, > close_nrt: demo_close_rt, > > ioctl_rt: NULL, > ioctl_nrt: demo_ioctl_rt, // rtdm_mmap_to_user is not RT safe > > read_rt: demo_read_rt, > read_nrt: NULL, > > write_rt: demo_write_rt, > write_nrt: NULL, > > recvmsg_rt: NULL, > recvmsg_nrt: NULL, > > sendmsg_rt: NULL, > sendmsg_nrt: NULL, > }, > > device_class: RTDM_CLASS_EXPERIMENTAL, > device_sub_class: 222, > driver_name: DRV_NAME, > peripheral_name: DEV_FILE_NAME, > provider_name: "-", > proc_name: demo_device.device_name, > }; > > /**********************************************************/ > /* INIT DRIVER */ > /**********************************************************/ > int init_module(void) > { > return rtdm_dev_register(&demo_device); > } > > /**********************************************************/ > /* CLEANUP DRIVER */ > /**********************************************************/ > void cleanup_module(void) > { > rtdm_dev_unregister(&demo_device, 1000); > } > > MODULE_LICENSE("GPL"); > MODULE_DESCRIPTION("RTDM Real Time Driver Example"); > > > ------------------------------------------------------------------------ > > #include > #include > #include > #include > > #include > #include > #include > #include "inc.h" > > unsigned int my_state = 0; > int timer_started = 0; > int my_fd = -1; > int shutdownnow = 0; > RT_TASK my_task; > // --s-ms-us-ns > RTIME my_task_period_ns = 1000000000llu; > > #ifdef USEMMAP > void *mmappointer; > #endif > > /**********************************************************/ > /* CLOSE RT DRIVER */ > /**********************************************************/ > static int close_file( int fd, unsigned char *name) { > int ret,i=0; > do { > i++; > ret = rt_dev_close(fd); > switch(-ret){ > case EBADF: printf("%s -> invalid fd or context\n",name); > break; > case EAGAIN: printf("%s -> EAGAIN (%d times)\n",name,i); > rt_task_sleep(50000); // wait 50us > break; > case 0: printf("%s -> closed\n",name); > break; > default: printf("%s -> ???\n",name); > break; > } > } while (ret == -EAGAIN && i < 10); > return ret; > } > > /**********************************************************/ > /* CLEANING UP */ > /**********************************************************/ > void cleanup_all(void) { > if (my_state & STATE_FILE_OPENED) { > close_file( my_fd, DEV_FILE " (user)"); > my_state &= ~STATE_FILE_OPENED; > } > if (my_state & STATE_TASK_CREATED) { > printf("delete my_task\n"); > rt_task_delete(&my_task); > my_state &= ~STATE_TASK_CREATED; > } > if (timer_started) { > printf("stop timer\n"); > rt_timer_stop(); > } > } > > void catch_signal(int sig) { > shutdownnow = 1; > cleanup_all(); > printf("exit\n"); > return; > } > > /**********************************************************/ > /* REAL TIME TASK */ > /**********************************************************/ > void my_task_proc(void *arg) { > int ret; > ssize_t sz = sizeof(RTIME); > ssize_t written = 0; > ssize_t read = 0; > int counter = 0; > int readbackcounter; > unsigned char buf[17] = "CAPTAIN WAS HERE\0"; > unsigned char buf2[17] = "XXXXXXXXXXXXXXXX\0"; > /* no periodic task, due blocking read from the RT driver (see below > too) > ret = rt_task_set_periodic(NULL, TM_NOW, > rt_timer_ns2ticks(my_task_period_ns)); > if (ret) { > printf("error while set periodic, code %d\n",ret); > goto exit_my_task; > } > */ > > #ifdef USEMMAP > printf("ioctl = %d\n", rt_dev_ioctl(my_fd, MMAP, &mmappointer)); > printf("*p = %d, p = %p\n", *((int *)mmappointer), mmappointer); > #endif > > while (1) { > sprintf(buf, "CAPTAIN %d", counter); > counter++; > if (counter > 100) counter = 0; > /* switch to primary mode */ > ret = rt_task_set_mode(0, T_PRIMARY, NULL); > if (ret) { > printf("error while rt_task_set_mode, code %d\n",ret); > goto exit_my_task; > } > > /* // rt_dev_read blocks, so we can't use rt_task_wait_period here, > // otherwise we get a ETIMEDOUT 110 = Connection timed out > // after the next rt_task_wait_period > ret = rt_task_wait_period(NULL); > if (ret) { > printf("error while rt_task_wait_period, code %d\n",ret); > goto exit_my_task; > } > */ > sz = sizeof(buf); > written = rt_dev_write(my_fd, &buf, sizeof(buf)); > printf("WRITE: written=%d sz=%d\n", written, sz); > if (written != sz ) { > if (written < 0 ) { > printf("error while rt_dev_write, code %d\n",written); > } else { > printf("only %d / %d byte transmitted\n",written, sz); > } > goto exit_my_task; > } > > sz = sizeof(buf2); > read = rt_dev_read(my_fd, &buf2, sizeof(buf2)); > if (read == sz ) { > printf("READ: read=%s\n",buf2); > } else { > if (read < 0 ) { > printf("error while rt_dev_read, code %d\n",read); > } else { > printf("only %d / %d byte received \n",read,sz); > } > } > > // read blocks, so check if user hit CTRL-C meanwhile > // otherwise we segfault when mmap'ing > if (shutdownnow == 1) break; > > #ifdef USEMMAP > *((int *)mmappointer + 10) = counter + 1000; > printf("MMAP: *((int *)mmappointer + 10) = %d\n", > *((int *)mmappointer + 10)); > #endif > > rt_dev_ioctl(my_fd, SETVALUE, &counter); > rt_dev_ioctl(my_fd, GETVALUE, &readbackcounter); > printf("IOCTL: readbackcounter=%d\n", readbackcounter); > > > } > exit_my_task: > if (my_state & STATE_FILE_OPENED) { > if (!close_file( my_fd, DEV_FILE " (write)")) { > my_state &= ~STATE_FILE_OPENED; > } > } > printf("exit\n"); > } > > /**********************************************************/ > /* MAIN: mainly RT task initialization */ > /**********************************************************/ > int main(int argc, char* argv[]) { > int ret = 0; > signal(SIGTERM, catch_signal); > signal(SIGINT, catch_signal); > > printf("PRESS CTRL-C to EXIT\n"); > /* no memory-swapping for this programm */ > mlockall(MCL_CURRENT | MCL_FUTURE); > > > /* open DEV_FILE */ > my_fd = rt_dev_open( DEV_FILE, 0); > if (my_fd < 0) { > printf("can't open %s\n", DEV_FILE); > goto error; > } > my_state |= STATE_FILE_OPENED; > printf("%s opened\n", DEV_FILE); > > /* create my_task */ > ret = rt_task_create(&my_task,"my_task",0,50,0); > if (ret) { > printf("failed to create my_task, code %d\n",ret); > goto error; > } > my_state |= STATE_TASK_CREATED; > printf("my_task created\n"); > > /* start my_task */ > printf("starting my_task\n"); > ret = rt_task_start(&my_task,&my_task_proc,NULL); > if (ret) { > printf("failed to start my_task, code %d\n",ret); > goto error; > } > > pause(); > return 0; > > error: > cleanup_all(); > return ret; > } > > > ------------------------------------------------------------------------ > > // if TIMERINT is defined, the linux timer interrupt is used > // otherwise the parallel port interrupt is used > #define TIMERINT > > // if USEMMAP IS defined, also MMAP operations will be made > #define USEMMAP > > #define DEV_FILE "demodev0" > #define DEV_FILE_NAME "demodev" > #define DRV_NAME "demodrv" > > #define BUFFER_SIZE 100000 > #define BUFSIZE 17 > #define PAR_INT 7 > #define TIMER_INT 0 > #define BASEPORT 0x378 > #define MMAP 0 > #define GETVALUE 1 > #define SETVALUE 2 > > #define STATE_FILE_OPENED 1 > #define STATE_TASK_CREATED 2 > > > ------------------------------------------------------------------------ > > _______________________________________________ > Xenomai-help mailing list > Xenomai-help@domain.hid > https://mail.gna.org/listinfo/xenomai-help -- Nichts ist so praktisch wie eine gute Theorie! --------------030406080900010906050903 Content-Type: text/x-vcard; charset=utf-8; name="Markus.Franke.vcf" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="Markus.Franke.vcf" begin:vcard fn:Markus Franke n:Franke;Markus adr;quoted-printable:;;Vettersstra=C3=9Fe 64/722;Chemnitz;Saxony;09126;Germany email;internet:Markus.Franke@domain.hid x-mozilla-html:FALSE url:http://www.tu-chemnitz.de/~franm version:2.1 end:vcard --------------030406080900010906050903--