4 Copyright (c) Eicon Networks, 2002.
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
9 Eicon File Revision : 2.1
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)
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.
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.
41 /*****************************************************************************/
42 #define MAX_XLOG_SIZE (64 * 1024)
44 /* --------------------------------------------------------------------------
45 Recovery XLOG from QBRI Card
46 -------------------------------------------------------------------------- */
47 static void qBri_cpu_trapped(PISDN_ADAPTER IoAdapter
) {
50 dword regs
[4], TrapID
, offset
, size
;
52 int factor
= (IoAdapter
->tasks
== 1) ? 1 : 2;
55 * check for trapped MIPS 46xx CPU, dump exception frame
58 base
= DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter
);
59 offset
= IoAdapter
->ControllerNumber
* (IoAdapter
->MemorySize
>> factor
);
61 TrapID
= READ_DWORD(&base
[0x80]);
63 if ((TrapID
== 0x99999999) || (TrapID
== 0x99999901))
65 dump_trap_frame(IoAdapter
, &base
[0x90]);
66 IoAdapter
->trapped
= 1;
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;
75 if ((regs
[0] >= offset
)
76 && (regs
[0] < offset
+ (IoAdapter
->MemorySize
>> factor
) - 1))
78 if (!(Xlog
= (word
*)diva_os_malloc(0, MAX_XLOG_SIZE
))) {
79 DIVA_OS_MEM_DETACH_CONTROL(IoAdapter
, base
);
83 size
= offset
+ (IoAdapter
->MemorySize
>> factor
) - regs
[0];
84 if (size
> MAX_XLOG_SIZE
)
86 memcpy_fromio(Xlog
, &base
[regs
[0]], size
);
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;
94 DIVA_OS_MEM_DETACH_CONTROL(IoAdapter
, base
);
97 /* --------------------------------------------------------------------------
99 -------------------------------------------------------------------------- */
100 static void reset_qBri_hardware(PISDN_ADAPTER IoAdapter
) {
101 word
volatile __iomem
*qBriReset
;
102 byte
volatile __iomem
*qBriCntrl
;
103 byte
volatile __iomem
*p
;
105 qBriReset
= (word
volatile __iomem
*)DIVA_OS_MEM_ATTACH_PROM(IoAdapter
);
106 WRITE_WORD(qBriReset
, READ_WORD(qBriReset
) | PLX9054_SOFT_RESET
);
108 WRITE_WORD(qBriReset
, READ_WORD(qBriReset
) & ~PLX9054_SOFT_RESET
);
110 WRITE_WORD(qBriReset
, READ_WORD(qBriReset
) | PLX9054_RELOAD_EEPROM
);
112 WRITE_WORD(qBriReset
, READ_WORD(qBriReset
) & ~PLX9054_RELOAD_EEPROM
);
114 DIVA_OS_MEM_DETACH_PROM(IoAdapter
, qBriReset
);
116 qBriCntrl
= DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter
);
117 p
= &qBriCntrl
[DIVA_4BRI_REVISION(IoAdapter
) ? (MQ2_BREG_RISC
) : (MQ_BREG_RISC
)];
119 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter
, qBriCntrl
);
121 DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset
))
122 DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p
))
125 /* --------------------------------------------------------------------------
127 -------------------------------------------------------------------------- */
128 void start_qBri_hardware(PISDN_ADAPTER IoAdapter
) {
129 byte
volatile __iomem
*qBriReset
;
130 byte
volatile __iomem
*p
;
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
);
136 WRITE_DWORD(qBriReset
, MQ_RISC_WARM_RESET_MASK
| MQ_RISC_COLD_RESET_MASK
);
138 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter
, p
);
140 DBG_TRC(("started processor @ addr 0x%08lx", qBriReset
))
143 /* --------------------------------------------------------------------------
145 -------------------------------------------------------------------------- */
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
);
156 if (IoAdapter
->ControllerNumber
> 0)
158 p
= DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter
);
159 qBriReset
= (dword
volatile __iomem
*)&p
[reset_offset
];
160 qBriIsacDspReset
= (dword
volatile __iomem
*)&p
[hw_offset
];
162 * clear interrupt line (reset Local Interrupt Test Register)
164 WRITE_DWORD(qBriReset
, 0);
165 WRITE_DWORD(qBriIsacDspReset
, 0);
166 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter
, p
);
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
);
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
);
177 DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset
))
181 /* --------------------------------------------------------------------------
183 -------------------------------------------------------------------------- */
184 #define FPGA_NAME_OFFSET 0x10
186 static byte
*qBri_check_FPGAsrc(PISDN_ADAPTER IoAdapter
, char *FileName
,
187 dword
*Length
, dword
*code
) {
189 char *fpgaFile
, *fpgaType
, *fpgaDate
, *fpgaTime
;
190 dword fpgaFlen
, fpgaTlen
, fpgaDlen
, cnt
, year
, i
;
192 if (!(File
= (byte
*)xdiLoadFile(FileName
, Length
, 0))) {
196 * scan file until FF and put id string into buffer
198 for (i
= 0; File
[i
] != 0xff;)
202 DBG_FTL(("FPGA download: start of data header not found"))
209 if ((File
[i
] & 0xF0) != 0x20)
211 DBG_FTL(("FPGA download: data header corrupted"))
215 fpgaFlen
= (dword
)File
[FPGA_NAME_OFFSET
- 1];
218 fpgaFile
= (char *)&File
[FPGA_NAME_OFFSET
];
219 fpgaTlen
= (dword
)fpgaFile
[fpgaFlen
+ 2];
222 fpgaType
= (char *)&fpgaFile
[fpgaFlen
+ 3];
223 fpgaDlen
= (dword
) fpgaType
[fpgaTlen
+ 2];
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));
231 if ((dword
)(i
+ (cnt
/ 8)) > *Length
)
233 DBG_FTL(("FPGA download: '%s' file too small (%ld < %ld)",
234 FileName
, *Length
, code
+ ((cnt
+ 7) / 8)))
241 while ((fpgaDate
[i
] != '\0')
242 && ((fpgaDate
[i
] < '0') || (fpgaDate
[i
] > '9')))
247 while ((fpgaDate
[i
] >= '0') && (fpgaDate
[i
] <= '9'))
248 year
= year
* 10 + (fpgaDate
[i
++] - '0');
249 } while ((year
< 2000) && (fpgaDate
[i
] != '\0'));
251 switch (IoAdapter
->cardType
) {
252 case CARDTYPE_DIVASRV_B_2F_PCI
:
257 IoAdapter
->fpga_features
|= PCINIT_FPGA_PLX_ACCESS_SUPPORTED
;
261 DBG_LOG(("FPGA[%s] file %s (%s %s) len %d",
262 fpgaType
, fpgaFile
, fpgaDate
, fpgaTime
, cnt
))
266 /******************************************************************************/
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 */
275 int qBri_FPGA_download(PISDN_ADAPTER IoAdapter
) {
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
;
284 if (DIVA_4BRI_REVISION(IoAdapter
))
288 switch (IoAdapter
->cardType
) {
289 case CARDTYPE_DIVASRV_B_2F_PCI
:
290 name
= "dsbri2f.bit";
293 case CARDTYPE_DIVASRV_B_2M_V2_PCI
:
294 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI
:
295 name
= "dsbri2m.bit";
299 name
= "ds4bri2.bit";
302 File
= qBri_check_FPGAsrc(IoAdapter
, name
,
307 File
= qBri_check_FPGAsrc(IoAdapter
, "ds4bri.bit",
311 DIVA_OS_MEM_DETACH_PROM(IoAdapter
, addr
);
315 * prepare download, pulse PROGRAM pin down.
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 */
321 * check done pin, must be low
323 if (READ_WORD(addr
) & FPGA_BUSY
)
325 DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing"))
327 DIVA_OS_MEM_DETACH_PROM(IoAdapter
, addr
);
331 * put data onto the FPGA
333 while (code
< FileLength
)
335 val
= ((word
)File
[code
++]) << 3;
337 for (bit
= 8; bit
-- > 0; val
<<= 1) /* put byte onto FPGA */
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 */
349 val
= READ_WORD(addr
);
351 DIVA_OS_MEM_DETACH_PROM(IoAdapter
, addr
);
353 if (!(val
& FPGA_BUSY
))
355 DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val
))
362 static int load_qBri_hardware(PISDN_ADAPTER IoAdapter
) {
366 /* --------------------------------------------------------------------------
368 -------------------------------------------------------------------------- */
369 static int qBri_ISR(struct _ISDN_ADAPTER
*IoAdapter
) {
370 dword
volatile __iomem
*qBriIrq
;
372 PADAPTER_LIST_ENTRY QuadroList
= IoAdapter
->QuadroList
;
378 p
= DIVA_OS_MEM_ATTACH_RESET(IoAdapter
);
380 if (!(READ_BYTE(&p
[PLX9054_INTCSR
]) & 0x80)) {
381 DIVA_OS_MEM_DETACH_RESET(IoAdapter
, p
);
384 DIVA_OS_MEM_DETACH_RESET(IoAdapter
, p
);
387 * clear interrupt line (reset Local Interrupt Test Register)
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
);
394 for (i
= 0; i
< IoAdapter
->tasks
; ++i
)
396 IoAdapter
= QuadroList
->QuadroAdapter
[i
];
398 if (IoAdapter
&& IoAdapter
->Initialized
399 && IoAdapter
->tst_irq(&IoAdapter
->a
))
401 IoAdapter
->IrqCount
++;
403 diva_os_schedule_soft_isr(&IoAdapter
->isr_soft_isr
);
410 /* --------------------------------------------------------------------------
411 Does disable the interrupt on the card
412 -------------------------------------------------------------------------- */
413 static void disable_qBri_interrupt(PISDN_ADAPTER IoAdapter
) {
414 dword
volatile __iomem
*qBriIrq
;
417 if (IoAdapter
->ControllerNumber
> 0)
420 * clear interrupt line (reset Local Interrupt Test Register)
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
);
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
);
432 /* --------------------------------------------------------------------------
433 Install Adapter Entry Points
434 -------------------------------------------------------------------------- */
435 static void set_common_qBri_functions(PISDN_ADAPTER IoAdapter
) {
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
;
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
;
455 IoAdapter
->load
= load_qBri_hardware
;
457 IoAdapter
->disIrq
= disable_qBri_interrupt
;
458 IoAdapter
->rstFnc
= reset_qBri_hardware
;
459 IoAdapter
->stop
= stop_qBri_hardware
;
460 IoAdapter
->trapFnc
= qBri_cpu_trapped
;
462 IoAdapter
->diva_isr_handler
= qBri_ISR
;
464 IoAdapter
->a
.io
= (void *)IoAdapter
;
467 static void set_qBri_functions(PISDN_ADAPTER IoAdapter
) {
468 if (!IoAdapter
->tasks
) {
469 IoAdapter
->tasks
= MQ_INSTANCE_COUNT
;
471 IoAdapter
->MemorySize
= MQ_MEMORY_SIZE
;
472 set_common_qBri_functions(IoAdapter
);
473 diva_os_set_qBri_functions(IoAdapter
);
476 static void set_qBri2_functions(PISDN_ADAPTER IoAdapter
) {
477 if (!IoAdapter
->tasks
) {
478 IoAdapter
->tasks
= MQ_INSTANCE_COUNT
;
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
);
485 /******************************************************************************/
487 void prepare_qBri_functions(PISDN_ADAPTER IoAdapter
) {
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]);
496 void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter
) {
497 if (!IoAdapter
->tasks
) {
498 IoAdapter
->tasks
= MQ_INSTANCE_COUNT
;
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]);
510 /* -------------------------------------------------------------------------- */