1/*
2 * Diva Server 4BRI specific part of initialisation
3 *
4 * Copyright (C) Eicon Technology Corporation, 2000.
5 *
6 * Eicon File Revision :    1.7
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 *
11 */
12
13#include "sys.h"
14#include "idi.h"
15#include "divas.h"
16#include "pc.h"
17#include "pr_pc.h"
18#include "dsp_defs.h"
19#include "constant.h"
20#include "adapter.h"
21#include "uxio.h"
22
23#define TEST_INT_DIVAS_Q	0x13
24
25#define	DIVAS_MAINT_OFFSET	0xff00	/* value for 4BRI card */
26#define MQ_BOARD_DSP_OFFSET 0x00a00000
27#define MQ_DSP1_ADDR_OFFSET 0x00000008
28#define MQ_DSP_JUNK_OFFSET  0x00000400
29#define MQ_DSP1_DATA_OFFSET 0x00000000
30#define MQ_BOARD_ISAC_DSP_RESET  0x00800028
31#define MQ_BREG_RISC  0x1200      /* RISC Reset */
32#define MQ_ISAC_DSP_RESET 0x0028 /* ISAC and DSP reset address offset */
33#define MQ_RISC_COLD_RESET_MASK         0x0001      /* RISC Cold reset                        */
34#define MQ_RISC_WARM_RESET_MASK         0x0002      /* RISC Warm reset                        */
35#define MQ_IRQ_REQ_ON                   0x1
36#define MQ_IRQ_REQ_OFF                  0x0
37#define MQ_BREG_IRQ_TEST                0x0608
38#define PLX9054_INTCSR      0x69
39#define PLX9054_INT_ENA     0x09
40
41#define DIVAS_IOBASE	0x01
42#define M_PCI_RESET	0x10
43
44byte mem_in(ADAPTER *a, void *adr);
45word mem_inw(ADAPTER *a, void *adr);
46void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
47void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
48void mem_out(ADAPTER *a, void *adr, byte data);
49void mem_outw(ADAPTER *a, void *adr, word data);
50void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
51void mem_inc(ADAPTER *a, void *adr);
52
53int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg);
54static int fourbri_ISR (card_t* card);
55
56int FPGA_Download(word, dword, byte *, byte *, int);
57extern byte FPGA_Bytes[];
58extern void *get_card(int);
59
60byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
61void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
62word GetProtFeatureValue(char *sw_id);
63
64void memcp(byte *dst, byte *src, dword dwLen);
65int memcm(byte *dst, byte *src, dword dwLen);
66
67static int diva_server_4bri_reset(card_t *card)
68{
69	byte *ctl;
70
71	DPRINTF(("divas: reset Diva Server 4BRI"));
72
73	ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
74
75	/* stop RISC, DSP's and ISAC  */
76   UxCardMemOut(card->hw, &ctl[MQ_BREG_RISC], 0);
77   UxCardMemOut(card->hw, &ctl[MQ_ISAC_DSP_RESET], 0);
78
79	UxCardMemDetach(card->hw, ctl);
80
81	return 0;
82}
83
84static int diva_server_4bri_config(card_t *card, dia_config_t *config)
85{
86	byte *shared;
87	int i, j;
88
89	DPRINTF(("divas: configure Diva Server 4BRI"));
90
91	shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
92
93	for (i=0; i<256; i++)
94	{
95		UxCardMemOut(card->hw, &shared[i], 0);
96	}
97
98	UxCardMemOut(card->hw, &shared[ 8], config->tei);
99	UxCardMemOut(card->hw, &shared[ 9], config->nt2);
100	UxCardMemOut(card->hw, &shared[10], config->sig_flags);
101	UxCardMemOut(card->hw, &shared[11], config->watchdog);
102	UxCardMemOut(card->hw, &shared[12], config->permanent);
103	UxCardMemOut(card->hw, &shared[13], config->x_interface);
104	UxCardMemOut(card->hw, &shared[14], config->stable_l2);
105	UxCardMemOut(card->hw, &shared[15], config->no_order_check);
106	UxCardMemOut(card->hw, &shared[16], config->handset_type);
107	UxCardMemOut(card->hw, &shared[17], 0);
108	UxCardMemOut(card->hw, &shared[18], config->low_channel);
109	UxCardMemOut(card->hw, &shared[19], config->prot_version);
110	UxCardMemOut(card->hw, &shared[20], config->crc4);
111
112	if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
113	{
114		DPRINTF(("divas: Signifying V.90"));
115		UxCardMemOut(card->hw, &shared[22], 4);
116	}
117	else
118	{
119		UxCardMemOut(card->hw, &shared[22], 0);
120	}
121
122	for (i=0; i<2; i++)
123	{
124		for (j=0; j<32; j++)
125		{
126			UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
127		}
128
129		for (j=0; j<32; j++)
130		{
131			UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
132		}
133
134		for (j=0; j<32; j++)
135		{
136			UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
137		}
138	}
139
140	UxCardMemDetach(card->hw, shared);
141
142	return 0;
143}
144
145static
146void diva_server_4bri_reset_int(card_t *card)
147{
148	byte *ctl;
149
150	ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
151
152	UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
153
154	UxCardMemDetach(card->hw, ctl);
155
156	return;
157}
158
159
160static int diva_server_4bri_test_int(card_t *card)
161{
162	byte *ctl, i;
163	byte *reg;
164
165	DPRINTF(("divas: test interrupt for Diva Server 4BRI"));
166
167	/* We get the last (dummy) adapter in so we need to go back to the first */
168
169	card = get_card(card->cfg.card_id - 3);
170
171	/* Enable interrupts on PLX chip */
172
173	reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
174
175	UxCardPortIoOut(card->hw, reg, PLX9054_INTCSR, PLX9054_INT_ENA);
176
177	UxCardMemDetach(card->hw, reg);
178
179	/* Set the test interrupt flag */
180	card->test_int_pend = TEST_INT_DIVAS_Q;
181
182	/* Now to trigger the interrupt */
183
184	ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
185
186	UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_ON);
187
188	UxCardMemDetach(card->hw, ctl);
189
190	for (i = 0; i < 50; i++)
191	{
192		if (!card->test_int_pend)
193		{
194			break;
195		}
196		UxPause(10);
197	}
198
199	if (card->test_int_pend)
200	{
201		DPRINTF(("active: timeout waiting for card to interrupt"));
202		return (-1);
203	}
204
205	return 0;
206}
207
208
209static void print_hdr(unsigned char *code, int offset)
210{
211	unsigned char hdr[80];
212	int i;
213
214	i = 0;
215
216	while ((i < (DIM(hdr) -1)) &&
217		(code[offset + i] != '\0') &&
218		(code[offset + i] != '\r') &&
219		(code[offset + i] != '\n'))
220	{
221		hdr[i] = code[offset + i];
222		i++;
223	}
224
225	hdr[i] = '\0';
226
227	DPRINTF(("divas: loading %s", hdr));
228}
229
230static int diva_server_4bri_load(card_t *card, dia_load_t *load)
231{
232	byte *pRAM=NULL;
233	int download_offset=0;
234	card_t *FirstCard;
235	byte sw_id[80];
236
237	DPRINTF(("divas: loading Diva Server 4BRI[%d]", load->card_id));
238
239	switch(load->code_type)
240	{
241		case DIA_CPU_CODE:
242			DPRINTF(("divas: RISC code"));
243			print_hdr(load->code, 0x80);
244			card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
245			download_offset = 0; // Protocol code written to offset 0
246			pRAM = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
247			break;
248
249		case DIA_DSP_CODE:
250			DPRINTF(("divas: DSP code"));
251			print_hdr(load->code, 0x0);
252			FirstCard = get_card(load->card_id - 3);
253			if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
254			{
255				download_offset = MQ_V90D_DSP_CODE_BASE;
256			}
257			else
258			{
259				download_offset = MQ_ORG_DSP_CODE_BASE;
260			}
261			pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
262			download_offset += (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC);
263
264			break;
265
266		case DIA_TABLE_CODE:
267			DPRINTF(("divas: TABLE code"));
268			FirstCard = get_card(load->card_id - 3);
269			if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
270			{
271				download_offset = MQ_V90D_DSP_CODE_BASE + sizeof(dword);
272			}
273			else
274			{
275				download_offset = MQ_ORG_DSP_CODE_BASE + sizeof(dword);
276			}
277			pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
278			break;
279
280		case DIA_CONT_CODE:
281			DPRINTF(("divas: continuation code"));
282			break;
283
284        case DIA_DLOAD_CNT:
285			DPRINTF(("divas: COUNT code"));
286			FirstCard = get_card(load->card_id - 3);
287			if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
288			{
289				download_offset = MQ_V90D_DSP_CODE_BASE;
290			}
291			else
292			{
293				download_offset = MQ_ORG_DSP_CODE_BASE;
294			}
295			pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
296			break;
297
298		case DIA_FPGA_CODE:
299			DPRINTF(("divas: 4BRI FPGA download - %d bytes", load->length));
300			if (FPGA_Download(IDI_ADAPTER_MAESTRAQ,
301 			card->hw->io_base,
302			 sw_id,
303			 load->code,
304			 load->length
305			) == -1)
306			{
307				DPRINTF(("divas: FPGA download failed"));
308				return -1;
309			}
310
311			/* NOW reset the 4BRI */
312			diva_server_4bri_reset(card);
313			return 0; // No need for anything further loading
314
315		default:
316			DPRINTF(("divas: unknown code type"));
317			return -1;
318	}
319
320   memcp(pRAM + (download_offset & 0x3FFFFF), load->code, load->length);
321
322	{
323		int mism_off;
324	if ((mism_off = memcm(pRAM + (download_offset & 0x3FFFFF), load->code, load->length)))
325	{
326		DPRINTF(("divas: memory mismatch at offset %d", mism_off));
327		UxCardMemDetach(card->hw, pRAM);
328		return -1;
329	}
330	}
331
332	UxCardMemDetach(card->hw, pRAM);
333
334	return 0;
335}
336
337static int diva_server_4bri_start(card_t *card, byte *channels)
338{
339	byte *ctl;
340	byte *shared, i;
341	int adapter_num;
342
343	DPRINTF(("divas: start Diva Server 4BRI"));
344	*channels = 0;
345	card->is_live = FALSE;
346
347	ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
348
349	UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_COLD_RESET_MASK);
350
351	UxPause(2);
352
353	UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
354
355	UxPause(10);
356
357	UxCardMemDetach(card->hw, ctl);
358
359	shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
360
361	for ( i = 0 ; i < 300 ; ++i )
362	{
363		UxPause (10) ;
364
365		if ( UxCardMemInW(card->hw, &shared[0x1E]) == 0x4447 )
366		{
367			DPRINTF(("divas: Protocol startup time %d.%02d seconds",
368			         (i / 100), (i % 100) ));
369
370			break;
371		}
372	}
373
374	if (i==300)
375	{
376		DPRINTF(("divas: Timeout starting card"));
377		DPRINTF(("divas: Signature == 0x%04X", UxCardMemInW(card->hw, &shared[0x1E])));
378
379		UxCardMemDetach(card->hw, shared);
380		return -1;
381	}
382
383	UxCardMemDetach(card->hw, shared);
384
385	for (adapter_num=3; adapter_num >= 0; adapter_num--)
386	{
387		card_t *qbri_card;
388
389		qbri_card = get_card(card->cfg.card_id - adapter_num);
390
391		if (qbri_card)
392		{
393			qbri_card->is_live = TRUE;
394			shared = UxCardMemAttach(qbri_card->hw, DIVAS_SHARED_MEMORY);
395			*channels += UxCardMemIn(qbri_card->hw, &shared[0x3F6]);
396			UxCardMemDetach(qbri_card->hw, shared);
397		}
398		else
399		{
400			DPRINTF(("divas: Couldn't get card info %d", card->cfg.card_id));
401		}
402	}
403
404	diva_server_4bri_test_int(card);
405
406	return 0;
407}
408
409static
410int 	diva_server_4bri_mem_get(card_t *card, mem_block_t *mem_block)
411
412{
413	byte	*a;
414	byte	*card_addr;
415	word	length = 0;
416	int		i;
417
418	a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
419
420	card_addr = a;
421	card_addr += mem_block->addr;
422
423	for (i=0; i < sizeof(mem_block->data); i++)
424	{
425		mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
426		card_addr++;
427		length++;
428	}
429
430	UxCardMemDetach(card->hw, a);
431
432	return length;
433}
434
435/*
436 * Initialise 4BRI specific entry points
437 */
438
439int Divas4BriInit(card_t *card, dia_card_t *cfg)
440{
441//	byte sw_id[80];
442//	extern int FPGA_Done;
443
444	DPRINTF(("divas: initialise Diva Server 4BRI"));
445
446	if (Divas4BRIInitPCI(card, cfg) == -1)
447	{
448		return -1;
449	}
450
451	/* Need to download the FPGA */
452/*	if (!FPGA_Done)
453	{
454		int retVal;
455
456		retVal=FPGA_Download(IDI_ADAPTER_MAESTRAQ,
457 			cfg->io_base,
458			 sw_id,
459			 FPGA_Bytes
460			);
461		if(retVal==-1)
462		{
463
464			DPRINTF(("divas: FPGA Download Failed"));
465			return -1;
466
467		}
468		FPGA_Done = 1;
469	} */
470
471	card->card_reset = diva_server_4bri_reset;
472	card->card_load = diva_server_4bri_load;
473	card->card_config = diva_server_4bri_config;
474	card->card_start = diva_server_4bri_start;
475	card->reset_int = diva_server_4bri_reset_int;
476	card->card_mem_get = diva_server_4bri_mem_get;
477
478	card->xlog_offset = DIVAS_MAINT_OFFSET;
479
480	card->out = DivasOut;
481	card->test_int = DivasTestInt;
482	card->dpc = DivasDpc;
483	card->clear_int = DivasClearInt;
484	card->card_isr = fourbri_ISR;
485
486	card->a.ram_out = mem_out;
487	card->a.ram_outw = mem_outw;
488	card->a.ram_out_buffer = mem_out_buffer;
489	card->a.ram_inc = mem_inc;
490
491	card->a.ram_in = mem_in;
492	card->a.ram_inw = mem_inw;
493	card->a.ram_in_buffer = mem_in_buffer;
494	card->a.ram_look_ahead = mem_look_ahead;
495
496	return 0;
497}
498
499void memcp(byte *dst, byte *src, dword dwLen)
500{
501	while (dwLen)
502	{
503		*dst = *src;
504		dst++; src++;
505		dwLen--;
506	}
507}
508
509int memcm(byte *dst, byte *src, dword dwLen)
510{
511	int offset = 0;
512
513	while (offset < dwLen)
514	{
515		if(*dst != *src)
516			return (offset+1);
517
518		offset++;
519		src++;
520		dst++;
521	}
522
523	return 0;
524}
525
526
527
528/*int fourbri_ISR (card_t* card)
529{
530	int served = 0;
531	byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
532
533
534	if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01)
535	{
536		served = 1;
537		card->int_pend  += 1;
538		DivasDpcSchedule();
539		UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
540	}
541
542	UxCardMemDetach(card->hw, DivasIOBase);
543
544	return (served != 0);
545}*/
546
547
548static int fourbri_ISR (card_t* card)
549{
550	byte *ctl;
551
552	card->int_pend  += 1;
553	DivasDpcSchedule(); /* ISR DPC */
554
555	ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
556	UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
557	UxCardMemDetach(card->hw, ctl);
558
559	return (1);
560}
561