1 // SPDX-License-Identifier: GPL-2.0
2 /* $Id: os_4bri.c,v 1.28.4.4 2005/02/11 19:40:25 armin Exp $ */
3
4 #include "platform.h"
5 #include "debuglib.h"
6 #include "cardtype.h"
7 #include "pc.h"
8 #include "pr_pc.h"
9 #include "di_defs.h"
10 #include "dsp_defs.h"
11 #include "di.h"
12 #include "io.h"
13
14 #include "xdi_msg.h"
15 #include "xdi_adapter.h"
16 #include "os_4bri.h"
17 #include "diva_pci.h"
18 #include "mi_pc.h"
19 #include "dsrv4bri.h"
20 #include "helpers.h"
21
22 static void *diva_xdiLoadFileFile = NULL;
23 static dword diva_xdiLoadFileLength = 0;
24
25 /*
26 ** IMPORTS
27 */
28 extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
29 extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
30 extern void diva_xdi_display_adapter_features(int card);
31 extern void diva_add_slave_adapter(diva_os_xdi_adapter_t *a);
32
33 extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
34 extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
35
36 extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
37
38 /*
39 ** LOCALS
40 */
41 static unsigned long _4bri_bar_length[4] = {
42 0x100,
43 0x100, /* I/O */
44 MQ_MEMORY_SIZE,
45 0x2000
46 };
47 static unsigned long _4bri_v2_bar_length[4] = {
48 0x100,
49 0x100, /* I/O */
50 MQ2_MEMORY_SIZE,
51 0x10000
52 };
53 static unsigned long _4bri_v2_bri_bar_length[4] = {
54 0x100,
55 0x100, /* I/O */
56 BRI2_MEMORY_SIZE,
57 0x10000
58 };
59
60
61 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
62 static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a);
63 static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
64 diva_xdi_um_cfg_cmd_t *cmd,
65 int length);
66 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a);
67 static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a,
68 byte *data, dword length);
69 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
70 static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
71 dword address,
72 const byte *data,
73 dword length, dword limit);
74 static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
75 dword start_address, dword features);
76 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
77 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a);
78
_4bri_is_rev_2_card(int card_ordinal)79 static int _4bri_is_rev_2_card(int card_ordinal)
80 {
81 switch (card_ordinal) {
82 case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
83 case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
84 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
85 case CARDTYPE_DIVASRV_B_2F_PCI:
86 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
87 return (1);
88 }
89 return (0);
90 }
91
_4bri_is_rev_2_bri_card(int card_ordinal)92 static int _4bri_is_rev_2_bri_card(int card_ordinal)
93 {
94 switch (card_ordinal) {
95 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
96 case CARDTYPE_DIVASRV_B_2F_PCI:
97 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
98 return (1);
99 }
100 return (0);
101 }
102
diva_4bri_set_addresses(diva_os_xdi_adapter_t * a)103 static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a)
104 {
105 dword offset = a->resources.pci.qoffset;
106 dword c_offset = offset * a->xdi_adapter.ControllerNumber;
107
108 a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 2;
109 a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2;
110 a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2;
111 a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 0;
112 a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 3;
113 a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 0;
114
115 /*
116 Set up hardware related pointers
117 */
118 a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */
119 a->xdi_adapter.Address += c_offset;
120
121 a->xdi_adapter.Control = a->resources.pci.addr[2]; /* BAR2 SDRAM */
122
123 a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */
124 a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE);
125
126 a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */
127 /*
128 ctlReg contains the register address for the MIPS CPU reset control
129 */
130 a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */
131 /*
132 prom contains the register address for FPGA and EEPROM programming
133 */
134 a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
135 }
136
137 /*
138 ** BAR0 - MEM - 0x100 - CONFIG MEM
139 ** BAR1 - I/O - 0x100 - UNUSED
140 ** BAR2 - MEM - MQ_MEMORY_SIZE (MQ2_MEMORY_SIZE on Rev.2) - SDRAM
141 ** BAR3 - MEM - 0x2000 (0x10000 on Rev.2) - CNTRL
142 **
143 ** Called by master adapter, that will initialize and add slave adapters
144 */
diva_4bri_init_card(diva_os_xdi_adapter_t * a)145 int diva_4bri_init_card(diva_os_xdi_adapter_t *a)
146 {
147 int bar, i;
148 byte __iomem *p;
149 PADAPTER_LIST_ENTRY quadro_list;
150 diva_os_xdi_adapter_t *diva_current;
151 diva_os_xdi_adapter_t *adapter_list[4];
152 PISDN_ADAPTER Slave;
153 unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
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 */
diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a)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
_4bri_get_serial_number(diva_os_xdi_adapter_t * a)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 */
diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a)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
diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter * a,diva_xdi_um_cfg_cmd_t * cmd,int length)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
xdiLoadFile(char * FileName,dword * FileLength,unsigned long lim)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
diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)833 void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
834 {
835 }
836
diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)837 void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
838 {
839 }
840
841 static int
diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a,byte * data,dword length)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
diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)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
diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,dword address,const byte * data,dword length,dword limit)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
diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,dword start_address,dword features)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
check_qBri_interrupt(PISDN_ADAPTER IoAdapter)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
diva_4bri_clear_interrupts(diva_os_xdi_adapter_t * a)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
diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a)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 }
1133