File: /usr/src/linux/drivers/isdn/eicon/pri.c

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