00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #define PCDSP_VERSION "V0.2 (C) P.Zahl 1998,1999,2000,2001"
00041
00042
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
00085 #define __KERNEL_SYSCALLS__
00086 #include <linux/unistd.h>
00087
00088 #include "dbgstuff.h"
00089 #include "dsp.h"
00090
00091
00092
00093
00094
00095 #define driver_name name
00096
00097
00098 #define TTY_HW_COOK_OUT 14
00099 #define TTY_HW_COOK_IN 15
00100
00101
00102
00103
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
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
00133 static int pci_remapp_aktive;
00134 static int pcdsp_iobase;
00135 static int pcdsp_dpram;
00136 static char *pcdsp_dprambaseptr;
00137
00138
00139 static unsigned long SemCrtlAdr[PCDSP_SEMANZ], SemCrtlLen[PCDSP_SEMANZ];
00140
00141 #include "mbox.h"
00142
00143
00144 static int wakeups = -1;
00145 static DECLARE_WAIT_QUEUE_HEAD(waitq);
00146
00147
00148
00149
00150
00151 #define TIMEOUT_TICKS 19
00152 #define JIFFIES_SEM 2
00153 #define MAXWAKEUPS_SEM 10
00154 #define MAXWAKEUPS_WMBOX 10
00155 #define MAXWAKEUPS_RMBOX 10
00156
00157
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
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
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
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
00253 void inline pcdsp_interrupt_0(void){
00254 CLR_IRQ0;
00255 SET_IRQ0;
00256 CLR_IRQ0;
00257 }
00258
00259
00260 void inline pcdsp_interrupt_1(void){
00261 CLR_IRQ1;
00262 SET_IRQ1;
00263 CLR_IRQ1;
00264 }
00265
00266
00267 #define free_dport() free_dport_range(0)
00268
00269 void inline free_dport_range(int semno){
00270 FREE_SEM(semno);
00271 }
00272
00273
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){
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
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
00321 void inline pcdsp_run(void){
00322 PCDSP_RUN_X;
00323 pcdsp_running=TRUE;
00324 mysleep(50);
00325 }
00326
00327
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
00338
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
00375
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
00411
00412
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
00447
00448
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
00484
00485
00486
00487
00488
00489
00490
00491 #define SEEK_SET 0
00492 #define SEEK_CUR 1
00493 #define SEEK_END 2
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
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
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
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
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
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
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
00777
00778 new_command = PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
00779
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
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
00846
00847
00848 struct file_operations pcdsp_fops = {
00849 llseek: pcdsp_seek,
00850 read: pcdsp_read,
00851 write: pcdsp_write,
00852
00853
00854 ioctl: pcdsp_ioctl,
00855
00856 open: pcdsp_open,
00857
00858 release: pcdsp_release,
00859
00860
00861
00862
00863
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;
00885
00886
00887
00888
00889
00890
00891
00892 return 0;
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
00904
00905
00906
00907
00908 KDEBUG("Module PCDSP unregistered.\n");
00909 }
00910
00911