1/*
2 * Diva Server PRI specific part of initialisation
3 *
4 * Copyright (C) Eicon Technology Corporation, 2000.
5 *
6 * Eicon File Revision :    1.5
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
20#include "adapter.h"
21#include "uxio.h"
22
23#define	DIVAS_LOAD_CMD		0x02
24#define	DIVAS_START_CMD		0x03
25#define	DIVAS_IRQ_RESET		0xC18
26#define DIVAS_IRQ_RESET_VAL	0xFE
27
28#define	TEST_INT_DIVAS		0x11
29#define TEST_INT_DIVAS_BRI	0x12
30
31#define DIVAS_RESET	0x81
32#define DIVAS_LED1	0x04
33#define DIVAS_LED2	0x08
34#define DIVAS_LED3	0x20
35#define DIVAS_LED4	0x40
36
37#define	DIVAS_RESET_REG		0x20
38
39#define	DIVAS_SIGNATURE	0x4447
40
41/* offset to start of MAINT area (used by xlog) */
42
43#define	DIVAS_MAINT_OFFSET	0xef00	/* value for PRI card */
44
45#define MP_PROTOCOL_ADDR		0xA0011000
46#define MP_DSP_CODE_BASE		0xa03a0000
47
48typedef struct {
49		dword cmd;
50		dword addr;
51		dword len;
52		dword err;
53		dword live;
54		dword reserved[(0x1020>>2)-6];
55		dword signature;
56		byte  data[1];
57} diva_server_boot_t;
58
59byte mem_in(ADAPTER *a, void *adr);
60word mem_inw(ADAPTER *a, void *adr);
61void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
62void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
63void mem_out(ADAPTER *a, void *adr, byte data);
64void mem_outw(ADAPTER *a, void *adr, word data);
65void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
66void mem_inc(ADAPTER *a, void *adr);
67
68int DivasPRIInitPCI(card_t *card, dia_card_t *cfg);
69static int pri_ISR (card_t* card);
70
71static int diva_server_reset(card_t *card)
72{
73	byte *reg;
74	diva_server_boot_t *boot = NULL;
75	dword live = 0;
76	int	i = 0;
77	dword	dwWait;
78
79	DPRINTF(("divas: reset Diva Server PRI"));
80
81	reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
82
83	UxCardMemOut(card->hw, &reg[DIVAS_RESET_REG], DIVAS_RESET |
84						DIVAS_LED1 | DIVAS_LED2 | DIVAS_LED3 | DIVAS_LED4);
85
86	for (dwWait = 0x000fffff; dwWait; dwWait--)
87		;
88
89	UxCardMemOut(card->hw, &reg[DIVAS_RESET_REG], 0x00);
90
91	for (dwWait = 0x000fffff; dwWait; dwWait--)
92		;
93
94	UxCardMemDetach(card->hw, reg);
95
96	boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
97
98	UxCardMemOutD(card->hw, boot->reserved, 0);
99
100	live = UxCardMemInD(card->hw, &boot->live);
101
102	for (i=0; i<5; i++)
103	{
104		if (live != UxCardMemInD(card->hw, &boot->live))
105		{
106			break;
107		}
108		UxPause(10);
109	}
110
111	if (i == 5)
112	{
113		UxCardMemDetach(card->hw, boot);
114
115		DPRINTF(("divas: card is reset but CPU not running"));
116		return -1;
117	}
118
119	UxCardMemDetach(card->hw, boot);
120
121	DPRINTF(("divas: card reset after %d ms", i * 10));
122
123	return 0;
124}
125
126static int diva_server_config(card_t *card, dia_config_t *config)
127{
128	byte *shared;
129	int i, j;
130
131	DPRINTF(("divas: configure Diva Server PRI"));
132
133	shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
134
135	UxCardLog(0);
136	for (i=0; i<256; i++)
137	{
138		UxCardMemOut(card->hw, &shared[i], 0);
139	}
140
141	UxCardMemOut(card->hw, &shared[ 8], config->tei);
142	UxCardMemOut(card->hw, &shared[ 9], config->nt2);
143	UxCardMemOut(card->hw, &shared[10], config->sig_flags);
144	UxCardMemOut(card->hw, &shared[11], config->watchdog);
145	UxCardMemOut(card->hw, &shared[12], config->permanent);
146	UxCardMemOut(card->hw, &shared[13], config->x_interface);
147	UxCardMemOut(card->hw, &shared[14], config->stable_l2);
148	UxCardMemOut(card->hw, &shared[15], config->no_order_check);
149	UxCardMemOut(card->hw, &shared[16], config->handset_type);
150	UxCardMemOut(card->hw, &shared[17], 0);
151	UxCardMemOut(card->hw, &shared[18], config->low_channel);
152	UxCardMemOut(card->hw, &shared[19], config->prot_version);
153	UxCardMemOut(card->hw, &shared[20], config->crc4);
154
155	for (i=0; i<2; i++)
156	{
157		for (j=0; j<32; j++)
158		{
159			UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
160		}
161
162		for (j=0; j<32; j++)
163		{
164			UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
165		}
166
167		for (j=0; j<32; j++)
168		{
169			UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
170		}
171	}
172
173	UxCardMemDetach(card->hw, shared);
174
175	return 0;
176}
177
178static
179void diva_server_reset_int(card_t *card)
180{
181	byte *cfg;
182
183	cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
184
185	UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET], DIVAS_IRQ_RESET_VAL);
186	UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET + 2], 0);
187	UxCardMemDetach(card->hw, cfg);
188
189	return;
190}
191
192
193static int diva_server_test_int(card_t *card)
194{
195	int i;
196	byte *shared;
197	byte req_int;
198
199	DPRINTF(("divas: test interrupt for Diva Server PRI"));
200
201	shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
202
203	UxCardMemIn(card->hw, &shared[0x3FE]);
204	UxCardMemOut(card->hw, &shared[0x3FE], 0);
205	UxCardMemIn(card->hw, &shared[0x3FE]);
206
207	UxCardMemDetach(card->hw, shared);
208
209	diva_server_reset_int(card);
210
211	shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
212
213	card->test_int_pend = TEST_INT_DIVAS;
214
215	req_int = UxCardMemIn(card->hw, &(((struct pr_ram *)shared)->ReadyInt));
216
217	req_int++;
218
219	UxCardMemOut(card->hw, &(((struct pr_ram *)shared)->ReadyInt), req_int);
220
221	UxCardMemDetach(card->hw, shared);
222
223	UxCardLog(0);
224	for (i = 0; i < 50; i++)
225	{
226		if (!card->test_int_pend)
227		{
228			break;
229		}
230		UxPause(10);
231	}
232
233
234	if (card->test_int_pend)
235	{
236
237		DPRINTF(("active: timeout waiting for card to interrupt"));
238		return (-1);
239
240	}
241
242	return 0;
243}
244
245
246static void print_hdr(unsigned char *code, int offset)
247{
248	unsigned char hdr[80];
249		int i;
250
251	i = 0;
252
253	while ((i < (DIM(hdr) -1)) &&
254		(code[offset + i] != '\0') &&
255		(code[offset + i] != '\r') &&
256		(code[offset + i] != '\n'))
257	{
258		hdr[i] = code[offset + i];
259		i++;
260	}
261
262	hdr[i] = '\0';
263
264	DPRINTF(("divas: loading %s", hdr));
265}
266
267static int diva_server_load(card_t *card, dia_load_t *load)
268{
269	diva_server_boot_t *boot;
270	int i, offset, length;
271	dword cmd = 0;
272
273	DPRINTF(("divas: loading Diva Server PRI"));
274
275	boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
276
277	switch(load->code_type)
278	{
279		case DIA_CPU_CODE:
280			DPRINTF(("divas: RISC code"));
281			print_hdr(load->code, 0x80);
282
283			UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
284			break;
285
286		case DIA_DSP_CODE:
287			DPRINTF(("divas: DSP code"));
288			print_hdr(load->code, 0x0);
289
290			UxCardMemOutD(card->hw, &boot->addr,
291				(MP_DSP_CODE_BASE + (((sizeof(dword) +
292				(sizeof(t_dsp_download_desc) * DSP_MAX_DOWNLOAD_COUNT))
293				+ ~ALIGNMENT_MASK_MAESTRA) & ALIGNMENT_MASK_MAESTRA)));
294			break;
295
296		case DIA_TABLE_CODE:
297			DPRINTF(("divas: TABLE code"));
298			UxCardMemOutD(card->hw, &boot->addr,
299				(MP_DSP_CODE_BASE + sizeof(dword)));
300			break;
301
302		case DIA_CONT_CODE:
303			DPRINTF(("divas: continuation code"));
304			break;
305
306        case DIA_DLOAD_CNT:
307			DPRINTF(("divas: COUNT code"));
308			UxCardMemOutD(card->hw, &boot->addr, MP_DSP_CODE_BASE);
309			break;
310
311		default:
312			DPRINTF(("divas: unknown code type"));
313			UxCardMemDetach(card->hw, boot);
314			return -1;
315	}
316
317	UxCardLog(0);
318	offset = 0;
319
320	do
321	{
322		length = (load->length - offset >= 400) ? 400 : load->length - offset;
323
324		for (i=0; i<length; i++)
325		{
326			UxCardMemOut(card->hw, &boot->data[i], load->code[offset+i]);
327		}
328
329        for (i=0; i<length; i++)
330		{
331			if (load->code[offset + i] != UxCardMemIn(card->hw, &boot->data[i]))
332			{
333				UxCardMemDetach(card->hw, boot);
334
335				DPRINTF(("divas: card code block verify failed"));
336				return -1;
337			}
338		}
339
340		UxCardMemOutD(card->hw, &boot->len, (length + 3) / 4);
341		UxCardMemOutD(card->hw, &boot->cmd, DIVAS_LOAD_CMD);
342
343		for (i=0; i<50000; i++)
344		{
345			cmd = UxCardMemInD(card->hw, &boot->cmd);
346			if (!cmd)
347			{
348				break;
349			}
350			/*UxPause(1);*/
351		}
352
353		if (cmd)
354		{
355			DPRINTF(("divas: timeout waiting for card to ACK load (offset = %d)", offset));
356			UxCardMemDetach(card->hw, boot);
357			return -1;
358		}
359
360		offset += length;
361
362	} while (offset < load->length);
363
364	UxCardMemDetach(card->hw, boot);
365
366	DPRINTF(("divas: DIVA Server card loaded"));
367
368	return 0;
369}
370
371static int diva_server_start(card_t *card, byte *channels)
372{
373	diva_server_boot_t *boot;
374	byte *ram;
375	int	i;
376	dword signature = 0;
377
378	DPRINTF(("divas: start Diva Server PRI"));
379
380	card->is_live = FALSE;
381
382	boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
383
384	UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
385	UxCardMemOutD(card->hw, &boot->cmd, DIVAS_START_CMD);
386
387	UxCardLog(0);
388
389	for (i = 0; i < 300; i++)
390	{
391		signature = UxCardMemInD(card->hw, &boot->signature);
392		if ((signature >> 16) == DIVAS_SIGNATURE)
393		{
394			DPRINTF(("divas: started card after %d ms", i * 10));
395			break;
396		}
397		UxPause(10);
398	}
399
400	if ((signature >> 16) != DIVAS_SIGNATURE)
401	{
402		UxCardMemDetach(card->hw, boot);
403		DPRINTF(("divas: timeout waiting for card to run protocol code (sig = 0x%x)", signature));
404		return -1;
405	}
406
407	card->is_live = TRUE;
408
409	ram = (byte *) boot;
410	ram += DIVAS_SHARED_OFFSET;
411
412	*channels = UxCardMemIn(card->hw, &ram[0x3F6]);
413	card->serial_no = UxCardMemInD(card->hw, &ram[0x3F0]);
414
415	UxCardMemDetach(card->hw, boot);
416
417	if (diva_server_test_int(card))
418	{
419		DPRINTF(("divas: interrupt test failed"));
420		return -1;
421	}
422
423	DPRINTF(("divas: DIVA Server card started"));
424
425	return 0;
426}
427
428static
429int 	diva_server_mem_get(card_t *card, mem_block_t *mem_block)
430
431{
432	byte	*a;
433	byte	*card_addr;
434	word	length = 0;
435	int		i;
436
437	a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
438
439	card_addr = a;
440	card_addr += mem_block->addr;
441
442	for (i=0; i < sizeof(mem_block->data); i++)
443	{
444		mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
445		card_addr++;
446		length++;
447	}
448
449	UxCardMemDetach(card->hw, a);
450
451	return length;
452}
453
454/*
455 * Initialise PRI specific entry points
456 */
457
458int DivasPriInit(card_t *card, dia_card_t *cfg)
459{
460	DPRINTF(("divas: initialise Diva Server PRI"));
461
462	if (DivasPRIInitPCI(card, cfg) == -1)
463	{
464		return -1;
465	}
466
467	card->card_reset = diva_server_reset;
468	card->card_load = diva_server_load;
469	card->card_config = diva_server_config;
470	card->card_start = diva_server_start;
471	card->reset_int = diva_server_reset_int;
472	card->card_mem_get = diva_server_mem_get;
473
474	card->xlog_offset = DIVAS_MAINT_OFFSET;
475
476	card->out = DivasOut;
477	card->test_int = DivasTestInt;
478	card->dpc = DivasDpc;
479	card->clear_int = DivasClearInt;
480	card->card_isr  = pri_ISR;
481
482	card->a.ram_out = mem_out;
483	card->a.ram_outw = mem_outw;
484	card->a.ram_out_buffer = mem_out_buffer;
485	card->a.ram_inc = mem_inc;
486
487	card->a.ram_in = mem_in;
488	card->a.ram_inw = mem_inw;
489	card->a.ram_in_buffer = mem_in_buffer;
490	card->a.ram_look_ahead = mem_look_ahead;
491
492	return 0;
493}
494
495
496static int pri_ISR (card_t* card)
497{
498	int served = 0;
499	byte* cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
500	volatile unsigned long* isr = (unsigned long*)&cfg[DIVAS_IRQ_RESET];
501	register unsigned long val = *isr;
502
503	if (val & 0x80000000)  /* our card had caused interrupt ??? */
504	{
505		served = 1;
506		card->int_pend  += 1;
507		DivasDpcSchedule(); /* ISR DPC */
508
509		*isr = (unsigned long)~0x03E00000; /* Clear interrupt line */
510	}
511
512	UxCardMemDetach(card->hw, cfg);
513
514	return (served != 0);
515}
516
517
518