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