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