/******************************************************************* * * * FPGA-Devicetreiber * * * * Dieser Treiber ermoeglicht es einen Interrupthandler in den * * Kernelspace einzutragen. Dies ist zur Kommunikation mit der * * FPGA notwendig. Falls das Device geoeffnet ist, kann mit dem * * Write Befehl 'p','L','H' die aktuelle Prozessnummer an den * * Treiber uebergeben werden. Der Prozess wird dann ueber das * * SIGUSR1-Signal informiert. 'p' steht fuer die Aktion: jetzt * * folgt die Prozess-Nummer. 'L', 'H' stehen fuer Low und High * * Byte der PID (Prozessnummer). * * * * (c) 2001 by Martin Kirsch * * The file is freely redistributable but not forcommercial use. * * * *******************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include /* Falls Definiert, wird der Debug-Modus eingeschaltet */ //#define FPGA_DEBUG #define MY_SIGNAL SIGUSR1 int fpga_major=50; /* Select 0 for Dynamic adressing */ /* lokal benutzte Datenstruktur */ struct FPGA_Device { struct fasync_struct *async_queue; int pid; } FPGA_Device; /* Sucht ueber die PID den zugehoerigen Taskpointer */ static struct task_struct *get_task(pid_t pid) { struct task_struct **p; p=task; while(++ppid == pid) return *p; }; return NULL; } /* Eigentlicher Interrupthandler, dieser Schickt ein Signal an den Hauptprozess */ static void fpga_interrupt(int irq, void *dev_id, struct pt_regs *regs) { #ifdef FPGA_DEBUG printk("FPGA-Interrupt has occured\n"); #endif if(FPGA_Device.pid) { send_sig(MY_SIGNAL, get_task(FPGA_Device.pid), 1); #ifdef FPGA_DEBUG printk("Sending SIGNAL to PID: %d, %p ...\n", FPGA_Device.pid, get_task(FPGA_Device.pid)); #endif }; return; } /* Read-Funktion des Devices - unused */ static int fpga_read(struct inode *inode, struct file *file, char *buffer, int size) { if(buffer==NULL) { #ifdef FPGA_DEBUG printk("FPGA-Driver: Read-Error, Null-Buffer\n"); #endif return -EINVAL; }; #ifdef FPGA_DEBUG printk("FPGA-Driver read\n"); #endif return 0; } /* Write-Funktion des Devices - falls 'p' kommt wird die nachfolgende nummer als pid eingetragen */ static int fpga_write(struct inode *inode, struct file *file, const char *buffer, int size) { int i; #ifdef FPGA_DEBUG printk("FPGA-Driver write\n"); #endif if(buffer[0] == 'p' && size > 2) { FPGA_Device.pid=buffer[1]+buffer[2]*256; #ifdef FPGA_DEBUG printk("FPGA-Device: PID was set to: %d\n", FPGA_Device.pid); #endif }; #ifdef FPGA_DEBUG for(i=0;iprivate_data; #ifdef FPGA_DEBUG printk("FPGA-Driver: Async\n"); #endif FPGA_Device.async_queue=dev->async_queue; return fasync_helper(inode, file, mode, &dev->async_queue); } struct file_operations fpga_fops= { NULL, /* seek */ fpga_read, /* read */ fpga_write, /* write */ NULL, /* readdir */ NULL, /* select */ NULL, /* ioctl */ fpga_mmap, /* mmap */ fpga_open, /* open */ fpga_close, /* release */ NULL, /* fsync/flush */ fpga_fasync, /* fasync */ /* fill rest with NULL */ }; /* Inser-Funktion des Devices - Diese Funktion traegt das Device und den Interrupthandler in den Kernel ein */ int insert_fpga(void) { int rc; rc=register_chrdev(fpga_major, "FPGA", &fpga_fops); if(rc<0) { printk("Panic! Could not register FPGA-Driver\n"); return rc; }; rc=request_irq(IRQ_MACHSPEC|IRQ3_IRQ_NUM, fpga_interrupt, IRQ_FLG_STD, "FPGA-IRQ", NULL/*Userdata!!!*/); if(rc) { printk("FPGA-Driver: Error while installing interrupt handler\n"); return -ENODEV; }; if(fpga_major==0) fpga_major=rc; return 0; } #ifdef MODULE #define fpga_init init_module #endif int fpga_init(void) { int rc; FPGA_Device.async_queue=NULL; FPGA_Device.pid=0; rc=insert_fpga(); if(rc==0) { printk("<1> ********** \n"); printk("<1> ********** ********** \n"); printk("<1> ********** -= FPGA =- ********** \n"); printk("<1> ** Driver for uCsimm. Designed to work ** \n"); printk("<1> ** under CIA/JANUS-Interface **\n"); printk("<1> ** V 0.01b/%s/%s ** \n", __DATE__, __TIME__); printk("<1> ********** (c) 2001 Martin Kirsch ********** \n"); printk("<1> ********** ********** \n"); printk("<1> ********** \n"); } else { printk("Panic! FPGA-driver could not be loaded!\n"); }; return rc; } void cleanup_module(void) { free_irq(IRQ_MACHSPEC|IRQ3_IRQ_NUM, NULL/*Userdata*/); unregister_chrdev(fpga_major, "FPGA"); printk("<1>FPGA char-driver removed\n"); }