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

Contents of /driver/ca91c042.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.2-dev