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#include "helpers.h" 20 21static void *diva_xdiLoadFileFile = NULL; 22static dword diva_xdiLoadFileLength = 0; 23 24/* 25** IMPORTS 26*/ 27extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter); 28extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter); 29extern void diva_xdi_display_adapter_features(int card); 30extern void diva_add_slave_adapter(diva_os_xdi_adapter_t *a); 31 32extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter); 33extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter); 34 35extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a); 36 37/* 38** LOCALS 39*/ 40static unsigned long _4bri_bar_length[4] = { 41 0x100, 42 0x100, /* I/O */ 43 MQ_MEMORY_SIZE, 44 0x2000 45}; 46static unsigned long _4bri_v2_bar_length[4] = { 47 0x100, 48 0x100, /* I/O */ 49 MQ2_MEMORY_SIZE, 50 0x10000 51}; 52static unsigned long _4bri_v2_bri_bar_length[4] = { 53 0x100, 54 0x100, /* I/O */ 55 BRI2_MEMORY_SIZE, 56 0x10000 57}; 58 59 60static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a); 61static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a); 62static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, 63 diva_xdi_um_cfg_cmd_t *cmd, 64 int length); 65static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a); 66static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a, 67 byte *data, dword length); 68static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter); 69static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter, 70 dword address, 71 const byte *data, 72 dword length, dword limit); 73static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter, 74 dword start_address, dword features); 75static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter); 76static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a); 77 78static int _4bri_is_rev_2_card(int card_ordinal) 79{ 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); 87 } 88 return (0); 89} 90 91static int _4bri_is_rev_2_bri_card(int card_ordinal) 92{ 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); 98 } 99 return (0); 100} 101 102static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a) 103{ 104 dword offset = a->resources.pci.qoffset; 105 dword c_offset = offset * a->xdi_adapter.ControllerNumber; 106 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; 113 114 /* 115 Set up hardware related pointers 116 */ 117 a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */ 118 a->xdi_adapter.Address += c_offset; 119 120 a->xdi_adapter.Control = a->resources.pci.addr[2]; /* BAR2 SDRAM */ 121 122 a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */ 123 a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE); 124 125 a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */ 126 /* 127 ctlReg contains the register address for the MIPS CPU reset control 128 */ 129 a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */ 130 /* 131 prom contains the register address for FPGA and EEPROM programming 132 */ 133 a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E]; 134} 135 136/* 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 141** 142** Called by master adapter, that will initialize and add slave adapters 143*/ 144int diva_4bri_init_card(diva_os_xdi_adapter_t *a) 145{ 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; 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 guaranteed by design: cleanup callback is set 467** by master adapter only 468*/ 469static 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 529static 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*/ 581static 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 626static int 627diva_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 818void *xdiLoadFile(char *FileName, dword *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 832void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter) 833{ 834} 835 836void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter) 837{ 838} 839 840static int 841diva_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 857static 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 908static int 909diva_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 932static int 933diva_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 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; 1004 } 1005 1006 return (0); 1007} 1008 1009static 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 1059static 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 1079static 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} 1132