Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux/fpc-iii.git] / drivers / isdn / hardware / eicon / os_4bri.c
blob1891246807edfadffbdb6d1cacb0b9a776217ac3
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[ARRAY_SIZE(_4bri_bar_length)];
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;
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));
165 } else {
166 memcpy(bar_length, _4bri_bar_length, sizeof(bar_length));
168 DBG_TRC(("SDRAM_LENGTH=%08x, tasks=%d, factor=%d",
169 bar_length[2], tasks, factor))
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
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);
184 Set properties
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))
193 First initialization step: get and check hardware resoures.
194 Do not map resources and do not access card at this step
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);
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);
218 a->xdi_adapter.sdram_bar = a->resources.pci.bar[2];
221 Map all MEMORY BAR's
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);
237 Register I/O port
239 sprintf(&a->port_name[0], "DIVA 4BRI %ld", (long) a->xdi_adapter.serialNo);
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);
248 a->resources.pci.addr[1] =
249 (void *) (unsigned long) a->resources.pci.bar[1];
252 Set cleanup pointer for base adapter only, so slave adapter
253 will be unable to get cleanup
255 a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
258 Create slave adapters
260 if (tasks > 1) {
261 if (!(a->slave_adapters[0] =
262 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
264 diva_4bri_cleanup_adapter(a);
265 return (-1);
267 if (!(a->slave_adapters[1] =
268 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
270 diva_os_free(0, a->slave_adapters[0]);
271 a->slave_adapters[0] = NULL;
272 diva_4bri_cleanup_adapter(a);
273 return (-1);
275 if (!(a->slave_adapters[2] =
276 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
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);
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));
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];
296 Allocate slave list
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;
305 diva_4bri_cleanup_adapter(a);
306 return (-1);
308 memset(quadro_list, 0x00, sizeof(*quadro_list));
311 Set interfaces
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;
321 for (i = 0; i < tasks; i++) {
322 diva_current = adapter_list[i];
324 diva_current->dsp_mask = 0x00000003;
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;
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));
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]);
349 return (-1);
351 memset(diva_current->xdi_adapter.e_tbl, 0x00,
352 diva_current->xdi_adapter.e_max * sizeof(E_INFO));
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]);
360 return (-1);
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]);
368 return (-1);
371 strcpy(diva_current->xdi_adapter.req_soft_isr. dpc_thread_name, "kdivas4brid");
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]);
380 return (-1);
384 Do not initialize second DPC - only one thread will be created
386 diva_current->xdi_adapter.isr_soft_isr.object =
387 diva_current->xdi_adapter.req_soft_isr.object;
390 if (v2) {
391 prepare_qBri2_functions(&a->xdi_adapter);
392 } else {
393 prepare_qBri_functions(&a->xdi_adapter);
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);
404 Set up hardware related pointers
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 */
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;
424 reset contains the base address for the PLX 9054 register set
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);
431 Set IRQ handler
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);
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]);
444 return (-1);
447 a->xdi_adapter.irq_info.registered = 1;
450 Add three slave adapters
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]);
458 diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
459 a->resources.pci.irq, a->xdi_adapter.serialNo);
461 return (0);
465 ** Cleanup function will be called for master adapter only
466 ** this is guaranteed by design: cleanup callback is set
467 ** by master adapter only
469 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
471 int bar;
474 Stop adapter if running
476 if (a->xdi_adapter.Initialized) {
477 diva_4bri_stop_adapter(a);
481 Remove IRQ handler
483 if (a->xdi_adapter.irq_info.registered) {
484 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
486 a->xdi_adapter.irq_info.registered = 0;
489 Free DPC's and spin locks on all adapters
491 diva_4bri_cleanup_slave_adapters(a);
494 Unmap all BARS
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;
508 Unregister I/O
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;
521 if (a->slave_list) {
522 diva_os_free(0, a->slave_list);
523 a->slave_list = NULL;
526 return (0);
529 static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a)
531 dword data[64];
532 dword serNo;
533 word addr, status, i, j;
534 byte Bus, Slot;
535 void *hdev;
537 Bus = a->resources.pci.bus;
538 Slot = a->resources.pci.func;
539 hdev = a->resources.pci.hdev;
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;
552 if (j >= 5) {
553 DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr))
554 return (0);
556 PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
558 DBG_BLK(((char *) &data[0], sizeof(data)))
560 serNo = data[32];
561 if (serNo == 0 || serNo == 0xffffffff)
562 serNo = data[63];
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;
571 a->xdi_adapter.serialNo = serNo;
573 DBG_REG(("Serial No. : %ld", a->xdi_adapter.serialNo))
575 return (serNo);
579 ** Release resources of slave adapters
581 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a)
583 diva_os_xdi_adapter_t *adapter_list[4];
584 diva_os_xdi_adapter_t *diva_current;
585 int i;
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];
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");
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);
608 diva_os_remove_soft_isr(&diva_current->xdi_adapter.
609 req_soft_isr);
610 diva_current->xdi_adapter.isr_soft_isr.object = NULL;
612 if (diva_current->xdi_adapter.e_tbl) {
613 diva_os_free(0,
614 diva_current->xdi_adapter.
615 e_tbl);
617 diva_current->xdi_adapter.e_tbl = NULL;
618 diva_current->xdi_adapter.e_max = 0;
619 diva_current->xdi_adapter.e_count = 0;
623 return (0);
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)
630 int ret = -1;
632 if (cmd->adapter != a->controller) {
633 DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d",
634 cmd->adapter, a->controller))
635 return (-1);
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;
649 break;
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;
661 break;
663 case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
664 if (!a->xdi_adapter.ControllerNumber) {
666 Only master adapter can access hardware config
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;
675 for (i = 0; i < 8; i++) {
676 *data++ = a->resources.pci.bar[i];
678 *data++ = (dword) a->resources.pci.irq;
679 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
680 ret = 0;
683 break;
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;
703 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
704 ret = 0;
707 break;
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);
718 break;
720 case DIVA_XDI_UM_CMD_RESET_ADAPTER:
721 if (!a->xdi_adapter.ControllerNumber) {
722 ret = diva_4bri_reset_adapter(&a->xdi_adapter);
724 break;
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);
742 break;
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);
752 break;
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;
764 break;
766 case DIVA_XDI_UM_CMD_STOP_ADAPTER:
767 if (!a->xdi_adapter.ControllerNumber) {
768 ret = diva_4bri_stop_adapter(a);
770 break;
772 case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
773 ret = diva_card_read_xlog(a);
774 break;
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;
796 src += cmd->command_data.read_sdram.offset;
798 while (len--) {
799 *dst++ = READ_BYTE(src++);
801 DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p);
802 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
803 ret = 0;
808 break;
810 default:
811 DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
812 cmd->command))
815 return (ret);
818 void *xdiLoadFile(char *FileName, dword *FileLength,
819 unsigned long lim)
821 void *ret = diva_xdiLoadFileFile;
823 if (FileLength) {
824 *FileLength = diva_xdiLoadFileLength;
826 diva_xdiLoadFileFile = NULL;
827 diva_xdiLoadFileLength = 0;
829 return (ret);
832 void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
836 void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
840 static int
841 diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a, byte *data,
842 dword length)
844 int ret;
846 diva_xdiLoadFileFile = data;
847 diva_xdiLoadFileLength = length;
849 ret = qBri_FPGA_download(&a->xdi_adapter);
851 diva_xdiLoadFileFile = NULL;
852 diva_xdiLoadFileLength = 0;
854 return (ret ? 0 : -1);
857 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)
859 PISDN_ADAPTER Slave;
860 int i;
862 if (!IoAdapter->Address || !IoAdapter->reset) {
863 return (-1);
865 if (IoAdapter->Initialized) {
866 DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first",
867 IoAdapter->ANum))
868 return (-1);
872 Forget all entities on all adapters
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));
881 Slave->head = 0;
882 Slave->tail = 0;
883 Slave->assign = 0;
884 Slave->trapped = 0;
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));
904 return (0);
908 static int
909 diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
910 dword address,
911 const byte *data, dword length, dword limit)
913 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
914 byte __iomem *mem = p;
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);
922 mem += address;
924 while (length--) {
925 WRITE_BYTE(mem++, *data++);
928 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
929 return (0);
932 static int
933 diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
934 dword start_address, dword features)
936 volatile word __iomem *signature;
937 int started = 0;
938 int i;
939 byte __iomem *p;
942 start adapter
944 start_qBri_hardware(IoAdapter);
946 p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
948 wait for signature in shared memory (max. 3 seconds)
950 signature = (volatile word __iomem *) (&p[0x1E]);
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;
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;
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);
978 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
980 for (i = 0; i < IoAdapter->tasks; i++) {
981 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1;
982 IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0;
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;
991 IoAdapter->stop(IoAdapter);
992 return (-1);
995 IoAdapter->Properties.Features = (word) features;
996 diva_xdi_display_adapter_features(IoAdapter->ANum);
998 for (i = 0; i < IoAdapter->tasks; i++) {
999 DBG_LOG(("A(%d) %s adapter successfully 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;
1006 return (0);
1009 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter)
1011 #ifdef SUPPORT_INTERRUPT_TEST_ON_4BRI
1012 int i;
1013 ADAPTER *a = &IoAdapter->a;
1014 byte __iomem *p;
1016 IoAdapter->IrqCount = 0;
1018 if (IoAdapter->ControllerNumber > 0)
1019 return (-1);
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);
1025 interrupt test
1027 a->ReadyInt = 1;
1028 a->ram_out(a, &PR_RAM->ReadyInt, 1);
1030 for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
1032 return ((IoAdapter->IrqCount > 0) ? 0 : -1);
1033 #else
1034 dword volatile __iomem *qBriIrq;
1035 byte __iomem *p;
1037 Reset on-board interrupt register
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)]);
1046 WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
1047 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
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);
1053 diva_os_wait(100);
1055 return (0);
1056 #endif /* SUPPORT_INTERRUPT_TEST_ON_4BRI */
1059 static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t *a)
1061 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1064 clear any pending interrupt
1066 IoAdapter->disIrq(IoAdapter);
1068 IoAdapter->tst_irq(&IoAdapter->a);
1069 IoAdapter->clr_irq(&IoAdapter->a);
1070 IoAdapter->tst_irq(&IoAdapter->a);
1073 kill pending dpcs
1075 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
1076 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
1079 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a)
1081 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1082 int i;
1084 if (!IoAdapter->ram) {
1085 return (-1);
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 */
1094 for (i = 0; i < IoAdapter->tasks; i++) {
1095 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
1099 Disconnect Adapters from DIDD
1101 for (i = 0; i < IoAdapter->tasks; i++) {
1102 diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1105 i = 100;
1108 Stop interrupts
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);
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))
1123 IoAdapter->a.ReadyInt = 0;
1126 Stop and reset adapter
1128 IoAdapter->stop(IoAdapter);
1130 return (0);