Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os_4bri.c
Go to the documentation of this file.
1 /* $Id: os_4bri.c,v 1.28.4.4 2005/02/11 19:40:25 armin Exp $ */
2 
3 #include "platform.h"
4 #include "debuglib.h"
5 #include "cardtype.h"
6 #include "pc.h"
7 #include "pr_pc.h"
8 #include "di_defs.h"
9 #include "dsp_defs.h"
10 #include "di.h"
11 #include "io.h"
12 
13 #include "xdi_msg.h"
14 #include "xdi_adapter.h"
15 #include "os_4bri.h"
16 #include "diva_pci.h"
17 #include "mi_pc.h"
18 #include "dsrv4bri.h"
19 #include "helpers.h"
20 
21 static void *diva_xdiLoadFileFile = NULL;
22 static dword diva_xdiLoadFileLength = 0;
23 
24 /*
25 ** IMPORTS
26 */
27 extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
28 extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
31 
32 extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
33 extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
34 
36 
37 /*
38 ** LOCALS
39 */
40 static unsigned long _4bri_bar_length[4] = {
41  0x100,
42  0x100, /* I/O */
44  0x2000
45 };
46 static unsigned long _4bri_v2_bar_length[4] = {
47  0x100,
48  0x100, /* I/O */
50  0x10000
51 };
52 static unsigned long _4bri_v2_bri_bar_length[4] = {
53  0x100,
54  0x100, /* I/O */
56  0x10000
57 };
58 
59 
60 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
61 static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a);
62 static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
64  int length);
65 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a);
66 static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a,
67  byte *data, dword length);
68 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
69 static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
70  dword address,
71  const byte *data,
73 static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
74  dword start_address, dword features);
75 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
76 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a);
77 
78 static int _4bri_is_rev_2_card(int card_ordinal)
79 {
80  switch (card_ordinal) {
86  return (1);
87  }
88  return (0);
89 }
90 
91 static int _4bri_is_rev_2_bri_card(int card_ordinal)
92 {
93  switch (card_ordinal) {
97  return (1);
98  }
99  return (0);
100 }
101 
102 static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a)
103 {
105  dword c_offset = offset * a->xdi_adapter.ControllerNumber;
106 
113 
114  /*
115  Set up hardware related pointers
116  */
117  a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */
118  a->xdi_adapter.Address += c_offset;
119 
120  a->xdi_adapter.Control = a->resources.pci.addr[2]; /* BAR2 SDRAM */
121 
122  a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */
123  a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE);
124 
125  a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */
126  /*
127  ctlReg contains the register address for the MIPS CPU reset control
128  */
129  a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */
130  /*
131  prom contains the register address for FPGA and EEPROM programming
132  */
133  a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
134 }
135 
136 /*
137 ** BAR0 - MEM - 0x100 - CONFIG MEM
138 ** BAR1 - I/O - 0x100 - UNUSED
139 ** BAR2 - MEM - MQ_MEMORY_SIZE (MQ2_MEMORY_SIZE on Rev.2) - SDRAM
140 ** BAR3 - MEM - 0x2000 (0x10000 on Rev.2) - CNTRL
141 **
142 ** Called by master adapter, that will initialize and add slave adapters
143 */
145 {
146  int bar, i;
147  byte __iomem *p;
148  PADAPTER_LIST_ENTRY quadro_list;
149  diva_os_xdi_adapter_t *diva_current;
150  diva_os_xdi_adapter_t *adapter_list[4];
151  PISDN_ADAPTER Slave;
152  unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
153  int v2 = _4bri_is_rev_2_card(a->CardOrdinal);
154  int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
155  int factor = (tasks == 1) ? 1 : 2;
156 
157  if (v2) {
158  if (_4bri_is_rev_2_bri_card(a->CardOrdinal)) {
159  memcpy(bar_length, _4bri_v2_bri_bar_length,
160  sizeof(bar_length));
161  } else {
162  memcpy(bar_length, _4bri_v2_bar_length,
163  sizeof(bar_length));
164  }
165  } else {
166  memcpy(bar_length, _4bri_bar_length, sizeof(bar_length));
167  }
168  DBG_TRC(("SDRAM_LENGTH=%08x, tasks=%d, factor=%d",
169  bar_length[2], tasks, factor))
170 
171  /*
172  Get Serial Number
173  The serial number of 4BRI is accessible in accordance with PCI spec
174  via command register located in configuration space, also we do not
175  have to map any BAR before we can access it
176  */
177  if (!_4bri_get_serial_number(a)) {
178  DBG_ERR(("A: 4BRI can't get Serial Number"))
179  diva_4bri_cleanup_adapter(a);
180  return (-1);
181  }
182 
183  /*
184  Set properties
185  */
187  DBG_LOG(("Load %s, SN:%ld, bus:%02x, func:%02x",
190  a->resources.pci.bus, a->resources.pci.func))
191 
192  /*
193  First initialization step: get and check hardware resoures.
194  Do not map resources and do not access card at this step
195  */
196  for (bar = 0; bar < 4; bar++) {
197  a->resources.pci.bar[bar] =
199  a->resources.pci.func, bar,
200  a->resources.pci.hdev);
201  if (!a->resources.pci.bar[bar]
202  || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
203  DBG_ERR(
204  ("A: invalid bar[%d]=%08x", bar,
205  a->resources.pci.bar[bar]))
206  return (-1);
207  }
208  }
209  a->resources.pci.irq =
211  a->resources.pci.func,
212  a->resources.pci.hdev);
213  if (!a->resources.pci.irq) {
214  DBG_ERR(("A: invalid irq"));
215  return (-1);
216  }
217 
219 
220  /*
221  Map all MEMORY BAR's
222  */
223  for (bar = 0; bar < 4; bar++) {
224  if (bar != 1) { /* ignore I/O */
225  a->resources.pci.addr[bar] =
226  divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar],
227  bar_length[bar]);
228  if (!a->resources.pci.addr[bar]) {
229  DBG_ERR(("A: 4BRI: can't map bar[%d]", bar))
230  diva_4bri_cleanup_adapter(a);
231  return (-1);
232  }
233  }
234  }
235 
236  /*
237  Register I/O port
238  */
239  sprintf(&a->port_name[0], "DIVA 4BRI %ld", (long) a->xdi_adapter.serialNo);
240 
241  if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1],
242  bar_length[1], &a->port_name[0], 1)) {
243  DBG_ERR(("A: 4BRI: can't register bar[1]"))
244  diva_4bri_cleanup_adapter(a);
245  return (-1);
246  }
247 
248  a->resources.pci.addr[1] =
249  (void *) (unsigned long) a->resources.pci.bar[1];
250 
251  /*
252  Set cleanup pointer for base adapter only, so slave adapter
253  will be unable to get cleanup
254  */
255  a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
256 
257  /*
258  Create slave adapters
259  */
260  if (tasks > 1) {
261  if (!(a->slave_adapters[0] =
262  (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
263  {
264  diva_4bri_cleanup_adapter(a);
265  return (-1);
266  }
267  if (!(a->slave_adapters[1] =
268  (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
269  {
270  diva_os_free(0, a->slave_adapters[0]);
271  a->slave_adapters[0] = NULL;
272  diva_4bri_cleanup_adapter(a);
273  return (-1);
274  }
275  if (!(a->slave_adapters[2] =
276  (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
277  {
278  diva_os_free(0, a->slave_adapters[0]);
279  diva_os_free(0, a->slave_adapters[1]);
280  a->slave_adapters[0] = NULL;
281  a->slave_adapters[1] = NULL;
282  diva_4bri_cleanup_adapter(a);
283  return (-1);
284  }
285  memset(a->slave_adapters[0], 0x00, sizeof(*a));
286  memset(a->slave_adapters[1], 0x00, sizeof(*a));
287  memset(a->slave_adapters[2], 0x00, sizeof(*a));
288  }
289 
290  adapter_list[0] = a;
291  adapter_list[1] = a->slave_adapters[0];
292  adapter_list[2] = a->slave_adapters[1];
293  adapter_list[3] = a->slave_adapters[2];
294 
295  /*
296  Allocate slave list
297  */
298  quadro_list =
299  (PADAPTER_LIST_ENTRY) diva_os_malloc(0, sizeof(*quadro_list));
300  if (!(a->slave_list = quadro_list)) {
301  for (i = 0; i < (tasks - 1); i++) {
302  diva_os_free(0, a->slave_adapters[i]);
303  a->slave_adapters[i] = NULL;
304  }
305  diva_4bri_cleanup_adapter(a);
306  return (-1);
307  }
308  memset(quadro_list, 0x00, sizeof(*quadro_list));
309 
310  /*
311  Set interfaces
312  */
313  a->xdi_adapter.QuadroList = quadro_list;
314  for (i = 0; i < tasks; i++) {
315  adapter_list[i]->xdi_adapter.ControllerNumber = i;
316  adapter_list[i]->xdi_adapter.tasks = tasks;
317  quadro_list->QuadroAdapter[i] =
318  &adapter_list[i]->xdi_adapter;
319  }
320 
321  for (i = 0; i < tasks; i++) {
322  diva_current = adapter_list[i];
323 
324  diva_current->dsp_mask = 0x00000003;
325 
326  diva_current->xdi_adapter.a.io =
327  &diva_current->xdi_adapter;
328  diva_current->xdi_adapter.DIRequest = request;
329  diva_current->interface.cmd_proc = diva_4bri_cmd_card_proc;
330  diva_current->xdi_adapter.Properties =
332  diva_current->CardOrdinal = a->CardOrdinal;
333 
334  diva_current->xdi_adapter.Channels =
336  diva_current->xdi_adapter.e_max =
338  diva_current->xdi_adapter.e_tbl =
339  diva_os_malloc(0,
340  diva_current->xdi_adapter.e_max *
341  sizeof(E_INFO));
342 
343  if (!diva_current->xdi_adapter.e_tbl) {
344  diva_4bri_cleanup_slave_adapters(a);
345  diva_4bri_cleanup_adapter(a);
346  for (i = 1; i < (tasks - 1); i++) {
347  diva_os_free(0, adapter_list[i]);
348  }
349  return (-1);
350  }
351  memset(diva_current->xdi_adapter.e_tbl, 0x00,
352  diva_current->xdi_adapter.e_max * sizeof(E_INFO));
353 
354  if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.isr_spin_lock, "isr")) {
355  diva_4bri_cleanup_slave_adapters(a);
356  diva_4bri_cleanup_adapter(a);
357  for (i = 1; i < (tasks - 1); i++) {
358  diva_os_free(0, adapter_list[i]);
359  }
360  return (-1);
361  }
362  if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.data_spin_lock, "data")) {
363  diva_4bri_cleanup_slave_adapters(a);
364  diva_4bri_cleanup_adapter(a);
365  for (i = 1; i < (tasks - 1); i++) {
366  diva_os_free(0, adapter_list[i]);
367  }
368  return (-1);
369  }
370 
371  strcpy(diva_current->xdi_adapter.req_soft_isr. dpc_thread_name, "kdivas4brid");
372 
374  &diva_current->xdi_adapter)) {
375  diva_4bri_cleanup_slave_adapters(a);
376  diva_4bri_cleanup_adapter(a);
377  for (i = 1; i < (tasks - 1); i++) {
378  diva_os_free(0, adapter_list[i]);
379  }
380  return (-1);
381  }
382 
383  /*
384  Do not initialize second DPC - only one thread will be created
385  */
386  diva_current->xdi_adapter.isr_soft_isr.object =
387  diva_current->xdi_adapter.req_soft_isr.object;
388  }
389 
390  if (v2) {
392  } else {
394  }
395 
396  for (i = 0; i < tasks; i++) {
397  diva_current = adapter_list[i];
398  if (i)
399  memcpy(&diva_current->resources, &a->resources, sizeof(divas_card_resources_t));
400  diva_current->resources.pci.qoffset = (a->xdi_adapter.MemorySize >> factor);
401  }
402 
403  /*
404  Set up hardware related pointers
405  */
406  a->xdi_adapter.cfg = (void *) (unsigned long) a->resources.pci.bar[0]; /* BAR0 CONFIG */
407  a->xdi_adapter.port = (void *) (unsigned long) a->resources.pci.bar[1]; /* BAR1 */
408  a->xdi_adapter.ctlReg = (void *) (unsigned long) a->resources.pci.bar[3]; /* BAR3 CNTRL */
409 
410  for (i = 0; i < tasks; i++) {
411  diva_current = adapter_list[i];
412  diva_4bri_set_addresses(diva_current);
413  Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
414  Slave->MultiMaster = &a->xdi_adapter;
415  Slave->sdram_bar = a->xdi_adapter.sdram_bar;
416  if (i) {
417  Slave->serialNo = ((dword) (Slave->ControllerNumber << 24)) |
419  Slave->cardType = a->xdi_adapter.cardType;
420  }
421  }
422 
423  /*
424  reset contains the base address for the PLX 9054 register set
425  */
427  WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */
429 
430  /*
431  Set IRQ handler
432  */
434  sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA 4BRI %ld",
435  (long) a->xdi_adapter.serialNo);
436 
439  diva_4bri_cleanup_slave_adapters(a);
440  diva_4bri_cleanup_adapter(a);
441  for (i = 1; i < (tasks - 1); i++) {
442  diva_os_free(0, adapter_list[i]);
443  }
444  return (-1);
445  }
446 
448 
449  /*
450  Add three slave adapters
451  */
452  if (tasks > 1) {
453  diva_add_slave_adapter(adapter_list[1]);
454  diva_add_slave_adapter(adapter_list[2]);
455  diva_add_slave_adapter(adapter_list[3]);
456  }
457 
458  diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
460 
461  return (0);
462 }
463 
464 /*
465 ** Cleanup function will be called for master adapter only
466 ** this is guaranteed by design: cleanup callback is set
467 ** by master adapter only
468 */
469 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
470 {
471  int bar;
472 
473  /*
474  Stop adapter if running
475  */
476  if (a->xdi_adapter.Initialized) {
477  diva_4bri_stop_adapter(a);
478  }
479 
480  /*
481  Remove IRQ handler
482  */
485  }
487 
488  /*
489  Free DPC's and spin locks on all adapters
490  */
491  diva_4bri_cleanup_slave_adapters(a);
492 
493  /*
494  Unmap all BARS
495  */
496  for (bar = 0; bar < 4; bar++) {
497  if (bar != 1) {
498  if (a->resources.pci.bar[bar]
499  && a->resources.pci.addr[bar]) {
501  a->resources.pci.bar[bar] = 0;
502  a->resources.pci.addr[bar] = NULL;
503  }
504  }
505  }
506 
507  /*
508  Unregister I/O
509  */
510  if (a->resources.pci.bar[1] && a->resources.pci.addr[1]) {
512  _4bri_is_rev_2_card(a->
513  CardOrdinal) ?
514  _4bri_v2_bar_length[1] :
515  _4bri_bar_length[1],
516  &a->port_name[0], 1);
517  a->resources.pci.bar[1] = 0;
518  a->resources.pci.addr[1] = NULL;
519  }
520 
521  if (a->slave_list) {
522  diva_os_free(0, a->slave_list);
523  a->slave_list = NULL;
524  }
525 
526  return (0);
527 }
528 
529 static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a)
530 {
531  dword data[64];
532  dword serNo;
533  word addr, status, i, j;
534  byte Bus, Slot;
535  void *hdev;
536 
537  Bus = a->resources.pci.bus;
538  Slot = a->resources.pci.func;
539  hdev = a->resources.pci.hdev;
540 
541  for (i = 0; i < 64; ++i) {
542  addr = i * 4;
543  for (j = 0; j < 5; ++j) {
544  PCIwrite(Bus, Slot, 0x4E, &addr, sizeof(addr),
545  hdev);
546  diva_os_wait(1);
547  PCIread(Bus, Slot, 0x4E, &status, sizeof(status),
548  hdev);
549  if (status & 0x8000)
550  break;
551  }
552  if (j >= 5) {
553  DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr))
554  return (0);
555  }
556  PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
557  }
558  DBG_BLK(((char *) &data[0], sizeof(data)))
559 
560  serNo = data[32];
561  if (serNo == 0 || serNo == 0xffffffff)
562  serNo = data[63];
563 
564  if (!serNo) {
565  DBG_LOG(("W: Serial Number == 0, create one serial number"));
566  serNo = a->resources.pci.bar[1] & 0xffff0000;
567  serNo |= a->resources.pci.bus << 8;
568  serNo |= a->resources.pci.func;
569  }
570 
571  a->xdi_adapter.serialNo = serNo;
572 
573  DBG_REG(("Serial No. : %ld", a->xdi_adapter.serialNo))
574 
575  return (serNo);
576 }
577 
578 /*
579 ** Release resources of slave adapters
580 */
581 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a)
582 {
583  diva_os_xdi_adapter_t *adapter_list[4];
584  diva_os_xdi_adapter_t *diva_current;
585  int i;
586 
587  adapter_list[0] = a;
588  adapter_list[1] = a->slave_adapters[0];
589  adapter_list[2] = a->slave_adapters[1];
590  adapter_list[3] = a->slave_adapters[2];
591 
592  for (i = 0; i < a->xdi_adapter.tasks; i++) {
593  diva_current = adapter_list[i];
594  if (diva_current) {
595  diva_os_destroy_spin_lock(&diva_current->
596  xdi_adapter.
597  isr_spin_lock, "unload");
598  diva_os_destroy_spin_lock(&diva_current->
599  xdi_adapter.
600  data_spin_lock,
601  "unload");
602 
603  diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
604  req_soft_isr);
605  diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
606  isr_soft_isr);
607 
608  diva_os_remove_soft_isr(&diva_current->xdi_adapter.
609  req_soft_isr);
610  diva_current->xdi_adapter.isr_soft_isr.object = NULL;
611 
612  if (diva_current->xdi_adapter.e_tbl) {
613  diva_os_free(0,
614  diva_current->xdi_adapter.
615  e_tbl);
616  }
617  diva_current->xdi_adapter.e_tbl = NULL;
618  diva_current->xdi_adapter.e_max = 0;
619  diva_current->xdi_adapter.e_count = 0;
620  }
621  }
622 
623  return (0);
624 }
625 
626 static int
627 diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
629 {
630  int ret = -1;
631 
632  if (cmd->adapter != a->controller) {
633  DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d",
634  cmd->adapter, a->controller))
635  return (-1);
636  }
637 
638  switch (cmd->command) {
640  a->xdi_mbox.data_length = sizeof(dword);
641  a->xdi_mbox.data =
642  diva_os_malloc(0, a->xdi_mbox.data_length);
643  if (a->xdi_mbox.data) {
644  *(dword *) a->xdi_mbox.data =
645  (dword) a->CardOrdinal;
647  ret = 0;
648  }
649  break;
650 
652  a->xdi_mbox.data_length = sizeof(dword);
653  a->xdi_mbox.data =
654  diva_os_malloc(0, a->xdi_mbox.data_length);
655  if (a->xdi_mbox.data) {
656  *(dword *) a->xdi_mbox.data =
659  ret = 0;
660  }
661  break;
662 
664  if (!a->xdi_adapter.ControllerNumber) {
665  /*
666  Only master adapter can access hardware config
667  */
668  a->xdi_mbox.data_length = sizeof(dword) * 9;
669  a->xdi_mbox.data =
670  diva_os_malloc(0, a->xdi_mbox.data_length);
671  if (a->xdi_mbox.data) {
672  int i;
673  dword *data = (dword *) a->xdi_mbox.data;
674 
675  for (i = 0; i < 8; i++) {
676  *data++ = a->resources.pci.bar[i];
677  }
678  *data++ = (dword) a->resources.pci.irq;
680  ret = 0;
681  }
682  }
683  break;
684 
686  if (!a->xdi_adapter.ControllerNumber) {
687  a->xdi_mbox.data_length = sizeof(dword);
688  a->xdi_mbox.data =
689  diva_os_malloc(0, a->xdi_mbox.data_length);
690  if (a->xdi_mbox.data) {
691  dword *data = (dword *) a->xdi_mbox.data;
692  if (!a->xdi_adapter.ram
693  || !a->xdi_adapter.reset
694  || !a->xdi_adapter.cfg) {
695  *data = 3;
696  } else if (a->xdi_adapter.trapped) {
697  *data = 2;
698  } else if (a->xdi_adapter.Initialized) {
699  *data = 1;
700  } else {
701  *data = 0;
702  }
704  ret = 0;
705  }
706  }
707  break;
708 
710  if (!a->xdi_adapter.ControllerNumber) {
711  ret =
712  diva_4bri_write_fpga_image(a,
713  (byte *)&cmd[1],
714  cmd->command_data.
715  write_fpga.
716  image_length);
717  }
718  break;
719 
721  if (!a->xdi_adapter.ControllerNumber) {
722  ret = diva_4bri_reset_adapter(&a->xdi_adapter);
723  }
724  break;
725 
727  if (!a->xdi_adapter.ControllerNumber) {
728  ret = diva_4bri_write_sdram_block(&a->xdi_adapter,
729  cmd->
730  command_data.
731  write_sdram.
732  offset,
733  (byte *) &
734  cmd[1],
735  cmd->
736  command_data.
737  write_sdram.
738  length,
739  a->xdi_adapter.
740  MemorySize);
741  }
742  break;
743 
745  if (!a->xdi_adapter.ControllerNumber) {
746  ret = diva_4bri_start_adapter(&a->xdi_adapter,
747  cmd->command_data.
748  start.offset,
749  cmd->command_data.
750  start.features);
751  }
752  break;
753 
755  if (!a->xdi_adapter.ControllerNumber) {
756  a->xdi_adapter.features =
760  DBG_TRC(("Set raw protocol features (%08x)",
761  a->xdi_adapter.features))
762  ret = 0;
763  }
764  break;
765 
767  if (!a->xdi_adapter.ControllerNumber) {
768  ret = diva_4bri_stop_adapter(a);
769  }
770  break;
771 
773  ret = diva_card_read_xlog(a);
774  break;
775 
778  && a->xdi_adapter.Address) {
779  if (
780  (a->xdi_mbox.data_length =
782  if (
783  (a->xdi_mbox.data_length +
785  a->xdi_adapter.MemorySize) {
786  a->xdi_mbox.data =
787  diva_os_malloc(0,
788  a->xdi_mbox.
789  data_length);
790  if (a->xdi_mbox.data) {
792  byte __iomem *src = p;
793  byte *dst = a->xdi_mbox.data;
795 
796  src += cmd->command_data.read_sdram.offset;
797 
798  while (len--) {
799  *dst++ = READ_BYTE(src++);
800  }
803  ret = 0;
804  }
805  }
806  }
807  }
808  break;
809 
810  default:
811  DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
812  cmd->command))
813  }
814 
815  return (ret);
816 }
817 
819  unsigned long lim)
820 {
821  void *ret = diva_xdiLoadFileFile;
822 
823  if (FileLength) {
824  *FileLength = diva_xdiLoadFileLength;
825  }
826  diva_xdiLoadFileFile = NULL;
827  diva_xdiLoadFileLength = 0;
828 
829  return (ret);
830 }
831 
833 {
834 }
835 
837 {
838 }
839 
840 static int
841 diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a, byte *data,
842  dword length)
843 {
844  int ret;
845 
846  diva_xdiLoadFileFile = data;
847  diva_xdiLoadFileLength = length;
848 
849  ret = qBri_FPGA_download(&a->xdi_adapter);
850 
851  diva_xdiLoadFileFile = NULL;
852  diva_xdiLoadFileLength = 0;
853 
854  return (ret ? 0 : -1);
855 }
856 
857 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)
858 {
859  PISDN_ADAPTER Slave;
860  int i;
861 
862  if (!IoAdapter->Address || !IoAdapter->reset) {
863  return (-1);
864  }
865  if (IoAdapter->Initialized) {
866  DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first",
867  IoAdapter->ANum))
868  return (-1);
869  }
870 
871  /*
872  Forget all entities on all adapters
873  */
874  for (i = 0; ((i < IoAdapter->tasks) && IoAdapter->QuadroList); i++) {
875  Slave = IoAdapter->QuadroList->QuadroAdapter[i];
876  Slave->e_count = 0;
877  if (Slave->e_tbl) {
878  memset(Slave->e_tbl, 0x00,
879  Slave->e_max * sizeof(E_INFO));
880  }
881  Slave->head = 0;
882  Slave->tail = 0;
883  Slave->assign = 0;
884  Slave->trapped = 0;
885 
886  memset(&Slave->a.IdTable[0], 0x00,
887  sizeof(Slave->a.IdTable));
888  memset(&Slave->a.IdTypeTable[0], 0x00,
889  sizeof(Slave->a.IdTypeTable));
890  memset(&Slave->a.FlowControlIdTable[0], 0x00,
891  sizeof(Slave->a.FlowControlIdTable));
892  memset(&Slave->a.FlowControlSkipTable[0], 0x00,
893  sizeof(Slave->a.FlowControlSkipTable));
894  memset(&Slave->a.misc_flags_table[0], 0x00,
895  sizeof(Slave->a.misc_flags_table));
896  memset(&Slave->a.rx_stream[0], 0x00,
897  sizeof(Slave->a.rx_stream));
898  memset(&Slave->a.tx_stream[0], 0x00,
899  sizeof(Slave->a.tx_stream));
900  memset(&Slave->a.tx_pos[0], 0x00, sizeof(Slave->a.tx_pos));
901  memset(&Slave->a.rx_pos[0], 0x00, sizeof(Slave->a.rx_pos));
902  }
903 
904  return (0);
905 }
906 
907 
908 static int
909 diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
910  dword address,
911  const byte *data, dword length, dword limit)
912 {
914  byte __iomem *mem = p;
915 
916  if (((address + length) >= limit) || !mem) {
917  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
918  DBG_ERR(("A: A(%d) write 4BRI address=0x%08lx",
919  IoAdapter->ANum, address + length))
920  return (-1);
921  }
922  mem += address;
923 
924  while (length--) {
925  WRITE_BYTE(mem++, *data++);
926  }
927 
928  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
929  return (0);
930 }
931 
932 static int
933 diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
934  dword start_address, dword features)
935 {
936  volatile word __iomem *signature;
937  int started = 0;
938  int i;
939  byte __iomem *p;
940 
941  /*
942  start adapter
943  */
944  start_qBri_hardware(IoAdapter);
945 
946  p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
947  /*
948  wait for signature in shared memory (max. 3 seconds)
949  */
950  signature = (volatile word __iomem *) (&p[0x1E]);
951 
952  for (i = 0; i < 300; ++i) {
953  diva_os_wait(10);
954  if (READ_WORD(&signature[0]) == 0x4447) {
955  DBG_TRC(("Protocol startup time %d.%02d seconds",
956  (i / 100), (i % 100)))
957  started = 1;
958  break;
959  }
960  }
961 
962  for (i = 1; i < IoAdapter->tasks; i++) {
963  IoAdapter->QuadroList->QuadroAdapter[i]->features =
964  IoAdapter->features;
965  IoAdapter->QuadroList->QuadroAdapter[i]->a.
966  protocol_capabilities = IoAdapter->features;
967  }
968 
969  if (!started) {
970  DBG_FTL(("%s: Adapter selftest failed, signature=%04x",
971  IoAdapter->Properties.Name,
972  READ_WORD(&signature[0])))
973  DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
974  (*(IoAdapter->trapFnc)) (IoAdapter);
975  IoAdapter->stop(IoAdapter);
976  return (-1);
977  }
978  DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
979 
980  for (i = 0; i < IoAdapter->tasks; i++) {
981  IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1;
982  IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0;
983  }
984 
985  if (check_qBri_interrupt(IoAdapter)) {
986  DBG_ERR(("A: A(%d) interrupt test failed",
987  IoAdapter->ANum))
988  for (i = 0; i < IoAdapter->tasks; i++) {
989  IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
990  }
991  IoAdapter->stop(IoAdapter);
992  return (-1);
993  }
994 
995  IoAdapter->Properties.Features = (word) features;
997 
998  for (i = 0; i < IoAdapter->tasks; i++) {
999  DBG_LOG(("A(%d) %s adapter successfully started",
1000  IoAdapter->QuadroList->QuadroAdapter[i]->ANum,
1001  (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI"))
1002  diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1003  IoAdapter->QuadroList->QuadroAdapter[i]->Properties.Features = (word) features;
1004  }
1005 
1006  return (0);
1007 }
1008 
1009 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter)
1010 {
1011 #ifdef SUPPORT_INTERRUPT_TEST_ON_4BRI
1012  int i;
1013  ADAPTER *a = &IoAdapter->a;
1014  byte __iomem *p;
1015 
1016  IoAdapter->IrqCount = 0;
1017 
1018  if (IoAdapter->ControllerNumber > 0)
1019  return (-1);
1020 
1021  p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
1023  DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
1024  /*
1025  interrupt test
1026  */
1027  a->ReadyInt = 1;
1028  a->ram_out(a, &PR_RAM->ReadyInt, 1);
1029 
1030  for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
1031 
1032  return ((IoAdapter->IrqCount > 0) ? 0 : -1);
1033 #else
1034  dword volatile __iomem *qBriIrq;
1035  byte __iomem *p;
1036  /*
1037  Reset on-board interrupt register
1038  */
1039  IoAdapter->IrqCount = 0;
1040  p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
1041  qBriIrq = (dword volatile __iomem *) (&p[_4bri_is_rev_2_card
1042  (IoAdapter->
1043  cardType) ? (MQ2_BREG_IRQ_TEST)
1044  : (MQ_BREG_IRQ_TEST)]);
1045 
1046  WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
1047  DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
1048 
1049  p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
1051  DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
1052 
1053  diva_os_wait(100);
1054 
1055  return (0);
1056 #endif /* SUPPORT_INTERRUPT_TEST_ON_4BRI */
1057 }
1058 
1059 static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t *a)
1060 {
1061  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1062 
1063  /*
1064  clear any pending interrupt
1065  */
1066  IoAdapter->disIrq(IoAdapter);
1067 
1068  IoAdapter->tst_irq(&IoAdapter->a);
1069  IoAdapter->clr_irq(&IoAdapter->a);
1070  IoAdapter->tst_irq(&IoAdapter->a);
1071 
1072  /*
1073  kill pending dpcs
1074  */
1077 }
1078 
1079 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a)
1080 {
1081  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1082  int i;
1083 
1084  if (!IoAdapter->ram) {
1085  return (-1);
1086  }
1087 
1088  if (!IoAdapter->Initialized) {
1089  DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
1090  IoAdapter->ANum))
1091  return (-1); /* nothing to stop */
1092  }
1093 
1094  for (i = 0; i < IoAdapter->tasks; i++) {
1095  IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
1096  }
1097 
1098  /*
1099  Disconnect Adapters from DIDD
1100  */
1101  for (i = 0; i < IoAdapter->tasks; i++) {
1103  }
1104 
1105  i = 100;
1106 
1107  /*
1108  Stop interrupts
1109  */
1110  a->clear_interrupts_proc = diva_4bri_clear_interrupts;
1111  IoAdapter->a.ReadyInt = 1;
1112  IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
1113  do {
1114  diva_os_sleep(10);
1115  } while (i-- && a->clear_interrupts_proc);
1116 
1117  if (a->clear_interrupts_proc) {
1118  diva_4bri_clear_interrupts(a);
1120  DBG_ERR(("A: A(%d) no final interrupt from 4BRI adapter",
1121  IoAdapter->ANum))
1122  }
1123  IoAdapter->a.ReadyInt = 0;
1124 
1125  /*
1126  Stop and reset adapter
1127  */
1128  IoAdapter->stop(IoAdapter);
1129 
1130  return (0);
1131 }