• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  *
4  Copyright (c) Eicon Networks, 2002.
5  *
6  This source file is supplied for the use with
7  Eicon Networks range of DIVA Server Adapters.
8  *
9  Eicon File Revision :    2.1
10  *
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2, or (at your option)
14  any later version.
15  *
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  See the GNU General Public License for more details.
20  *
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26 #include "platform.h"
27 #include "di_defs.h"
28 #include "pc.h"
29 #include "pr_pc.h"
30 #include "di.h"
31 #include "mi_pc.h"
32 #include "pc_maint.h"
33 #include "divasync.h"
34 #include "pc_init.h"
35 #include "io.h"
36 #include "helpers.h"
37 #include "dsrv4bri.h"
38 #include "dsp_defs.h"
39 #include "sdp_hdr.h"
40 
41 /*****************************************************************************/
42 #define	MAX_XLOG_SIZE	(64 * 1024)
43 
44 /* --------------------------------------------------------------------------
45    Recovery XLOG from QBRI Card
46    -------------------------------------------------------------------------- */
qBri_cpu_trapped(PISDN_ADAPTER IoAdapter)47 static void qBri_cpu_trapped(PISDN_ADAPTER IoAdapter) {
48 	byte  __iomem *base;
49 	word *Xlog;
50 	dword   regs[4], TrapID, offset, size;
51 	Xdesc   xlogDesc;
52 	int factor = (IoAdapter->tasks == 1) ? 1 : 2;
53 
54 /*
55  *	check for trapped MIPS 46xx CPU, dump exception frame
56  */
57 
58 	base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter);
59 	offset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor);
60 
61 	TrapID = READ_DWORD(&base[0x80]);
62 
63 	if ((TrapID == 0x99999999) || (TrapID == 0x99999901))
64 	{
65 		dump_trap_frame(IoAdapter, &base[0x90]);
66 		IoAdapter->trapped = 1;
67 	}
68 
69 	regs[0] = READ_DWORD((base + offset) + 0x70);
70 	regs[1] = READ_DWORD((base + offset) + 0x74);
71 	regs[2] = READ_DWORD((base + offset) + 0x78);
72 	regs[3] = READ_DWORD((base + offset) + 0x7c);
73 	regs[0] &= IoAdapter->MemorySize - 1;
74 
75 	if ((regs[0] >= offset)
76 	    && (regs[0] < offset + (IoAdapter->MemorySize >> factor) - 1))
77 	{
78 		if (!(Xlog = (word *)diva_os_malloc(0, MAX_XLOG_SIZE))) {
79 			DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
80 			return;
81 		}
82 
83 		size = offset + (IoAdapter->MemorySize >> factor) - regs[0];
84 		if (size > MAX_XLOG_SIZE)
85 			size = MAX_XLOG_SIZE;
86 		memcpy_fromio(Xlog, &base[regs[0]], size);
87 		xlogDesc.buf = Xlog;
88 		xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]);
89 		xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]);
90 		dump_xlog_buffer(IoAdapter, &xlogDesc);
91 		diva_os_free(0, Xlog);
92 		IoAdapter->trapped = 2;
93 	}
94 	DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
95 }
96 
97 /* --------------------------------------------------------------------------
98    Reset QBRI Hardware
99    -------------------------------------------------------------------------- */
reset_qBri_hardware(PISDN_ADAPTER IoAdapter)100 static void reset_qBri_hardware(PISDN_ADAPTER IoAdapter) {
101 	word volatile __iomem *qBriReset;
102 	byte  volatile __iomem *qBriCntrl;
103 	byte  volatile __iomem *p;
104 
105 	qBriReset = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
106 	WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET);
107 	diva_os_wait(1);
108 	WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET);
109 	diva_os_wait(1);
110 	WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_RELOAD_EEPROM);
111 	diva_os_wait(1);
112 	WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_RELOAD_EEPROM);
113 	diva_os_wait(1);
114 	DIVA_OS_MEM_DETACH_PROM(IoAdapter, qBriReset);
115 
116 	qBriCntrl = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
117 	p = &qBriCntrl[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
118 	WRITE_DWORD(p, 0);
119 	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, qBriCntrl);
120 
121 	DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset))
122 		DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p))
123 		}
124 
125 /* --------------------------------------------------------------------------
126    Start Card CPU
127    -------------------------------------------------------------------------- */
start_qBri_hardware(PISDN_ADAPTER IoAdapter)128 void start_qBri_hardware(PISDN_ADAPTER IoAdapter) {
129 	byte volatile __iomem *qBriReset;
130 	byte volatile __iomem *p;
131 
132 	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
133 	qBriReset = &p[(DIVA_4BRI_REVISION(IoAdapter)) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
134 	WRITE_DWORD(qBriReset, MQ_RISC_COLD_RESET_MASK);
135 	diva_os_wait(2);
136 	WRITE_DWORD(qBriReset, MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
137 	diva_os_wait(10);
138 	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
139 
140 	DBG_TRC(("started processor @ addr 0x%08lx", qBriReset))
141 		}
142 
143 /* --------------------------------------------------------------------------
144    Stop Card CPU
145    -------------------------------------------------------------------------- */
stop_qBri_hardware(PISDN_ADAPTER IoAdapter)146 static void stop_qBri_hardware(PISDN_ADAPTER IoAdapter) {
147 	byte volatile __iomem *p;
148 	dword volatile __iomem *qBriReset;
149 	dword volatile __iomem *qBriIrq;
150 	dword volatile __iomem *qBriIsacDspReset;
151 	int rev2 = DIVA_4BRI_REVISION(IoAdapter);
152 	int reset_offset = rev2 ? (MQ2_BREG_RISC)      : (MQ_BREG_RISC);
153 	int irq_offset   = rev2 ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST);
154 	int hw_offset    = rev2 ? (MQ2_ISAC_DSP_RESET) : (MQ_ISAC_DSP_RESET);
155 
156 	if (IoAdapter->ControllerNumber > 0)
157 		return;
158 	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
159 	qBriReset = (dword volatile __iomem *)&p[reset_offset];
160 	qBriIsacDspReset = (dword volatile __iomem *)&p[hw_offset];
161 /*
162  *	clear interrupt line (reset Local Interrupt Test Register)
163  */
164 	WRITE_DWORD(qBriReset, 0);
165 	WRITE_DWORD(qBriIsacDspReset, 0);
166 	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
167 
168 	p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
169 	WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);	/* disable PCI interrupts */
170 	DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
171 
172 	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
173 	qBriIrq   = (dword volatile __iomem *)&p[irq_offset];
174 	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
175 	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
176 
177 	DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset))
178 
179 		}
180 
181 /* --------------------------------------------------------------------------
182    FPGA download
183    -------------------------------------------------------------------------- */
184 #define FPGA_NAME_OFFSET         0x10
185 
qBri_check_FPGAsrc(PISDN_ADAPTER IoAdapter,char * FileName,dword * Length,dword * code)186 static byte *qBri_check_FPGAsrc(PISDN_ADAPTER IoAdapter, char *FileName,
187 				dword *Length, dword *code) {
188 	byte *File;
189 	char *fpgaFile, *fpgaType, *fpgaDate, *fpgaTime;
190 	dword fpgaFlen, fpgaTlen, fpgaDlen, cnt, year, i;
191 
192 	if (!(File = (byte *)xdiLoadFile(FileName, Length, 0))) {
193 		return (NULL);
194 	}
195 /*
196  *	 scan file until FF and put id string into buffer
197  */
198 	for (i = 0; File[i] != 0xff;)
199 	{
200 		if (++i >= *Length)
201 		{
202 			DBG_FTL(("FPGA download: start of data header not found"))
203 				xdiFreeFile(File);
204 			return (NULL);
205 		}
206 	}
207 	*code = i++;
208 
209 	if ((File[i] & 0xF0) != 0x20)
210 	{
211 		DBG_FTL(("FPGA download: data header corrupted"))
212 			xdiFreeFile(File);
213 		return (NULL);
214 	}
215 	fpgaFlen = (dword)File[FPGA_NAME_OFFSET - 1];
216 	if (fpgaFlen == 0)
217 		fpgaFlen = 12;
218 	fpgaFile = (char *)&File[FPGA_NAME_OFFSET];
219 	fpgaTlen = (dword)fpgaFile[fpgaFlen + 2];
220 	if (fpgaTlen == 0)
221 		fpgaTlen = 10;
222 	fpgaType = (char *)&fpgaFile[fpgaFlen + 3];
223 	fpgaDlen = (dword)  fpgaType[fpgaTlen + 2];
224 	if (fpgaDlen == 0)
225 		fpgaDlen = 11;
226 	fpgaDate = (char *)&fpgaType[fpgaTlen + 3];
227 	fpgaTime = (char *)&fpgaDate[fpgaDlen + 3];
228 	cnt = (dword)(((File[i] & 0x0F) << 20) + (File[i + 1] << 12)
229 		      + (File[i + 2] << 4) + (File[i + 3] >> 4));
230 
231 	if ((dword)(i + (cnt / 8)) > *Length)
232 	{
233 		DBG_FTL(("FPGA download: '%s' file too small (%ld < %ld)",
234 			 FileName, *Length, code + ((cnt + 7) / 8)))
235 			xdiFreeFile(File);
236 		return (NULL);
237 	}
238 	i = 0;
239 	do
240 	{
241 		while ((fpgaDate[i] != '\0')
242 		       && ((fpgaDate[i] < '0') || (fpgaDate[i] > '9')))
243 		{
244 			i++;
245 		}
246 		year = 0;
247 		while ((fpgaDate[i] >= '0') && (fpgaDate[i] <= '9'))
248 			year = year * 10 + (fpgaDate[i++] - '0');
249 	} while ((year < 2000) && (fpgaDate[i] != '\0'));
250 
251 	switch (IoAdapter->cardType) {
252 	case CARDTYPE_DIVASRV_B_2F_PCI:
253 		break;
254 
255 	default:
256 		if (year >= 2001) {
257 			IoAdapter->fpga_features |= PCINIT_FPGA_PLX_ACCESS_SUPPORTED;
258 		}
259 	}
260 
261 	DBG_LOG(("FPGA[%s] file %s (%s %s) len %d",
262 		 fpgaType, fpgaFile, fpgaDate, fpgaTime, cnt))
263 		return (File);
264 }
265 
266 /******************************************************************************/
267 
268 #define FPGA_PROG   0x0001		/* PROG enable low */
269 #define FPGA_BUSY   0x0002		/* BUSY high, DONE low */
270 #define	FPGA_CS     0x000C		/* Enable I/O pins */
271 #define FPGA_CCLK   0x0100
272 #define FPGA_DOUT   0x0400
273 #define FPGA_DIN    FPGA_DOUT   /* bidirectional I/O */
274 
qBri_FPGA_download(PISDN_ADAPTER IoAdapter)275 int qBri_FPGA_download(PISDN_ADAPTER IoAdapter) {
276 	int            bit;
277 	byte           *File;
278 	dword          code, FileLength;
279 	word volatile __iomem *addr = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
280 	word           val, baseval = FPGA_CS | FPGA_PROG;
281 
282 
283 
284 	if (DIVA_4BRI_REVISION(IoAdapter))
285 	{
286 		char *name;
287 
288 		switch (IoAdapter->cardType) {
289 		case CARDTYPE_DIVASRV_B_2F_PCI:
290 			name = "dsbri2f.bit";
291 			break;
292 
293 		case CARDTYPE_DIVASRV_B_2M_V2_PCI:
294 		case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
295 			name = "dsbri2m.bit";
296 			break;
297 
298 		default:
299 			name = "ds4bri2.bit";
300 		}
301 
302 		File = qBri_check_FPGAsrc(IoAdapter, name,
303 					  &FileLength, &code);
304 	}
305 	else
306 	{
307 		File = qBri_check_FPGAsrc(IoAdapter, "ds4bri.bit",
308 					  &FileLength, &code);
309 	}
310 	if (!File) {
311 		DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
312 		return (0);
313 	}
314 /*
315  *	prepare download, pulse PROGRAM pin down.
316  */
317 	WRITE_WORD(addr, baseval & ~FPGA_PROG); /* PROGRAM low pulse */
318 	WRITE_WORD(addr, baseval);              /* release */
319 	diva_os_wait(50);  /* wait until FPGA finished internal memory clear */
320 /*
321  *	check done pin, must be low
322  */
323 	if (READ_WORD(addr) & FPGA_BUSY)
324 	{
325 		DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing"))
326 			xdiFreeFile(File);
327 		DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
328 		return (0);
329 	}
330 /*
331  *	put data onto the FPGA
332  */
333 	while (code < FileLength)
334 	{
335 		val = ((word)File[code++]) << 3;
336 
337 		for (bit = 8; bit-- > 0; val <<= 1) /* put byte onto FPGA */
338 		{
339 			baseval &= ~FPGA_DOUT;             /* clr  data bit */
340 			baseval |= (val & FPGA_DOUT);      /* copy data bit */
341 			WRITE_WORD(addr, baseval);
342 			WRITE_WORD(addr, baseval | FPGA_CCLK);     /* set CCLK hi */
343 			WRITE_WORD(addr, baseval | FPGA_CCLK);     /* set CCLK hi */
344 			WRITE_WORD(addr, baseval);                 /* set CCLK lo */
345 		}
346 	}
347 	xdiFreeFile(File);
348 	diva_os_wait(100);
349 	val = READ_WORD(addr);
350 
351 	DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
352 
353 	if (!(val & FPGA_BUSY))
354 	{
355 		DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val))
356 			return (0);
357 	}
358 
359 	return (1);
360 }
361 
load_qBri_hardware(PISDN_ADAPTER IoAdapter)362 static int load_qBri_hardware(PISDN_ADAPTER IoAdapter) {
363 	return (0);
364 }
365 
366 /* --------------------------------------------------------------------------
367    Card ISR
368    -------------------------------------------------------------------------- */
qBri_ISR(struct _ISDN_ADAPTER * IoAdapter)369 static int qBri_ISR(struct _ISDN_ADAPTER *IoAdapter) {
370 	dword volatile     __iomem *qBriIrq;
371 
372 	PADAPTER_LIST_ENTRY QuadroList = IoAdapter->QuadroList;
373 
374 	word			i;
375 	int			serviced = 0;
376 	byte __iomem *p;
377 
378 	p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
379 
380 	if (!(READ_BYTE(&p[PLX9054_INTCSR]) & 0x80)) {
381 		DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
382 		return (0);
383 	}
384 	DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
385 
386 /*
387  *	clear interrupt line (reset Local Interrupt Test Register)
388  */
389 	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
390 	qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
391 	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
392 	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
393 
394 	for (i = 0; i < IoAdapter->tasks; ++i)
395 	{
396 		IoAdapter = QuadroList->QuadroAdapter[i];
397 
398 		if (IoAdapter && IoAdapter->Initialized
399 		    && IoAdapter->tst_irq(&IoAdapter->a))
400 		{
401 			IoAdapter->IrqCount++;
402 			serviced = 1;
403 			diva_os_schedule_soft_isr(&IoAdapter->isr_soft_isr);
404 		}
405 	}
406 
407 	return (serviced);
408 }
409 
410 /* --------------------------------------------------------------------------
411    Does disable the interrupt on the card
412    -------------------------------------------------------------------------- */
disable_qBri_interrupt(PISDN_ADAPTER IoAdapter)413 static void disable_qBri_interrupt(PISDN_ADAPTER IoAdapter) {
414 	dword volatile __iomem *qBriIrq;
415 	byte __iomem *p;
416 
417 	if (IoAdapter->ControllerNumber > 0)
418 		return;
419 /*
420  *	clear interrupt line (reset Local Interrupt Test Register)
421  */
422 	p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
423 	WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);	/* disable PCI interrupts */
424 	DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
425 
426 	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
427 	qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST)  : (MQ_BREG_IRQ_TEST)]);
428 	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
429 	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
430 }
431 
432 /* --------------------------------------------------------------------------
433    Install Adapter Entry Points
434    -------------------------------------------------------------------------- */
set_common_qBri_functions(PISDN_ADAPTER IoAdapter)435 static void set_common_qBri_functions(PISDN_ADAPTER IoAdapter) {
436 	ADAPTER *a;
437 
438 	a = &IoAdapter->a;
439 
440 	a->ram_in           = mem_in;
441 	a->ram_inw          = mem_inw;
442 	a->ram_in_buffer    = mem_in_buffer;
443 	a->ram_look_ahead   = mem_look_ahead;
444 	a->ram_out          = mem_out;
445 	a->ram_outw         = mem_outw;
446 	a->ram_out_buffer   = mem_out_buffer;
447 	a->ram_inc          = mem_inc;
448 
449 	IoAdapter->out = pr_out;
450 	IoAdapter->dpc = pr_dpc;
451 	IoAdapter->tst_irq = scom_test_int;
452 	IoAdapter->clr_irq  = scom_clear_int;
453 	IoAdapter->pcm  = (struct pc_maint *)MIPS_MAINT_OFFS;
454 
455 	IoAdapter->load = load_qBri_hardware;
456 
457 	IoAdapter->disIrq = disable_qBri_interrupt;
458 	IoAdapter->rstFnc = reset_qBri_hardware;
459 	IoAdapter->stop = stop_qBri_hardware;
460 	IoAdapter->trapFnc = qBri_cpu_trapped;
461 
462 	IoAdapter->diva_isr_handler = qBri_ISR;
463 
464 	IoAdapter->a.io = (void *)IoAdapter;
465 }
466 
set_qBri_functions(PISDN_ADAPTER IoAdapter)467 static void set_qBri_functions(PISDN_ADAPTER IoAdapter) {
468 	if (!IoAdapter->tasks) {
469 		IoAdapter->tasks = MQ_INSTANCE_COUNT;
470 	}
471 	IoAdapter->MemorySize = MQ_MEMORY_SIZE;
472 	set_common_qBri_functions(IoAdapter);
473 	diva_os_set_qBri_functions(IoAdapter);
474 }
475 
set_qBri2_functions(PISDN_ADAPTER IoAdapter)476 static void set_qBri2_functions(PISDN_ADAPTER IoAdapter) {
477 	if (!IoAdapter->tasks) {
478 		IoAdapter->tasks = MQ_INSTANCE_COUNT;
479 	}
480 	IoAdapter->MemorySize = (IoAdapter->tasks == 1) ? BRI2_MEMORY_SIZE : MQ2_MEMORY_SIZE;
481 	set_common_qBri_functions(IoAdapter);
482 	diva_os_set_qBri2_functions(IoAdapter);
483 }
484 
485 /******************************************************************************/
486 
prepare_qBri_functions(PISDN_ADAPTER IoAdapter)487 void prepare_qBri_functions(PISDN_ADAPTER IoAdapter) {
488 
489 	set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[0]);
490 	set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[1]);
491 	set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[2]);
492 	set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[3]);
493 
494 }
495 
prepare_qBri2_functions(PISDN_ADAPTER IoAdapter)496 void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter) {
497 	if (!IoAdapter->tasks) {
498 		IoAdapter->tasks = MQ_INSTANCE_COUNT;
499 	}
500 
501 	set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[0]);
502 	if (IoAdapter->tasks > 1) {
503 		set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[1]);
504 		set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[2]);
505 		set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[3]);
506 	}
507 
508 }
509 
510 /* -------------------------------------------------------------------------- */
511