blob: 25c5d7feb8382df4da3d6054d6234d0273b45563 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001
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 -------------------------------------------------------------------------- */
47static 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 -------------------------------------------------------------------------- */
100static 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 -------------------------------------------------------------------------- */
128void 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 -------------------------------------------------------------------------- */
146static 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
186static 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
275int 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
362static int load_qBri_hardware (PISDN_ADAPTER IoAdapter) {
363 return (0);
364}
365
366/* --------------------------------------------------------------------------
367 Card ISR
368 -------------------------------------------------------------------------- */
369static 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 -------------------------------------------------------------------------- */
413static 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 -------------------------------------------------------------------------- */
435static 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
467static 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
476static 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
487void 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
496void 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/* -------------------------------------------------------------------------- */