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