Linux-2.6.12-rc2
[safe/jmp/linux-2.6] / drivers / isdn / hardware / eicon / os_4bri.c
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
20 static void *diva_xdiLoadFileFile = NULL;
21 static dword diva_xdiLoadFileLength = 0;
22
23 /*
24 **  IMPORTS
25 */
26 extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
27 extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
28 extern void diva_xdi_display_adapter_features(int card);
29 extern void diva_add_slave_adapter(diva_os_xdi_adapter_t * a);
30
31 extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
32 extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
33
34 extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a);
35
36 /*
37 **  LOCALS
38 */
39 static unsigned long _4bri_bar_length[4] = {
40         0x100,
41         0x100,                  /* I/O */
42         MQ_MEMORY_SIZE,
43         0x2000
44 };
45 static unsigned long _4bri_v2_bar_length[4] = {
46         0x100,
47         0x100,                  /* I/O */
48         MQ2_MEMORY_SIZE,
49         0x10000
50 };
51 static unsigned long _4bri_v2_bri_bar_length[4] = {
52         0x100,
53         0x100,                  /* I/O */
54         BRI2_MEMORY_SIZE,
55         0x10000
56 };
57
58
59 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a);
60 static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a);
61 static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
62                                    diva_xdi_um_cfg_cmd_t * cmd,
63                                    int length);
64 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a);
65 static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a,
66                                       byte * data, dword length);
67 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
68 static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
69                                        dword address,
70                                        const byte * data,
71                                        dword length, dword limit);
72 static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
73                                    dword start_address, dword features);
74 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
75 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a);
76
77 static int _4bri_is_rev_2_card(int card_ordinal)
78 {
79         switch (card_ordinal) {
80         case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
81         case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
82         case CARDTYPE_DIVASRV_B_2M_V2_PCI:
83         case CARDTYPE_DIVASRV_B_2F_PCI:
84         case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
85                 return (1);
86         }
87         return (0);
88 }
89
90 static int _4bri_is_rev_2_bri_card(int card_ordinal)
91 {
92         switch (card_ordinal) {
93         case CARDTYPE_DIVASRV_B_2M_V2_PCI:
94         case CARDTYPE_DIVASRV_B_2F_PCI:
95         case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
96                 return (1);
97         }
98         return (0);
99 }
100
101 static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a)
102 {
103         dword offset = a->resources.pci.qoffset;
104         dword c_offset = offset * a->xdi_adapter.ControllerNumber;
105
106         a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 2;
107         a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2;
108         a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2;
109         a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 0;
110         a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 3;
111         a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 0;
112
113         /*
114            Set up hardware related pointers
115          */
116         a->xdi_adapter.Address = a->resources.pci.addr[2];      /* BAR2 SDRAM  */
117         a->xdi_adapter.Address += c_offset;
118
119         a->xdi_adapter.Control = a->resources.pci.addr[2];      /* BAR2 SDRAM  */
120
121         a->xdi_adapter.ram = a->resources.pci.addr[2];  /* BAR2 SDRAM  */
122         a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE);
123         
124         a->xdi_adapter.reset = a->resources.pci.addr[0];        /* BAR0 CONFIG */
125         /*
126            ctlReg contains the register address for the MIPS CPU reset control
127          */
128         a->xdi_adapter.ctlReg = a->resources.pci.addr[3];       /* BAR3 CNTRL  */
129         /*
130            prom contains the register address for FPGA and EEPROM programming
131          */
132         a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
133 }
134
135 /*
136 **  BAR0 - MEM - 0x100    - CONFIG MEM
137 **  BAR1 - I/O - 0x100    - UNUSED
138 **  BAR2 - MEM - MQ_MEMORY_SIZE (MQ2_MEMORY_SIZE on Rev.2) - SDRAM
139 **  BAR3 - MEM - 0x2000 (0x10000 on Rev.2)   - CNTRL
140 **
141 **  Called by master adapter, that will initialize and add slave adapters
142 */
143 int diva_4bri_init_card(diva_os_xdi_adapter_t * a)
144 {
145         int bar, i;
146         byte __iomem *p;
147         PADAPTER_LIST_ENTRY quadro_list;
148         diva_os_xdi_adapter_t *diva_current;
149         diva_os_xdi_adapter_t *adapter_list[4];
150         PISDN_ADAPTER Slave;
151         unsigned long bar_length[sizeof(_4bri_bar_length) /
152                                  sizeof(_4bri_bar_length[0])];
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          */
186         a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
187         DBG_LOG(("Load %s, SN:%ld, bus:%02x, func:%02x",
188                  a->xdi_adapter.Properties.Name,
189                  a->xdi_adapter.serialNo,
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] =
198                     divasa_get_pci_bar(a->resources.pci.bus,
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 =
210             (byte) divasa_get_pci_irq(a->resources.pci.bus,
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
218         a->xdi_adapter.sdram_bar = a->resources.pci.bar[2];
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 =
331                     CardProperties[a->CardOrdinal];
332                 diva_current->CardOrdinal = a->CardOrdinal;
333
334                 diva_current->xdi_adapter.Channels =
335                     CardProperties[a->CardOrdinal].Channels;
336                 diva_current->xdi_adapter.e_max =
337                     CardProperties[a->CardOrdinal].E_info;
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
373                 if (diva_os_initialize_soft_isr (&diva_current->xdi_adapter.req_soft_isr, DIDpcRoutine,
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) {
391                 prepare_qBri2_functions(&a->xdi_adapter);
392         } else {
393                 prepare_qBri_functions(&a->xdi_adapter);
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)) |
418                                         a->xdi_adapter.serialNo;
419                         Slave->cardType = a->xdi_adapter.cardType;
420                 }
421         }
422
423         /*
424            reset contains the base address for the PLX 9054 register set
425          */
426         p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
427         WRITE_BYTE(&p[PLX9054_INTCSR], 0x00);   /* disable PCI interrupts */
428         DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
429
430         /*
431            Set IRQ handler
432          */
433         a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
434         sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA 4BRI %ld",
435                 (long) a->xdi_adapter.serialNo);
436
437         if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
438                                  a->xdi_adapter.irq_info.irq_name)) {
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
447         a->xdi_adapter.irq_info.registered = 1;
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,
459                       a->resources.pci.irq, a->xdi_adapter.serialNo);
460
461         return (0);
462 }
463
464 /*
465 **  Cleanup function will be called for master adapter only
466 **  this is garanteed 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          */
483         if (a->xdi_adapter.irq_info.registered) {
484                 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
485         }
486         a->xdi_adapter.irq_info.registered = 0;
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]) {
500                                 divasa_unmap_pci_bar(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]) {
511                 diva_os_register_io_port(a, 0, a->resources.pci.bar[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,
628                         diva_xdi_um_cfg_cmd_t * cmd, int length)
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) {
639         case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
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;
646                         a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
647                         ret = 0;
648                 }
649                 break;
650
651         case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
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 =
657                             (dword) a->xdi_adapter.serialNo;
658                         a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
659                         ret = 0;
660                 }
661                 break;
662
663         case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
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;
679                                 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
680                                 ret = 0;
681                         }
682                 }
683                 break;
684
685         case DIVA_XDI_UM_CMD_GET_CARD_STATE:
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                                 }
703                                 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
704                                 ret = 0;
705                         }
706                 }
707                 break;
708
709         case DIVA_XDI_UM_CMD_WRITE_FPGA:
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
720         case DIVA_XDI_UM_CMD_RESET_ADAPTER:
721                 if (!a->xdi_adapter.ControllerNumber) {
722                         ret = diva_4bri_reset_adapter(&a->xdi_adapter);
723                 }
724                 break;
725
726         case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
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
744         case DIVA_XDI_UM_CMD_START_ADAPTER:
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
754         case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
755                 if (!a->xdi_adapter.ControllerNumber) {
756                         a->xdi_adapter.features =
757                             cmd->command_data.features.features;
758                         a->xdi_adapter.a.protocol_capabilities =
759                             a->xdi_adapter.features;
760                         DBG_TRC(("Set raw protocol features (%08x)",
761                                  a->xdi_adapter.features))
762                         ret = 0;
763                 }
764                 break;
765
766         case DIVA_XDI_UM_CMD_STOP_ADAPTER:
767                 if (!a->xdi_adapter.ControllerNumber) {
768                         ret = diva_4bri_stop_adapter(a);
769                 }
770                 break;
771
772         case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
773                 ret = diva_card_read_xlog(a);
774                 break;
775
776         case DIVA_XDI_UM_CMD_READ_SDRAM:
777                 if (!a->xdi_adapter.ControllerNumber
778                     && a->xdi_adapter.Address) {
779                         if (
780                             (a->xdi_mbox.data_length =
781                              cmd->command_data.read_sdram.length)) {
782                                 if (
783                                     (a->xdi_mbox.data_length +
784                                      cmd->command_data.read_sdram.offset) <
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) {
791                                                 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter);
792                                                 byte __iomem *src = p;
793                                                 byte *dst = a->xdi_mbox.data;
794                                                 dword len = a->xdi_mbox.data_length;
795
796                                                 src += cmd->command_data.read_sdram.offset;
797
798                                                 while (len--) {
799                                                         *dst++ = READ_BYTE(src++);
800                                                 }
801                                                 DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p);
802                                                 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
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
818 void *xdiLoadFile(char *FileName, unsigned long *FileLength,
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
832 void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
833 {
834 }
835
836 void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
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 {
913         byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
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;
996         diva_xdi_display_adapter_features(IoAdapter->ANum);
997
998         for (i = 0; i < IoAdapter->tasks; i++) {
999                 DBG_LOG(("A(%d) %s adapter successfull 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);
1022         WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE);
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);
1050         WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE);
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          */
1075         diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
1076         diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
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++) {
1102                 diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
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);
1119                 a->clear_interrupts_proc = NULL;
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 }