Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
s_4bri.c
Go to the documentation of this file.
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  -------------------------------------------------------------------------- */
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  -------------------------------------------------------------------------- */
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  -------------------------------------------------------------------------- */
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)];
135  diva_os_wait(2);
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  -------------------------------------------------------------------------- */
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 
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) {
253  break;
254 
255  default:
256  if (year >= 2001) {
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 
276  int bit;
277  byte *File;
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) {
290  name = "dsbri2f.bit";
291  break;
292 
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 
362 static int load_qBri_hardware(PISDN_ADAPTER IoAdapter) {
363  return (0);
364 }
365 
366 /* --------------------------------------------------------------------------
367  Card ISR
368  -------------------------------------------------------------------------- */
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;
404  }
405  }
406 
407  return (serviced);
408 }
409 
410 /* --------------------------------------------------------------------------
411  Does disable the interrupt on the card
412  -------------------------------------------------------------------------- */
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  -------------------------------------------------------------------------- */
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;
444  a->ram_out = mem_out;
445  a->ram_outw = mem_outw;
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 
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 
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 
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 
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 /* -------------------------------------------------------------------------- */