1/* $Id: os_pri.c,v 1.1.1.1 2007/08/03 18:52:35 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_pri.h" 16#include "diva_pci.h" 17#include "mi_pc.h" 18#include "pc_maint.h" 19#include "dsp_tst.h" 20#include "diva_dma.h" 21#include "dsrv_pri.h" 22 23/* -------------------------------------------------------------------------- 24 OS Dependent part of XDI driver for DIVA PRI Adapter 25 26 DSP detection/validation by Anthony Booth (Eicon Networks, www.eicon.com) 27-------------------------------------------------------------------------- */ 28 29#define DIVA_PRI_NO_PCI_BIOS_WORKAROUND 1 30 31extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a); 32 33/* 34** IMPORTS 35*/ 36extern void prepare_pri_functions(PISDN_ADAPTER IoAdapter); 37extern void prepare_pri2_functions(PISDN_ADAPTER IoAdapter); 38extern void diva_xdi_display_adapter_features(int card); 39 40static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t * a); 41static int diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a, 42 diva_xdi_um_cfg_cmd_t * cmd, int length); 43static int pri_get_serial_number(diva_os_xdi_adapter_t * a); 44static int diva_pri_stop_adapter(diva_os_xdi_adapter_t * a); 45static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a); 46 47/* 48** Check card revision 49*/ 50static int pri_is_rev_2_card(int card_ordinal) 51{ 52 switch (card_ordinal) { 53 case CARDTYPE_DIVASRV_P_30M_V2_PCI: 54 case CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI: 55 return (1); 56 } 57 return (0); 58} 59 60static void diva_pri_set_addresses(diva_os_xdi_adapter_t * a) 61{ 62 a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 0; 63 a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2; 64 a->resources.pci.mem_type_id[MEM_TYPE_CONFIG] = 4; 65 a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0; 66 a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 2; 67 a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 4; 68 a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 3; 69 70 a->xdi_adapter.Address = a->resources.pci.addr[0]; 71 a->xdi_adapter.Control = a->resources.pci.addr[2]; 72 a->xdi_adapter.Config = a->resources.pci.addr[4]; 73 74 a->xdi_adapter.ram = a->resources.pci.addr[0]; 75 a->xdi_adapter.ram += MP_SHARED_RAM_OFFSET; 76 77 a->xdi_adapter.reset = a->resources.pci.addr[2]; 78 a->xdi_adapter.reset += MP_RESET; 79 80 a->xdi_adapter.cfg = a->resources.pci.addr[4]; 81 a->xdi_adapter.cfg += MP_IRQ_RESET; 82 83 a->xdi_adapter.sdram_bar = a->resources.pci.bar[0]; 84 85 a->xdi_adapter.prom = a->resources.pci.addr[3]; 86} 87 88/* 89** BAR0 - SDRAM, MP_MEMORY_SIZE, MP2_MEMORY_SIZE by Rev.2 90** BAR1 - DEVICES, 0x1000 91** BAR2 - CONTROL (REG), 0x2000 92** BAR3 - FLASH (REG), 0x8000 93** BAR4 - CONFIG (CFG), 0x1000 94*/ 95int diva_pri_init_card(diva_os_xdi_adapter_t * a) 96{ 97 int bar = 0; 98 int pri_rev_2; 99 unsigned long bar_length[5] = { 100 MP_MEMORY_SIZE, 101 0x1000, 102 0x2000, 103 0x8000, 104 0x1000 105 }; 106 107 pri_rev_2 = pri_is_rev_2_card(a->CardOrdinal); 108 109 if (pri_rev_2) { 110 bar_length[0] = MP2_MEMORY_SIZE; 111 } 112 /* 113 Set properties 114 */ 115 a->xdi_adapter.Properties = CardProperties[a->CardOrdinal]; 116 DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name)) 117 118 /* 119 First initialization step: get and check hardware resoures. 120 Do not map resources and do not acecess card at this step 121 */ 122 for (bar = 0; bar < 5; bar++) { 123 a->resources.pci.bar[bar] = 124 divasa_get_pci_bar(a->resources.pci.bus, 125 a->resources.pci.func, bar, 126 a->resources.pci.hdev); 127 if (!a->resources.pci.bar[bar] 128 || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) { 129 DBG_ERR(("A: invalid bar[%d]=%08x", bar, 130 a->resources.pci.bar[bar])) 131 return (-1); 132 } 133 } 134 a->resources.pci.irq = 135 (byte) divasa_get_pci_irq(a->resources.pci.bus, 136 a->resources.pci.func, 137 a->resources.pci.hdev); 138 if (!a->resources.pci.irq) { 139 DBG_ERR(("A: invalid irq")); 140 return (-1); 141 } 142 143 /* 144 Map all BAR's 145 */ 146 for (bar = 0; bar < 5; bar++) { 147 a->resources.pci.addr[bar] = 148 divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar], 149 bar_length[bar]); 150 if (!a->resources.pci.addr[bar]) { 151 DBG_ERR(("A: A(%d), can't map bar[%d]", 152 a->controller, bar)) 153 diva_pri_cleanup_adapter(a); 154 return (-1); 155 } 156 } 157 158 /* 159 Set all memory areas 160 */ 161 diva_pri_set_addresses(a); 162 163 /* 164 Get Serial Number of this adapter 165 */ 166 if (pri_get_serial_number(a)) { 167 dword serNo; 168 serNo = a->resources.pci.bar[1] & 0xffff0000; 169 serNo |= ((dword) a->resources.pci.bus) << 8; 170 serNo += (a->resources.pci.func + a->controller + 1); 171 a->xdi_adapter.serialNo = serNo & ~0xFF000000; 172 DBG_ERR(("A: A(%d) can't get Serial Number, generated serNo=%ld", 173 a->controller, a->xdi_adapter.serialNo)) 174 } 175 176 177 /* 178 Initialize os objects 179 */ 180 if (diva_os_initialize_spin_lock(&a->xdi_adapter.isr_spin_lock, "isr")) { 181 diva_pri_cleanup_adapter(a); 182 return (-1); 183 } 184 if (diva_os_initialize_spin_lock 185 (&a->xdi_adapter.data_spin_lock, "data")) { 186 diva_pri_cleanup_adapter(a); 187 return (-1); 188 } 189 190 strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasprid"); 191 192 if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr, 193 DIDpcRoutine, &a->xdi_adapter)) { 194 diva_pri_cleanup_adapter(a); 195 return (-1); 196 } 197 198 /* 199 Do not initialize second DPC - only one thread will be created 200 */ 201 a->xdi_adapter.isr_soft_isr.object = 202 a->xdi_adapter.req_soft_isr.object; 203 204 /* 205 Next step of card initialization: 206 set up all interface pointers 207 */ 208 a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels; 209 a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info; 210 211 a->xdi_adapter.e_tbl = 212 diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO)); 213 if (!a->xdi_adapter.e_tbl) { 214 diva_pri_cleanup_adapter(a); 215 return (-1); 216 } 217 memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO)); 218 219 a->xdi_adapter.a.io = &a->xdi_adapter; 220 a->xdi_adapter.DIRequest = request; 221 a->interface.cleanup_adapter_proc = diva_pri_cleanup_adapter; 222 a->interface.cmd_proc = diva_pri_cmd_card_proc; 223 224 if (pri_rev_2) { 225 prepare_pri2_functions(&a->xdi_adapter); 226 } else { 227 prepare_pri_functions(&a->xdi_adapter); 228 } 229 230 a->dsp_mask = diva_pri_detect_dsps(a); 231 232 /* 233 Allocate DMA map 234 */ 235 if (pri_rev_2) { 236 diva_init_dma_map(a->resources.pci.hdev, 237 (struct _diva_dma_map_entry **) &a->xdi_adapter.dma_map, 32); 238 } 239 240 /* 241 Set IRQ handler 242 */ 243 a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq; 244 sprintf(a->xdi_adapter.irq_info.irq_name, 245 "DIVA PRI %ld", (long) a->xdi_adapter.serialNo); 246 247 if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr, 248 a->xdi_adapter.irq_info.irq_name)) { 249 diva_pri_cleanup_adapter(a); 250 return (-1); 251 } 252 a->xdi_adapter.irq_info.registered = 1; 253 254 diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name, 255 a->resources.pci.irq, a->xdi_adapter.serialNo); 256 257 return (0); 258} 259 260static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t * a) 261{ 262 int bar = 0; 263 264 /* 265 Stop Adapter if adapter is running 266 */ 267 if (a->xdi_adapter.Initialized) { 268 diva_pri_stop_adapter(a); 269 } 270 271 /* 272 Remove ISR Handler 273 */ 274 if (a->xdi_adapter.irq_info.registered) { 275 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr); 276 } 277 a->xdi_adapter.irq_info.registered = 0; 278 279 /* 280 Step 1: unmap all BAR's, if any was mapped 281 */ 282 for (bar = 0; bar < 5; bar++) { 283 if (a->resources.pci.bar[bar] 284 && a->resources.pci.addr[bar]) { 285 divasa_unmap_pci_bar(a->resources.pci.addr[bar]); 286 a->resources.pci.bar[bar] = 0; 287 a->resources.pci.addr[bar] = NULL; 288 } 289 } 290 291 /* 292 Free OS objects 293 */ 294 diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr); 295 diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr); 296 297 diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr); 298 a->xdi_adapter.isr_soft_isr.object = NULL; 299 300 diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm"); 301 diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm"); 302 303 /* 304 Free memory accupied by XDI adapter 305 */ 306 if (a->xdi_adapter.e_tbl) { 307 diva_os_free(0, a->xdi_adapter.e_tbl); 308 a->xdi_adapter.e_tbl = NULL; 309 } 310 a->xdi_adapter.Channels = 0; 311 a->xdi_adapter.e_max = 0; 312 313 314 /* 315 Free adapter DMA map 316 */ 317 diva_free_dma_map(a->resources.pci.hdev, 318 (struct _diva_dma_map_entry *) a->xdi_adapter. 319 dma_map); 320 a->xdi_adapter.dma_map = NULL; 321 322 323 /* 324 Detach this adapter from debug driver 325 */ 326 327 return (0); 328} 329 330/* 331** Activate On Board Boot Loader 332*/ 333static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter) 334{ 335 dword i; 336 struct mp_load __iomem *boot; 337 338 if (!IoAdapter->Address || !IoAdapter->reset) { 339 return (-1); 340 } 341 if (IoAdapter->Initialized) { 342 DBG_ERR(("A: A(%d) can't reset PRI adapter - please stop first", 343 IoAdapter->ANum)) 344 return (-1); 345 } 346 347 boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); 348 WRITE_DWORD(&boot->err, 0); 349 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); 350 351 IoAdapter->rstFnc(IoAdapter); 352 353 diva_os_wait(10); 354 355 boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); 356 i = READ_DWORD(&boot->live); 357 358 diva_os_wait(10); 359 if (i == READ_DWORD(&boot->live)) { 360 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); 361 DBG_ERR(("A: A(%d) CPU on PRI %ld is not alive!", 362 IoAdapter->ANum, IoAdapter->serialNo)) 363 return (-1); 364 } 365 if (READ_DWORD(&boot->err)) { 366 DBG_ERR(("A: A(%d) PRI %ld Board Selftest failed, error=%08lx", 367 IoAdapter->ANum, IoAdapter->serialNo, 368 READ_DWORD(&boot->err))) 369 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); 370 return (-1); 371 } 372 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); 373 374 /* 375 Forget all outstanding entities 376 */ 377 IoAdapter->e_count = 0; 378 if (IoAdapter->e_tbl) { 379 memset(IoAdapter->e_tbl, 0x00, 380 IoAdapter->e_max * sizeof(E_INFO)); 381 } 382 IoAdapter->head = 0; 383 IoAdapter->tail = 0; 384 IoAdapter->assign = 0; 385 IoAdapter->trapped = 0; 386 387 memset(&IoAdapter->a.IdTable[0], 0x00, 388 sizeof(IoAdapter->a.IdTable)); 389 memset(&IoAdapter->a.IdTypeTable[0], 0x00, 390 sizeof(IoAdapter->a.IdTypeTable)); 391 memset(&IoAdapter->a.FlowControlIdTable[0], 0x00, 392 sizeof(IoAdapter->a.FlowControlIdTable)); 393 memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00, 394 sizeof(IoAdapter->a.FlowControlSkipTable)); 395 memset(&IoAdapter->a.misc_flags_table[0], 0x00, 396 sizeof(IoAdapter->a.misc_flags_table)); 397 memset(&IoAdapter->a.rx_stream[0], 0x00, 398 sizeof(IoAdapter->a.rx_stream)); 399 memset(&IoAdapter->a.tx_stream[0], 0x00, 400 sizeof(IoAdapter->a.tx_stream)); 401 memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos)); 402 memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos)); 403 404 return (0); 405} 406 407static int 408diva_pri_write_sdram_block(PISDN_ADAPTER IoAdapter, 409 dword address, 410 const byte * data, dword length, dword limit) 411{ 412 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); 413 byte __iomem *mem = p; 414 415 if (((address + length) >= limit) || !mem) { 416 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); 417 DBG_ERR(("A: A(%d) write PRI address=0x%08lx", 418 IoAdapter->ANum, address + length)) 419 return (-1); 420 } 421 mem += address; 422 423 /* memcpy_toio(), maybe? */ 424 while (length--) { 425 WRITE_BYTE(mem++, *data++); 426 } 427 428 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); 429 return (0); 430} 431 432static int 433diva_pri_start_adapter(PISDN_ADAPTER IoAdapter, 434 dword start_address, dword features) 435{ 436 dword i; 437 int started = 0; 438 byte __iomem *p; 439 struct mp_load __iomem *boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); 440 ADAPTER *a = &IoAdapter->a; 441 442 if (IoAdapter->Initialized) { 443 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); 444 DBG_ERR(("A: A(%d) pri_start_adapter, adapter already running", 445 IoAdapter->ANum)) 446 return (-1); 447 } 448 if (!boot) { 449 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); 450 DBG_ERR(("A: PRI %ld can't start, adapter not mapped", 451 IoAdapter->serialNo)) 452 return (-1); 453 } 454 455 sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum); 456 DBG_LOG(("A(%d) start PRI at 0x%08lx", IoAdapter->ANum, 457 start_address)) 458 459 WRITE_DWORD(&boot->addr, start_address); 460 WRITE_DWORD(&boot->cmd, 3); 461 462 for (i = 0; i < 300; ++i) { 463 diva_os_wait(10); 464 if ((READ_DWORD(&boot->signature) >> 16) == 0x4447) { 465 DBG_LOG(("A(%d) Protocol startup time %d.%02d seconds", 466 IoAdapter->ANum, (i / 100), (i % 100))) 467 started = 1; 468 break; 469 } 470 } 471 472 if (!started) { 473 byte __iomem *p = (byte __iomem *)boot; 474 dword TrapId; 475 dword debug; 476 TrapId = READ_DWORD(&p[0x80]); 477 debug = READ_DWORD(&p[0x1c]); 478 DBG_ERR(("A(%d) Adapter start failed 0x%08lx, TrapId=%08lx, debug=%08lx", 479 IoAdapter->ANum, READ_DWORD(&boot->signature), 480 TrapId, debug)) 481 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); 482 if (IoAdapter->trapFnc) { 483 (*(IoAdapter->trapFnc)) (IoAdapter); 484 } 485 IoAdapter->stop(IoAdapter); 486 return (-1); 487 } 488 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); 489 490 IoAdapter->Initialized = true; 491 492 /* 493 Check Interrupt 494 */ 495 IoAdapter->IrqCount = 0; 496 p = DIVA_OS_MEM_ATTACH_CFG(IoAdapter); 497 WRITE_DWORD(p, (dword) ~ 0x03E00000); 498 DIVA_OS_MEM_DETACH_CFG(IoAdapter, p); 499 a->ReadyInt = 1; 500 a->ram_out(a, &PR_RAM->ReadyInt, 1); 501 502 for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10)); 503 504 if (!IoAdapter->IrqCount) { 505 DBG_ERR(("A: A(%d) interrupt test failed", 506 IoAdapter->ANum)) 507 IoAdapter->Initialized = false; 508 IoAdapter->stop(IoAdapter); 509 return (-1); 510 } 511 512 IoAdapter->Properties.Features = (word) features; 513 514 diva_xdi_display_adapter_features(IoAdapter->ANum); 515 516 DBG_LOG(("A(%d) PRI adapter successfull started", IoAdapter->ANum)) 517 /* 518 Register with DIDD 519 */ 520 diva_xdi_didd_register_adapter(IoAdapter->ANum); 521 522 return (0); 523} 524 525static void diva_pri_clear_interrupts(diva_os_xdi_adapter_t * a) 526{ 527 PISDN_ADAPTER IoAdapter = &a->xdi_adapter; 528 529 /* 530 clear any pending interrupt 531 */ 532 IoAdapter->disIrq(IoAdapter); 533 534 IoAdapter->tst_irq(&IoAdapter->a); 535 IoAdapter->clr_irq(&IoAdapter->a); 536 IoAdapter->tst_irq(&IoAdapter->a); 537 538 /* 539 kill pending dpcs 540 */ 541 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr); 542 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr); 543} 544 545/* 546** Stop Adapter, but do not unmap/unregister - adapter 547** will be restarted later 548*/ 549static int diva_pri_stop_adapter(diva_os_xdi_adapter_t * a) 550{ 551 PISDN_ADAPTER IoAdapter = &a->xdi_adapter; 552 int i = 100; 553 554 if (!IoAdapter->ram) { 555 return (-1); 556 } 557 if (!IoAdapter->Initialized) { 558 DBG_ERR(("A: A(%d) can't stop PRI adapter - not running", 559 IoAdapter->ANum)) 560 return (-1); /* nothing to stop */ 561 } 562 IoAdapter->Initialized = 0; 563 564 /* 565 Disconnect Adapter from DIDD 566 */ 567 diva_xdi_didd_remove_adapter(IoAdapter->ANum); 568 569 /* 570 Stop interrupts 571 */ 572 a->clear_interrupts_proc = diva_pri_clear_interrupts; 573 IoAdapter->a.ReadyInt = 1; 574 IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt); 575 do { 576 diva_os_sleep(10); 577 } while (i-- && a->clear_interrupts_proc); 578 579 if (a->clear_interrupts_proc) { 580 diva_pri_clear_interrupts(a); 581 a->clear_interrupts_proc = NULL; 582 DBG_ERR(("A: A(%d) no final interrupt from PRI adapter", 583 IoAdapter->ANum)) 584 } 585 IoAdapter->a.ReadyInt = 0; 586 587 /* 588 Stop and reset adapter 589 */ 590 IoAdapter->stop(IoAdapter); 591 592 return (0); 593} 594 595/* 596** Process commands form configuration/download framework and from 597** user mode 598** 599** return 0 on success 600*/ 601static int 602diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a, 603 diva_xdi_um_cfg_cmd_t * cmd, int length) 604{ 605 int ret = -1; 606 607 if (cmd->adapter != a->controller) { 608 DBG_ERR(("A: pri_cmd, invalid controller=%d != %d", 609 cmd->adapter, a->controller)) 610 return (-1); 611 } 612 613 switch (cmd->command) { 614 case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL: 615 a->xdi_mbox.data_length = sizeof(dword); 616 a->xdi_mbox.data = 617 diva_os_malloc(0, a->xdi_mbox.data_length); 618 if (a->xdi_mbox.data) { 619 *(dword *) a->xdi_mbox.data = 620 (dword) a->CardOrdinal; 621 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 622 ret = 0; 623 } 624 break; 625 626 case DIVA_XDI_UM_CMD_GET_SERIAL_NR: 627 a->xdi_mbox.data_length = sizeof(dword); 628 a->xdi_mbox.data = 629 diva_os_malloc(0, a->xdi_mbox.data_length); 630 if (a->xdi_mbox.data) { 631 *(dword *) a->xdi_mbox.data = 632 (dword) a->xdi_adapter.serialNo; 633 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 634 ret = 0; 635 } 636 break; 637 638 case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG: 639 a->xdi_mbox.data_length = sizeof(dword) * 9; 640 a->xdi_mbox.data = 641 diva_os_malloc(0, a->xdi_mbox.data_length); 642 if (a->xdi_mbox.data) { 643 int i; 644 dword *data = (dword *) a->xdi_mbox.data; 645 646 for (i = 0; i < 8; i++) { 647 *data++ = a->resources.pci.bar[i]; 648 } 649 *data++ = (dword) a->resources.pci.irq; 650 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 651 ret = 0; 652 } 653 break; 654 655 case DIVA_XDI_UM_CMD_RESET_ADAPTER: 656 ret = diva_pri_reset_adapter(&a->xdi_adapter); 657 break; 658 659 case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK: 660 ret = diva_pri_write_sdram_block(&a->xdi_adapter, 661 cmd->command_data. 662 write_sdram.offset, 663 (byte *) & cmd[1], 664 cmd->command_data. 665 write_sdram.length, 666 pri_is_rev_2_card(a-> 667 CardOrdinal) 668 ? MP2_MEMORY_SIZE : 669 MP_MEMORY_SIZE); 670 break; 671 672 case DIVA_XDI_UM_CMD_STOP_ADAPTER: 673 ret = diva_pri_stop_adapter(a); 674 break; 675 676 case DIVA_XDI_UM_CMD_START_ADAPTER: 677 ret = diva_pri_start_adapter(&a->xdi_adapter, 678 cmd->command_data.start. 679 offset, 680 cmd->command_data.start. 681 features); 682 break; 683 684 case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES: 685 a->xdi_adapter.features = 686 cmd->command_data.features.features; 687 a->xdi_adapter.a.protocol_capabilities = 688 a->xdi_adapter.features; 689 DBG_TRC(("Set raw protocol features (%08x)", 690 a->xdi_adapter.features)) 691 ret = 0; 692 break; 693 694 case DIVA_XDI_UM_CMD_GET_CARD_STATE: 695 a->xdi_mbox.data_length = sizeof(dword); 696 a->xdi_mbox.data = 697 diva_os_malloc(0, a->xdi_mbox.data_length); 698 if (a->xdi_mbox.data) { 699 dword *data = (dword *) a->xdi_mbox.data; 700 if (!a->xdi_adapter.ram || 701 !a->xdi_adapter.reset || 702 !a->xdi_adapter.cfg) { 703 *data = 3; 704 } else if (a->xdi_adapter.trapped) { 705 *data = 2; 706 } else if (a->xdi_adapter.Initialized) { 707 *data = 1; 708 } else { 709 *data = 0; 710 } 711 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 712 ret = 0; 713 } 714 break; 715 716 case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY: 717 ret = diva_card_read_xlog(a); 718 break; 719 720 case DIVA_XDI_UM_CMD_READ_SDRAM: 721 if (a->xdi_adapter.Address) { 722 if ( 723 (a->xdi_mbox.data_length = 724 cmd->command_data.read_sdram.length)) { 725 if ( 726 (a->xdi_mbox.data_length + 727 cmd->command_data.read_sdram.offset) < 728 a->xdi_adapter.MemorySize) { 729 a->xdi_mbox.data = 730 diva_os_malloc(0, 731 a->xdi_mbox. 732 data_length); 733 if (a->xdi_mbox.data) { 734 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter); 735 byte __iomem *src = p; 736 byte *dst = a->xdi_mbox.data; 737 dword len = a->xdi_mbox.data_length; 738 739 src += cmd->command_data.read_sdram.offset; 740 741 while (len--) { 742 *dst++ = READ_BYTE(src++); 743 } 744 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 745 DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p); 746 ret = 0; 747 } 748 } 749 } 750 } 751 break; 752 753 default: 754 DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller, 755 cmd->command)) 756 } 757 758 return (ret); 759} 760 761/* 762** Get Serial Number 763*/ 764static int pri_get_serial_number(diva_os_xdi_adapter_t * a) 765{ 766 byte data[64]; 767 int i; 768 dword len = sizeof(data); 769 volatile byte __iomem *config; 770 volatile byte __iomem *flash; 771 byte c; 772 773/* 774 * First set some GT6401x config registers before accessing the BOOT-ROM 775 */ 776 config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); 777 c = READ_BYTE(&config[0xc3c]); 778 if (!(c & 0x08)) { 779 WRITE_BYTE(&config[0xc3c], c); /* Base Address enable register */ 780 } 781 WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0x00); 782 WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF); 783 DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); 784/* 785 * Read only the last 64 bytes of manufacturing data 786 */ 787 memset(data, '\0', len); 788 flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter); 789 for (i = 0; i < len; i++) { 790 data[i] = READ_BYTE(&flash[0x8000 - len + i]); 791 } 792 DIVA_OS_MEM_DETACH_PROM(&a->xdi_adapter, flash); 793 794 config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); 795 WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0xFC); /* Disable FLASH EPROM access */ 796 WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF); 797 DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); 798 799 if (memcmp(&data[48], "DIVAserverPR", 12)) { 800#if !defined(DIVA_PRI_NO_PCI_BIOS_WORKAROUND) /* { */ 801 word cmd = 0, cmd_org; 802 void *addr; 803 dword addr1, addr3, addr4; 804 byte Bus, Slot; 805 void *hdev; 806 addr4 = a->resources.pci.bar[4]; 807 addr3 = a->resources.pci.bar[3]; /* flash */ 808 addr1 = a->resources.pci.bar[1]; /* unused */ 809 810 DBG_ERR(("A: apply Compaq BIOS workaround")) 811 DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 812 data[0], data[1], data[2], data[3], 813 data[4], data[5], data[6], data[7])) 814 815 Bus = a->resources.pci.bus; 816 Slot = a->resources.pci.func; 817 hdev = a->resources.pci.hdev; 818 PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev); 819 PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev); 820 821 PCIwrite(Bus, Slot, 0x14, &addr4, sizeof(addr4), hdev); 822 PCIwrite(Bus, Slot, 0x20, &addr1, sizeof(addr1), hdev); 823 824 PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev); 825 826 addr = a->resources.pci.addr[1]; 827 a->resources.pci.addr[1] = a->resources.pci.addr[4]; 828 a->resources.pci.addr[4] = addr; 829 830 addr1 = a->resources.pci.bar[1]; 831 a->resources.pci.bar[1] = a->resources.pci.bar[4]; 832 a->resources.pci.bar[4] = addr1; 833 834 /* 835 Try to read Flash again 836 */ 837 len = sizeof(data); 838 839 config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); 840 if (!(config[0xc3c] & 0x08)) { 841 config[0xc3c] |= 0x08; /* Base Address enable register */ 842 } 843 config[LOW_BOOTCS_DREG] = 0x00; 844 config[HI_BOOTCS_DREG] = 0xFF; 845 DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); 846 847 memset(data, '\0', len); 848 flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter); 849 for (i = 0; i < len; i++) { 850 data[i] = flash[0x8000 - len + i]; 851 } 852 DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter, flash); 853 config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); 854 config[LOW_BOOTCS_DREG] = 0xFC; 855 config[HI_BOOTCS_DREG] = 0xFF; 856 DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); 857 858 if (memcmp(&data[48], "DIVAserverPR", 12)) { 859 DBG_ERR(("A: failed to read serial number")) 860 DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 861 data[0], data[1], data[2], data[3], 862 data[4], data[5], data[6], data[7])) 863 return (-1); 864 } 865#else /* } { */ 866 DBG_ERR(("A: failed to read DIVA signature word")) 867 DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 868 data[0], data[1], data[2], data[3], 869 data[4], data[5], data[6], data[7])) 870 DBG_LOG(("%02x:%02x:%02x:%02x", data[47], data[46], 871 data[45], data[44])) 872#endif /* } */ 873 } 874 875 a->xdi_adapter.serialNo = 876 (data[47] << 24) | (data[46] << 16) | (data[45] << 8) | 877 data[44]; 878 if (!a->xdi_adapter.serialNo 879 || (a->xdi_adapter.serialNo == 0xffffffff)) { 880 a->xdi_adapter.serialNo = 0; 881 DBG_ERR(("A: failed to read serial number")) 882 return (-1); 883 } 884 885 DBG_LOG(("Serial No. : %ld", a->xdi_adapter.serialNo)) 886 DBG_TRC(("Board Revision : %d.%02d", (int) data[41], 887 (int) data[40])) 888 DBG_TRC(("PLD revision : %d.%02d", (int) data[33], 889 (int) data[32])) 890 DBG_TRC(("Boot loader version : %d.%02d", (int) data[37], 891 (int) data[36])) 892 893 DBG_TRC(("Manufacturing Date : %d/%02d/%02d (yyyy/mm/dd)", 894 (int) ((data[28] > 90) ? 1900 : 2000) + 895 (int) data[28], (int) data[29], (int) data[30])) 896 897 return (0); 898} 899 900void diva_os_prepare_pri2_functions(PISDN_ADAPTER IoAdapter) 901{ 902} 903 904void diva_os_prepare_pri_functions(PISDN_ADAPTER IoAdapter) 905{ 906} 907 908/* 909** Checks presence of DSP on board 910*/ 911static int 912dsp_check_presence(volatile byte __iomem * addr, volatile byte __iomem * data, int dsp) 913{ 914 word pattern; 915 916 WRITE_WORD(addr, 0x4000); 917 WRITE_WORD(data, DSP_SIGNATURE_PROBE_WORD); 918 919 WRITE_WORD(addr, 0x4000); 920 pattern = READ_WORD(data); 921 922 if (pattern != DSP_SIGNATURE_PROBE_WORD) { 923 DBG_TRC(("W: DSP[%d] %04x(is) != %04x(should)", 924 dsp, pattern, DSP_SIGNATURE_PROBE_WORD)) 925 return (-1); 926 } 927 928 WRITE_WORD(addr, 0x4000); 929 WRITE_WORD(data, ~DSP_SIGNATURE_PROBE_WORD); 930 931 WRITE_WORD(addr, 0x4000); 932 pattern = READ_WORD(data); 933 934 if (pattern != (word) ~ DSP_SIGNATURE_PROBE_WORD) { 935 DBG_ERR(("A: DSP[%d] %04x(is) != %04x(should)", 936 dsp, pattern, (word) ~ DSP_SIGNATURE_PROBE_WORD)) 937 return (-2); 938 } 939 940 DBG_TRC(("DSP[%d] present", dsp)) 941 942 return (0); 943} 944 945 946/* 947** Check if DSP's are present and operating 948** Information about detected DSP's is returned as bit mask 949** Bit 0 - DSP1 950** ... 951** ... 952** ... 953** Bit 29 - DSP30 954*/ 955static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a) 956{ 957 byte __iomem *base; 958 byte __iomem *p; 959 dword ret = 0; 960 dword row_offset[7] = { 961 0x00000000, 962 0x00000800, /* 1 - ROW 1 */ 963 0x00000840, /* 2 - ROW 2 */ 964 0x00001000, /* 3 - ROW 3 */ 965 0x00001040, /* 4 - ROW 4 */ 966 0x00000000 /* 5 - ROW 0 */ 967 }; 968 969 byte __iomem *dsp_addr_port; 970 byte __iomem *dsp_data_port; 971 byte row_state; 972 int dsp_row = 0, dsp_index, dsp_num; 973 974 if (!a->xdi_adapter.Control || !a->xdi_adapter.reset) { 975 return (0); 976 } 977 978 p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); 979 WRITE_BYTE(p, _MP_RISC_RESET | _MP_DSP_RESET); 980 DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); 981 diva_os_wait(5); 982 983 base = DIVA_OS_MEM_ATTACH_CONTROL(&a->xdi_adapter); 984 985 for (dsp_num = 0; dsp_num < 30; dsp_num++) { 986 dsp_row = dsp_num / 7 + 1; 987 dsp_index = dsp_num % 7; 988 989 dsp_data_port = base; 990 dsp_addr_port = base; 991 992 dsp_data_port += row_offset[dsp_row]; 993 dsp_addr_port += row_offset[dsp_row]; 994 995 dsp_data_port += (dsp_index * 8); 996 dsp_addr_port += (dsp_index * 8) + 0x80; 997 998 if (!dsp_check_presence 999 (dsp_addr_port, dsp_data_port, dsp_num + 1)) { 1000 ret |= (1 << dsp_num); 1001 } 1002 } 1003 DIVA_OS_MEM_DETACH_CONTROL(&a->xdi_adapter, base); 1004 1005 p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); 1006 WRITE_BYTE(p, _MP_RISC_RESET | _MP_LED1 | _MP_LED2); 1007 DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); 1008 diva_os_wait(5); 1009 1010 /* 1011 Verify modules 1012 */ 1013 for (dsp_row = 0; dsp_row < 4; dsp_row++) { 1014 row_state = ((ret >> (dsp_row * 7)) & 0x7F); 1015 if (row_state && (row_state != 0x7F)) { 1016 for (dsp_index = 0; dsp_index < 7; dsp_index++) { 1017 if (!(row_state & (1 << dsp_index))) { 1018 DBG_ERR(("A: MODULE[%d]-DSP[%d] failed", 1019 dsp_row + 1, 1020 dsp_index + 1)) 1021 } 1022 } 1023 } 1024 } 1025 1026 if (!(ret & 0x10000000)) { 1027 DBG_ERR(("A: ON BOARD-DSP[1] failed")) 1028 } 1029 if (!(ret & 0x20000000)) { 1030 DBG_ERR(("A: ON BOARD-DSP[2] failed")) 1031 } 1032 1033 /* 1034 Print module population now 1035 */ 1036 DBG_LOG(("+-----------------------+")) 1037 DBG_LOG(("| DSP MODULE POPULATION |")) 1038 DBG_LOG(("+-----------------------+")) 1039 DBG_LOG(("| 1 | 2 | 3 | 4 |")) 1040 DBG_LOG(("+-----------------------+")) 1041 DBG_LOG(("| %s | %s | %s | %s |", 1042 ((ret >> (0 * 7)) & 0x7F) ? "Y" : "N", 1043 ((ret >> (1 * 7)) & 0x7F) ? "Y" : "N", 1044 ((ret >> (2 * 7)) & 0x7F) ? "Y" : "N", 1045 ((ret >> (3 * 7)) & 0x7F) ? "Y" : "N")) 1046 DBG_LOG(("+-----------------------+")) 1047 1048 DBG_LOG(("DSP's(present-absent):%08x-%08x", ret, 1049 ~ret & 0x3fffffff)) 1050 1051 return (ret); 1052} 1053