pci32.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  * DSP Kernel Module
00029  * Master File for all kernel modules / device drivers
00030  * driver type is selected by -DCARD_PCI32, _PC31, _SIM !
00031  *
00032  * ##old##Device: /dev/pcdsp 
00033  * ##look in dsp.h: #define PCDSP_DEVICE "/dev/pcdsp" and ..NAME
00034  *
00035  * ##making device: mknod -m 666 /dev/pcdsp c xxx 0
00036  * ##for major "xxx" look in log/messages while loading module !
00037  * ##old##in most cases: xxx = 254
00038  * using devfs now!! => /dev/pcdsps/pci32|pc31 (major=240)
00039  */
00040 #define PCDSP_VERSION "V0.2 (C) P.Zahl 1998,1999,2000,2001"
00041 /*
00042  * Compile all versions with make
00043  *
00044  */
00045 
00046 
00047 #include <linux/config.h>
00048 #include <linux/module.h>
00049 #include <linux/version.h>
00050 #include <linux/kernel.h>
00051 #include <linux/sched.h>
00052 #include <linux/smp_lock.h>
00053 #include <linux/devfs_fs_kernel.h>
00054 
00055 #include <linux/pci.h>
00056 #include <linux/types.h>
00057 #include <linux/major.h>
00058 #include <linux/errno.h>
00059 #include <linux/signal.h>
00060 #include <linux/fcntl.h>
00061 #include <linux/interrupt.h>
00062 #include <linux/devpts_fs.h>
00063 #include <linux/file.h>
00064 #include <linux/console.h>
00065 #include <linux/timer.h>
00066 #include <linux/ctype.h>
00067 #include <linux/kd.h>
00068 #include <linux/mm.h>
00069 #include <linux/string.h>
00070 #include <linux/poll.h>
00071 #include <linux/proc_fs.h>
00072 #include <linux/init.h>
00073 
00074 #include <asm/io.h>
00075 #include <asm/uaccess.h>
00076 #include <asm/system.h>
00077 #include <asm/bitops.h>
00078 
00079 #ifdef __SMP__
00080 #include <asm/pgtable.h>
00081 #include <linux/smp_lock.h>
00082 #endif
00083 
00084 /* kernel_thread */
00085 #define __KERNEL_SYSCALLS__
00086 #include <linux/unistd.h>
00087 
00088 #include "dbgstuff.h"
00089 #include "dsp.h"
00090 
00091 /* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
00092    to the "name" field that does exist. As long as the assignments are
00093    done in the right order, there is nothing to worry about. */
00094 
00095 #define driver_name           name 
00096 
00097 /* Should be in a header somewhere. They are in tty.h on 2.2 */
00098 #define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
00099 #define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
00100 
00101 
00102 
00103 /* Card special things */
00104 #ifdef CARD_PCI32
00105  #include "pci32.h"
00106 #else
00107  #ifdef CARD_PC31
00108   #include "pc31.h"
00109  #else
00110   #ifndef CARD_SIM
00111    #define CARD_SIM
00112   #endif
00113   #include "pcsim.h"
00114  #endif
00115 #endif
00116 
00117 /*
00118  * Driver Variables 
00119  */
00120 
00121 static devfs_handle_t devfs_handle = NULL;
00122 
00123 static int pcdsp_error;
00124 
00125 static int opened;
00126 
00127 static char *tmp_buf;
00128 static int pcdsp_running=FALSE;
00129 
00130 static unsigned long PutMem32Adr;
00131 
00132 /* Hardware Location */
00133 static int  pci_remapp_aktive;
00134 static int  pcdsp_iobase;
00135 static int  pcdsp_dpram;
00136 static char *pcdsp_dprambaseptr;
00137 
00138 /* Locations of SEM0..3 controlled Regions */
00139 static unsigned long SemCrtlAdr[PCDSP_SEMANZ], SemCrtlLen[PCDSP_SEMANZ];
00140 
00141 #include "mbox.h"
00142 
00143 /* Process handling... */
00144 static int wakeups = -1;
00145 static DECLARE_WAIT_QUEUE_HEAD(waitq);
00146 
00147 /*
00148  * Timings in jiffies,  1 jiffie dauert ca. 10ms (HZ = #jiffies fue 1sec)
00149  */
00150 
00151 #define TIMEOUT_TICKS    19      /* 200ms */
00152 #define JIFFIES_SEM      2      /* timeout after 50ms */
00153 #define MAXWAKEUPS_SEM   10
00154 #define MAXWAKEUPS_WMBOX 10
00155 #define MAXWAKEUPS_RMBOX 10
00156 
00157 /* Prototypes */
00158 
00159 int SetSemCrtlAdr(int n, unsigned long arg);
00160 int SetSemCrtlLen(int n, unsigned long arg);
00161 int FindSem(unsigned long adr);
00162 static void timeout(unsigned long ignore);
00163 void mysleep(unsigned long myjiffies);
00164 
00165 void pcdsp_interrupt_0(void);
00166 void pcdsp_interrupt_1(void);
00167 void free_dport_range(int semno);
00168 int get_dport_range(int wait, int semno);
00169 void pcdsp_halt(void);
00170 void pcdsp_run(void);
00171 void pcdsp_reset(void);
00172 
00173 int BoxFull(int wait);
00174 int BoxEmpty(int wait);
00175 int ChkBoxEmpty(int wait);
00176 int WriteBox(unsigned long data, int wait);
00177 int ChkBoxFull(int wait);
00178 int ReadBox(unsigned long *data, int wait);
00179 
00180 /* Device Service Functions */
00181 static loff_t pcdsp_seek (struct file *, loff_t, int);
00182 static ssize_t pcdsp_read (struct file *, char *, size_t, loff_t *);
00183 static ssize_t pcdsp_write (struct file *, const char *, size_t, loff_t *);
00184 static int pcdsp_release (struct inode *, struct file *);
00185 static int pcdsp_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
00186 
00187 #ifdef NO_INTERRUPT_SUPPORT_UNTIL_NOW
00188 static void pcdsp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
00189 #endif
00190 int pcdsp_initialize(void);
00191 inline void pcdsp_quit(void);
00192 
00193 int init_module(void);
00194 void cleanup_module(void);
00195 
00196 // Timeout Fkt.
00197 
00198 static void timeout(unsigned long ignore){
00199   KDEBUG_L3("tmout wakeups %d\n", wakeups);
00200   wake_up_interruptible(&waitq);
00201 }
00202 
00203 #define MAKE_MY_TIMEOUT_TMR(tmr) \
00204   struct timer_list tmr; \
00205   init_timer(&tmr); \
00206   tmr.function = timeout; \
00207   tmr.data = 0
00208 
00209 void mysleep(unsigned long myjiffies){
00210   MAKE_MY_TIMEOUT_TMR(timeout_tmr);
00211 
00212   del_timer(&timeout_tmr);
00213   timeout_tmr.expires = jiffies + myjiffies;
00214   add_timer(&timeout_tmr);
00215   interruptible_sleep_on(&waitq);
00216 }
00217 
00218 
00219 /* Semaphore Control */
00220 
00221 int SetSemCrtlAdr(int n, unsigned long arg){
00222   if(arg > 0 && arg < PCDSP_DPRAM_SIZE && n >= 0 && n < PCDSP_SEMANZ){
00223     SemCrtlAdr[n] = arg;
00224     SemCrtlLen[n] = 0;
00225     return 0;
00226   }
00227   return -1;
00228 }
00229 
00230 int SetSemCrtlLen(int n, unsigned long arg){
00231   if(arg > 0 && (SemCrtlAdr[n]+arg) < PCDSP_DPRAM_SIZE && n >= 0 && n < PCDSP_SEMANZ){
00232     SemCrtlLen[n] = arg;
00233     return(0);
00234   }
00235   return(-1);
00236 }
00237 
00238 int inline FindSem(unsigned long adr){
00239 #ifdef CARD_PCI32
00240   int i;
00241   for(i=0; i<PCDSP_SEMANZ; i++)
00242     if(adr >= SemCrtlAdr[i] && adr < (SemCrtlAdr[i]+SemCrtlLen[i]))
00243       return i;
00244 #endif
00245 #ifdef CARD_PC31
00246 #endif
00247 #ifdef CARD_SIM
00248 #endif
00249   return 0;
00250 }
00251 
00252 /* Fire DSP INT0 */
00253 void inline pcdsp_interrupt_0(void){
00254   CLR_IRQ0;
00255   SET_IRQ0;
00256   CLR_IRQ0;
00257 }
00258 
00259 /* Fire DSP INT1 */
00260 void inline pcdsp_interrupt_1(void){
00261   CLR_IRQ1;
00262   SET_IRQ1;
00263   CLR_IRQ1;
00264 }
00265 
00266 /* Release DPRAM */
00267 #define free_dport() free_dport_range(0)
00268 
00269 void inline free_dport_range(int semno){
00270   FREE_SEM(semno);
00271 }
00272 
00273 /* Get DPRAM */
00274 #define get_dport(W) get_dport_range(W, 0)
00275 
00276 int get_dport_range(int wait, int semno){
00277     unsigned long timeoutpoint;
00278     MAKE_MY_TIMEOUT_TMR(timeout_tmr);
00279 
00280     KDEBUG_L3("get SEM%d\n", semno);
00281     GET_SEM(semno);
00282     wakeups=0;
00283     while(pcdsp_running && !SEM(semno) && wakeups < MAXWAKEUPS_SEM){ /* SEM DPRAM access OK ? */
00284         timeoutpoint = jiffies + JIFFIES_SEM;
00285         while(!SEM(semno) && timeoutpoint >= jiffies)
00286             ;
00287         if(SEM(semno))
00288             break;
00289         if(!wait){
00290             free_dport_range(semno);
00291             return FALSE;
00292         }
00293         del_timer(&timeout_tmr);
00294         timeout_tmr.expires = jiffies + TIMEOUT_TICKS;
00295         add_timer(&timeout_tmr);
00296         interruptible_sleep_on(&waitq);
00297         wakeups++;
00298     }
00299     KDEBUG_L3("wakeups for SEM%d: %d\n", semno, wakeups);
00300     if(wakeups == MAXWAKEUPS_SEM){
00301         free_dport_range(semno);
00302         return FALSE;
00303     }
00304     return TRUE;
00305 }
00306 
00307 /* Set Reset Bit: halts DSP */
00308 void inline pcdsp_halt(void){
00309   PCDSP_HALT_X;
00310   pcdsp_running=FALSE;
00311   CLR_IRQ0;
00312   CLR_IRQ1;
00313   free_dport_range(0);
00314   free_dport_range(1);
00315   free_dport_range(2);
00316   free_dport_range(3);
00317   mysleep(50);
00318 }
00319 
00320 /* Clr Reset Bit: starts DSP */
00321 void inline pcdsp_run(void){
00322   PCDSP_RUN_X;
00323   pcdsp_running=TRUE;
00324   mysleep(50);
00325 }
00326 
00327 /* Fire DSP Reset */
00328 void inline pcdsp_reset(void){
00329   PCDSP_HALT_X;
00330   mysleep(50);
00331   PCDSP_RUN_X;
00332   mysleep(50);
00333   pcdsp_running=TRUE;
00334 }
00335 
00336 /*
00337  * Data Acknowledged by DSP / BoxFull ? 
00338  * Achtung: ist Box full, dann bleibt DPORT aktiv !
00339  */
00340 int BoxFull(int wait){
00341     MAKE_MY_TIMEOUT_TMR(timeout_tmr);
00342     
00343     KDEBUG_L2("BoxFull ?\n");
00344     wakeups=0;
00345     if(get_dport(wait)){
00346         while(!(ACKD_DSP) && wakeups < MAXWAKEUPS_RMBOX){
00347             free_dport();
00348             if(!wait)
00349                 return FALSE;
00350             del_timer(&timeout_tmr);
00351             timeout_tmr.expires = jiffies + TIMEOUT_TICKS;
00352             add_timer(&timeout_tmr);
00353             interruptible_sleep_on(&waitq);
00354             wakeups++;
00355             if(!get_dport(wait)){
00356                 KDEBUG_L2("BoxFull !SEM\n");
00357                 return FALSE;
00358             }
00359         }
00360         KDEBUG_L2("BoxFull wakeups %d\n",wakeups);
00361         if(wakeups == MAXWAKEUPS_WMBOX){
00362             free_dport();
00363             KDEBUG_L2("BoxFull timeout\n");
00364             return FALSE;
00365         }
00366         KDEBUG_L2("BoxFull OK\n");
00367         return TRUE;
00368     }
00369     KDEBUG_L2("BoxFull !SEM\n");
00370     return FALSE;
00371 }
00372 
00373 /*
00374  * Data received by DSP / BoxEmpty ?
00375  * Achtung: ist Box empty, dann bleibt DPORT aktiv !
00376  */
00377 int BoxEmpty(int wait){
00378     MAKE_MY_TIMEOUT_TMR(timeout_tmr);
00379     KDEBUG_L2("BoxEmpty ?\n");
00380     wakeups=0;
00381     if(get_dport(wait)){
00382         while(REQD_DSP && wakeups < MAXWAKEUPS_WMBOX){
00383             free_dport();
00384             if(!wait)
00385                 return FALSE;
00386             del_timer(&timeout_tmr);
00387             timeout_tmr.expires = jiffies + TIMEOUT_TICKS;
00388             add_timer(&timeout_tmr);
00389             interruptible_sleep_on(&waitq);
00390             wakeups++;
00391             if(!get_dport(wait)){
00392                 KDEBUG_L2("BoxEmpty !SEM\n");
00393                 return FALSE;
00394             }
00395         }
00396         KDEBUG_L2("BoxEmpty wakeups %d\n",wakeups);
00397         if(wakeups == MAXWAKEUPS_WMBOX){
00398             free_dport();
00399             KDEBUG_L2("BoxEmpty timeout\n");
00400             return FALSE;
00401         }
00402         KDEBUG_L2("BoxEmpty OK\n");
00403         return TRUE;
00404     }
00405     KDEBUG_L2("BoxEmpty !SEM\n");
00406     return FALSE;
00407 }
00408 
00409 /* 
00410  * ChkBoxEmpty:  wurde Mail von DSP abgeholt ?
00411  * WriteBox   :  REQD_DSP ?  ->  XMT_DSP(value), REQ_DSP  ->  [ REQD_DSP ? ] === BoxEmpty()
00412  *               warten auf Box leer und senden
00413  */
00414 
00415 int ChkBoxEmpty(int wait){
00416   if(BoxEmpty(wait)){
00417     free_dport();
00418     return TRUE;
00419   }
00420   return FALSE;
00421 }
00422 
00423 int WriteBox(unsigned long data, int wait){
00424   if(BoxEmpty(wait)){
00425     KDEBUG_L3("WriteBox* %08x %08x %08x %08x\n",
00426             readl(pcdsp_dprambaseptr+PCDSP_TALK_RCV),
00427             readl(pcdsp_dprambaseptr+PCDSP_TALK_ACK),
00428             readl(pcdsp_dprambaseptr+PCDSP_TALK_XMT),
00429             readl(pcdsp_dprambaseptr+PCDSP_TALK_REQ)
00430             );
00431     XMT_DSP(data);
00432     REQ_DSP;
00433     KDEBUG_L3("WriteBox# %08x %08x %08x %08x\n",
00434             readl(pcdsp_dprambaseptr+PCDSP_TALK_RCV),
00435             readl(pcdsp_dprambaseptr+PCDSP_TALK_ACK),
00436             readl(pcdsp_dprambaseptr+PCDSP_TALK_XMT),
00437             readl(pcdsp_dprambaseptr+PCDSP_TALK_REQ)
00438             );
00439     free_dport();
00440     return TRUE;
00441   }
00442   return FALSE;
00443 }
00444 
00445 /*
00446  * ChkBoxFull:   Neue Mail von DSP empfangen ?
00447  * ReadBox:      ACKD_DSP ?  ->  value = RCV_DSP, ACK_DSP  ->  [ ACKD_DSP ? ] === BoxFull()
00448  *               warten auf Mail und lesen
00449  */
00450 
00451 int ChkBoxFull(int wait){
00452   if(BoxFull(wait)){
00453     free_dport();
00454     return TRUE;
00455   }
00456   return FALSE;
00457 }
00458 
00459 int ReadBox(unsigned long *data, int wait){
00460   if(BoxFull(wait)){
00461     KDEBUG_L3("ReadBox* %08x %08x %08x %08x\n",
00462             readl(pcdsp_dprambaseptr+PCDSP_TALK_RCV),
00463             readl(pcdsp_dprambaseptr+PCDSP_TALK_ACK),
00464             readl(pcdsp_dprambaseptr+PCDSP_TALK_XMT),
00465             readl(pcdsp_dprambaseptr+PCDSP_TALK_REQ)
00466             );
00467     *data = RCV_DSP;
00468     ACK_DSP;
00469     KDEBUG_L3("ReadBox# %08x %08x %08x %08x\n",
00470             readl(pcdsp_dprambaseptr+PCDSP_TALK_RCV),
00471             readl(pcdsp_dprambaseptr+PCDSP_TALK_ACK),
00472             readl(pcdsp_dprambaseptr+PCDSP_TALK_XMT),
00473             readl(pcdsp_dprambaseptr+PCDSP_TALK_REQ)
00474             );
00475     free_dport();
00476     return TRUE;
00477   }
00478   return FALSE;
00479 }
00480 
00481 
00482 /*
00483  * Driver FS-Functionality Implementation
00484  */
00485 /* 
00486   defined in /usr/include/unistd.h, but trouble to include it here..., 
00487   so I define it myself here.
00488   If someone can fix this, I'll be happy!
00489 */
00490 
00491 #define SEEK_SET        0       /* Seek from beginning of file.  */
00492 #define SEEK_CUR        1       /* Seek from current position.  */
00493 #define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
00494 
00495 
00496 static loff_t pcdsp_seek(struct file *f, loff_t offset, int orig)
00497 {
00498   switch(orig){
00499   case SEEK_SET: f->f_pos  = offset; break;
00500   case SEEK_CUR: f->f_pos += offset; break;
00501   case SEEK_END: return EBADF;
00502   }
00503   if(   f->f_pos < 0 
00504      || f->f_pos >= PCDSP_DPRAM_SIZE)
00505     f->f_pos = 0;
00506 
00507   KDEBUG("seek to: %04x\n", (int)(f->f_pos));
00508   return f->f_pos;
00509 }
00510 
00511 /* Read Data from DSP */
00512 static ssize_t pcdsp_read(struct file *f, char *buf, size_t count, loff_t *ppos)
00513 {
00514   int semno;
00515   semno = FindSem(f->f_pos);
00516 
00517   if(get_dport_range(TRUE, semno)){
00518     KDEBUG_L2("%d bytes at %x\n",count, f->f_pos);
00519     tmp_buf=(char *)kmalloc(count, GFP_KERNEL );
00520     memcpy_fromio(tmp_buf, pcdsp_dprambaseptr + (unsigned int)f->f_pos, count);
00521     copy_to_user(buf, tmp_buf, count);
00522     kfree(tmp_buf);
00523     tmp_buf=NULL;
00524     free_dport();
00525     return 0;
00526   }
00527   return -EINVAL;
00528 }
00529 
00530 /* Write Data to DSP */
00531 static ssize_t pcdsp_write(struct file *f, const char *buf, size_t count, loff_t *ppos)
00532 {
00533   int semno;
00534   semno = FindSem(f->f_pos);
00535 
00536   if(get_dport_range(TRUE, semno)){
00537     KDEBUG_L2("write %d bytes at %x\n", count, f->f_pos);
00538     tmp_buf=(char *)kmalloc(count, GFP_KERNEL );
00539     copy_from_user(tmp_buf, buf, count);
00540     memcpy_toio(pcdsp_dprambaseptr + (unsigned int)f->f_pos, tmp_buf, count);
00541     kfree(tmp_buf);
00542     tmp_buf=NULL;
00543     free_dport();
00544     return 0;
00545   }
00546   return -EINVAL;
00547 }
00548 
00549 static int pcdsp_open(struct inode *inode, struct file *f){
00550   MOD_INC_USE_COUNT;
00551   opened++;  
00552   f->f_pos=0;
00553   KDEBUG("Opened %d times\n",opened);
00554   return 0;
00555 }
00556 
00557 static int pcdsp_release (struct inode *inode, struct file *f ){
00558   KDEBUG("release, still open:%d\n", opened-1);
00559   MOD_DEC_USE_COUNT;
00560   opened--;
00561   return 0;
00562 }
00563 
00564 static int pcdsp_ioctl(struct inode *inode, struct file *f, unsigned int cmd, unsigned long arg){
00565   KDEBUG("pcdsp_ioctl::%d\n", cmd);
00566   switch(cmd){
00567   case PCDSP_MBOX_FULL:
00568     return ChkBoxFull((int)arg);
00569   case PCDSP_MBOX_READ_WAIT: 
00570     ReadBox(&arg, TRUE);
00571     return (int)(arg&0x00ffffff);
00572   case PCDSP_MBOX_READ_NOWAIT: 
00573     ReadBox(&arg, FALSE);
00574     return (int)(arg&0x00ffffff);
00575 
00576   case PCDSP_MBOX_EMPTY:
00577     return ChkBoxEmpty((int)arg);
00578   case PCDSP_MBOX_WRITE_WAIT: 
00579     return WriteBox(arg, TRUE);
00580   case PCDSP_MBOX_WRITE_NOWAIT: 
00581     return WriteBox(arg, FALSE);
00582 
00583   case PCDSP_SET_MBOX_LOCATION: 
00584     if(arg >= 0 && arg <= (0x07ff-4))
00585       mbox_location = arg << 2;
00586     else
00587       KDEBUG("illegal Mailbox Location");
00588     return 0;
00589   case PCDSP_PUT_SPEED: 
00590     if(get_dport(TRUE)){
00591       writel(arg, pcdsp_dprambaseptr+mbox_location-4);
00592       free_dport();
00593       return 0;
00594     }
00595     return -EINVAL;
00596   case PCDSP_PUTMEM32: 
00597     if(get_dport(TRUE)){
00598       writel(arg, pcdsp_dprambaseptr+PutMem32Adr);
00599       free_dport();
00600       return 0;
00601     }
00602     return -EINVAL;
00603   case PCDSP_PUTMEM32INC: 
00604     if(get_dport(TRUE)){
00605       writel(arg, pcdsp_dprambaseptr+PutMem32Adr);
00606       free_dport();
00607       PutMem32Adr += 4;
00608       if(PutMem32Adr >= (2048*2))
00609         PutMem32Adr = 0;
00610       return 0;
00611     }
00612     return -EINVAL;
00613   case PCDSP_ADDRESS: 
00614     if(arg > (2048*2)){ KDEBUG("invalid address %x\n",(int)arg); return 0; }
00615     PutMem32Adr = arg;
00616     return 0;
00617   case PCDSP_RESET:
00618     pcdsp_reset();
00619     KDEBUG("reset\n");
00620     return 0;
00621   case PCDSP_HALT:   
00622     pcdsp_halt();
00623     KDEBUG("halt\n");
00624     return 0;
00625   case PCDSP_RUN:   
00626     pcdsp_run();
00627     KDEBUG("run\n");
00628     return 0;
00629   case PCDSP_SEM0START:
00630     return SetSemCrtlAdr(0, arg);
00631   case PCDSP_SEM0LEN:
00632     return SetSemCrtlLen(0, arg);
00633   case PCDSP_SEM1START:
00634     return SetSemCrtlAdr(1, arg);
00635   case PCDSP_SEM1LEN:
00636     return SetSemCrtlLen(1, arg);
00637   case PCDSP_SEM2START:
00638     return SetSemCrtlAdr(2, arg);
00639   case PCDSP_SEM2LEN:
00640     return SetSemCrtlLen(2, arg);
00641   case PCDSP_SEM3START:
00642     return SetSemCrtlAdr(3, arg);
00643   case PCDSP_SEM3LEN:
00644     return SetSemCrtlLen(3, arg);
00645 
00646 #ifdef CARD_PC31
00647   case PCDSP_PC31SRQ:   PC31_SRQ((short)arg&1); return 1;
00648   case PCDSP_PC31SRQED: return(PC31_SRQED);
00649   case PCDSP_PC31ACKED: return(PC31_ACKED);
00650   case PCDSP_PC31ACK:   PC31_ACK; return 1;
00651   case PCDSP_PC31ADDR:
00652     outw_p((arg >> 16)&0xffff, DSP_ADR_H);
00653     outw_p( arg       &0xffff, DSP_ADR_L);
00654     return 1;
00655   case PCDSP_PC31STORE:
00656     outw_p((arg >> 16)&0xffff, DSP_DAT_H);
00657     outw_p( arg       &0xffff, DSP_DAT_L);
00658     return 1;
00659   case PCDSP_PC31FETCH:
00660     return(((unsigned long)inw_p(DSP_DAT_H) << 16) | (unsigned long)inw_p(DSP_DAT_L));
00661   case PCDSP_PC31DPENABLE:
00662     ENABLE_PC31_DPRAM;
00663   case PCDSP_PC31CONTROL:
00664     PC31_CONTROL((short)(arg&0xff));
00665     return 1;
00666 #endif
00667 
00668   case PCDSP_GETMODID:
00669     return MODID;
00670 
00671   default: 
00672     KDEBUG_L3("MBox: %08x %08x %08x %08x\n",
00673             (int)readl(arg+pcdsp_dprambaseptr+PCDSP_TALK_RCV),
00674             (int)readl(arg+pcdsp_dprambaseptr+PCDSP_TALK_ACK),
00675             (int)readl(arg+pcdsp_dprambaseptr+PCDSP_TALK_XMT),
00676             (int)readl(arg+pcdsp_dprambaseptr+PCDSP_TALK_REQ)
00677             );
00678     if(get_dport(TRUE)){
00679       KDEBUG("MBox:[%08X]: %08x %08x %08x %08x\n",
00680              (int)(PCDSP_TALK_RCV),
00681              (int)readl(arg+pcdsp_dprambaseptr+PCDSP_TALK_RCV),
00682              (int)readl(arg+pcdsp_dprambaseptr+PCDSP_TALK_ACK),
00683              (int)readl(arg+pcdsp_dprambaseptr+PCDSP_TALK_XMT),
00684              (int)readl(arg+pcdsp_dprambaseptr+PCDSP_TALK_REQ)
00685              );
00686       free_dport();
00687     }else{
00688       KDEBUG("MBox: no SEM acess\n");
00689     }
00690     /*
00691       KDEBUG("ioctl with unknown cmd\n",cmd,arg); 
00692      */
00693     return -1;
00694   }
00695   return 0;
00696 }
00697 
00698 #ifdef NO_INTERRUPT_SUPPORT_UNTIL_NOW
00699 static void pcdsp_interrupt(int irq, void *dev_id, struct pt_regs *regs){  
00700   ;
00701 }
00702 #endif
00703 
00704 /*
00705  * init some module variables
00706  */
00707 int pcdsp_initialize(){
00708   PutMem32Adr=0L;
00709   pci_remapp_aktive=FALSE;
00710   pcdsp_iobase=0;
00711   pcdsp_dpram=0;
00712   pcdsp_dprambaseptr=NULL;
00713   opened=0;
00714 
00715   tmp_buf=NULL;
00716 
00717   // check Memory availability
00718   tmp_buf = (void *)kmalloc (10, GFP_KERNEL);
00719   if (tmp_buf == NULL){
00720     KDEBUG("Could not allocate Memory !\n");
00721     pcdsp_error = 2;
00722   }
00723   kfree(tmp_buf);
00724   tmp_buf=NULL;
00725 
00726   KDEBUG_L1("Driver %s\n", PCDSP_VERSION);
00727 #ifdef CARD_PCI32
00728   if(pcibios_present()){
00729     unsigned char pci_irq_line;
00730     int pci_ioaddr, pci_memaddr;
00731     int pci_index;
00732     unsigned short pci_command, new_command;
00733     pci_irq_line = pci_ioaddr = pci_memaddr = 0;
00734 
00735     for(pci_index = 0; pci_index < 8; pci_index++){
00736       unsigned char pci_bus, pci_device_fn;
00737       unsigned int pci_ioaddr;
00738       if(pcibios_find_device(PCI_VENDOR_ID_INNOVATIVE, PCI_DEVICE_ID_PCI32DSP,
00739                              pci_index, &pci_bus, &pci_device_fn))
00740         break;
00741       pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq_line);
00742 
00743       /* Reading PCI-Info */
00744       pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_ioaddr);
00745       pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
00746       pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_memaddr);
00747       pci_memaddr &= PCI_BASE_ADDRESS_IO_MASK;
00748       KDEBUG("PCI32 card #%d found at I/O:%x mem:%x IRQ %d\n", 
00749              pci_index, pci_ioaddr, pci_memaddr, pci_irq_line);
00750       pcdsp_dpram  = pci_memaddr;
00751       pcdsp_iobase = pci_ioaddr;
00752       pcdsp_dprambaseptr = ioremap(pcdsp_dpram, PCDSP_DPRAM_SIZE);
00753       if(pcdsp_dprambaseptr){
00754         KDEBUG("ioremapping 0x%08x to 0x%08x\n", (int)pcdsp_dpram, (int)pcdsp_dprambaseptr);
00755         pci_remapp_aktive=TRUE;
00756       }else{
00757         KDEBUG("no ioremap, using 0x%08x\n", (int)pcdsp_dpram);
00758         pci_remapp_aktive=FALSE;
00759         pcdsp_dprambaseptr = (char*)pcdsp_dpram;
00760       }
00761 
00762       KDEBUG("checking PCI_COMMAND\n");
00763 
00764       pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_command);
00765       if(pci_command & PCI_COMMAND_MEMORY)
00766         KDEBUG("PCI_CMD_MEMORY\n");
00767       if(pci_command & PCI_COMMAND_IO)
00768         KDEBUG("PCI_CMD_IO\n");
00769       if(pci_command & PCI_COMMAND_MASTER)
00770         KDEBUG("PCI_CMD_MASTER\n");
00771       if(pci_command & PCI_COMMAND_INVALIDATE)
00772         KDEBUG("PCI_CMD_INVALIDATE\n");
00773       if(pci_command & PCI_COMMAND_WAIT)
00774         KDEBUG("PCI_CMD_WAIT\n");
00775 
00776       /* Activate the card. */
00777       //      new_command = pci_command | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;      
00778       new_command = PCI_COMMAND_IO | PCI_COMMAND_MEMORY;      
00779       //      new_command = pci_command | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_INVALIDATE | PCI_COMMAND_WAIT;
00780       if (pci_command != new_command) {
00781         KDEBUG("The PCI BIOS has not enabled this"
00782                " device!  Updating PCI command %4.4x->%4.4x.\n",
00783                pci_command, new_command);
00784         pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, new_command);
00785         
00786       }
00787 
00788       pcdsp_halt();
00789 
00790       /* Setup default SEM - regions */
00791       SetSemCrtlAdr(0, PCDSP_MBOX);
00792       SetSemCrtlLen(0, PCDSP_MBOX_SIZE);
00793       SetSemCrtlAdr(1, PCDSP_DATA1);
00794       SetSemCrtlLen(1, PCDSP_DATA1_SIZE);
00795       SetSemCrtlAdr(2, PCDSP_DATA2);
00796       SetSemCrtlLen(2, PCDSP_DATA2_SIZE);
00797       SetSemCrtlAdr(3, PCDSP_DATA3);
00798       SetSemCrtlLen(3, PCDSP_DATA3_SIZE);
00799 
00800       KDEBUG_L1("Init PCDSP::CARD_PCI32 module OK.\n");
00801     }
00802     if(!pci_index){
00803       KDEBUG("no PCI32 card found this system\n");
00804       return -2;
00805     }
00806   }else{
00807     KDEBUG("no PCI support with this system\n");
00808     return -1;
00809   }
00810 #endif
00811 #ifdef CARD_PC31
00812   pcdsp_iobase = BASEPORT;
00813   pcdsp_dpram  = DPRAMBASE;
00814   pci_remapp_aktive=FALSE;
00815   pcdsp_dprambaseptr = (char*)pcdsp_dpram;
00816   ENABLE_PC31_DPRAM;
00817   KDEBUG("iobase, using port 0x%03x\n", pcdsp_iobase);
00818   KDEBUG("dprambase: 0x%08x\n", pcdsp_dpram);
00819 
00820   KDEBUG("Init PCDSP::CARD_PC31 module OK.\n");
00821 #endif
00822 #ifdef CARD_SIM
00823   KDEBUG_L1("Init PCDSP::CARD_SIM module OK.\n");
00824 #endif
00825 
00826   return 0;
00827 }
00828 
00829 inline void pcdsp_quit(){
00830 #ifdef CARD_PCI32
00831   if(pci_remapp_aktive)
00832     iounmap(pcdsp_dprambaseptr);
00833 
00834   KDEBUG("PCI32 Driver deinstalled\n");
00835 #endif
00836 #ifdef CARD_PC31
00837   KDEBUG("PC31 Driver deinstalled\n");
00838 #endif
00839 #ifdef CARD_SIM
00840   KDEBUG("Simulation Driver deinstalled\n");
00841 #endif
00842 }
00843 
00844 /*
00845  * And now module code and kernel interface.
00846  */
00847 
00848 struct file_operations pcdsp_fops = {
00849   llseek:    pcdsp_seek,   /* Set DPRAM R/W Position */
00850   read:    pcdsp_read,   /* Read Data to DPRAM */
00851   write:   pcdsp_write,  /* Write Data to DPRAM */
00852   //  NULL,         /* readdir */
00853   //  NULL,         /* poll */
00854   ioctl:   pcdsp_ioctl,  /* ioctl */
00855   //  NULL,         /* mmap */
00856   open:    pcdsp_open,   /* open */
00857   //  NULL,         /* flush */
00858   release: pcdsp_release,/* release */
00859   //  NULL,         /* fsync */
00860   //  NULL,         /* fasync */
00861   //  NULL,         /* check_media_change */
00862   //  NULL,         /* revalidate */
00863   //  NULL          /* lock */
00864 };
00865 
00866 int init_module(void){
00867     KDEBUG("init_module PCDSP\n");
00868     if ( devfs_register_chrdev (PCDSP_MAJOR, PCDSP_DEVICE_NAME, &pcdsp_fops) ){
00869         KDEBUG("unable create devfs entry for pcdsp device: %s, major: %d\n", PCDSP_DEVICE_NAME, PCDSP_MAJOR);
00870         return -EIO;
00871     }
00872     KDEBUG("Major number :%i \n", PCDSP_MAJOR);
00873 
00874     devfs_handle = devfs_mk_dir (NULL, PCDSP_DEVFS_DIR, NULL);
00875 
00876     devfs_register (devfs_handle, PCDSP_DEVICE_NAME,
00877                         DEVFS_FL_DEFAULT, PCDSP_MAJOR, 0,
00878                         S_IFCHR | S_IRUGO | S_IWUGO,
00879                         &pcdsp_fops, NULL);
00880 
00881 
00882 
00883     if(pcdsp_initialize())
00884         return -1; /* some error occured */
00885 
00886     // int request_irq(unsigned int irq,
00887     //              void (*handler)(int, void *, struct pt_regs *),
00888     //              unsigned long irqflags, const char *devname,
00889     //              void *dev_id);
00890     //       void free_irq(unsigned int irq, void *dev_id);
00891   
00892     return 0; /* success */
00893 }
00894 
00895 void cleanup_module(void){
00896     KDEBUG("Module PCDSP unregistered\n");
00897     
00898     pcdsp_quit();
00899 
00900     devfs_unregister (devfs_handle);
00901     devfs_unregister_chrdev(PCDSP_MAJOR, PCDSP_DEVICE_NAME);
00902     
00903     //  if(pcdsp_busy) ...
00904     //  release_region (0x280, 15);
00905     //  free_irq(pcdsp_interrupt,NULL);
00906     
00907     //  disable_irq(pcdsp_interrupt);
00908     KDEBUG("Module PCDSP unregistered.\n");
00909 }
00910 
00911 

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