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