/[VMELinux]/driver/ca91c042.c
ViewVC logotype

Contents of /driver/ca91c042.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations)
Mon Jun 18 14:57:36 2001 UTC (18 years, 3 months ago) by astro
Branch: MAIN
CVS Tags: vmelinux-1_1_2
Changes since 1.1: +1 -11 lines
File MIME type: text/plain
Changed the device number from 70 to 221 as assigned by the Linux authorities.
1 //------------------------------------------------------------------------------
2 //title: Tundra Universe PCI-VME Kernel Driver
3 //version: Linux
4 //date: March 1999
5 //designer: Michael Wyrick
6 //programmer: Michael Wyrick
7 //platform: Linux 2.2.12
8 //language: GCC 2.8.1
9 //module: ca91c042
10 //------------------------------------------------------------------------------
11 // Purpose: Provide a Kernel Driver to Linux for the Universe I and II
12 // Universe model number ca91c042
13 // Docs:
14 // This driver supports both the Universe and Universe II chips
15 //------------------------------------------------------------------------------
16 // RCS:
17 // $Id: ca91c042.c,v 1.2 2001/06/18 14:57:36 astro Exp $
18 //
19 //-----------------------------------------------------------------------------
20 #define MODULE
21
22 static char Version[] = "1.0 00Oct3";
23
24 #include <linux/config.h>
25 #include <linux/version.h>
26
27 #ifdef CONFIG_MODVERSIONS
28 #define MODVERSIONS
29 #include <linux/modversions.h>
30 #endif
31
32 #include <linux/module.h>
33 #include <linux/types.h>
34 #include <linux/errno.h>
35 #include <linux/proc_fs.h>
36 #include <linux/pci.h>
37 #include <linux/poll.h>
38 #include <asm/io.h>
39 #include <asm/uaccess.h>
40
41 #include "ca91c042.h"
42
43 #if LINUX_VERSION_CODE < 0x020100
44 #define ioremap vremap
45 #define iounmap vfree
46 #endif
47
48
49 //----------------------------------------------------------------------------
50 // Prototypes
51 //----------------------------------------------------------------------------
52 static int uni_open(struct inode *, struct file *);
53 static int uni_release(struct inode *, struct file *);
54 static ssize_t uni_read(struct file *,char *, size_t, loff_t *);
55 static ssize_t uni_write(struct file *,const char *, size_t, loff_t *);
56 static unsigned int uni_poll(struct file *, poll_table *);
57 static int uni_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
58 static long long uni_llseek(struct file *,loff_t,int);
59 //static int uni_mmap(struct inode *inode,struct file *file,struct vm_area_struct *vma);
60 //static int uni_select(struct inode *inode,struct file *file,int mode, select_table *table);
61 static int uni_procinfo(char *, char **, off_t, int, int *,void *);
62
63 //----------------------------------------------------------------------------
64 // Types
65 //----------------------------------------------------------------------------
66 static struct proc_dir_entry *uni_procdir;
67
68 static struct file_operations uni_fops =
69 {
70 uni_llseek,
71 uni_read,
72 uni_write,
73 NULL, // uni_readdir
74 uni_poll, // uni_poll
75 uni_ioctl,
76 NULL, // uni_mmap
77 uni_open,
78 NULL, // Flush
79 uni_release
80 };
81
82 static int aCTL[] = {LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL};
83 static int aBS[] = {LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS};
84 static int aBD[] = {LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD};
85 static int aTO[] = {LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO};
86
87 //----------------------------------------------------------------------------
88 // Vars and Defines
89 //----------------------------------------------------------------------------
90 #define UNI_MAJOR 221
91 #define MAX_MINOR 8
92 #define CONTROL_MINOR 8
93
94 #define MODE_UNDEFINED 0
95 #define MODE_PROGRAMMED 1
96 #define MODE_DMA 2
97
98 #define DMATYPE_SINGLE 1
99 #define DMATYPE_LLIST 2
100
101 static int OkToWrite[MAX_MINOR + 1]; // Can I write to the Hardware
102
103 static int opened[MAX_MINOR + 1];
104 static int mode[MAX_MINOR + 1]; // DMA or Programmed I/O
105
106 static unsigned long DMA[MAX_MINOR + 1]; // DMA Control Reg
107
108 static int status;
109 static int DMAType = 0;
110 static int irq = 0;
111 static char *baseaddr = 0;
112 static char *image_ba[MAX_MINOR+1]; // Base PCI Address
113
114 static unsigned int image_ptr[MAX_MINOR+1];
115 static unsigned int image_va[MAX_MINOR+1];
116
117 // Hold the VME Irq Handlers
118 static TirqHandler vmeirqs[7] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
119 static short vmeirqbit[7] = {IRQ_VIRQ1, IRQ_VIRQ2, IRQ_VIRQ3, IRQ_VIRQ4,
120 IRQ_VIRQ5, IRQ_VIRQ6, IRQ_VIRQ7};
121 static int vmevec[7] = {V1_STATID, V2_STATID, V3_STATID, V4_STATID,
122 V5_STATID, V6_STATID, V7_STATID};
123
124 // Status Vars
125 static unsigned int reads = 0;
126 static unsigned int writes = 0;
127 static unsigned int ioctls = 0;
128
129 static TDMAcallback DMACallBackFunc = NULL;
130 static void *debugptr = NULL;
131
132 // Timers
133 struct timer_list DMA_timer; // This is a timer for returning status
134
135 //----------------------------------------------------------------------------
136 // uni_procinfo()
137 //----------------------------------------------------------------------------
138 static int uni_procinfo(char *buf, char **start, off_t fpos, int lenght, int *eof, void *data)
139 {
140 char *p;
141 unsigned int temp1,temp2,x;
142
143 p = buf;
144 p += sprintf(p,"Universe driver %s\n",Version);
145
146 p += sprintf(p," baseaddr = %08X\n",(int)baseaddr);
147 p += sprintf(p," Stats reads = %i writes = %i ioctls = %i\n",
148 reads,writes,ioctls);
149
150 for(x=0;x<4;x+=2) {
151 temp1 = readl(baseaddr+aCTL[x]);
152 temp2 = readl(baseaddr+aCTL[x+1]);
153 p += sprintf(p," LSI%i_CTL = %08X LSI%i_CTL = %08X\n",x,temp1,x+1,temp2);
154 temp1 = readl(baseaddr+aBS[x]);
155 temp2 = readl(baseaddr+aBS[x+1]);
156 p += sprintf(p," LSI%i_BS = %08X LSI%i_BS = %08X\n",x,temp1,x+1,temp2);
157 temp1 = readl(baseaddr+aBD[x]);
158 temp2 = readl(baseaddr+aBD[x+1]);
159 p += sprintf(p," LSI%i_BD = %08X LSI%i_BD = %08X\n",x,temp1,x+1,temp2);
160 temp1 = readl(baseaddr+aTO[x]);
161 temp2 = readl(baseaddr+aTO[x+1]);
162 p += sprintf(p," LSI%i_TO = %08X LSI%i_TO = %08X\n",x,temp1,x+1,temp2);
163 }
164
165 for(x=0;x<3;x+=2)
166 p += sprintf(p," image_va%i = %08X image_va%i = %08X\n",
167 x,image_va[x],x+1,image_va[x+1]);
168 p += sprintf(p,"\nDriver Program Status:\n");
169
170 for(x=0;x<3;x+=2)
171 p += sprintf(p," DMACTL %i = %08lX DMACTL %i = %08lX\n",
172 x,DMA[x],x+1,DMA[x+1]);
173 for(x=0;x<3;x+=2)
174 p += sprintf(p," OkToWrite %i = %1X OkToWrite %i = %1X\n",
175 x,OkToWrite[x],x+1,OkToWrite[x+1]);
176 for(x=0;x<3;x+=2)
177 p += sprintf(p," Mode %i = %1X Mode %i = %1X\n",
178 x,mode[x],x+1,mode[x+1]);
179
180 p += sprintf(p,"\n");
181
182 temp1 = 0;
183 p += sprintf(p, "VMEIrqs Assigned: ");
184 for(x=0;x<7;x++) {
185 if(vmeirqs[x] != NULL) {
186 p += sprintf(p, "%i ",x+1);
187 temp1++;
188 }
189 }
190 if(temp1 == 0)
191 p += sprintf(p, "none\n");
192 else
193 p += sprintf(p,"\n");
194
195 *eof = 1;
196 return p - buf;
197 }
198
199 //----------------------------------------------------------------------------
200 // register_proc()
201 //----------------------------------------------------------------------------
202 static void register_proc()
203 {
204 uni_procdir = create_proc_entry("ca91c042", S_IFREG | S_IRUGO, 0);
205 uni_procdir->read_proc = uni_procinfo;
206 }
207
208 //----------------------------------------------------------------------------
209 // unregister_proc()
210 //----------------------------------------------------------------------------
211 static void unregister_proc()
212 {
213 remove_proc_entry("ca91c042",0);
214 }
215
216 //----------------------------------------------------------------------------
217 //
218 // uni_poll()
219 //
220 //----------------------------------------------------------------------------
221 static unsigned int uni_poll(struct file* file, poll_table* wait)
222 {
223 return 0;
224 }
225
226 //----------------------------------------------------------------------------
227 //
228 // uni_open()
229 //
230 //----------------------------------------------------------------------------
231 static int uni_open(struct inode *inode,struct file *file)
232 {
233 unsigned int minor = MINOR(inode->i_rdev);
234
235 if(minor > MAX_MINOR) {
236 return(-ENODEV);
237 }
238
239 if(minor == CONTROL_MINOR) {
240 opened[minor]++;
241 return(0);
242 }
243
244 if(!opened[minor]) {
245 opened[minor] = 1;
246 return(0);
247 } else
248 return(-EBUSY);
249 }
250
251 //----------------------------------------------------------------------------
252 //
253 // uni_release()
254 //
255 //----------------------------------------------------------------------------
256 static int uni_release(struct inode *inode,struct file *file)
257 {
258 unsigned int minor = MINOR(inode->i_rdev);
259
260 opened[minor]--;
261
262 return 0;
263 }
264
265 //----------------------------------------------------------------------------
266 //
267 // uni_lseek()
268 //
269 //----------------------------------------------------------------------------
270 static long long uni_llseek(struct file *file,loff_t offset,int whence)
271 {
272 unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
273 unsigned int toffset,base,paddr;
274
275 if(whence == SEEK_SET) {
276 if(minor == CONTROL_MINOR) {
277 image_ptr[minor] = offset;
278 } else {
279 toffset = readl(baseaddr+aTO[minor]);
280 base = readl(baseaddr+aBS[minor]);
281 paddr = offset-toffset;
282 image_ptr[minor] = (int)(image_ba[minor]+(paddr-base));
283 }
284 return 0;
285 } else if(whence == SEEK_CUR) {
286 image_ptr[minor] += offset;
287 return 0;
288 } else
289 return -1;
290 }
291
292 //----------------------------------------------------------------------------
293 //
294 // uni_read()
295 //
296 //----------------------------------------------------------------------------
297 static ssize_t uni_read(struct file *file, char *buf, size_t count, loff_t *ppos)
298 {
299 int x = 0;
300 unsigned int v,numt,remain,tmp;
301 char *temp = buf;
302 unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
303 int p;
304
305 unsigned char vc;
306 unsigned short vs;
307 unsigned int vl;
308
309 char *DMA_Buffer;
310 unsigned int DMA_Buffer_Size = 0,
311 order = 0,
312 a_size = 0,
313 dma_align = 0,
314 timeout = 0;
315 int val,
316 pci = 0,
317 vme = 0,
318 okcount = 0;
319
320 if(minor == CONTROL_MINOR) {
321 p = (int)image_ptr[minor];
322 v = readl(baseaddr+p);
323 __copy_to_user(temp,&v,4);
324 } else {
325 reads++;
326 if(OkToWrite[minor]) {
327 if(mode[minor] == MODE_PROGRAMMED) {
328 numt = count;
329 remain = count;
330
331 // Calc the number of longs we need
332 numt = count / 4;
333 remain = count % 4;
334 for(x=0;x<numt;x++) {
335 vl = readl(image_ptr[minor]);
336
337 // Lets Check for a Bus Error
338 tmp = readl(baseaddr+PCI_CSR);
339 if(tmp & 0x08000000) {
340 writel(tmp,baseaddr+PCI_CSR);
341 return(okcount);
342 } else
343 okcount += 4;
344
345 __copy_to_user(temp,&vl,4);
346 image_ptr[minor]+=4;
347 temp+=4;
348 }
349
350 // Calc the number of Words we need
351 numt = remain / 2;
352 remain = remain % 2;
353 for(x=0;x<numt;x++) {
354 vs = readw(image_ptr[minor]);
355
356 // Lets Check for a Bus Error
357 tmp = readl(baseaddr+PCI_CSR);
358 if(tmp & 0x08000000) {
359 writel(tmp,baseaddr+PCI_CSR);
360 return(okcount);
361 } else
362 okcount += 2;
363
364 __copy_to_user(temp,&vs,2);
365 image_ptr[minor]+=2;
366 temp+=2;
367 }
368
369 for(x=0;x<remain;x++) {
370 vc = readb(image_ptr[minor]);
371
372 // Lets Check for a Bus Error
373 tmp = readl(baseaddr+PCI_CSR);
374 if(tmp & 0x08000000) {
375 writel(tmp,baseaddr+PCI_CSR);
376 return(okcount);
377 } else
378 okcount++;
379
380 __copy_to_user(temp,&vc,1);
381 image_ptr[minor]+=1;
382 temp+=1;
383 }
384
385 } else if(mode[minor] == MODE_DMA) {
386 // ------------------------------------------------------------------
387 //
388 // ------------------------------------------------------------------
389 // Wait for DMA to finish, This needs to be changed
390 val = readl(baseaddr+DGCS);
391 while((val & 0x00008000) && (timeout++ < 1000000))
392 val = readl(baseaddr+DGCS);
393
394 // VME Address
395 vme = image_va[minor] + (image_ptr[minor] - (unsigned int)image_ba[minor]);
396 dma_align = vme % 8;
397
398 // Setup DMA Buffer to read data into
399 DMA_Buffer_Size = count + ((int)image_ptr % 8) + dma_align;
400 a_size = PAGE_SIZE;
401 while(a_size < DMA_Buffer_Size) {
402 order++;
403 a_size <<= 1;
404 }
405 DMA_Buffer = (char *)__get_dma_pages(GFP_KERNEL,order);
406
407 // PCI Address
408 pci = virt_to_bus(DMA_Buffer) + dma_align;
409
410 // Setup DMA regs
411 writel(DMA[minor],baseaddr+DCTL); // Setup Control Reg
412 writel(count,baseaddr+DTBC); // Count
413 writel(pci,baseaddr+DLA); // PCI Address
414 writel(vme,baseaddr+DVA); // VME Address
415
416 // Start DMA
417 writel(0x80006F00,baseaddr+DGCS); // GO
418
419 // Wait for DMA to finish, This needs to be changed
420 val = readl(baseaddr+DGCS);
421 while((val & 0x00008000) && (timeout++ < 100000))
422 val = readl(baseaddr+DGCS);
423
424 if(timeout == 100000)
425 printk("<<ca91c042 DMA Timed out>>\n");
426
427 if(! (val & 0x00000800)) { // An Error Happened
428 count -= readl(baseaddr+DTBC);
429 }
430
431 image_ptr[minor] += count;
432
433 // Copy pages to User Memory
434 __copy_to_user(temp,DMA_Buffer+dma_align,count);
435
436 free_pages((unsigned long)DMA_Buffer,order);
437 } // end of MODE_DMA
438 } // end of OKtoWrite
439 }
440 *ppos += count;
441 return(count);
442 }
443
444 //----------------------------------------------------------------------------
445 //
446 // uni_write()
447 //
448 //----------------------------------------------------------------------------
449 static ssize_t uni_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
450 {
451 int x,p;
452 unsigned int numt,remain,tmp;
453 char *temp = (char *)buf;
454 unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
455
456 unsigned char vc;
457 unsigned short vs;
458 unsigned int vl;
459
460 char *DMA_Buffer;
461 unsigned int DMA_Buffer_Size = 0,
462 order = 0,
463 a_size = 0,
464 dma_align = 0,
465 timeout = 0;
466 int val,
467 pci = 0,
468 vme = 0,
469 okcount = 0;
470
471 writes++;
472 if(minor == CONTROL_MINOR) {
473 __copy_from_user(&vl,temp,4);
474 p = (int)image_ptr[minor];
475 writel(vl,baseaddr+p);
476 } else {
477 if(OkToWrite[minor]) {
478 if(mode[minor] == MODE_PROGRAMMED) {
479 // Calc the number of longs we need
480 numt = count;
481 remain = count;
482
483 numt = count / 4;
484 remain = count % 4;
485 for(x=0;x<numt;x++) {
486 __copy_from_user(&vl,temp,4);
487 writel(vl,image_ptr[minor]);
488
489 // Lets Check for a Bus Error
490 tmp = readl(baseaddr+PCI_CSR);
491 if(tmp & 0x08000000) {
492 writel(tmp,baseaddr+PCI_CSR);
493 return(okcount);
494 } else
495 okcount += 4;
496
497 image_ptr[minor]+=4;
498 temp+=4;
499 }
500
501 // Calc the number of Words we need
502 numt = remain / 2;
503 remain = remain % 2;
504
505 for(x=0;x<numt;x++) {
506 __copy_from_user(&vs,temp,2);
507 writew(vs,image_ptr[minor]);
508
509 // Lets Check for a Bus Error
510 tmp = readl(baseaddr+PCI_CSR);
511 if(tmp & 0x08000000) {
512 writel(tmp,baseaddr+PCI_CSR);
513 return(okcount);
514 } else
515 okcount += 2;
516
517 image_ptr[minor]+=2;
518 temp+=2;
519 }
520
521 for(x=0;x<remain;x++) {
522 __copy_from_user(&vc,temp,1);
523 writeb(vc,image_ptr[minor]);
524
525 // Lets Check for a Bus Error
526 tmp = readl(baseaddr+PCI_CSR);
527 if(tmp & 0x08000000) {
528 writel(tmp,baseaddr+PCI_CSR);
529 return(okcount);
530 } else
531 okcount += 2;
532
533 image_ptr[minor]+=1;
534 temp+=1;
535 }
536
537 // Lets Check for a Bus Error
538 tmp = readl(baseaddr+PCI_CSR);
539 if(tmp & 0x08000000) { // S_TA is Set
540 writel(0x08000000,baseaddr+PCI_CSR);
541 count = 0;
542 }
543
544 } else if(mode[minor] == MODE_DMA) {
545 // ------------------------------------------------------------------
546 //
547 // ------------------------------------------------------------------
548 // Wait for DMA to finish, This needs to be changed
549 val = readl(baseaddr+DGCS);
550 while((val & 0x00008000) && (timeout++ < 100000))
551 val = readl(baseaddr+DGCS);
552
553 // Setup DMA Buffer to write data into
554 // VME Address
555 vme = image_va[minor] + (image_ptr[minor] - (unsigned int)image_ba[minor]);
556 dma_align = vme % 8;
557
558 DMA_Buffer_Size = count + ((int)image_ptr % 8) + dma_align;
559 a_size = PAGE_SIZE;
560 while(a_size < DMA_Buffer_Size) {
561 order++;
562 a_size <<= 1;
563 }
564 DMA_Buffer = (char *)__get_dma_pages(GFP_KERNEL,order);
565
566 // Copy User Memory into buffer
567 __copy_from_user(DMA_Buffer + dma_align,temp,count);
568
569
570 // PCI Address
571 pci = virt_to_bus(DMA_Buffer) + dma_align;
572
573 // Setup DMA regs
574 writel(DMA[minor]|0x80000000,baseaddr+DCTL); // Setup Control Reg
575 writel(count,baseaddr+DTBC); // Count
576 writel(pci,baseaddr+DLA); // PCI Address
577 writel(vme,baseaddr+DVA); // VME Address
578
579 // Start DMA
580 writel(0x80006F00,baseaddr+DGCS); // GO
581
582 // Wait for DMA to finish, This needs to be changed
583 val = readl(baseaddr+DGCS);
584 while((val & 0x00008000) && (timeout++ < 100000))
585 val = readl(baseaddr+DGCS);
586
587 if(timeout == 100000)
588 printk("<<ca91c042 DMA Timed out>>\n");
589
590 if(! (val & 0x00000800)) { // An Error Happened
591 // The Universe Seems to return an invalid value in DTBC on
592 // Bus Errors during DMA, so invalidate the count
593 count = 0;
594 }
595 image_ptr[minor] += count;
596
597 free_pages((unsigned long)DMA_Buffer,order);
598 } // end of MODE_DMA
599 } //OKtoWrite
600 }
601 *ppos += count;
602 return(count);
603 }
604
605 //----------------------------------------------------------------------------
606 // uni_ioctl()
607 //----------------------------------------------------------------------------
608 static int uni_ioctl(struct inode *inode,struct file *file,unsigned int cmd, unsigned long arg)
609 {
610 unsigned int minor = MINOR(inode->i_rdev);
611 unsigned int sizetomap = 0, to = 0, bs = 0;
612
613 ioctls++;
614 switch(cmd) {
615 case IOCTL_SET_CTL:
616 writel(arg,baseaddr+aCTL[minor]);
617
618 // Lets compute and save the DMA CTL Register
619 DMA[minor] = arg & 0x00FFFF00;
620 break;
621
622 case IOCTL_SET_MODE:
623 mode[minor] = arg;
624 break;
625
626 // Lets Map the VME Bus to the PCI Bus
627 //
628 // << NOTE >> BD Must already be set before you call this!!!!
629 //
630 //
631 case IOCTL_SET_BS:
632 writel(arg,baseaddr+aBS[minor]);
633 if(image_ba[minor])
634 iounmap(image_ba[minor]);
635
636 // This uses the BD Register to Find the size of the Image Mapping
637 sizetomap = readl(baseaddr+aBD[minor]);
638 sizetomap -= arg;
639
640 image_ba[minor] = (char *)ioremap(arg,sizetomap);
641 if(!image_ba[minor]) {
642 OkToWrite[minor] = 0;
643 return -1;
644 }
645 image_ptr[minor] = (int)image_ba[minor];
646 OkToWrite[minor] = 1;
647
648 // Calculate the VME Address
649 bs = readl(baseaddr+aBS[minor]);
650 to = readl(baseaddr+aTO[minor]);
651 image_va[minor] = bs + to;
652 break;
653
654 case IOCTL_SET_BD:
655 writel(arg,baseaddr+aBD[minor]);
656 break;
657 case IOCTL_SET_TO:
658 writel(arg,baseaddr+aTO[minor]);
659
660 // Calculate the VME Address
661 bs = readl(baseaddr+aBS[minor]);
662 to = readl(baseaddr+aTO[minor]);
663 image_va[minor] = bs + to;
664 break;
665 default:
666 if(cmd < 0x1000) { // This is a Register value so write to it.
667 writel(arg,baseaddr+cmd);
668 }
669 break;
670 }
671 return(0);
672 }
673
674 //-----------------------------------------------------------------------------
675 // Function : PrintCmdPacketList
676 // Inputs : TDMA_Cmd_Packet* cpl (PCI Phys Address)
677 // Outputs : void
678 // Description:
679 // Remarks :
680 // History :
681 //-----------------------------------------------------------------------------
682 void PrintCmdPacketList(TDMA_Cmd_Packet* cpl)
683 {
684 TDMA_Cmd_Packet *p = bus_to_virt((int)cpl);
685 char buff[100];
686 int x = 0;
687 int done = 0;
688
689 while(!done && (x < 10)) {
690 x++;
691 sprintf(buff,"<ca91c042> (%i) dctl=%08X, dtbc=%08X\n",x,p->dctl,p->dtbc);
692 printk(buff);
693 sprintf(buff,"<ca91c042> dlv=%08X, dva=%08X\n",p->dlv,p->dva);
694 printk(buff);
695 sprintf(buff,"<ca91c042> dcpp=%08X\n",p->dcpp);
696 printk(buff);
697 done = (p->dcpp & 0x00000001);
698 p = bus_to_virt((int)(TDMA_Cmd_Packet*)(p->dcpp & 0xFFFFFFF8)); // Next in Line Please
699 }
700 }
701
702 //-----------------------------------------------------------------------------
703 // Function : void DMA_status
704 // Inputs : unsigned long __data
705 // Outputs : static
706 // Description:
707 // Remarks :
708 // History :
709 //-----------------------------------------------------------------------------
710 static void DMA_status(unsigned long __data)
711 {
712 printk("<<ca91c042>> DMA Timed out\n");
713
714 if(DMACallBackFunc)
715 DMACallBackFunc(1);
716 DMACallBackFunc = NULL;
717 }
718
719 //-----------------------------------------------------------------------------
720 // Function : DMA_irq_handler
721 // Inputs : void
722 // Outputs : void
723 // Description:
724 // Remarks :
725 // History :
726 //-----------------------------------------------------------------------------
727 void DMA_irq_handler(void)
728 {
729 int val;
730 int cbv=0;
731 char buf[100];
732 TDMA_Cmd_Packet *cpl;
733
734 del_timer(&DMA_timer); // Cancel DMA Time Out
735
736 val = readl(baseaddr+DGCS);
737
738 if(!(val & 0x00000800)) {
739 sprintf(buf,"<<ca91c042>> DMA Error in DMA_irq_handler DGCS=%08X\n",val);
740 printk(buf);
741 val = readl(baseaddr+DCPP);
742 sprintf(buf,"<<ca91c042>> DCPP=%08X\n",val);
743 printk(buf);
744 val = readl(baseaddr+DCTL);
745 sprintf(buf,"<<ca91c042>> DCTL=%08X\n",val);
746 printk(buf);
747 val = readl(baseaddr+DTBC);
748 sprintf(buf,"<<ca91c042>> DTBC=%08X\n",val);
749 printk(buf);
750 val = readl(baseaddr+DLA);
751 sprintf(buf,"<<ca91c042>> DLA=%08X\n",val);
752 printk(buf);
753 val = readl(baseaddr+DVA);
754 sprintf(buf,"<<ca91c042>> DVA=%08X\n",val);
755 printk(buf);
756
757 if(DMAType == DMATYPE_LLIST) {
758 printk("<<ca91c042>> CmdPacketList sent to DMARead\n");
759 PrintCmdPacketList(debugptr);
760
761 printk("<<ca91c042>> CmdPacketList as seen by DCPP\n");
762 cpl = (TDMA_Cmd_Packet*)readl(baseaddr+DCPP); // Command Packet Pointer
763 cpl = (TDMA_Cmd_Packet*)((int)cpl & ~0x03);
764
765 PrintCmdPacketList(cpl);
766 }
767 cbv = 1; // Call Back value is set to 1 to show error condition
768 }
769
770 if(DMACallBackFunc)
771 DMACallBackFunc(cbv);
772
773 // We are done with the Call Back so clear it
774 DMACallBackFunc = NULL;
775 }
776
777 //-----------------------------------------------------------------------------
778 // Function : LERR_irq_handler
779 // Inputs : void
780 // Outputs : void
781 // Description:
782 // Remarks :
783 // History :
784 //-----------------------------------------------------------------------------
785 void LERR_irq_handler(void)
786 {
787 int val;
788 char buf[100];
789 TDMA_Cmd_Packet *cpl;
790
791 del_timer(&DMA_timer); // Cancel DMA Time Out
792
793 val = readl(baseaddr+DGCS);
794
795 if(!(val & 0x00000800)) {
796 sprintf(buf,"<<ca91c042>> LERR_irq_handler DMA Read Error DGCS=%08X\n",val);
797 printk(buf);
798
799 if(DMAType == DMATYPE_LLIST) {
800 cpl = (TDMA_Cmd_Packet*)readl(baseaddr+DCPP); // Command Packet Pointer
801 cpl = (TDMA_Cmd_Packet*)((int)cpl & ~0x03);
802 PrintCmdPacketList(cpl);
803
804 sprintf(buf,"<<ca91c042>> DMAReadCallBack Request of cmdpack=0x%08X\n",(int)cpl);
805 printk(buf);
806 }
807 }
808
809 if(DMACallBackFunc)
810 DMACallBackFunc(1);
811 DMACallBackFunc = NULL;
812 }
813
814 //-----------------------------------------------------------------------------
815 // Function : VERR_irq_handler
816 // Inputs : void
817 // Outputs : void
818 // Description:
819 // Remarks :
820 // History :
821 //-----------------------------------------------------------------------------
822 void VERR_irq_handler(void)
823 {
824 int val;
825 char buf[100];
826 TDMA_Cmd_Packet *cpl;
827
828 del_timer(&DMA_timer); // Cancel DMA Time Out
829
830 val = readl(baseaddr+DGCS);
831
832 if(!(val & 0x00000800)) {
833 sprintf(buf,"<<ca91c042>> VERR_irq_handler DMA Read Error DGCS=%08X\n",val);
834 printk(buf);
835
836 if(DMAType == DMATYPE_LLIST) {
837 cpl = (TDMA_Cmd_Packet*)readl(baseaddr+DCPP); // Command Packet Pointer
838 cpl = (TDMA_Cmd_Packet*)((int)cpl & ~0x03);
839
840 PrintCmdPacketList(cpl);
841
842 sprintf(buf,"<<ca91c042>> DMAReadCallBack Request of cmdpack=0x%08X\n",(int)cpl);
843 printk(buf);
844 }
845 }
846
847 if(DMACallBackFunc)
848 DMACallBackFunc(1);
849 DMACallBackFunc = NULL;
850 }
851
852 //-----------------------------------------------------------------------------
853 // Function : irq_handler
854 // Inputs : int irq, void *dev_id, struct pt_regs *regs
855 // Outputs : void
856 // Description:
857 // Remarks :
858 // History :
859 //-----------------------------------------------------------------------------
860 static void irq_handler(int irq, void *dev_id, struct pt_regs *regs)
861 {
862 long stat, enable, i, vector;
863
864 enable = readl(baseaddr+LINT_EN);
865 stat = readl(baseaddr+LINT_STAT);
866
867 if(stat & 0x0100)
868 DMA_irq_handler();
869 if(stat & 0x0200)
870 LERR_irq_handler();
871 if(stat & 0x0400)
872 VERR_irq_handler();
873
874 for(i=0;i<7;i++) {
875 vector = readl(baseaddr+vmevec[i]);
876 if(stat & vmeirqbit[i] & enable) {
877 if(vmeirqs[i] != NULL) {
878 vmeirqs[i](i+1, vector, dev_id, regs);
879 }
880 }
881 }
882
883 writel(stat, baseaddr+LINT_STAT); // Clear all pending ints
884 }
885
886 //-----------------------------------------------------------------------------
887 // Function : cleanup_module
888 // Inputs : void
889 // Outputs : void
890 // Description:
891 // Remarks :
892 // History :
893 //-----------------------------------------------------------------------------
894 void cleanup_module(void)
895 {
896 int x;
897 int pcivector;
898
899 writel(0,baseaddr+LINT_EN); // Turn off Ints
900 pcivector = readl(baseaddr+PCI_MISC1) & 0x000000FF;
901 free_irq(pcivector,NULL); // Free Vector
902
903 for(x=1;x<MAX_MINOR+1;x++) {
904 if(image_ba[x])
905 iounmap(image_ba[x]);
906 }
907 iounmap(baseaddr);
908 unregister_proc();
909 unregister_chrdev(UNI_MAJOR, "uni");
910 }
911
912 //----------------------------------------------------------------------------
913 // init_module()
914 //----------------------------------------------------------------------------
915 int init_module(void)
916 {
917 int x, result;
918 unsigned int temp, ba;
919 char vstr[80];
920
921 struct pci_dev *uni_pci_dev = NULL;
922
923 sprintf(vstr,"Tundra Universe PCI-VME Bridge Driver %s\n",Version);
924 printk(vstr);
925 printk(" Copyright 1997-2000, Michael J. Wyrick\n");
926
927 if((uni_pci_dev = pci_find_device(PCI_VENDOR_ID_TUNDRA,
928 PCI_DEVICE_ID_TUNDRA_CA91C042,
929 uni_pci_dev))) {
930 printk(" Universe device found.");
931
932 // Lets turn Latency off
933 pci_write_config_dword(uni_pci_dev, PCI_MISC0, 0);
934
935 // Display PCI Registers
936 pci_read_config_dword(uni_pci_dev, PCI_CSR, &status);
937 printk(" Vendor = %04X Device = %04X Status = %08X\n",
938 uni_pci_dev->vendor,uni_pci_dev->device,status);
939 printk(" Class = %08X\n",uni_pci_dev->class);
940
941 pci_read_config_dword(uni_pci_dev, PCI_MISC0, &temp);
942 printk(" Misc0 = %08X\n",temp);
943
944 // Setup Universe Config Space
945 // This is a 4k wide memory area that need to be mapped into the kernel
946 // virtual memory space so we can access it.
947 pci_write_config_dword(uni_pci_dev, PCI_BS, CONFIG_REG_SPACE);
948 pci_read_config_dword(uni_pci_dev, PCI_BS, &ba);
949 baseaddr = (char *)ioremap(ba,4096);
950 if(!baseaddr) {
951 printk(" vremap failed to map Universe to Kernel Space.\r");
952 return 1;
953 }
954
955 // Check to see if the Mapping Worked out
956 temp = readl(baseaddr);
957 printk(" Read via mapping, PCI_ID = %08X\n",temp);
958 if(temp != 0x000010E3) {
959 printk(" Universe Chip Failed to Return PCI_ID in Memory Map.\n");
960 return 1;
961 }
962
963 // OK, Every this is ok so lets turn off the windows
964 writel(0x00800000,baseaddr+LSI0_CTL);
965 writel(0x00800000,baseaddr+LSI1_CTL);
966 writel(0x00800000,baseaddr+LSI2_CTL);
967 writel(0x00800000,baseaddr+LSI3_CTL);
968
969 // Lets turn off interrupts
970 writel(0x00000000,baseaddr+LINT_EN); // Disable interrupts in the Universe first
971 writel(0x0000FFFF,baseaddr+LINT_STAT); // Clear Any Pending Interrupts
972
973 pci_read_config_dword(uni_pci_dev, PCI_INTERRUPT_LINE, &irq);
974 irq &= 0x000000FF; // Only a byte in size
975 result = request_irq(irq, irq_handler, SA_INTERRUPT, "VMEBus (ca91c042)", NULL);
976 if(result) {
977 printk(" ca91c042: can't get assigned pci irq vector %02X\n", irq);
978 } else {
979 writel(0x0000, baseaddr+LINT_MAP0); // Map all ints to 0
980 writel(0x0000, baseaddr+LINT_MAP1); // Map all ints to 0
981 }
982
983 } else {
984 printk(" Universe device not found on PCI Bus.\n");
985 return 1;
986 }
987
988 if(register_chrdev(UNI_MAJOR, "uni", &uni_fops)) {
989 printk(" Error getting Major Number for Drivers\n");
990 iounmap(baseaddr);
991 return(1);
992 } else {
993 printk(" Tundra Loaded.\n");
994 }
995
996 register_proc();
997
998 for(x=0;x<MAX_MINOR+1;x++) {
999 image_ba[x] = 0; // Not defined
1000 image_ptr[x] = 0; // Not defined
1001 opened[x] = 0; // Closed
1002 OkToWrite[x] = 0; // Not OK
1003 mode[x] = MODE_UNDEFINED; // Undefined
1004 }
1005
1006 // Setup the DMA Timer
1007 init_timer(&DMA_timer);
1008 DMA_timer.function = DMA_status;
1009
1010 // Enable DMA Interrupts
1011 writel(0x0700, baseaddr+LINT_EN);
1012
1013 return 0;
1014 }
1015
1016 //-----------------------------------------------------------------------------
1017 //
1018 // Public Interface
1019 //
1020 //-----------------------------------------------------------------------------
1021 //-----------------------------------------------------------------------------
1022 // Function : Universe_BaseAddr
1023 // Inputs : void
1024 // Outputs : char*
1025 // Description: Returns the Base Address of the Universe
1026 // Remarks : Used for direct access to the Universe for unsupported functions
1027 // History :
1028 //-----------------------------------------------------------------------------
1029 char* Universe_BaseAddr(void)
1030 {
1031 return baseaddr;
1032 }
1033
1034 //-----------------------------------------------------------------------------
1035 // Function : Universe_IRQ
1036 // Inputs : void
1037 // Outputs : int
1038 // Description: Returns the PCI IRQ that the Universe is on
1039 // Remarks : Used mostly for Status and Debugging
1040 // History :
1041 //-----------------------------------------------------------------------------
1042 int Universe_IRQ(void)
1043 {
1044 return irq;
1045 }
1046
1047 //-----------------------------------------------------------------------------
1048 // Function : enable_vmeirq
1049 // Inputs : int irq
1050 // Outputs : int
1051 // Description: Enable a VME IRQ
1052 // Remarks :
1053 // History :
1054 //-----------------------------------------------------------------------------
1055 void enable_vmeirq(unsigned int irq)
1056 {
1057 int enable;
1058
1059 enable = readl(baseaddr+LINT_EN);
1060 enable |= vmeirqbit[irq-1];
1061 writel(enable, baseaddr+LINT_EN);
1062 }
1063
1064 //-----------------------------------------------------------------------------
1065 // Function : disable_vmeirq
1066 // Inputs : unsigned int irq
1067 // Outputs : void
1068 // Description: Disable a VME IRQ
1069 // Remarks :
1070 // History :
1071 //-----------------------------------------------------------------------------
1072 void disable_vmeirq(unsigned int irq)
1073 {
1074 int enable;
1075
1076 enable = readl(baseaddr+LINT_EN);
1077 enable &= ~vmeirqbit[irq-1];
1078 writel(enable, baseaddr+LINT_EN);
1079 }
1080
1081 //-----------------------------------------------------------------------------
1082 // Function : request_vmeirq
1083 // Inputs : unsigned int irq, TirqHandler handler
1084 // Outputs : int, 0 if successful
1085 // Description: assign a handler to a vme interrupt
1086 // Remarks : uses a simple check to see if the interrupt is free, then
1087 // assigns a handler for the Interrupt
1088 // History :
1089 //-----------------------------------------------------------------------------
1090 int request_vmeirq(unsigned int irq, TirqHandler handler)
1091 {
1092 if((irq >= 1) && (irq <= 7)) {
1093 if(vmeirqs[irq-1] == NULL) {
1094 vmeirqs[irq-1] = handler;
1095 return 0;
1096 }
1097 }
1098 return -1; // IRQ is already assigned or invalid
1099 }
1100
1101 //-----------------------------------------------------------------------------
1102 // Function : free_vmeirq
1103 // Inputs : unsigned int irq
1104 // Outputs : void
1105 // Description: release the vmeirq
1106 // Remarks : This does not check that a module is freeing an interrupt it
1107 // owns. It is up to the programmer to make sure he knows what
1108 // what he is doing
1109 // History :
1110 //-----------------------------------------------------------------------------
1111 void free_vmeirq(unsigned int irq)
1112 {
1113 if((irq >= 1) && (irq <= 7))
1114 vmeirqs[irq-1] = NULL;
1115 }
1116
1117 //-----------------------------------------------------------------------------
1118 // Function : mapvme
1119 // Inputs : unsigned int pci - PCI Address of Image Map (See howto)
1120 // unsigned int vme - VME Address of Image (See howto)
1121 // unsigned int size - Size of Image
1122 // int image - Image Number to Use (See howto)
1123 // int ctl - VME Address Space (See howto)
1124 // Outputs : char*
1125 // Description:
1126 // Remarks :
1127 // History :
1128 //-----------------------------------------------------------------------------
1129 char* mapvme(unsigned int pci,unsigned int vme, unsigned int size,
1130 int image, int ctl)
1131 {
1132 char *ptr;
1133 unsigned int to;
1134
1135 if((image >=0) && (image <=3)) {
1136 if((pci >= 0xB0000000) && (pci <= 0xE0000000)) {
1137 to = vme-pci;
1138 // Setup the Mapping in the Universe
1139 writel(pci, baseaddr + aBS[image]);
1140 writel(pci + size, baseaddr + aBD[image]);
1141 writel(to, baseaddr + aTO[image]);
1142 writel(ctl | 0x80000000, baseaddr + aCTL[image]);
1143
1144 // Get the Virtual address of the PCI Address map
1145 ptr = (char *)ioremap(pci,size);
1146 if(ptr == NULL) {
1147 printk("<ca91c042> ioremap failed in mapvme\n");
1148 return NULL;
1149 } else {
1150 return ptr; // Everything went ok, return the address pointer
1151 }
1152 }
1153 }
1154 return NULL;
1155 }
1156
1157 //-----------------------------------------------------------------------------
1158 // Function : unmapvme
1159 // Inputs : char *ptr, int image
1160 // Outputs : void
1161 // Description:
1162 // Remarks :
1163 // History :
1164 //-----------------------------------------------------------------------------
1165 void unmapvme(char *ptr, int image)
1166 {
1167 if((image >= 0) && (image <=3)) {
1168 // Clear the Mapping in the Universe
1169 writel(0x00000000, baseaddr + aCTL[image]);
1170 writel(0x00000000, baseaddr + aBS[image]);
1171 writel(0x00000000, baseaddr + aBD[image]);
1172 writel(0x00000000, baseaddr + aTO[image]);
1173 }
1174
1175 // Clear Mapping of PCI Memory
1176 iounmap(ptr);
1177 }
1178
1179 //-----------------------------------------------------------------------------
1180 // Function : VME_DMA
1181 // Inputs : unsigned int pci - PCI Address of Image Map (See howto)
1182 // unsigned int vme - VME Address of Image (See howto)
1183 // unsigned int count - Size of Image
1184 // int image - Image Number to Use (See howto)
1185 // int ctl - VME Address Space (See howto)
1186 // Outputs : void
1187 // Description:
1188 // Remarks : This is Like the CMD Packet Version but will do only one transfer
1189 // History :
1190 //-----------------------------------------------------------------------------
1191 void VME_DMA(void* pci, void* vme, unsigned int count, int ctl, TDMAcallback cback)
1192 {
1193 #ifdef __DEBUG__
1194 char buf[256];
1195 sprintf(buf,"<<ca91c042>> DMA Request of virtpci=0x%08X vme=0x%08X cnt=%i ctl=0x%08X\n",
1196 pci,vme,count,ctl);
1197 printk(buf);
1198 #endif
1199
1200 // Setup the DMA Transfer in the Universe
1201 writel(ctl, baseaddr + DCTL);
1202 writel(count, baseaddr + DTBC);
1203 writel(virt_to_bus(pci), baseaddr + DLA);
1204 writel((int)vme, baseaddr + DVA);
1205
1206 // We need to build a timer to timeout DMA access
1207 DMA_timer.expires = jiffies + DMATIMEOUT;
1208 add_timer(&DMA_timer);
1209
1210 // Setup CallBack Function
1211 DMACallBackFunc = cback;
1212
1213 // Start the Transfer,
1214 // Interrupt on Stop,Halt,Done,LERR,VERR,Prot Error
1215 DMAType = DMATYPE_SINGLE;
1216 writel(0x80216F6F,baseaddr+DGCS);
1217
1218 // We are now all setup, so lets return to the calling function so it can
1219 // sleep or what ever until the DMA is done
1220 }
1221
1222 //-----------------------------------------------------------------------------
1223 // Function : VME_DMA_LinkedList
1224 // Inputs : void* CmdPacketList,TDMAcallback cback
1225 // Outputs : int
1226 // Description:
1227 // Remarks : CmdPacketList is a Phys Address
1228 // History :
1229 //-----------------------------------------------------------------------------
1230 void VME_DMA_LinkedList(void* CmdPacketList,TDMAcallback cback)
1231 {
1232 debugptr = CmdPacketList;
1233
1234 // Setup a DMA Transfer and once the Transfer is complete call cback
1235 writel(0x08316F00,baseaddr+DGCS);
1236 writel(0x00000000,baseaddr+DTBC);
1237 writel((int)CmdPacketList,baseaddr+DCPP); // Command Packet Pointer
1238
1239 // We need to build a timer to timeout DMA access
1240 DMA_timer.expires = jiffies + DMATIMEOUT;
1241 add_timer(&DMA_timer);
1242
1243 // Setup CallBack Function
1244 DMACallBackFunc = cback;
1245
1246 // Start the Transfer,
1247 // Interrupt on Stop,Halt,Done,LERR,VERR,Prot Error
1248 DMAType = DMATYPE_LLIST;
1249 writel(0x88216F6F,baseaddr+DGCS);
1250
1251 // We are now all setup, so lets return to the calling function so it can
1252 // sleep or what ever until the DMA is done
1253 }
1254
1255

  ViewVC Help
Powered by ViewVC 1.2-dev