File: /usr/src/linux/drivers/isdn/eicon/common.c
1
2 /*
3 *
4 * Copyright (C) Eicon Technology Corporation, 2000.
5 *
6 * Eicon File Revision : 1.15
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 #include "eicon.h"
26 #include "sys.h"
27 #include "idi.h"
28 #include "constant.h"
29 #include "divas.h"
30 #include "pc.h"
31 #include "pr_pc.h"
32
33 #include "uxio.h"
34
35 #define DIVAS_LOAD_CMD 0x02
36 #define DIVAS_START_CMD 0x03
37 #define DIVAS_IRQ_RESET 0xC18
38 #define DIVAS_IRQ_RESET_VAL 0xFE
39
40 #define TEST_INT_DIVAS 0x11
41 #define TEST_INT_DIVAS_BRI 0x12
42 #define TEST_INT_DIVAS_Q 0x13
43
44 #define DIVAS_RESET 0x81
45 #define DIVAS_LED1 0x04
46 #define DIVAS_LED2 0x08
47 #define DIVAS_LED3 0x20
48 #define DIVAS_LED4 0x40
49
50 #define DIVAS_SIGNATURE 0x4447
51
52 #define MP_PROTOCOL_ADDR 0xA0011000
53
54 #define PLX_IOBASE 0
55 #define DIVAS_IOBASE 1
56
57 typedef struct {
58 dword cmd;
59 dword addr;
60 dword len;
61 dword err;
62 dword live;
63 dword reserved[(0x1020>>2)-6];
64 dword signature;
65 byte data[1];
66 } diva_server_boot_t;
67
68 int DivasCardNext;
69 card_t DivasCards[MAX_CARDS];
70
71 dia_config_t *DivasConfig(card_t *, dia_config_t *);
72
73 static
74 DESCRIPTOR DIDD_Table[32];
75
76 void DIVA_DIDD_Read( DESCRIPTOR *table, int tablelength )
77 {
78 memset(table, 0, tablelength);
79
80 if (tablelength > sizeof(DIDD_Table))
81 tablelength = sizeof(DIDD_Table);
82
83 if(tablelength % sizeof(DESCRIPTOR)) {
84 tablelength /= sizeof(DESCRIPTOR);
85 tablelength *= sizeof(DESCRIPTOR);
86 }
87
88 if (tablelength > 0)
89 memcpy((void *)table, (void *)DIDD_Table, tablelength);
90
91 return;
92 }
93
94 void DIVA_DIDD_Write(DESCRIPTOR *table, int tablelength)
95 {
96 if (tablelength > sizeof(DIDD_Table))
97 tablelength = sizeof(DIDD_Table);
98
99 memcpy((void *)DIDD_Table, (void *)table, tablelength);
100
101 return;
102 }
103
104 static
105 void init_idi_tab(void)
106 {
107 DESCRIPTOR d[32];
108
109 memset(d, 0, sizeof(d));
110
111 d[0].type = IDI_DIMAINT; /* identify the DIMAINT entry */
112 d[0].channels = 0; /* zero channels associated with dimaint*/
113 d[0].features = 0; /* no features associated with dimaint */
114 d[0].request = (IDI_CALL) DivasPrintf;
115
116 DIVA_DIDD_Write(d, sizeof(d));
117
118 return;
119 }
120
121 /*
122 * I/O routines for memory mapped cards
123 */
124
125 byte mem_in(ADAPTER *a, void *adr)
126 {
127 card_t *card = a->io;
128 unsigned char *b, *m;
129 byte value;
130
131 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
132
133 m += (unsigned int) adr;
134
135 value = UxCardMemIn(card->hw, m);
136
137 UxCardMemDetach(card->hw, b);
138
139 return value;
140 }
141
142 word mem_inw(ADAPTER *a, void *adr)
143 {
144 card_t *card = a->io;
145 unsigned char *b, *m;
146 word value;
147
148 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
149
150 m += (unsigned int) adr;
151
152 value = UxCardMemInW(card->hw, m);
153
154 UxCardMemDetach(card->hw, b);
155
156 return value;
157 }
158
159 void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length)
160 {
161 card_t *card = a->io;
162 unsigned char *b, *m;
163
164 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
165
166 m += (unsigned int) adr;
167
168 UxCardMemInBuffer(card->hw, m, P, length);
169
170 UxCardMemDetach(card->hw, b);
171
172 return;
173 }
174
175 void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
176 {
177 card_t *card = a->io;
178 unsigned char *b, *m;
179
180 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
181
182 m += (dword) &RBuffer->length;
183 card->RBuffer.length = UxCardMemInW(card->hw, m);
184
185 m = b;
186 m += (dword) &RBuffer->P;
187 UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length);
188
189 e->RBuffer = (DBUFFER *) &card->RBuffer;
190
191 UxCardMemDetach(card->hw, b);
192
193 return;
194 }
195
196 void mem_out(ADAPTER *a, void *adr, byte data)
197 {
198 card_t *card = a->io;
199 unsigned char *b, *m;
200
201 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
202
203 m += (unsigned int) adr;
204
205 UxCardMemOut(card->hw, m, data);
206
207 UxCardMemDetach(card->hw, b);
208
209 return;
210 }
211
212 void mem_outw(ADAPTER *a, void *adr, word data)
213 {
214 card_t *card = a->io;
215 unsigned char *b, *m;
216
217 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
218
219 m += (unsigned int) adr;
220
221 UxCardMemOutW(card->hw, m, data);
222
223 UxCardMemDetach(card->hw, b);
224
225 return;
226 }
227
228 void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length)
229 {
230 card_t *card = a->io;
231 unsigned char *b, *m;
232
233 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
234
235 m += (unsigned int) adr;
236
237 UxCardMemOutBuffer(card->hw, m, P, length);
238
239 UxCardMemDetach(card->hw, b);
240
241 return;
242 }
243
244 void mem_inc(ADAPTER *a, void *adr)
245 {
246 word value;
247 card_t *card = a->io;
248 unsigned char *b, *m;
249
250 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
251
252 m += (unsigned int) adr;
253
254 value = UxCardMemInW(card->hw, m);
255 value++;
256 UxCardMemOutW(card->hw, m, value);
257
258 UxCardMemDetach(card->hw, b);
259
260 return;
261 }
262
263 /*
264 * I/O routines for I/O mapped cards
265 */
266
267 byte io_in(ADAPTER *a, void *adr)
268 {
269 card_t *card = a->io;
270 byte value;
271 byte *DivasIOBase = NULL;
272
273 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
274
275 value = UxCardIoIn(card->hw, DivasIOBase, adr);
276
277 UxCardMemDetach(card->hw, DivasIOBase);
278
279 return value;
280 }
281
282 word io_inw(ADAPTER *a, void *adr)
283 {
284 card_t *card = a->io;
285 word value;
286 byte *DivasIOBase = NULL;
287
288 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
289
290 value = UxCardIoInW(card->hw, DivasIOBase, adr);
291
292 UxCardMemDetach(card->hw, DivasIOBase);
293
294 return value;
295 }
296
297 void io_in_buffer(ADAPTER *a, void *adr, void *P, word length)
298 {
299 card_t *card = a->io;
300 byte *DivasIOBase = NULL;
301
302 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
303
304 UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length);
305
306 UxCardMemDetach(card->hw, DivasIOBase);
307
308 return;
309 }
310
311 void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
312 {
313 card_t *card = a->io;
314 byte *DivasIOBase = NULL;
315
316 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
317
318 card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer);
319
320 UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length);
321
322 UxCardMemDetach(card->hw, DivasIOBase);
323
324 e->RBuffer = (DBUFFER *) &card->RBuffer;
325
326 return;
327 }
328
329 void io_out(ADAPTER *a, void *adr, byte data)
330 {
331 card_t *card = a->io;
332 byte *DivasIOBase = NULL;
333
334 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
335
336 UxCardIoOut(card->hw, DivasIOBase, adr, data);
337
338 UxCardMemDetach(card->hw, DivasIOBase);
339
340 return;
341 }
342
343 void io_outw(ADAPTER *a, void *adr, word data)
344 {
345 card_t *card = a->io;
346 byte *DivasIOBase = NULL;
347
348 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
349
350 UxCardIoOutW(card->hw, DivasIOBase, adr, data);
351
352 UxCardMemDetach(card->hw, DivasIOBase);
353
354 return;
355 }
356
357 void io_out_buffer(ADAPTER *a, void *adr, void *P, word length)
358 {
359 card_t *card = a->io;
360 byte *DivasIOBase = NULL;
361
362 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
363
364 UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length);
365
366 UxCardMemDetach(card->hw, DivasIOBase);
367
368 return;
369 }
370
371 void io_inc(ADAPTER *a, void *adr)
372 {
373 word value;
374 card_t *card = a->io;
375 byte *DivasIOBase;
376
377 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
378
379 value = UxCardIoInW(card->hw, DivasIOBase, adr);
380
381 value++;
382
383 UxCardIoOutW(card->hw, DivasIOBase, adr, value);
384
385 UxCardMemDetach(card->hw, DivasIOBase);
386
387 return;
388 }
389
390 static
391 void test_int(card_t *card)
392
393 {
394 byte *shared, *DivasIOBase;
395
396 switch (card->test_int_pend)
397 {
398 case TEST_INT_DIVAS:
399 DPRINTF(("divas: test interrupt pending"));
400 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
401
402 if (UxCardMemIn(card->hw, &shared[0x3FE]))
403 {
404 UxCardMemOut(card->hw,
405 &(((struct pr_ram *)shared)->RcOutput), 0);
406 UxCardMemDetach(card->hw, shared);
407 (*card->reset_int)(card);
408 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
409 UxCardMemOut(card->hw, &shared[0x3FE], 0);
410 DPRINTF(("divas: test interrupt cleared"));
411 }
412
413 UxCardMemDetach(card->hw, shared);
414
415 card->test_int_pend = 0;
416 break;
417
418 case TEST_INT_DIVAS_BRI:
419 DPRINTF(("divas: BRI test interrupt pending"));
420 (*card->reset_int)(card);
421 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
422 UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0);
423 UxCardMemDetach(card->hw, DivasIOBase);
424 DPRINTF(("divas: test interrupt cleared"));
425 card->test_int_pend = 0;
426 break;
427
428 case TEST_INT_DIVAS_Q:
429 DPRINTF(("divas: 4BRI test interrupt pending"));
430 (*card->reset_int)(card);
431 card->test_int_pend = 0;
432 break;
433
434 default:
435 DPRINTF(("divas: unknown test interrupt pending"));
436 return;
437 }
438 return;
439 }
440
441 void card_isr (void *dev_id)
442 {
443 card_t *card = (card_t *) dev_id;
444 ADAPTER *a = &card->a;
445 int ipl;
446
447 if (card->test_int_pend)
448 {
449 ipl = UxCardLock(card->hw);
450 card->int_pend=0;
451 test_int(card);
452 UxCardUnlock(card->hw,ipl);
453 return;
454 }
455
456 if(card->card_isr)
457 {
458 (*(card->card_isr))(card);
459 }
460 else
461 {
462 ipl = UxCardLock(card->hw);
463
464 if ((card->test_int)(a))
465 {
466 (card->reset_int)(card);
467 }
468
469 UxCardUnlock(card->hw,ipl);
470
471 }
472
473 }
474
475 int DivasCardNew(dia_card_t *card_info)
476 {
477 card_t *card;
478 static boolean_t first_call = TRUE;
479 boolean_t NeedISRandReset = FALSE;
480
481 DPRINTF(("divas: new card "));
482
483 if (first_call)
484 {
485 first_call = FALSE;
486 init_idi_tab();
487 }
488
489 DivasConfigGet(card_info);
490
491 if (DivasCardNext == DIM(DivasCards))
492 {
493 KDPRINTF((KERN_WARNING "Divas: no space available for new card"));
494 return -1;
495 }
496
497 card = &DivasCards[DivasCardNext];
498
499 card->state = DIA_UNKNOWN;
500
501 card->cfg = *card_info;
502
503 card->a.io = card;
504
505 if (UxCardHandleGet(&card->hw, card_info))
506 {
507 KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card"));
508 return -1;
509 }
510
511 if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
512 {
513 DivasBriPatch(card);
514 card_info->io_base = card->cfg.io_base;
515 }
516
517 switch (card_info->card_type)
518 {
519 case DIA_CARD_TYPE_DIVA_SERVER:
520 if (DivasPriInit(card, card_info))
521 {
522 return -1;
523 }
524 NeedISRandReset = TRUE;
525 break;
526
527 case DIA_CARD_TYPE_DIVA_SERVER_B:
528 if (DivasBriInit(card, card_info))
529 {
530 return -1;
531 }
532 NeedISRandReset = TRUE;
533 break;
534
535 case DIA_CARD_TYPE_DIVA_SERVER_Q:
536 if (Divas4BriInit(card, card_info))
537 {
538 return -1;
539 }
540
541 if (card_info->name[6] == '0')
542 {
543 NeedISRandReset = TRUE;
544 }
545 else // Need to set paramater for ISR anyway
546 {
547 card->hw->user_isr_arg = card;
548 card->hw->user_isr = card_isr;
549 }
550 break;
551
552 default:
553 KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type));
554 return -1;
555 }
556
557 if (NeedISRandReset)
558 {
559 if (UxIsrInstall(card->hw, card_isr, card))
560 {
561 KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq));
562 UxCardHandleFree(card->hw);
563 return -1;
564 }
565
566 if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
567 {
568 if ((*card->card_reset)(card))
569 {
570 KDPRINTF((KERN_WARNING "Divas: Adapter reset failed"));
571 return -1;
572 }
573 card->state = DIA_RESET;
574 }
575
576 NeedISRandReset = FALSE;
577 }
578
579 DivasCardNext++;
580
581 return 0;
582 }
583
584 void *get_card(int card_id)
585 {
586 int i;
587
588 for (i=0; i < DivasCardNext; i++)
589 {
590 if (DivasCards[i].cfg.card_id == card_id)
591 {
592 return(&DivasCards[i]);
593 }
594 }
595
596 DPRINTF(("divas: get_card() : no such card id (%d)", card_id));
597
598 return NULL;
599 }
600
601 int DivasCardConfig(dia_config_t *config)
602 {
603 card_t *card;
604 int status;
605
606 DPRINTF(("divas: configuring card"));
607
608 card = get_card(config->card_id);
609 if (!card)
610 {
611 return -1;
612 }
613
614 config = DivasConfig(card, config);
615
616 status = (*card->card_config)(card, config);
617
618 if (!status)
619 {
620 card->state = DIA_CONFIGURED;
621 }
622 return status;
623 }
624
625 int DivasCardLoad(dia_load_t *load)
626 {
627 card_t *card;
628 int status;
629
630 card = get_card(load->card_id);
631 if (!card)
632 {
633 return -1;
634 }
635
636 if (card->state == DIA_RUNNING)
637 {
638 (*card->card_reset)(card);
639 }
640
641 status = (*card->card_load)(card, load);
642 if (!status)
643 {
644 card->state = DIA_LOADED;
645 }
646 return status;
647 }
648
649 static int idi_register(card_t *card, byte channels)
650 {
651 DESCRIPTOR d[32];
652 int length, num_entities;
653
654 DPRINTF(("divas: registering card with IDI"));
655
656 num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES;
657 card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities);
658
659 if (!card->e_tbl)
660 {
661 KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available"));
662 return -1;
663 }
664
665 memset(card->e_tbl, 0, sizeof(E_INFO) * num_entities);
666 card->e_max = num_entities;
667
668 DIVA_DIDD_Read(d, sizeof(d));
669
670 for(length=0; length < DIM(d); length++)
671 if (d[length].type == 0) break;
672
673 if (length >= DIM(d))
674 {
675 KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full"));
676 return -1;
677 }
678
679 switch (card->cfg.card_type)
680 {
681 case DIA_CARD_TYPE_DIVA_SERVER:
682 d[length].type = IDI_ADAPTER_PR;
683 /* d[length].serial = card->serial_no; */
684 break;
685
686 case DIA_CARD_TYPE_DIVA_SERVER_B:
687 d[length].type = IDI_ADAPTER_MAESTRA;
688 /* d[length].serial = card->serial_no; */
689 break;
690
691 // 4BRI is treated as 4 BRI adapters
692 case DIA_CARD_TYPE_DIVA_SERVER_Q:
693 d[length].type = IDI_ADAPTER_MAESTRA;
694 /* d[length].serial = card->cfg.serial; */
695 }
696
697 d[length].features = 0;
698 d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120;
699
700 if ( card->hw->features & PROTCAP_MANIF )
701 {
702 d[length].features |= DI_MANAGE ;
703 }
704 if ( card->hw->features & PROTCAP_V_42 )
705 {
706 d[length].features |= DI_V_42 ;
707 }
708 if ( card->hw->features & PROTCAP_EXTD_FAX )
709 {
710 d[length].features |= DI_EXTD_FAX ;
711 }
712
713 d[length].channels = channels;
714 d[length].request = DivasIdiRequest[card - DivasCards];
715
716 length++;
717
718 DIVA_DIDD_Write(d, sizeof(d));
719
720 return 0;
721 }
722
723 int DivasCardStart(int card_id)
724 {
725 card_t *card;
726 byte channels;
727 int status;
728
729 DPRINTF(("divas: starting card"));
730
731 card = get_card(card_id);
732 if (!card)
733 {
734 return -1;
735 }
736
737 status = (*card->card_start)(card, &channels);
738 if (status)
739 {
740 return status;
741 }
742
743 /* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */
744 if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
745 {
746 int i;
747 card_t *FourBRISlave;
748
749 for (i=3; i >= 0; i--)
750 {
751 FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */
752 if (FourBRISlave)
753 {
754 idi_register(FourBRISlave, 2);
755 FourBRISlave->state = DIA_RUNNING;
756 }
757 }
758 card->serial_no = card->cfg.serial;
759
760 DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels",
761 card_id - 3, card->serial_no, (int) channels));
762 }
763 else
764 {
765 status = idi_register(card, channels);
766 if (!status)
767 {
768 card->state = DIA_RUNNING;
769 DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels",
770 card_id, card->serial_no, (int) channels));
771 }
772 }
773
774 return status;
775 }
776
777 int DivasGetMem(mem_block_t *mem_block)
778 {
779 card_t *card;
780 word card_id = mem_block->card_id;
781
782 card = get_card(card_id);
783 if (!card)
784 {
785 return 0;
786 }
787
788 return (*card->card_mem_get)(card, mem_block);
789 }
790
791
792 /*
793 * Deleyed Procedure Call for handling interrupts from card
794 */
795
796 void DivaDoCardDpc(card_t *card)
797 {
798 ADAPTER *a;
799
800 a = &card->a;
801
802 if(UxInterlockedIncrement(card->hw, &card->dpc_reentered) > 1)
803 {
804 return;
805 }
806
807 do{
808 if((*(card->test_int))(a))
809 {
810 (*(card->dpc))(a);
811 (*(card->clear_int))(a);
812 }
813 (*(card->out))(a);
814 }while(UxInterlockedDecrement(card->hw, &card->dpc_reentered));
815
816 }
817
818 void DivasDoDpc(void *pData)
819 {
820 card_t *card = DivasCards;
821 int i = DivasCardNext;
822
823 while(i--)
824 {
825 DivaDoCardDpc(card++);
826 }
827 }
828
829 void DivasDoRequestDpc(void *pData)
830 {
831 DivasDoDpc(pData);
832 }
833
834 /*
835 * DivasGetNum
836 * Returns the number of active adapters
837 */
838
839 int DivasGetNum(void)
840 {
841 return(DivasCardNext);
842 }
843
844 /*
845 * DivasGetList
846 * Returns a list of active adapters
847 */
848 int DivasGetList(dia_card_list_t *card_list)
849 {
850 int i;
851
852 memset(card_list, 0, sizeof(dia_card_list_t));
853
854 for(i = 0; i < DivasCardNext; i++)
855 {
856 card_list->card_type = DivasCards[i].cfg.card_type;
857 card_list->card_slot = DivasCards[i].cfg.slot;
858 card_list->state = DivasCards[i].state;
859 card_list++;
860 }
861
862 return 0;
863
864 }
865
866 /*
867 * control logging for specified card
868 */
869
870 void DivasLog(dia_log_t *log)
871 {
872 card_t *card;
873
874 card = get_card(log->card_id);
875 if (!card)
876 {
877 return;
878 }
879
880 card->log_types = log->log_types;
881
882 return;
883 }
884
885