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

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