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 /*
00029  * CCD Kernel Module
00030  * CCD on ParPort
00031  *
00032  * Device: /dev/ccd
00033  *
00034  * making device: mknod -m 666 /dev/ccd c xxx 0
00035  * for major "xxx" look in log/messages while loading module !
00036  * in most cases: xxx = 254
00037  */
00038 #define CCD_VERSION "V0.1 (C) P.Zahl 2000"
00039 /*
00040  * Compile all versions with make
00041  *
00042  */
00043 
00044 
00045 #include <linux/config.h>
00046 #include <linux/module.h>
00047 #include <linux/pci.h>
00048 #include <linux/types.h>
00049 #include <linux/major.h>
00050 #include <linux/errno.h>
00051 #include <linux/signal.h>
00052 #include <linux/fcntl.h>
00053 #include <linux/sched.h>
00054 #include <linux/interrupt.h>
00055 #include <linux/devpts_fs.h>
00056 #include <linux/file.h>
00057 #include <linux/console.h>
00058 #include <linux/timer.h>
00059 #include <linux/ctype.h>
00060 #include <linux/kd.h>
00061 #include <linux/mm.h>
00062 #include <linux/string.h>
00063 #include <linux/malloc.h>
00064 #include <linux/poll.h>
00065 #include <linux/proc_fs.h>
00066 #include <linux/init.h>
00067 #include <linux/smp_lock.h>
00068 
00069 #include <asm/io.h>
00070 #include <asm/uaccess.h>
00071 #include <asm/system.h>
00072 #include <asm/bitops.h>
00073 
00074 #include "ccd.h"
00075 #include "dbgstuff.h"
00076 
00077 
00078 #define my_iounmap(x, b)             (((long)x<0x100000)?0:vfree ((void*)x))
00079 
00080 #define capable(x)                   suser()
00081 
00082 #define queue_task                   queue_task_irq_off
00083 #define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
00084 #define signal_pending(current)      (current->signal & ~current->blocked)
00085 #define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
00086 
00087 
00088 #define test_and_set_bit(nr, addr)   set_bit(nr, addr)
00089 #define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
00090 
00091 /* Not yet implemented on 2.0 */
00092 #define ASYNC_SPD_SHI  -1
00093 #define ASYNC_SPD_WARP -1
00094 
00095 
00096 
00097 
00098 /* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
00099    to the "name" field that does exist. As long as the assignments are
00100    done in the right order, there is nothing to worry about. */
00101 #define driver_name           name 
00102 
00103 /* Should be in a header somewhere. They are in tty.h on 2.2 */
00104 #define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
00105 #define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
00106 
00107 
00108 /*
00109  * Driver Variables 
00110  */
00111 
00112 static int ccd_major;
00113 static int opened;
00114 
00115 /* Hardware Location */
00116 static ccd_parport ccd_parport_io;
00117 static ccd_parport *ccd_io;
00118 
00119 /* Process handling... */
00120 static struct wait_queue *waitq = NULL;
00121 
00122 /*
00123  * Timings in jiffies,  1 jiffie dauert ca. 10ms (HZ = #jiffies fue 1sec)
00124  */
00125 
00126 #define TIMEOUT_TICKS    19      /* 200ms */
00127 #define JIFFIES_SEM      2      /* timeout after 50ms */
00128 #define MAXWAKEUPS_SEM   10
00129 
00130 /* Prototypes */
00131 
00132 static void timeout(unsigned long ignore);
00133 void mysleep(unsigned long myjiffies);
00134 
00135 /* Device Service Functions */
00136 static ssize_t ccd_read (struct file *, char *, size_t, loff_t *);
00137 static int ccd_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
00138 
00139 int ccd_initialize(void);
00140 inline void ccd_quit(void);
00141 
00142 int init_module(void);
00143 void cleanup_module(void);
00144 
00145 static void timeout(unsigned long ignore){
00146   KDEBUG_L3("tmout wakeups %d\n", wakeups);
00147   wake_up_interruptible(&waitq);
00148 }
00149 
00150 void mysleep(unsigned long myjiffies){
00151   static struct timer_list timeout_tmr = { NULL, NULL, 0, 0, timeout };
00152   del_timer(&timeout_tmr);
00153   timeout_tmr.expires = jiffies + myjiffies;
00154   add_timer(&timeout_tmr);
00155   interruptible_sleep_on(&waitq);
00156 }
00157 
00158 /*
00159  * Driver FS-Functionality Implementation
00160  */
00161 
00162 /* Read CCD Data */
00163 static ssize_t ccd_read(struct file *f, char *buf, size_t count, loff_t *ppos)
00164 {
00165     /*
00166     KDEBUG_L2("%d bytes at %x\n",count, f->f_pos);
00167     tmp_buf=(char *)kmalloc(count, GFP_KERNEL );
00168     memcpy_fromio(tmp_buf, pcdsp_dprambaseptr + (unsigned int)f->f_pos, count);
00169     copy_to_user(buf, tmp_buf, count);
00170     kfree(tmp_buf);
00171     tmp_buf=NULL;
00172     free_dport();
00173     */
00174     return 0;
00175 }
00176 
00177 static int ccd_open(struct inode *inode, struct file *f){
00178   MOD_INC_USE_COUNT;
00179   opened++;  
00180   f->f_pos=0;
00181   KDEBUG("Opened %d times\n",opened);
00182   return 0;
00183 }
00184 
00185 static int ccd_release (struct inode *inode, struct file *f ){
00186   KDEBUG("release, still open:%d\n", opened-1);
00187   MOD_DEC_USE_COUNT;
00188   opened--;
00189   return 0;
00190 }
00191 
00192 static int ccd_ioctl(struct inode *inode, struct file *f, unsigned int cmd, unsigned long arg){
00193     unsigned int cycles=arg/10;
00194     int pixelvalue;
00195     //    KDEBUG("ccd_ioctl::%d\n", cmd);
00196     switch(cmd){
00197     case CCD_CMD_GETPIXEL:
00198         pixelvalue = (int)CCD_PixWert(ccd_io);
00199         CCD_Next(ccd_io);
00200         CCD_Lesen(ccd_io);
00201         return pixelvalue;
00202 
00203     case CCD_CMD_INITLESEN:
00204         CCD_Lesen(ccd_io);
00205         return 0;
00206         
00207     case CCD_CMD_MONITORENABLE:
00208         // Switch in Monitoring Mode as default (free fast videomode run @ ~20ms)
00209         CCD_Monitoring(ccd_io);
00210         return 0;
00211         
00212     case CCD_CMD_CLEAR:
00213         CCD_Monitoring(ccd_io);
00214         mysleep(6);
00215         CCD_Sammeln(ccd_io);
00216         mysleep(4);
00217         CCD_Move2Mem(ccd_io);
00218         return 0;
00219         
00220     case CCD_CMD_EXPOSURE:
00221         if(cycles < 2) cycles = 2;
00222         CCD_Sammeln(ccd_io);
00223         mysleep(4);
00224         CCD_Move2Mem(ccd_io);
00225         CCD_Sammeln(ccd_io);
00226         mysleep(cycles);
00227         CCD_Move2Mem(ccd_io);
00228         CCD_Sammeln(ccd_io);
00229         mysleep(4);
00230         CCD_Move2Mem(ccd_io);
00231         CCD_Sammeln(ccd_io);
00232         return 0;
00233         
00234     default: 
00235         return -1;
00236     }
00237     return 0;
00238 }
00239 
00240 /*
00241  * init some module variables
00242  */
00243 int ccd_initialize(){
00244   opened=0;
00245 
00246   ccd_io = &ccd_parport_io;
00247 
00248   KDEBUG_L1("Driver %s\n", CCD_VERSION);
00249 
00250   ccd_io->base   = LPT1_BASE;
00251   ccd_io->basehi = ccd_io->base + 0x400;
00252   KDEBUG("iobase: 0x%03x\n", (int)ccd_io->base);
00253 
00254   ccd_io->save_status = inw_p(PARP_DATA(ccd_io));
00255   ccd_io->save_mode   = inb_p(PARP_CONTROL(ccd_io));
00256   ccd_io->save_ecmode = inb_p(PARP_ECPCONTROL(ccd_io));
00257   // Setup for 8bit reading
00258   outw_p(0xffff, PARP_DATA(ccd_io));
00259   outb_p(0x20,   PARP_ECPCONTROL(ccd_io));
00260 
00261   // Switch in Monitoring Mode as default (free fast videomode run @ ~20ms)
00262   CCD_Monitoring(ccd_io);
00263 
00264   KDEBUG("Init CCD module OK.\n");
00265 
00266   return 0;
00267 }
00268 
00269 inline void ccd_quit(){
00270   // Switch in Monitoring Mode as default (free fast videomode run @ ~20ms)
00271   CCD_Monitoring(ccd_io);
00272 
00273   // Restore previous mode
00274   outw_p(ccd_io->save_status, PARP_DATA(ccd_io));
00275   outb_p(ccd_io->save_mode, PARP_CONTROL(ccd_io));
00276   outb_p(ccd_io->save_ecmode, PARP_ECPCONTROL(ccd_io));
00277 
00278   KDEBUG("CCD Driver deinstalled\n");
00279 }
00280 
00281 /*
00282  * And now module code and kernel interface.
00283  */
00284 /*
00285 struct file_operations {
00286         loff_t (*llseek) (struct file *, loff_t, int);
00287         ssize_t (*read) (struct file *, char *, size_t, loff_t *);
00288         ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
00289         int (*readdir) (struct file *, void *, filldir_t);
00290         unsigned int (*poll) (struct file *, struct poll_table_struct *);
00291         int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
00292         int (*mmap) (struct file *, struct vm_area_struct *);
00293         int (*open) (struct inode *, struct file *);
00294         int (*flush) (struct file *);
00295         int (*release) (struct inode *, struct file *);
00296         int (*fsync) (struct file *, struct dentry *);
00297         int (*fasync) (int, struct file *, int);
00298         int (*check_media_change) (kdev_t dev);
00299         int (*revalidate) (kdev_t dev);
00300         int (*lock) (struct file *, int, struct file_lock *);
00301 };
00302 */
00303 
00304 struct file_operations ccd_fops = {
00305   NULL,         /* Set DPRAM R/W Position */
00306   ccd_read,   /* Read Data to DPRAM */
00307   NULL,         /* Write Data to DPRAM */
00308   NULL,         /* readdir */
00309   NULL,         /* poll */
00310   ccd_ioctl,  /* ioctl */
00311   NULL,         /* mmap */
00312   ccd_open,   /* open */
00313   NULL,         /* flush */
00314   ccd_release,/* release */
00315   NULL,         /* fsync */
00316   NULL,         /* fasync */
00317   NULL,         /* check_media_change */
00318   NULL,         /* revalidate */
00319   NULL          /* lock */
00320 };
00321 
00322 int init_module(void){
00323   KDEBUG("init_module CCD\n");
00324   if ((ccd_major = register_chrdev (0, CCD_DEVICE_NAME, &ccd_fops))== -EBUSY){
00325       KDEBUG("unable to get major for ccd device: %s\n", CCD_DEVICE_NAME);
00326       return -EIO;
00327     }
00328   KDEBUG("Major number :%i \n", ccd_major);
00329 
00330   if(ccd_initialize())
00331     return -1; /* some error occured */
00332 
00333   return 0; /* success */
00334 }
00335 
00336 void cleanup_module(void){
00337   KDEBUG("Module CCD unregistered\n");
00338   unregister_chrdev(ccd_major, CCD_DEVICE_NAME);
00339 
00340   ccd_quit();
00341 
00342   KDEBUG("cleanup_module\n");
00343 }
00344 
00345 

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