allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / drivers / isdn / hardware / eicon / os_4bri.c
blob7b4ec3f60dbf6c61b5d0b24e584d6aa137f7a73f
1 /* $Id: os_4bri.c,v 1.28.4.4 2005/02/11 19:40:25 armin Exp $ */
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"
13 #include "xdi_msg.h"
14 #include "xdi_adapter.h"
15 #include "os_4bri.h"
16 #include "diva_pci.h"
17 #include "mi_pc.h"
18 #include "dsrv4bri.h"
19 #include "helpers.h"
21 static void *diva_xdiLoadFileFile = NULL;
22 static dword diva_xdiLoadFileLength = 0;
25 ** IMPORTS
27 extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
28 extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
29 extern void diva_xdi_display_adapter_features(int card);
30 extern void diva_add_slave_adapter(diva_os_xdi_adapter_t * a);
32 extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
33 extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
35 extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a);
38 ** LOCALS
40 static unsigned long _4bri_bar_length[4] = {
41 0x100,
42 0x100, /* I/O */
43 MQ_MEMORY_SIZE,
44 0x2000
46 static unsigned long _4bri_v2_bar_length[4] = {
47 0x100,
48 0x100, /* I/O */
49 MQ2_MEMORY_SIZE,
50 0x10000
52 static unsigned long _4bri_v2_bri_bar_length[4] = {
53 0x100,
54 0x100, /* I/O */
55 BRI2_MEMORY_SIZE,
56 0x10000
60 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a);
61 static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a);
62 static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
63 diva_xdi_um_cfg_cmd_t * cmd,
64 int length);
65 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a);
66 static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a,
67 byte * data, dword length);
68 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
69 static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
70 dword address,
71 const byte * data,
72 dword length, dword limit);
73 static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
74 dword start_address, dword features);
75 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
76 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a);
78 static int _4bri_is_rev_2_card(int card_ordinal)
80 switch (card_ordinal) {
81 case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
82 case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
83 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
84 case CARDTYPE_DIVASRV_B_2F_PCI:
85 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
86 return (1);
88 return (0);
91 static int _4bri_is_rev_2_bri_card(int card_ordinal)
93 switch (card_ordinal) {
94 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
95 case CARDTYPE_DIVASRV_B_2F_PCI:
96 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
97 return (1);
99 return (0);
102 static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a)
104 dword offset = a->resources.pci.qoffset;
105 dword c_offset = offset * a->xdi_adapter.ControllerNumber;
107 a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 2;
108 a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2;
109 a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2;
110 a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 0;
111 a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 3;
112 a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 0;
115 Set up hardware related pointers
117 a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */
118 a->xdi_adapter.Address += c_offset;
120 a->xdi_adapter.Control = a->resources.pci.addr[2]; /* BAR2 SDRAM */
122 a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */
123 a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE);
125 a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */
127 ctlReg contains the register address for the MIPS CPU reset control
129 a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */
131 prom contains the register address for FPGA and EEPROM programming
133 a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
137 ** BAR0 - MEM - 0x100 - CONFIG MEM
138 ** BAR1 - I/O - 0x100 - UNUSED
139 ** BAR2 - MEM - MQ_MEMORY_SIZE (MQ2_MEMORY_SIZE on Rev.2) - SDRAM
140 ** BAR3 - MEM - 0x2000 (0x10000 on Rev.2) - CNTRL
142 ** Called by master adapter, that will initialize and add slave adapters
144 int diva_4bri_init_card(diva_os_xdi_adapter_t * a)
146 int bar, i;
147 byte __iomem *p;
148 PADAPTER_LIST_ENTRY quadro_list;
149 diva_os_xdi_adapter_t *diva_current;
150 diva_os_xdi_adapter_t *adapter_list[4];
151 PISDN_ADAPTER Slave;
152 unsigned long bar_length[sizeof(_4bri_bar_length) /
153 sizeof(_4bri_bar_length[0])];
154 int v2 = _4bri_is_rev_2_card(a->CardOrdinal);
155 int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
156 int factor = (tasks == 1) ? 1 : 2;
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));
166 } else {
167 memcpy(bar_length, _4bri_bar_length, sizeof(bar_length));
169 DBG_TRC(("SDRAM_LENGTH=%08x, tasks=%d, factor=%d",
170 bar_length[2], tasks, factor))
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
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);
185 Set properties
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))
194 First initialization step: get and check hardware resoures.
195 Do not map resources and do not access card at this step
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);
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);
219 a->xdi_adapter.sdram_bar = a->resources.pci.bar[2];
222 Map all MEMORY BAR's
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);
238 Register I/O port
240 sprintf(&a->port_name[0], "DIVA 4BRI %ld", (long) a->xdi_adapter.serialNo);
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);
249 a->resources.pci.addr[1] =
250 (void *) (unsigned long) a->resources.pci.bar[1];
253 Set cleanup pointer for base adapter only, so slave adapter
254 will be unable to get cleanup
256 a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
259 Create slave adapters
261 if (tasks > 1) {
262 if (!(a->slave_adapters[0] =
263 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
265 diva_4bri_cleanup_adapter(a);
266 return (-1);
268 if (!(a->slave_adapters[1] =
269 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
271 diva_os_free(0, a->slave_adapters[0]);
272 a->slave_adapters[0] = NULL;
273 diva_4bri_cleanup_adapter(a);
274 return (-1);
276 if (!(a->slave_adapters[2] =
277 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
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);
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));
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];
297 Allocate slave list
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;
306 diva_4bri_cleanup_adapter(a);
307 return (-1);
309 memset(quadro_list, 0x00, sizeof(*quadro_list));
312 Set interfaces
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;
322 for (i = 0; i < tasks; i++) {
323 diva_current = adapter_list[i];
325 diva_current->dsp_mask = 0x00000003;
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;
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));
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]);
350 return (-1);
352 memset(diva_current->xdi_adapter.e_tbl, 0x00,
353 diva_current->xdi_adapter.e_max * sizeof(E_INFO));
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]);
361 return (-1);
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]);
369 return (-1);
372 strcpy(diva_current->xdi_adapter.req_soft_isr. dpc_thread_name, "kdivas4brid");
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]);
381 return (-1);
385 Do not initialize second DPC - only one thread will be created
387 diva_current->xdi_adapter.isr_soft_isr.object =
388 diva_current->xdi_adapter.req_soft_isr.object;
391 if (v2) {
392 prepare_qBri2_functions(&a->xdi_adapter);
393 } else {
394 prepare_qBri_functions(&a->xdi_adapter);
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);
405 Set up hardware related pointers
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 */
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;
425 reset contains the base address for the PLX 9054 register set
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);
432 Set IRQ handler
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);
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]);
445 return (-1);
448 a->xdi_adapter.irq_info.registered = 1;
451 Add three slave adapters
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]);
459 diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
460 a->resources.pci.irq, a->xdi_adapter.serialNo);
462 return (0);
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
470 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a)
472 int bar;
475 Stop adapter if running
477 if (a->xdi_adapter.Initialized) {
478 diva_4bri_stop_adapter(a);
482 Remove IRQ handler
484 if (a->xdi_adapter.irq_info.registered) {
485 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
487 a->xdi_adapter.irq_info.registered = 0;
490 Free DPC's and spin locks on all adapters
492 diva_4bri_cleanup_slave_adapters(a);
495 Unmap all BARS
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;
509 Unregister I/O
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;
522 if (a->slave_list) {
523 diva_os_free(0, a->slave_list);
524 a->slave_list = NULL;
527 return (0);
530 static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a)
532 dword data[64];
533 dword serNo;
534 word addr, status, i, j;
535 byte Bus, Slot;
536 void *hdev;
538 Bus = a->resources.pci.bus;
539 Slot = a->resources.pci.func;
540 hdev = a->resources.pci.hdev;
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;
553 if (j >= 5) {
554 DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr))
555 return (0);
557 PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
559 DBG_BLK(((char *) &data[0], sizeof(data)))
561 serNo = data[32];
562 if (serNo == 0 || serNo == 0xffffffff)
563 serNo = data[63];
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;
572 a->xdi_adapter.serialNo = serNo;
574 DBG_REG(("Serial No. : %ld", a->xdi_adapter.serialNo))
576 return (serNo);
580 ** Release resources of slave adapters
582 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a)
584 diva_os_xdi_adapter_t *adapter_list[4];
585 diva_os_xdi_adapter_t *diva_current;
586 int i;
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];
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");
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);
609 diva_os_remove_soft_isr(&diva_current->xdi_adapter.
610 req_soft_isr);
611 diva_current->xdi_adapter.isr_soft_isr.object = NULL;
613 if (diva_current->xdi_adapter.e_tbl) {
614 diva_os_free(0,
615 diva_current->xdi_adapter.
616 e_tbl);
618 diva_current->xdi_adapter.e_tbl = NULL;
619 diva_current->xdi_adapter.e_max = 0;
620 diva_current->xdi_adapter.e_count = 0;
624 return (0);
627 static int
628 diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
629 diva_xdi_um_cfg_cmd_t * cmd, int length)
631 int ret = -1;
633 if (cmd->adapter != a->controller) {
634 DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d",
635 cmd->adapter, a->controller))
636 return (-1);
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;
650 break;
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;
662 break;
664 case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
665 if (!a->xdi_adapter.ControllerNumber) {
667 Only master adapter can access hardware config
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;
676 for (i = 0; i < 8; i++) {
677 *data++ = a->resources.pci.bar[i];
679 *data++ = (dword) a->resources.pci.irq;
680 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
681 ret = 0;
684 break;
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;
704 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
705 ret = 0;
708 break;
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);
719 break;
721 case DIVA_XDI_UM_CMD_RESET_ADAPTER:
722 if (!a->xdi_adapter.ControllerNumber) {
723 ret = diva_4bri_reset_adapter(&a->xdi_adapter);
725 break;
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);
743 break;
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);
753 break;
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;
765 break;
767 case DIVA_XDI_UM_CMD_STOP_ADAPTER:
768 if (!a->xdi_adapter.ControllerNumber) {
769 ret = diva_4bri_stop_adapter(a);
771 break;
773 case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
774 ret = diva_card_read_xlog(a);
775 break;
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;
797 src += cmd->command_data.read_sdram.offset;
799 while (len--) {
800 *dst++ = READ_BYTE(src++);
802 DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p);
803 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
804 ret = 0;
809 break;
811 default:
812 DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
813 cmd->command))
816 return (ret);
819 void *xdiLoadFile(char *FileName, dword *FileLength,
820 unsigned long lim)
822 void *ret = diva_xdiLoadFileFile;
824 if (FileLength) {
825 *FileLength = diva_xdiLoadFileLength;
827 diva_xdiLoadFileFile = NULL;
828 diva_xdiLoadFileLength = 0;
830 return (ret);
833 void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
837 void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
841 static int
842 diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a, byte * data,
843 dword length)
845 int ret;
847 diva_xdiLoadFileFile = data;
848 diva_xdiLoadFileLength = length;
850 ret = qBri_FPGA_download(&a->xdi_adapter);
852 diva_xdiLoadFileFile = NULL;
853 diva_xdiLoadFileLength = 0;
855 return (ret ? 0 : -1);
858 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)
860 PISDN_ADAPTER Slave;
861 int i;
863 if (!IoAdapter->Address || !IoAdapter->reset) {
864 return (-1);
866 if (IoAdapter->Initialized) {
867 DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first",
868 IoAdapter->ANum))
869 return (-1);
873 Forget all entities on all adapters
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));
882 Slave->head = 0;
883 Slave->tail = 0;
884 Slave->assign = 0;
885 Slave->trapped = 0;
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));
905 return (0);
909 static int
910 diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
911 dword address,
912 const byte * data, dword length, dword limit)
914 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
915 byte __iomem *mem = p;
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);
923 mem += address;
925 while (length--) {
926 WRITE_BYTE(mem++, *data++);
929 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
930 return (0);
933 static int
934 diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
935 dword start_address, dword features)
937 volatile word __iomem *signature;
938 int started = 0;
939 int i;
940 byte __iomem *p;
943 start adapter
945 start_qBri_hardware(IoAdapter);
947 p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
949 wait for signature in shared memory (max. 3 seconds)
951 signature = (volatile word __iomem *) (&p[0x1E]);
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;
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;
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);
979 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
981 for (i = 0; i < IoAdapter->tasks; i++) {
982 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1;
983 IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0;
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;
992 IoAdapter->stop(IoAdapter);
993 return (-1);
996 IoAdapter->Properties.Features = (word) features;
997 diva_xdi_display_adapter_features(IoAdapter->ANum);
999 for (i = 0; i < IoAdapter->tasks; i++) {
1000 DBG_LOG(("A(%d) %s adapter successfull 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;
1007 return (0);
1010 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter)
1012 #ifdef SUPPORT_INTERRUPT_TEST_ON_4BRI
1013 int i;
1014 ADAPTER *a = &IoAdapter->a;
1015 byte __iomem *p;
1017 IoAdapter->IrqCount = 0;
1019 if (IoAdapter->ControllerNumber > 0)
1020 return (-1);
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);
1026 interrupt test
1028 a->ReadyInt = 1;
1029 a->ram_out(a, &PR_RAM->ReadyInt, 1);
1031 for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
1033 return ((IoAdapter->IrqCount > 0) ? 0 : -1);
1034 #else
1035 dword volatile __iomem *qBriIrq;
1036 byte __iomem *p;
1038 Reset on-board interrupt register
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)]);
1047 WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
1048 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
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);
1054 diva_os_wait(100);
1056 return (0);
1057 #endif /* SUPPORT_INTERRUPT_TEST_ON_4BRI */
1060 static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t * a)
1062 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1065 clear any pending interrupt
1067 IoAdapter->disIrq(IoAdapter);
1069 IoAdapter->tst_irq(&IoAdapter->a);
1070 IoAdapter->clr_irq(&IoAdapter->a);
1071 IoAdapter->tst_irq(&IoAdapter->a);
1074 kill pending dpcs
1076 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
1077 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
1080 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a)
1082 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1083 int i;
1085 if (!IoAdapter->ram) {
1086 return (-1);
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 */
1095 for (i = 0; i < IoAdapter->tasks; i++) {
1096 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
1100 Disconnect Adapters from DIDD
1102 for (i = 0; i < IoAdapter->tasks; i++) {
1103 diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1106 i = 100;
1109 Stop interrupts
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);
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))
1124 IoAdapter->a.ReadyInt = 0;
1127 Stop and reset adapter
1129 IoAdapter->stop(IoAdapter);
1131 return (0);