Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os_pri.c
Go to the documentation of this file.
1 /* $Id: os_pri.c,v 1.32 2004/03/21 17:26:01 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_pri.h"
16 #include "diva_pci.h"
17 #include "mi_pc.h"
18 #include "pc_maint.h"
19 #include "dsp_tst.h"
20 #include "diva_dma.h"
21 #include "dsrv_pri.h"
22 
23 /* --------------------------------------------------------------------------
24  OS Dependent part of XDI driver for DIVA PRI Adapter
25 
26  DSP detection/validation by Anthony Booth (Eicon Networks, www.eicon.com)
27  -------------------------------------------------------------------------- */
28 
29 #define DIVA_PRI_NO_PCI_BIOS_WORKAROUND 1
30 
32 
33 /*
34 ** IMPORTS
35 */
36 extern void prepare_pri_functions(PISDN_ADAPTER IoAdapter);
37 extern void prepare_pri2_functions(PISDN_ADAPTER IoAdapter);
39 
40 static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t *a);
41 static int diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
43 static int pri_get_serial_number(diva_os_xdi_adapter_t *a);
44 static int diva_pri_stop_adapter(diva_os_xdi_adapter_t *a);
45 static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t *a);
46 
47 /*
48 ** Check card revision
49 */
50 static int pri_is_rev_2_card(int card_ordinal)
51 {
52  switch (card_ordinal) {
55  return (1);
56  }
57  return (0);
58 }
59 
60 static void diva_pri_set_addresses(diva_os_xdi_adapter_t *a)
61 {
69 
72  a->xdi_adapter.Config = a->resources.pci.addr[4];
73 
74  a->xdi_adapter.ram = a->resources.pci.addr[0];
76 
77  a->xdi_adapter.reset = a->resources.pci.addr[2];
79 
80  a->xdi_adapter.cfg = a->resources.pci.addr[4];
82 
84 
85  a->xdi_adapter.prom = a->resources.pci.addr[3];
86 }
87 
88 /*
89 ** BAR0 - SDRAM, MP_MEMORY_SIZE, MP2_MEMORY_SIZE by Rev.2
90 ** BAR1 - DEVICES, 0x1000
91 ** BAR2 - CONTROL (REG), 0x2000
92 ** BAR3 - FLASH (REG), 0x8000
93 ** BAR4 - CONFIG (CFG), 0x1000
94 */
96 {
97  int bar = 0;
98  int pri_rev_2;
99  unsigned long bar_length[5] = {
101  0x1000,
102  0x2000,
103  0x8000,
104  0x1000
105  };
106 
107  pri_rev_2 = pri_is_rev_2_card(a->CardOrdinal);
108 
109  if (pri_rev_2) {
110  bar_length[0] = MP2_MEMORY_SIZE;
111  }
112  /*
113  Set properties
114  */
116  DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
117 
118  /*
119  First initialization step: get and check hardware resoures.
120  Do not map resources and do not acecess card at this step
121  */
122  for (bar = 0; bar < 5; bar++) {
123  a->resources.pci.bar[bar] =
125  a->resources.pci.func, bar,
126  a->resources.pci.hdev);
127  if (!a->resources.pci.bar[bar]
128  || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
129  DBG_ERR(("A: invalid bar[%d]=%08x", bar,
130  a->resources.pci.bar[bar]))
131  return (-1);
132  }
133  }
134  a->resources.pci.irq =
136  a->resources.pci.func,
137  a->resources.pci.hdev);
138  if (!a->resources.pci.irq) {
139  DBG_ERR(("A: invalid irq"));
140  return (-1);
141  }
142 
143  /*
144  Map all BAR's
145  */
146  for (bar = 0; bar < 5; bar++) {
147  a->resources.pci.addr[bar] =
148  divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar],
149  bar_length[bar]);
150  if (!a->resources.pci.addr[bar]) {
151  DBG_ERR(("A: A(%d), can't map bar[%d]",
152  a->controller, bar))
153  diva_pri_cleanup_adapter(a);
154  return (-1);
155  }
156  }
157 
158  /*
159  Set all memory areas
160  */
161  diva_pri_set_addresses(a);
162 
163  /*
164  Get Serial Number of this adapter
165  */
166  if (pri_get_serial_number(a)) {
167  dword serNo;
168  serNo = a->resources.pci.bar[1] & 0xffff0000;
169  serNo |= ((dword) a->resources.pci.bus) << 8;
170  serNo += (a->resources.pci.func + a->controller + 1);
171  a->xdi_adapter.serialNo = serNo & ~0xFF000000;
172  DBG_ERR(("A: A(%d) can't get Serial Number, generated serNo=%ld",
174  }
175 
176 
177  /*
178  Initialize os objects
179  */
180  if (diva_os_initialize_spin_lock(&a->xdi_adapter.isr_spin_lock, "isr")) {
181  diva_pri_cleanup_adapter(a);
182  return (-1);
183  }
184  if (diva_os_initialize_spin_lock
185  (&a->xdi_adapter.data_spin_lock, "data")) {
186  diva_pri_cleanup_adapter(a);
187  return (-1);
188  }
189 
191 
193  DIDpcRoutine, &a->xdi_adapter)) {
194  diva_pri_cleanup_adapter(a);
195  return (-1);
196  }
197 
198  /*
199  Do not initialize second DPC - only one thread will be created
200  */
203 
204  /*
205  Next step of card initialization:
206  set up all interface pointers
207  */
210 
211  a->xdi_adapter.e_tbl =
212  diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO));
213  if (!a->xdi_adapter.e_tbl) {
214  diva_pri_cleanup_adapter(a);
215  return (-1);
216  }
217  memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
218 
219  a->xdi_adapter.a.io = &a->xdi_adapter;
221  a->interface.cleanup_adapter_proc = diva_pri_cleanup_adapter;
222  a->interface.cmd_proc = diva_pri_cmd_card_proc;
223 
224  if (pri_rev_2) {
226  } else {
228  }
229 
230  a->dsp_mask = diva_pri_detect_dsps(a);
231 
232  /*
233  Allocate DMA map
234  */
235  if (pri_rev_2) {
237  (struct _diva_dma_map_entry **) &a->xdi_adapter.dma_map, 32);
238  }
239 
240  /*
241  Set IRQ handler
242  */
245  "DIVA PRI %ld", (long) a->xdi_adapter.serialNo);
246 
249  diva_pri_cleanup_adapter(a);
250  return (-1);
251  }
253 
254  diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
256 
257  return (0);
258 }
259 
260 static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t *a)
261 {
262  int bar = 0;
263 
264  /*
265  Stop Adapter if adapter is running
266  */
267  if (a->xdi_adapter.Initialized) {
268  diva_pri_stop_adapter(a);
269  }
270 
271  /*
272  Remove ISR Handler
273  */
276  }
278 
279  /*
280  Step 1: unmap all BAR's, if any was mapped
281  */
282  for (bar = 0; bar < 5; bar++) {
283  if (a->resources.pci.bar[bar]
284  && a->resources.pci.addr[bar]) {
286  a->resources.pci.bar[bar] = 0;
287  a->resources.pci.addr[bar] = NULL;
288  }
289  }
290 
291  /*
292  Free OS objects
293  */
296 
299 
302 
303  /*
304  Free memory accupied by XDI adapter
305  */
306  if (a->xdi_adapter.e_tbl) {
307  diva_os_free(0, a->xdi_adapter.e_tbl);
308  a->xdi_adapter.e_tbl = NULL;
309  }
310  a->xdi_adapter.Channels = 0;
311  a->xdi_adapter.e_max = 0;
312 
313 
314  /*
315  Free adapter DMA map
316  */
318  (struct _diva_dma_map_entry *) a->xdi_adapter.
319  dma_map);
320  a->xdi_adapter.dma_map = NULL;
321 
322 
323  /*
324  Detach this adapter from debug driver
325  */
326 
327  return (0);
328 }
329 
330 /*
331 ** Activate On Board Boot Loader
332 */
333 static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter)
334 {
335  dword i;
336  struct mp_load __iomem *boot;
337 
338  if (!IoAdapter->Address || !IoAdapter->reset) {
339  return (-1);
340  }
341  if (IoAdapter->Initialized) {
342  DBG_ERR(("A: A(%d) can't reset PRI adapter - please stop first",
343  IoAdapter->ANum))
344  return (-1);
345  }
346 
347  boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
348  WRITE_DWORD(&boot->err, 0);
349  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
350 
351  IoAdapter->rstFnc(IoAdapter);
352 
353  diva_os_wait(10);
354 
355  boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
356  i = READ_DWORD(&boot->live);
357 
358  diva_os_wait(10);
359  if (i == READ_DWORD(&boot->live)) {
360  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
361  DBG_ERR(("A: A(%d) CPU on PRI %ld is not alive!",
362  IoAdapter->ANum, IoAdapter->serialNo))
363  return (-1);
364  }
365  if (READ_DWORD(&boot->err)) {
366  DBG_ERR(("A: A(%d) PRI %ld Board Selftest failed, error=%08lx",
367  IoAdapter->ANum, IoAdapter->serialNo,
368  READ_DWORD(&boot->err)))
369  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
370  return (-1);
371  }
372  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
373 
374  /*
375  Forget all outstanding entities
376  */
377  IoAdapter->e_count = 0;
378  if (IoAdapter->e_tbl) {
379  memset(IoAdapter->e_tbl, 0x00,
380  IoAdapter->e_max * sizeof(E_INFO));
381  }
382  IoAdapter->head = 0;
383  IoAdapter->tail = 0;
384  IoAdapter->assign = 0;
385  IoAdapter->trapped = 0;
386 
387  memset(&IoAdapter->a.IdTable[0], 0x00,
388  sizeof(IoAdapter->a.IdTable));
389  memset(&IoAdapter->a.IdTypeTable[0], 0x00,
390  sizeof(IoAdapter->a.IdTypeTable));
391  memset(&IoAdapter->a.FlowControlIdTable[0], 0x00,
392  sizeof(IoAdapter->a.FlowControlIdTable));
393  memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00,
394  sizeof(IoAdapter->a.FlowControlSkipTable));
395  memset(&IoAdapter->a.misc_flags_table[0], 0x00,
396  sizeof(IoAdapter->a.misc_flags_table));
397  memset(&IoAdapter->a.rx_stream[0], 0x00,
398  sizeof(IoAdapter->a.rx_stream));
399  memset(&IoAdapter->a.tx_stream[0], 0x00,
400  sizeof(IoAdapter->a.tx_stream));
401  memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos));
402  memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos));
403 
404  return (0);
405 }
406 
407 static int
408 diva_pri_write_sdram_block(PISDN_ADAPTER IoAdapter,
409  dword address,
410  const byte *data, dword length, dword limit)
411 {
413  byte __iomem *mem = p;
414 
415  if (((address + length) >= limit) || !mem) {
416  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
417  DBG_ERR(("A: A(%d) write PRI address=0x%08lx",
418  IoAdapter->ANum, address + length))
419  return (-1);
420  }
421  mem += address;
422 
423  /* memcpy_toio(), maybe? */
424  while (length--) {
425  WRITE_BYTE(mem++, *data++);
426  }
427 
428  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
429  return (0);
430 }
431 
432 static int
433 diva_pri_start_adapter(PISDN_ADAPTER IoAdapter,
434  dword start_address, dword features)
435 {
436  dword i;
437  int started = 0;
438  byte __iomem *p;
439  struct mp_load __iomem *boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
440  ADAPTER *a = &IoAdapter->a;
441 
442  if (IoAdapter->Initialized) {
443  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
444  DBG_ERR(("A: A(%d) pri_start_adapter, adapter already running",
445  IoAdapter->ANum))
446  return (-1);
447  }
448  if (!boot) {
449  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
450  DBG_ERR(("A: PRI %ld can't start, adapter not mapped",
451  IoAdapter->serialNo))
452  return (-1);
453  }
454 
455  sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum);
456  DBG_LOG(("A(%d) start PRI at 0x%08lx", IoAdapter->ANum,
457  start_address))
458 
459  WRITE_DWORD(&boot->addr, start_address);
460  WRITE_DWORD(&boot->cmd, 3);
461 
462  for (i = 0; i < 300; ++i) {
463  diva_os_wait(10);
464  if ((READ_DWORD(&boot->signature) >> 16) == 0x4447) {
465  DBG_LOG(("A(%d) Protocol startup time %d.%02d seconds",
466  IoAdapter->ANum, (i / 100), (i % 100)))
467  started = 1;
468  break;
469  }
470  }
471 
472  if (!started) {
473  byte __iomem *p = (byte __iomem *)boot;
474  dword TrapId;
475  dword debug;
476  TrapId = READ_DWORD(&p[0x80]);
477  debug = READ_DWORD(&p[0x1c]);
478  DBG_ERR(("A(%d) Adapter start failed 0x%08lx, TrapId=%08lx, debug=%08lx",
479  IoAdapter->ANum, READ_DWORD(&boot->signature),
480  TrapId, debug))
481  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
482  if (IoAdapter->trapFnc) {
483  (*(IoAdapter->trapFnc)) (IoAdapter);
484  }
485  IoAdapter->stop(IoAdapter);
486  return (-1);
487  }
488  DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
489 
490  IoAdapter->Initialized = true;
491 
492  /*
493  Check Interrupt
494  */
495  IoAdapter->IrqCount = 0;
496  p = DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
497  WRITE_DWORD(p, (dword)~0x03E00000);
498  DIVA_OS_MEM_DETACH_CFG(IoAdapter, p);
499  a->ReadyInt = 1;
500  a->ram_out(a, &PR_RAM->ReadyInt, 1);
501 
502  for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
503 
504  if (!IoAdapter->IrqCount) {
505  DBG_ERR(("A: A(%d) interrupt test failed",
506  IoAdapter->ANum))
507  IoAdapter->Initialized = false;
508  IoAdapter->stop(IoAdapter);
509  return (-1);
510  }
511 
512  IoAdapter->Properties.Features = (word) features;
513 
514  diva_xdi_display_adapter_features(IoAdapter->ANum);
515 
516  DBG_LOG(("A(%d) PRI adapter successfully started", IoAdapter->ANum))
517  /*
518  Register with DIDD
519  */
520  diva_xdi_didd_register_adapter(IoAdapter->ANum);
521 
522  return (0);
523 }
524 
525 static void diva_pri_clear_interrupts(diva_os_xdi_adapter_t *a)
526 {
527  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
528 
529  /*
530  clear any pending interrupt
531  */
532  IoAdapter->disIrq(IoAdapter);
533 
534  IoAdapter->tst_irq(&IoAdapter->a);
535  IoAdapter->clr_irq(&IoAdapter->a);
536  IoAdapter->tst_irq(&IoAdapter->a);
537 
538  /*
539  kill pending dpcs
540  */
543 }
544 
545 /*
546 ** Stop Adapter, but do not unmap/unregister - adapter
547 ** will be restarted later
548 */
549 static int diva_pri_stop_adapter(diva_os_xdi_adapter_t *a)
550 {
551  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
552  int i = 100;
553 
554  if (!IoAdapter->ram) {
555  return (-1);
556  }
557  if (!IoAdapter->Initialized) {
558  DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
559  IoAdapter->ANum))
560  return (-1); /* nothing to stop */
561  }
562  IoAdapter->Initialized = 0;
563 
564  /*
565  Disconnect Adapter from DIDD
566  */
567  diva_xdi_didd_remove_adapter(IoAdapter->ANum);
568 
569  /*
570  Stop interrupts
571  */
572  a->clear_interrupts_proc = diva_pri_clear_interrupts;
573  IoAdapter->a.ReadyInt = 1;
574  IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
575  do {
576  diva_os_sleep(10);
577  } while (i-- && a->clear_interrupts_proc);
578 
579  if (a->clear_interrupts_proc) {
580  diva_pri_clear_interrupts(a);
582  DBG_ERR(("A: A(%d) no final interrupt from PRI adapter",
583  IoAdapter->ANum))
584  }
585  IoAdapter->a.ReadyInt = 0;
586 
587  /*
588  Stop and reset adapter
589  */
590  IoAdapter->stop(IoAdapter);
591 
592  return (0);
593 }
594 
595 /*
596 ** Process commands form configuration/download framework and from
597 ** user mode
598 **
599 ** return 0 on success
600 */
601 static int
602 diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
603  diva_xdi_um_cfg_cmd_t *cmd, int length)
604 {
605  int ret = -1;
606 
607  if (cmd->adapter != a->controller) {
608  DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
609  cmd->adapter, a->controller))
610  return (-1);
611  }
612 
613  switch (cmd->command) {
615  a->xdi_mbox.data_length = sizeof(dword);
616  a->xdi_mbox.data =
617  diva_os_malloc(0, a->xdi_mbox.data_length);
618  if (a->xdi_mbox.data) {
619  *(dword *) a->xdi_mbox.data =
620  (dword) a->CardOrdinal;
622  ret = 0;
623  }
624  break;
625 
627  a->xdi_mbox.data_length = sizeof(dword);
628  a->xdi_mbox.data =
629  diva_os_malloc(0, a->xdi_mbox.data_length);
630  if (a->xdi_mbox.data) {
631  *(dword *) a->xdi_mbox.data =
634  ret = 0;
635  }
636  break;
637 
639  a->xdi_mbox.data_length = sizeof(dword) * 9;
640  a->xdi_mbox.data =
641  diva_os_malloc(0, a->xdi_mbox.data_length);
642  if (a->xdi_mbox.data) {
643  int i;
644  dword *data = (dword *) a->xdi_mbox.data;
645 
646  for (i = 0; i < 8; i++) {
647  *data++ = a->resources.pci.bar[i];
648  }
649  *data++ = (dword) a->resources.pci.irq;
651  ret = 0;
652  }
653  break;
654 
656  ret = diva_pri_reset_adapter(&a->xdi_adapter);
657  break;
658 
660  ret = diva_pri_write_sdram_block(&a->xdi_adapter,
661  cmd->command_data.
662  write_sdram.offset,
663  (byte *)&cmd[1],
664  cmd->command_data.
665  write_sdram.length,
666  pri_is_rev_2_card(a->
667  CardOrdinal)
668  ? MP2_MEMORY_SIZE :
670  break;
671 
673  ret = diva_pri_stop_adapter(a);
674  break;
675 
677  ret = diva_pri_start_adapter(&a->xdi_adapter,
678  cmd->command_data.start.
679  offset,
680  cmd->command_data.start.
681  features);
682  break;
683 
685  a->xdi_adapter.features =
689  DBG_TRC(("Set raw protocol features (%08x)",
690  a->xdi_adapter.features))
691  ret = 0;
692  break;
693 
695  a->xdi_mbox.data_length = sizeof(dword);
696  a->xdi_mbox.data =
697  diva_os_malloc(0, a->xdi_mbox.data_length);
698  if (a->xdi_mbox.data) {
699  dword *data = (dword *) a->xdi_mbox.data;
700  if (!a->xdi_adapter.ram ||
701  !a->xdi_adapter.reset ||
702  !a->xdi_adapter.cfg) {
703  *data = 3;
704  } else if (a->xdi_adapter.trapped) {
705  *data = 2;
706  } else if (a->xdi_adapter.Initialized) {
707  *data = 1;
708  } else {
709  *data = 0;
710  }
712  ret = 0;
713  }
714  break;
715 
717  ret = diva_card_read_xlog(a);
718  break;
719 
721  if (a->xdi_adapter.Address) {
722  if (
723  (a->xdi_mbox.data_length =
725  if (
726  (a->xdi_mbox.data_length +
728  a->xdi_adapter.MemorySize) {
729  a->xdi_mbox.data =
730  diva_os_malloc(0,
731  a->xdi_mbox.
732  data_length);
733  if (a->xdi_mbox.data) {
735  byte __iomem *src = p;
736  byte *dst = a->xdi_mbox.data;
737  dword len = a->xdi_mbox.data_length;
738 
739  src += cmd->command_data.read_sdram.offset;
740 
741  while (len--) {
742  *dst++ = READ_BYTE(src++);
743  }
746  ret = 0;
747  }
748  }
749  }
750  }
751  break;
752 
753  default:
754  DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
755  cmd->command))
756  }
757 
758  return (ret);
759 }
760 
761 /*
762 ** Get Serial Number
763 */
764 static int pri_get_serial_number(diva_os_xdi_adapter_t *a)
765 {
766  byte data[64];
767  int i;
768  dword len = sizeof(data);
769  volatile byte __iomem *config;
770  volatile byte __iomem *flash;
771  byte c;
772 
773 /*
774  * First set some GT6401x config registers before accessing the BOOT-ROM
775  */
777  c = READ_BYTE(&config[0xc3c]);
778  if (!(c & 0x08)) {
779  WRITE_BYTE(&config[0xc3c], c); /* Base Address enable register */
780  }
781  WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0x00);
782  WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF);
784 /*
785  * Read only the last 64 bytes of manufacturing data
786  */
787  memset(data, '\0', len);
789  for (i = 0; i < len; i++) {
790  data[i] = READ_BYTE(&flash[0x8000 - len + i]);
791  }
793 
795  WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0xFC); /* Disable FLASH EPROM access */
796  WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF);
798 
799  if (memcmp(&data[48], "DIVAserverPR", 12)) {
800 #if !defined(DIVA_PRI_NO_PCI_BIOS_WORKAROUND) /* { */
801  word cmd = 0, cmd_org;
802  void *addr;
803  dword addr1, addr3, addr4;
804  byte Bus, Slot;
805  void *hdev;
806  addr4 = a->resources.pci.bar[4];
807  addr3 = a->resources.pci.bar[3]; /* flash */
808  addr1 = a->resources.pci.bar[1]; /* unused */
809 
810  DBG_ERR(("A: apply Compaq BIOS workaround"))
811  DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
812  data[0], data[1], data[2], data[3],
813  data[4], data[5], data[6], data[7]))
814 
815  Bus = a->resources.pci.bus;
816  Slot = a->resources.pci.func;
817  hdev = a->resources.pci.hdev;
818  PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
819  PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
820 
821  PCIwrite(Bus, Slot, 0x14, &addr4, sizeof(addr4), hdev);
822  PCIwrite(Bus, Slot, 0x20, &addr1, sizeof(addr1), hdev);
823 
824  PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
825 
826  addr = a->resources.pci.addr[1];
827  a->resources.pci.addr[1] = a->resources.pci.addr[4];
828  a->resources.pci.addr[4] = addr;
829 
830  addr1 = a->resources.pci.bar[1];
831  a->resources.pci.bar[1] = a->resources.pci.bar[4];
832  a->resources.pci.bar[4] = addr1;
833 
834  /*
835  Try to read Flash again
836  */
837  len = sizeof(data);
838 
839  config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
840  if (!(config[0xc3c] & 0x08)) {
841  config[0xc3c] |= 0x08; /* Base Address enable register */
842  }
843  config[LOW_BOOTCS_DREG] = 0x00;
844  config[HI_BOOTCS_DREG] = 0xFF;
846 
847  memset(data, '\0', len);
849  for (i = 0; i < len; i++) {
850  data[i] = flash[0x8000 - len + i];
851  }
854  config[LOW_BOOTCS_DREG] = 0xFC;
855  config[HI_BOOTCS_DREG] = 0xFF;
857 
858  if (memcmp(&data[48], "DIVAserverPR", 12)) {
859  DBG_ERR(("A: failed to read serial number"))
860  DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
861  data[0], data[1], data[2], data[3],
862  data[4], data[5], data[6], data[7]))
863  return (-1);
864  }
865 #else /* } { */
866  DBG_ERR(("A: failed to read DIVA signature word"))
867  DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
868  data[0], data[1], data[2], data[3],
869  data[4], data[5], data[6], data[7]))
870  DBG_LOG(("%02x:%02x:%02x:%02x", data[47], data[46],
871  data[45], data[44]))
872 #endif /* } */
873  }
874 
875  a->xdi_adapter.serialNo =
876  (data[47] << 24) | (data[46] << 16) | (data[45] << 8) |
877  data[44];
878  if (!a->xdi_adapter.serialNo
879  || (a->xdi_adapter.serialNo == 0xffffffff)) {
880  a->xdi_adapter.serialNo = 0;
881  DBG_ERR(("A: failed to read serial number"))
882  return (-1);
883  }
884 
885  DBG_LOG(("Serial No. : %ld", a->xdi_adapter.serialNo))
886  DBG_TRC(("Board Revision : %d.%02d", (int) data[41],
887  (int) data[40]))
888  DBG_TRC(("PLD revision : %d.%02d", (int) data[33],
889  (int) data[32]))
890  DBG_TRC(("Boot loader version : %d.%02d", (int) data[37],
891  (int) data[36]))
892 
893  DBG_TRC(("Manufacturing Date : %d/%02d/%02d (yyyy/mm/dd)",
894  (int) ((data[28] > 90) ? 1900 : 2000) +
895  (int) data[28], (int) data[29], (int) data[30]))
896 
897  return (0);
898 }
899 
901 {
902 }
903 
905 {
906 }
907 
908 /*
909 ** Checks presence of DSP on board
910 */
911 static int
912 dsp_check_presence(volatile byte __iomem *addr, volatile byte __iomem *data, int dsp)
913 {
914  word pattern;
915 
916  WRITE_WORD(addr, 0x4000);
918 
919  WRITE_WORD(addr, 0x4000);
920  pattern = READ_WORD(data);
921 
922  if (pattern != DSP_SIGNATURE_PROBE_WORD) {
923  DBG_TRC(("W: DSP[%d] %04x(is) != %04x(should)",
924  dsp, pattern, DSP_SIGNATURE_PROBE_WORD))
925  return (-1);
926  }
927 
928  WRITE_WORD(addr, 0x4000);
930 
931  WRITE_WORD(addr, 0x4000);
932  pattern = READ_WORD(data);
933 
934  if (pattern != (word)~DSP_SIGNATURE_PROBE_WORD) {
935  DBG_ERR(("A: DSP[%d] %04x(is) != %04x(should)",
936  dsp, pattern, (word)~DSP_SIGNATURE_PROBE_WORD))
937  return (-2);
938  }
939 
940  DBG_TRC(("DSP[%d] present", dsp))
941 
942  return (0);
943 }
944 
945 
946 /*
947 ** Check if DSP's are present and operating
948 ** Information about detected DSP's is returned as bit mask
949 ** Bit 0 - DSP1
950 ** ...
951 ** ...
952 ** ...
953 ** Bit 29 - DSP30
954 */
955 static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t *a)
956 {
957  byte __iomem *base;
958  byte __iomem *p;
959  dword ret = 0;
960  dword row_offset[7] = {
961  0x00000000,
962  0x00000800, /* 1 - ROW 1 */
963  0x00000840, /* 2 - ROW 2 */
964  0x00001000, /* 3 - ROW 3 */
965  0x00001040, /* 4 - ROW 4 */
966  0x00000000 /* 5 - ROW 0 */
967  };
968 
969  byte __iomem *dsp_addr_port;
970  byte __iomem *dsp_data_port;
971  byte row_state;
972  int dsp_row = 0, dsp_index, dsp_num;
973 
974  if (!a->xdi_adapter.Control || !a->xdi_adapter.reset) {
975  return (0);
976  }
977 
978  p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
980  DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
981  diva_os_wait(5);
982 
983  base = DIVA_OS_MEM_ATTACH_CONTROL(&a->xdi_adapter);
984 
985  for (dsp_num = 0; dsp_num < 30; dsp_num++) {
986  dsp_row = dsp_num / 7 + 1;
987  dsp_index = dsp_num % 7;
988 
989  dsp_data_port = base;
990  dsp_addr_port = base;
991 
992  dsp_data_port += row_offset[dsp_row];
993  dsp_addr_port += row_offset[dsp_row];
994 
995  dsp_data_port += (dsp_index * 8);
996  dsp_addr_port += (dsp_index * 8) + 0x80;
997 
998  if (!dsp_check_presence
999  (dsp_addr_port, dsp_data_port, dsp_num + 1)) {
1000  ret |= (1 << dsp_num);
1001  }
1002  }
1003  DIVA_OS_MEM_DETACH_CONTROL(&a->xdi_adapter, base);
1004 
1005  p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
1007  DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
1008  diva_os_wait(5);
1009 
1010  /*
1011  Verify modules
1012  */
1013  for (dsp_row = 0; dsp_row < 4; dsp_row++) {
1014  row_state = ((ret >> (dsp_row * 7)) & 0x7F);
1015  if (row_state && (row_state != 0x7F)) {
1016  for (dsp_index = 0; dsp_index < 7; dsp_index++) {
1017  if (!(row_state & (1 << dsp_index))) {
1018  DBG_ERR(("A: MODULE[%d]-DSP[%d] failed",
1019  dsp_row + 1,
1020  dsp_index + 1))
1021  }
1022  }
1023  }
1024  }
1025 
1026  if (!(ret & 0x10000000)) {
1027  DBG_ERR(("A: ON BOARD-DSP[1] failed"))
1028  }
1029  if (!(ret & 0x20000000)) {
1030  DBG_ERR(("A: ON BOARD-DSP[2] failed"))
1031  }
1032 
1033  /*
1034  Print module population now
1035  */
1036  DBG_LOG(("+-----------------------+"))
1037  DBG_LOG(("| DSP MODULE POPULATION |"))
1038  DBG_LOG(("+-----------------------+"))
1039  DBG_LOG(("| 1 | 2 | 3 | 4 |"))
1040  DBG_LOG(("+-----------------------+"))
1041  DBG_LOG(("| %s | %s | %s | %s |",
1042  ((ret >> (0 * 7)) & 0x7F) ? "Y" : "N",
1043  ((ret >> (1 * 7)) & 0x7F) ? "Y" : "N",
1044  ((ret >> (2 * 7)) & 0x7F) ? "Y" : "N",
1045  ((ret >> (3 * 7)) & 0x7F) ? "Y" : "N"))
1046  DBG_LOG(("+-----------------------+"))
1047 
1048  DBG_LOG(("DSP's(present-absent):%08x-%08x", ret,
1049  ~ret & 0x3fffffff))
1050 
1051  return (ret);
1052 }