License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-block.git] / drivers / isdn / hardware / eicon / os_4bri.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
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"
7019e7e4 20#include "helpers.h"
1da177e4
LT
21
22static void *diva_xdiLoadFileFile = NULL;
23static dword diva_xdiLoadFileLength = 0;
24
25/*
26** IMPORTS
27*/
28extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
29extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
30extern void diva_xdi_display_adapter_features(int card);
475be4d8 31extern void diva_add_slave_adapter(diva_os_xdi_adapter_t *a);
1da177e4
LT
32
33extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
34extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
35
475be4d8 36extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
1da177e4
LT
37
38/*
39** LOCALS
40*/
41static unsigned long _4bri_bar_length[4] = {
42 0x100,
43 0x100, /* I/O */
44 MQ_MEMORY_SIZE,
45 0x2000
46};
47static unsigned long _4bri_v2_bar_length[4] = {
48 0x100,
49 0x100, /* I/O */
50 MQ2_MEMORY_SIZE,
51 0x10000
52};
53static unsigned long _4bri_v2_bri_bar_length[4] = {
54 0x100,
55 0x100, /* I/O */
56 BRI2_MEMORY_SIZE,
57 0x10000
58};
59
60
475be4d8
JP
61static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
62static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a);
1da177e4 63static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
475be4d8 64 diva_xdi_um_cfg_cmd_t *cmd,
1da177e4 65 int length);
475be4d8
JP
66static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a);
67static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a,
68 byte *data, dword length);
1da177e4
LT
69static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
70static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
71 dword address,
475be4d8 72 const byte *data,
1da177e4
LT
73 dword length, dword limit);
74static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
75 dword start_address, dword features);
76static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
475be4d8 77static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a);
1da177e4
LT
78
79static 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
92static 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
103static 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 /*
475be4d8
JP
116 Set up hardware related pointers
117 */
1da177e4
LT
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);
475be4d8 125
1da177e4
LT
126 a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */
127 /*
475be4d8
JP
128 ctlReg contains the register address for the MIPS CPU reset control
129 */
1da177e4
LT
130 a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */
131 /*
475be4d8
JP
132 prom contains the register address for FPGA and EEPROM programming
133 */
1da177e4
LT
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*/
475be4d8 145int diva_4bri_init_card(diva_os_xdi_adapter_t *a)
1da177e4
LT
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;
ba2d6ccb 153 unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
1da177e4
LT
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
475be4d8
JP
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 }
1da177e4
LT
183
184 /*
475be4d8
JP
185 Set properties
186 */
1da177e4
LT
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
475be4d8
JP
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 }
1da177e4 209 }
1da177e4 210 a->resources.pci.irq =
475be4d8
JP
211 (byte) divasa_get_pci_irq(a->resources.pci.bus,
212 a->resources.pci.func,
213 a->resources.pci.hdev);
1da177e4
LT
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 /*
475be4d8
JP
222 Map all MEMORY BAR's
223 */
1da177e4
LT
224 for (bar = 0; bar < 4; bar++) {
225 if (bar != 1) { /* ignore I/O */
226 a->resources.pci.addr[bar] =
475be4d8
JP
227 divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar],
228 bar_length[bar]);
1da177e4
LT
229 if (!a->resources.pci.addr[bar]) {
230 DBG_ERR(("A: 4BRI: can't map bar[%d]", bar))
475be4d8 231 diva_4bri_cleanup_adapter(a);
1da177e4
LT
232 return (-1);
233 }
234 }
235 }
236
237 /*
475be4d8
JP
238 Register I/O port
239 */
1da177e4
LT
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]"))
475be4d8 245 diva_4bri_cleanup_adapter(a);
1da177e4
LT
246 return (-1);
247 }
248
249 a->resources.pci.addr[1] =
250 (void *) (unsigned long) a->resources.pci.bar[1];
251
252 /*
475be4d8
JP
253 Set cleanup pointer for base adapter only, so slave adapter
254 will be unable to get cleanup
255 */
1da177e4
LT
256 a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
257
258 /*
475be4d8
JP
259 Create slave adapters
260 */
1da177e4
LT
261 if (tasks > 1) {
262 if (!(a->slave_adapters[0] =
475be4d8 263 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
1da177e4
LT
264 {
265 diva_4bri_cleanup_adapter(a);
266 return (-1);
267 }
268 if (!(a->slave_adapters[1] =
475be4d8 269 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
1da177e4
LT
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] =
475be4d8 277 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
1da177e4
LT
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 /*
475be4d8
JP
297 Allocate slave list
298 */
1da177e4 299 quadro_list =
475be4d8 300 (PADAPTER_LIST_ENTRY) diva_os_malloc(0, sizeof(*quadro_list));
1da177e4
LT
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 /*
475be4d8
JP
312 Set interfaces
313 */
1da177e4
LT
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] =
475be4d8 319 &adapter_list[i]->xdi_adapter;
1da177e4
LT
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 =
475be4d8 328 &diva_current->xdi_adapter;
1da177e4
LT
329 diva_current->xdi_adapter.DIRequest = request;
330 diva_current->interface.cmd_proc = diva_4bri_cmd_card_proc;
331 diva_current->xdi_adapter.Properties =
475be4d8 332 CardProperties[a->CardOrdinal];
1da177e4
LT
333 diva_current->CardOrdinal = a->CardOrdinal;
334
335 diva_current->xdi_adapter.Channels =
475be4d8 336 CardProperties[a->CardOrdinal].Channels;
1da177e4 337 diva_current->xdi_adapter.e_max =
475be4d8 338 CardProperties[a->CardOrdinal].E_info;
1da177e4 339 diva_current->xdi_adapter.e_tbl =
475be4d8
JP
340 diva_os_malloc(0,
341 diva_current->xdi_adapter.e_max *
342 sizeof(E_INFO));
1da177e4
LT
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
475be4d8
JP
374 if (diva_os_initialize_soft_isr(&diva_current->xdi_adapter.req_soft_isr, DIDpcRoutine,
375 &diva_current->xdi_adapter)) {
1da177e4
LT
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 /*
475be4d8
JP
385 Do not initialize second DPC - only one thread will be created
386 */
1da177e4 387 diva_current->xdi_adapter.isr_soft_isr.object =
475be4d8 388 diva_current->xdi_adapter.req_soft_isr.object;
1da177e4
LT
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));
475be4d8 401 diva_current->resources.pci.qoffset = (a->xdi_adapter.MemorySize >> factor);
1da177e4
LT
402 }
403
404 /*
475be4d8
JP
405 Set up hardware related pointers
406 */
1da177e4
LT
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)) |
475be4d8 419 a->xdi_adapter.serialNo;
1da177e4
LT
420 Slave->cardType = a->xdi_adapter.cardType;
421 }
422 }
423
424 /*
475be4d8
JP
425 reset contains the base address for the PLX 9054 register set
426 */
1da177e4
LT
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 /*
475be4d8
JP
432 Set IRQ handler
433 */
1da177e4
LT
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 /*
475be4d8
JP
451 Add three slave adapters
452 */
1da177e4
LT
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
0779bf2d 467** this is guaranteed by design: cleanup callback is set
1da177e4
LT
468** by master adapter only
469*/
475be4d8 470static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
1da177e4
LT
471{
472 int bar;
473
474 /*
475be4d8
JP
475 Stop adapter if running
476 */
1da177e4
LT
477 if (a->xdi_adapter.Initialized) {
478 diva_4bri_stop_adapter(a);
479 }
480
481 /*
475be4d8
JP
482 Remove IRQ handler
483 */
1da177e4
LT
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 /*
475be4d8
JP
490 Free DPC's and spin locks on all adapters
491 */
1da177e4
LT
492 diva_4bri_cleanup_slave_adapters(a);
493
494 /*
475be4d8
JP
495 Unmap all BARS
496 */
1da177e4
LT
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 /*
475be4d8
JP
509 Unregister I/O
510 */
1da177e4
LT
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
475be4d8 530static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a)
1da177e4
LT
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))
475be4d8 555 return (0);
1da177e4
LT
556 }
557 PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
558 }
559 DBG_BLK(((char *) &data[0], sizeof(data)))
560
475be4d8 561 serNo = data[32];
1da177e4
LT
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
475be4d8 576 return (serNo);
1da177e4
LT
577}
578
579/*
580** Release resources of slave adapters
581*/
475be4d8 582static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a)
1da177e4
LT
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
627static int
628diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
475be4d8 629 diva_xdi_um_cfg_cmd_t *cmd, int length)
1da177e4
LT
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))
475be4d8 636 return (-1);
1da177e4
LT
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 =
475be4d8 643 diva_os_malloc(0, a->xdi_mbox.data_length);
1da177e4
LT
644 if (a->xdi_mbox.data) {
645 *(dword *) a->xdi_mbox.data =
475be4d8 646 (dword) a->CardOrdinal;
1da177e4
LT
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 =
475be4d8 655 diva_os_malloc(0, a->xdi_mbox.data_length);
1da177e4
LT
656 if (a->xdi_mbox.data) {
657 *(dword *) a->xdi_mbox.data =
475be4d8 658 (dword) a->xdi_adapter.serialNo;
1da177e4
LT
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 /*
475be4d8
JP
667 Only master adapter can access hardware config
668 */
1da177e4
LT
669 a->xdi_mbox.data_length = sizeof(dword) * 9;
670 a->xdi_mbox.data =
475be4d8 671 diva_os_malloc(0, a->xdi_mbox.data_length);
1da177e4
LT
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 =
475be4d8 690 diva_os_malloc(0, a->xdi_mbox.data_length);
1da177e4
LT
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 =
475be4d8
JP
713 diva_4bri_write_fpga_image(a,
714 (byte *)&cmd[1],
715 cmd->command_data.
716 write_fpga.
717 image_length);
1da177e4
LT
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 =
475be4d8 758 cmd->command_data.features.features;
1da177e4 759 a->xdi_adapter.a.protocol_capabilities =
475be4d8 760 a->xdi_adapter.features;
1da177e4
LT
761 DBG_TRC(("Set raw protocol features (%08x)",
762 a->xdi_adapter.features))
475be4d8 763 ret = 0;
1da177e4
LT
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 (
475be4d8
JP
781 (a->xdi_mbox.data_length =
782 cmd->command_data.read_sdram.length)) {
1da177e4 783 if (
475be4d8
JP
784 (a->xdi_mbox.data_length +
785 cmd->command_data.read_sdram.offset) <
786 a->xdi_adapter.MemorySize) {
1da177e4 787 a->xdi_mbox.data =
475be4d8
JP
788 diva_os_malloc(0,
789 a->xdi_mbox.
790 data_length);
1da177e4
LT
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))
475be4d8 814 }
1da177e4
LT
815
816 return (ret);
817}
818
7019e7e4 819void *xdiLoadFile(char *FileName, dword *FileLength,
1da177e4
LT
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
833void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
834{
835}
836
837void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
838{
839}
840
841static int
475be4d8 842diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a, byte *data,
1da177e4
LT
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
858static 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))
475be4d8 869 return (-1);
1da177e4
LT
870 }
871
872 /*
475be4d8
JP
873 Forget all entities on all adapters
874 */
1da177e4
LT
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
909static int
910diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
911 dword address,
475be4d8 912 const byte *data, dword length, dword limit)
1da177e4
LT
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))
475be4d8 921 return (-1);
1da177e4
LT
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
933static int
934diva_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 /*
475be4d8
JP
943 start adapter
944 */
1da177e4
LT
945 start_qBri_hardware(IoAdapter);
946
947 p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
948 /*
475be4d8
JP
949 wait for signature in shared memory (max. 3 seconds)
950 */
1da177e4
LT
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)))
475be4d8 958 started = 1;
1da177e4
LT
959 break;
960 }
961 }
962
963 for (i = 1; i < IoAdapter->tasks; i++) {
964 IoAdapter->QuadroList->QuadroAdapter[i]->features =
475be4d8 965 IoAdapter->features;
1da177e4 966 IoAdapter->QuadroList->QuadroAdapter[i]->a.
475be4d8 967 protocol_capabilities = IoAdapter->features;
1da177e4
LT
968 }
969
970 if (!started) {
971 DBG_FTL(("%s: Adapter selftest failed, signature=%04x",
972 IoAdapter->Properties.Name,
973 READ_WORD(&signature[0])))
475be4d8 974 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
1da177e4
LT
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))
475be4d8
JP
989 for (i = 0; i < IoAdapter->tasks; i++) {
990 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
991 }
1da177e4
LT
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++) {
73ac36ea 1000 DBG_LOG(("A(%d) %s adapter successfully started",
1da177e4
LT
1001 IoAdapter->QuadroList->QuadroAdapter[i]->ANum,
1002 (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI"))
475be4d8 1003 diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1da177e4
LT
1004 IoAdapter->QuadroList->QuadroAdapter[i]->Properties.Features = (word) features;
1005 }
1006
1007 return (0);
1008}
1009
1010static 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 /*
475be4d8
JP
1026 interrupt test
1027 */
1da177e4
LT
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 /*
475be4d8
JP
1038 Reset on-board interrupt register
1039 */
1da177e4
LT
1040 IoAdapter->IrqCount = 0;
1041 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
1042 qBriIrq = (dword volatile __iomem *) (&p[_4bri_is_rev_2_card
475be4d8
JP
1043 (IoAdapter->
1044 cardType) ? (MQ2_BREG_IRQ_TEST)
1045 : (MQ_BREG_IRQ_TEST)]);
1da177e4
LT
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
475be4d8 1060static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t *a)
1da177e4
LT
1061{
1062 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1063
1064 /*
475be4d8
JP
1065 clear any pending interrupt
1066 */
1da177e4
LT
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 /*
475be4d8
JP
1074 kill pending dpcs
1075 */
1da177e4
LT
1076 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
1077 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
1078}
1079
475be4d8 1080static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a)
1da177e4
LT
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))
475be4d8 1092 return (-1); /* nothing to stop */
1da177e4
LT
1093 }
1094
1095 for (i = 0; i < IoAdapter->tasks; i++) {
1096 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
1097 }
1098
1099 /*
475be4d8
JP
1100 Disconnect Adapters from DIDD
1101 */
1da177e4
LT
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 /*
475be4d8
JP
1109 Stop interrupts
1110 */
1da177e4
LT
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))
475be4d8 1123 }
1da177e4
LT
1124 IoAdapter->a.ReadyInt = 0;
1125
1126 /*
475be4d8
JP
1127 Stop and reset adapter
1128 */
1da177e4
LT
1129 IoAdapter->stop(IoAdapter);
1130
1131 return (0);
1132}