ccd.c

Go to the documentation of this file.
00001 /* Gxsm - Gnome X Scanning Microscopy
00002  * universal STM/AFM/SARLS/SPALEED/... controlling and
00003  * data analysis software
00004  * 
00005  * Copyright (C) 1999,2000,2001 Percy Zahl
00006  *
00007  * Authors: Percy Zahl <zahl@users.sf.net>
00008  * additional features: Andreas Klust <klust@users.sf.net>
00009  * WWW Home: http://gxsm.sf.net
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00024  */
00025 
00026 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 8 c-style: "K&R" -*- */
00027 /*
00028  * CCD Kernel Module
00029  * CCD on ParPort
00030  *
00031  * Device: /dev/ccd
00032  *
00033  * making device: mknod -m 666 /dev/ccd c xxx 0
00034  * for major "xxx" look in log/messages while loading module !
00035  * in most cases: xxx = 254
00036  */
00037 #define CCD_VERSION "V0.1 (C) P.Zahl 2000"
00038 /*
00039  * Compile all versions with make
00040  *
00041  */
00042 
00043 
00044 #include <linux/config.h>
00045 #include <linux/module.h>
00046 #include <linux/pci.h>
00047 #include <linux/types.h>
00048 #include <linux/major.h>
00049 #include <linux/errno.h>
00050 #include <linux/signal.h>
00051 #include <linux/fcntl.h>
00052 #include <linux/sched.h>
00053 #include <linux/interrupt.h>
00054 #include <linux/devpts_fs.h>
00055 #include <linux/file.h>
00056 #include <linux/console.h>
00057 #include <linux/timer.h>
00058 #include <linux/ctype.h>
00059 #include <linux/kd.h>
00060 #include <linux/mm.h>
00061 #include <linux/string.h>
00062 #include <linux/poll.h>
00063 #include <linux/proc_fs.h>
00064 #include <linux/init.h>
00065 #include <linux/smp_lock.h>
00066 #include <linux/devfs_fs_kernel.h>
00067 
00068 #include <asm/io.h>
00069 #include <asm/uaccess.h>
00070 #include <asm/system.h>
00071 #include <asm/bitops.h>
00072 
00073 #include "ccd.h"
00074 #include "dbgstuff.h"
00075 
00076 
00077 /*
00078  * Driver Variables 
00079  */
00080 
00081 static devfs_handle_t devfs_handle = NULL;
00082 
00083 static int opened;
00084 
00085 /* Hardware Location */
00086 static ccd_parport ccd_parport_io;
00087 static ccd_parport *ccd_io;
00088 
00089 /* Process handling... */
00090 // static int wakeups = -1;
00091 static DECLARE_WAIT_QUEUE_HEAD(waitq);
00092 
00093 /*
00094  * Timings in jiffies,  1 jiffie dauert ca. 10ms (HZ = #jiffies fue 1sec)
00095  */
00096 
00097 #define TIMEOUT_TICKS    19      /* 200ms */
00098 #define JIFFIES_SEM      2      /* timeout after 50ms */
00099 #define MAXWAKEUPS_SEM   10
00100 
00101 /* Prototypes */
00102 
00103 static void timeout(unsigned long ignore);
00104 void mysleep(unsigned long myjiffies);
00105 
00106 /* Device Service Functions */
00107 static ssize_t ccd_read (struct file *, char *, size_t, loff_t *);
00108 static int ccd_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
00109 
00110 int ccd_initialize(void);
00111 inline void ccd_quit(void);
00112 
00113 int init_module(void);
00114 void cleanup_module(void);
00115 
00116 static void timeout(unsigned long ignore){
00117   KDEBUG_L3("tmout wakeups %d\n", wakeups);
00118   wake_up_interruptible(&waitq);
00119 }
00120 
00121 #define MAKE_MY_TIMEOUT_TMR(tmr) \
00122   struct timer_list tmr; \
00123   init_timer(&tmr); \
00124   tmr.function = timeout; \
00125   tmr.data = 0
00126 
00127 
00128 void mysleep(unsigned long myjiffies){
00129   MAKE_MY_TIMEOUT_TMR(timeout_tmr);
00130 
00131   del_timer(&timeout_tmr);
00132   timeout_tmr.expires = jiffies + myjiffies;
00133   add_timer(&timeout_tmr);
00134   interruptible_sleep_on(&waitq);
00135 }
00136 
00137 /*
00138  * Driver FS-Functionality Implementation
00139  */
00140 
00141 /* Read CCD Data */
00142 static ssize_t ccd_read(struct file *f, char *buf, size_t count, loff_t *ppos)
00143 {
00144     /*
00145     KDEBUG_L2("%d bytes at %x\n",count, f->f_pos);
00146     tmp_buf=(char *)kmalloc(count, GFP_KERNEL );
00147     memcpy_fromio(tmp_buf, pcdsp_dprambaseptr + (unsigned int)f->f_pos, count);
00148     copy_to_user(buf, tmp_buf, count);
00149     kfree(tmp_buf);
00150     tmp_buf=NULL;
00151     free_dport();
00152     */
00153     return 0;
00154 }
00155 
00156 static int ccd_open(struct inode *inode, struct file *f){
00157   MOD_INC_USE_COUNT;
00158   opened++;  
00159   f->f_pos=0;
00160   KDEBUG("Opened %d times\n",opened);
00161   return 0;
00162 }
00163 
00164 static int ccd_release (struct inode *inode, struct file *f ){
00165   KDEBUG("release, still open:%d\n", opened-1);
00166   MOD_DEC_USE_COUNT;
00167   opened--;
00168   return 0;
00169 }
00170 
00171 static int ccd_ioctl(struct inode *inode, struct file *f, unsigned int cmd, unsigned long arg){
00172     unsigned int cycles=arg/10;
00173     int pixelvalue;
00174     //    KDEBUG("ccd_ioctl::%d\n", cmd);
00175     switch(cmd){
00176     case CCD_CMD_GETPIXEL:
00177         pixelvalue = (int)CCD_PixWert(ccd_io);
00178         CCD_Next(ccd_io);
00179         CCD_Lesen(ccd_io);
00180         return pixelvalue;
00181 
00182     case CCD_CMD_INITLESEN:
00183         CCD_Lesen(ccd_io);
00184         return 0;
00185         
00186     case CCD_CMD_MONITORENABLE:
00187         // Switch in Monitoring Mode as default (free fast videomode run @ ~20ms)
00188         CCD_Monitoring(ccd_io);
00189         return 0;
00190         
00191     case CCD_CMD_CLEAR:
00192         CCD_Monitoring(ccd_io);
00193         mysleep(6);
00194         CCD_Sammeln(ccd_io);
00195         mysleep(4);
00196         CCD_Move2Mem(ccd_io);
00197         return 0;
00198         
00199     case CCD_CMD_EXPOSURE:
00200         if(cycles < 2) cycles = 2;
00201         CCD_Sammeln(ccd_io);
00202         mysleep(4);
00203         CCD_Move2Mem(ccd_io);
00204         CCD_Sammeln(ccd_io);
00205         mysleep(cycles);
00206         CCD_Move2Mem(ccd_io);
00207         CCD_Sammeln(ccd_io);
00208         mysleep(4);
00209         CCD_Move2Mem(ccd_io);
00210         CCD_Sammeln(ccd_io);
00211         return 0;
00212         
00213     default: 
00214         return -1;
00215     }
00216     return 0;
00217 }
00218 
00219 /*
00220  * init some module variables
00221  */
00222 int ccd_initialize(){
00223   opened=0;
00224 
00225   ccd_io = &ccd_parport_io;
00226 
00227   KDEBUG_L1("Driver %s\n", CCD_VERSION);
00228 
00229   ccd_io->base   = LPT3_BASE;
00230   ccd_io->basehi = ccd_io->base + 0x400;
00231   KDEBUG("iobase: 0x%03x\n", (int)ccd_io->base);
00232 
00233   ccd_io->save_status = inw_p(PARP_DATA(ccd_io));
00234   ccd_io->save_mode   = inb_p(PARP_CONTROL(ccd_io));
00235   ccd_io->save_ecmode = inb_p(PARP_ECPCONTROL(ccd_io));
00236   // Setup for 8bit reading
00237   outw_p(0xffff, PARP_DATA(ccd_io));
00238   outb_p(0x20,   PARP_ECPCONTROL(ccd_io));
00239 
00240   // Switch in Monitoring Mode as default (free fast videomode run @ ~20ms)
00241   CCD_Monitoring(ccd_io);
00242 
00243   KDEBUG("Init CCD module OK.\n");
00244 
00245   return 0;
00246 }
00247 
00248 inline void ccd_quit(){
00249   // Switch in Monitoring Mode as default (free fast videomode run @ ~20ms)
00250   CCD_Monitoring(ccd_io);
00251 
00252   // Restore previous mode
00253   outw_p(ccd_io->save_status, PARP_DATA(ccd_io));
00254   outb_p(ccd_io->save_mode, PARP_CONTROL(ccd_io));
00255   outb_p(ccd_io->save_ecmode, PARP_ECPCONTROL(ccd_io));
00256 
00257   KDEBUG("CCD Driver deinstalled\n");
00258 }
00259 
00260 /*
00261  * And now module code and kernel interface.
00262  */
00263 
00264 struct file_operations ccd_fops = {
00265     // NULL           /* llseek */
00266   read:    ccd_read,  /* Read Data to DPRAM */
00267   // NULL,            /* Write Data to DPRAM */
00268   //  NULL,           /* readdir */
00269   //  NULL,           /* poll */
00270   ioctl:   ccd_ioctl, /* ioctl */
00271   //  NULL,           /* mmap */
00272   open:    ccd_open,  /* open */
00273   //  NULL,           /* flush */
00274   release: ccd_release,/* release */
00275   //  NULL,          /* fsync */
00276   //  NULL,          /* fasync */
00277   //  NULL,          /* check_media_change */
00278   //  NULL,          /* revalidate */
00279   //  NULL           /* lock */
00280 };
00281 
00282 int init_module(void){
00283     KDEBUG("init_module CCD\n");
00284 
00285     if ( devfs_register_chrdev (CCD_MAJOR, CCD_DEVICE_NAME, &ccd_fops) ){
00286         KDEBUG("unable create devfs entry for ccd device: %s, major: %d\n", CCD_DEVICE_NAME, CCD_MAJOR);
00287         return -EIO;
00288     }
00289     KDEBUG("Major number :%i \n", CCD_MAJOR);
00290 
00291     devfs_handle = devfs_mk_dir (NULL, CCD_DEVFS_DIR, NULL);
00292 
00293     devfs_register (devfs_handle, CCD_DEVICE_NAME,
00294                         DEVFS_FL_DEFAULT, CCD_MAJOR, 0,
00295                         S_IFCHR | S_IRUGO | S_IWUGO,
00296                         &ccd_fops, NULL);
00297 
00298     if(ccd_initialize())
00299         return -1; /* some error occured */
00300 
00301   return 0; /* success */
00302 }
00303 
00304 void cleanup_module(void){
00305     KDEBUG("Module CCD unregistered\n");
00306     ccd_quit();
00307 
00308     devfs_unregister (devfs_handle);
00309     devfs_unregister_chrdev(CCD_MAJOR, CCD_DEVICE_NAME);
00310 
00311     KDEBUG("cleanup_module\n");
00312 }
00313 
00314 

Generated on Sat Apr 1 09:04:16 2006 for GXSM by  doxygen 1.4.6