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

Contents of /driver/ca91c042.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.2-dev