File: /usr/src/linux/drivers/isdn/eicon/linio.c
1
2 /*
3 *
4 * Copyright (C) Eicon Technology Corporation, 2000.
5 *
6 * Eicon File Revision : 1.16
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
15 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24
25 #define N_DATA
26
27 #include <asm/io.h>
28 #include <asm/system.h>
29 #include <linux/slab.h>
30 #include <linux/pci.h>
31 #include <linux/delay.h>
32 #undef N_DATA
33
34 #include "uxio.h"
35
36 static
37 int log_on=0;
38
39 int Divasdevflag = 0;
40
41 //spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
42
43 static
44 ux_diva_card_t card_pool[MAX_CARDS];
45
46 void UxPause(long int ms)
47 {
48 int timeout = jiffies + ((ms * HZ) / 1000);
49
50 while (time_before(jiffies, timeout));
51 }
52
53 int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
54 {
55 int i;
56 ux_diva_card_t *c;
57
58 if (cfg->bus_type != DIA_BUS_TYPE_PCI)
59 {
60 DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
61 return -1;
62 }
63
64 for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
65 {
66 ;
67 }
68
69 if (i == DIM(card_pool))
70 {
71 DPRINTF(("divas hw: card_pool exhausted"));
72 return -1;
73 }
74
75 c = *card = &card_pool[i];
76
77 switch (cfg->bus_type)
78 {
79 case DIA_BUS_TYPE_PCI:
80 c->bus_num = cfg->bus_num;
81 c->func_num = cfg->func_num;
82 c->io_base = cfg->io_base;
83 c->reset_base = cfg->reset_base;
84 c->card_type = cfg->card_type;
85 c->mapped = NULL;
86 c->slot = cfg->slot;
87 c->irq = (int) cfg->irq;
88 c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
89 c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
90 c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
91 c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
92 c->pCONTROL = cfg->memory[DIVAS_CTL_MEMORY];
93
94 /* c->bus_type = DIA_BUS_TYPE_PCI;
95 c->bus_num = cfg->bus_num & 0x3f;
96 c->slot = cfg->slot;
97 c->irq = (int) cfg->irq;
98 c->int_priority = (int) cfg->int_priority;
99 c->card_type = cfg->card_type;
100 c->io_base = cfg->io_base;
101 c->reset_base = cfg->reset_base;
102 c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
103 c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
104 c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
105 c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
106 DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
107 DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
108 DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
109 c->cm_key = cm_getbrdkey("Divas", cfg->card_id);*/
110 break;
111 default:
112 break;
113 }
114
115 c->in_use = TRUE;
116
117 return 0;
118 }
119
120 void UxCardHandleFree(ux_diva_card_t *card)
121 {
122 card->in_use = FALSE;
123 }
124
125
126 #define PLX_IOBASE 0
127 #define DIVAS_IOBASE 1
128 void *UxCardMemAttach(ux_diva_card_t *card, int id)
129 {
130 if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
131 {
132 switch (id)
133 {
134 case DIVAS_SHARED_MEMORY:
135 card->mapped = card->pSHARED;
136 return card->pSHARED;
137 break;
138 case DIVAS_RAM_MEMORY:
139 card->mapped = card->pDRAM;
140 return card->pDRAM;
141 break;
142 case DIVAS_REG_MEMORY:
143 card->mapped = card->pDEVICES;
144 return card->pDEVICES;
145 break;
146 case DIVAS_CFG_MEMORY:
147 card->mapped = card->pCONFIG;
148 return card->pCONFIG;
149 break;
150 default:
151 ASSERT(FALSE);
152 card->mapped = NULL;
153 return (void *) 0;
154 }
155 }
156 else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
157 {
158 switch (id)
159 {
160 case PLX_IOBASE:
161 return (void *) card->reset_base;
162 break;
163 case DIVAS_IOBASE:
164 return (void *) card->io_base;
165 break;
166 default:
167 ASSERT(FALSE);
168 return 0;
169 }
170 }
171
172 else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
173 {
174 switch (id)
175 {
176 case DIVAS_SHARED_MEMORY:
177 card->mapped = card->pSHARED;
178 return card->pSHARED;
179 break;
180 case DIVAS_RAM_MEMORY:
181 card->mapped = card->pDRAM;
182 return card->pDRAM;
183 break;
184 case DIVAS_REG_MEMORY:
185 card->mapped = (void *) card->io_base;
186 return (void *) card->io_base;
187 break;
188 case DIVAS_CTL_MEMORY:
189 card->mapped = card->pCONTROL;
190 return card->pCONTROL;
191 break;
192 default:
193 // ASSERT(FALSE);
194 DPRINTF(("divas: Trying to attach to mem %d", id));
195 card->mapped = NULL;
196 return (void *) 0;
197 }
198 } else
199 DPRINTF(("divas: Tried to attach to unknown card"));
200
201 /* Unknown card type */
202 return NULL;
203 }
204
205 void UxCardMemDetach(ux_diva_card_t *card, void *address)
206 {
207 return; // Just a place holder. No un-mapping done.
208 }
209
210 void UxCardLog(int turn_on)
211 {
212 log_on = turn_on;
213 }
214
215 /*
216 * Control Register I/O Routines to be performed on Attached I/O ports
217 */
218
219 void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
220 {
221 word base = (word) (dword) AttachedBase;
222
223 base += offset;
224
225 outb(the_byte, base);
226 }
227
228 void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
229 {
230 word base = (word) (dword) AttachedBase;
231
232 base += offset;
233
234 outw(the_word, base);
235 }
236
237 void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
238 {
239 word base = (word) (dword) AttachedBase;
240
241 base += offset;
242
243 outl(the_dword, base);
244 }
245
246 byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
247 {
248 word base = (word) (dword) AttachedBase;
249
250 base += offset;
251
252 return inb(base);
253 }
254
255 word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
256 {
257 word base = (word) (dword) AttachedBase;
258
259 base += offset;
260
261 return inw(base);
262 }
263
264 /*
265 * Memory mapped card I/O functions
266 */
267
268 byte UxCardMemIn(ux_diva_card_t *card, void *address)
269 {
270 byte b;
271 volatile byte* t = (byte*)address;
272
273 b = *t;
274
275 if (log_on)
276 {
277 byte *a = address;
278 a -= (int) card->mapped;
279 DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
280 }
281
282 return(b);
283 }
284
285 word UxCardMemInW(ux_diva_card_t *card, void *address)
286 {
287 word w;
288 volatile word* t = (word*)address;
289
290 w = *t;
291
292 if (log_on)
293 {
294 byte *a = address;
295 a -= (int) card->mapped;
296 DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
297 }
298
299 return (w);
300 }
301
302 dword UxCardMemInD(ux_diva_card_t *card, void *address)
303 {
304 dword dw;
305 volatile dword* t = (dword*)address;
306
307 dw = *t;
308
309 if (log_on)
310 {
311 byte *a = address;
312 a -= (int) card->mapped;
313 DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
314 }
315
316 return (dw);
317 }
318
319 void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
320 {
321 volatile byte *pSource = address;
322 byte *pDest = buffer;
323
324 while (length--)
325 {
326 *pDest++ = *pSource++;
327 }
328
329 if (log_on)
330 {
331 byte *a = address;
332 a -= (int) card->mapped;
333 pDest = buffer;
334 DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)",
335 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
336 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
337 a));
338 }
339
340 return;
341 }
342
343 void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
344 {
345 volatile byte* t = (byte*)address;
346
347 if (log_on)
348 {
349 byte *a = address;
350 a -= (int) card->mapped;
351 DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
352 }
353
354 *t = data;
355
356 return;
357 }
358
359 void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
360 {
361 volatile word* t = (word*)address;
362
363 if (log_on)
364 {
365 byte *a = address;
366 a -= (int) card->mapped;
367 DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
368 }
369
370 *t = data;
371 return;
372 }
373
374 void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
375 {
376 volatile dword* t = (dword*)address;
377
378 if (log_on)
379 {
380 byte *a = address;
381 a -= (int) card->mapped;
382 DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
383 }
384
385 *t = data;
386 return;
387 }
388
389 void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
390 {
391 byte *pSource = buffer;
392 byte *pDest = address;
393
394 while (length--)
395 {
396 *pDest++ = *pSource++;
397 }
398
399 if (log_on)
400 {
401 byte *a = address;
402 a -= (int) card->mapped;
403 pDest = buffer;
404 DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)",
405 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
406 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
407 a));
408 }
409
410 return;
411 }
412
413 /*
414 * Memory mapped card I/O functions
415 */
416
417 byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
418
419 {
420 byte the_byte;
421
422 outb(0xFF, card->io_base + 0xC);
423 outw((word) (dword) address, card->io_base + 4);
424
425 the_byte = inb(card->io_base);
426
427 if (log_on)
428 {
429 DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)",
430 the_byte & 0xff, address));
431 }
432
433 return the_byte;
434 }
435
436 word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
437
438 {
439 word the_word;
440
441 outb(0xFF, card->io_base + 0xC);
442 outw((word) (dword) address, card->io_base + 4);
443 the_word = inw(card->io_base);
444
445 if (log_on)
446 {
447 DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)",
448 the_word & 0xffff, address));
449 }
450
451 return the_word;
452 }
453
454 dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
455
456 {
457 dword the_dword;
458
459 outb(0xFF, card->io_base + 0xC);
460 outw((word) (dword) address, card->io_base + 4);
461 the_dword = inl(card->io_base);
462
463 if (log_on)
464 {
465 DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)",
466 the_dword, address));
467 }
468
469 return the_dword;
470 }
471
472 void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
473
474 {
475 byte *pSource = address;
476 byte *pDest = buffer;
477
478 if ((word) (dword) address & 0x1)
479 {
480 outb(0xFF, card->io_base + 0xC);
481 outw((word) (dword) pSource, card->io_base + 4);
482 *pDest = (byte) inb(card->io_base);
483 pDest++;
484 pSource++;
485 length--;
486 if (!length)
487 {
488 return;
489 }
490 }
491
492 outb(0xFF, card->io_base + 0xC);
493 outw((word) (dword) pSource, card->io_base + 4);
494 insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
495
496 if (log_on)
497 {
498 pDest = buffer;
499 DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)",
500 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
501 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
502 address));
503 }
504
505 return;
506 }
507
508 /* Output */
509
510 void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
511 {
512 if (log_on)
513 {
514 DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)",
515 data & 0xff, address));
516 }
517
518 outb(0xFF, card->io_base + 0xC);
519 outw((word) (dword) address, card->io_base + 4);
520 outb((byte) data & 0xFF, card->io_base);
521
522 return;
523 }
524
525 void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
526 {
527 if (log_on)
528 {
529 DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)",
530 data & 0xffff, address));
531 }
532
533 outb(0xFF, card->io_base + 0xC);
534 outw((word) (dword) address, card->io_base + 4);
535 outw((word) data & 0xFFFF, card->io_base);
536
537 return;
538 }
539
540 void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
541 {
542 if (log_on)
543 {
544 DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
545 }
546
547 outb(0xFF, card->io_base + 0xC);
548 outw((word) (dword) address, card->io_base + 4);
549 outl((dword) data & 0xFFFFFFFF, card->io_base);
550
551 return;
552 }
553
554 void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
555
556 {
557 byte *pSource = buffer;
558 byte *pDest = address;
559
560 if ((word) (dword) address & 1)
561 {
562 outb(0xFF, card->io_base + 0xC);
563 outw((word) (dword) pDest, card->io_base + 4);
564 outb(*pSource, card->io_base);
565 pSource++;
566 pDest++;
567 length--;
568 if (!length)
569 {
570 return;
571 }
572 }
573
574 outb(0xFF, card->io_base + 0xC);
575 outw((word) (dword) pDest, card->io_base + 4);
576 outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
577
578 if (log_on)
579 {
580 pDest = buffer;
581 DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)",
582 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
583 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
584 address));
585 }
586
587 return;
588 }
589
590 void Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
591 {
592 int i;
593 card_t *card = NULL;
594 ux_diva_card_t *ux_ref = NULL;
595
596 for (i = 0; i < DivasCardNext; i++)
597 {
598
599 if (arg == DivasCards[i].cfg.irq)
600 {
601 card = &DivasCards[i];
602 ux_ref = card->hw;
603
604 if ((ux_ref) && (card->is_live))
605 {
606 (*ux_ref->user_isr)(ux_ref->user_isr_arg);
607 }
608 else
609 {
610 DPRINTF(("divas: ISR couldn't locate card"));
611 }
612 }
613 }
614
615 return;
616 }
617
618
619 int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
620 {
621 int result;
622
623 card->user_isr = isr_fn;
624 card->user_isr_arg = isr_arg;
625
626 result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
627
628 return result;
629 }
630
631 void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
632 {
633 free_irq(card->irq, card->user_isr_arg);
634 }
635
636 void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
637 {
638 switch (size)
639 {
640 case sizeof(byte):
641 pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
642 break;
643 case sizeof(word):
644 pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
645 break;
646 case sizeof(dword):
647 pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
648 break;
649 default:
650 printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
651 }
652 }
653
654 void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
655 {
656 switch (size)
657 {
658 case sizeof(byte):
659 pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
660 break;
661 case sizeof(word):
662 pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
663 break;
664 case sizeof(dword):
665 pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
666 break;
667 default:
668 printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
669 }
670 }
671
672 void *UxAlloc(unsigned int size)
673 {
674 void *m;
675
676 m = kmalloc(size, GFP_ATOMIC);
677
678 return m;
679 }
680
681 void UxFree(void *ptr)
682 {
683 kfree(ptr);
684 }
685
686 long UxCardLock(ux_diva_card_t *card)
687 {
688 unsigned long flags;
689
690 //spin_lock_irqsave(&diva_lock, flags);
691
692 save_flags(flags);
693 cli();
694 return flags;
695
696 }
697
698 void UxCardUnlock(ux_diva_card_t *card, long ipl)
699 {
700 //spin_unlock_irqrestore(&diva_lock, ipl);
701
702 restore_flags(ipl);
703
704 }
705
706 dword UxTimeGet(void)
707 {
708 return jiffies;
709 }
710
711 long UxInterlockedIncrement(ux_diva_card_t *card, long *dst)
712 {
713 register volatile long *p;
714 register long ret;
715 int ipl;
716
717 p =dst;
718
719 ipl = UxCardLock(card);
720
721 *p += 1;
722 ret = *p;
723
724 UxCardUnlock(card,ipl);
725
726 return(ret);
727
728 }
729
730 long UxInterlockedDecrement(ux_diva_card_t *card, long *dst)
731 {
732 register volatile long *p;
733 register long ret;
734 int ipl;
735
736 p =dst;
737
738 ipl = UxCardLock(card);
739
740 *p -= 1;
741 ret = *p;
742
743 UxCardUnlock(card,ipl);
744
745 return(ret);
746
747 }
748