1/* $Id: os_bri.c,v 1.21 2004/03/21 17:26:01 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_bri.h" 16#include "diva_pci.h" 17#include "mi_pc.h" 18#include "pc_maint.h" 19#include "dsrv_bri.h" 20 21/* 22** IMPORTS 23*/ 24extern void prepare_maestra_functions(PISDN_ADAPTER IoAdapter); 25extern void diva_xdi_display_adapter_features(int card); 26extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a); 27 28/* 29** LOCALS 30*/ 31static int bri_bar_length[3] = { 32 0x80, 33 0x80, 34 0x20 35}; 36static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t *a); 37static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t *a); 38static int diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, 39 diva_xdi_um_cfg_cmd_t *cmd, int length); 40static int diva_bri_reregister_io(diva_os_xdi_adapter_t *a); 41static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter); 42static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter, 43 dword address, 44 const byte *data, dword length); 45static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter, 46 dword start_address, dword features); 47static int diva_bri_stop_adapter(diva_os_xdi_adapter_t *a); 48 49static void diva_bri_set_addresses(diva_os_xdi_adapter_t *a) 50{ 51 a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0; 52 a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 1; 53 a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2; 54 a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 1; 55 a->resources.pci.mem_type_id[MEM_TYPE_PORT] = 2; 56 a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 2; 57 58 a->xdi_adapter.ram = a->resources.pci.addr[0]; 59 a->xdi_adapter.cfg = a->resources.pci.addr[1]; 60 a->xdi_adapter.Address = a->resources.pci.addr[2]; 61 62 a->xdi_adapter.reset = a->xdi_adapter.cfg; 63 a->xdi_adapter.port = a->xdi_adapter.Address; 64 65 a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET; 66 67 a->xdi_adapter.reset += 0x4C; /* PLX 9050 !! */ 68} 69 70/* 71** BAR0 - MEM Addr - 0x80 - NOT USED 72** BAR1 - I/O Addr - 0x80 73** BAR2 - I/O Addr - 0x20 74*/ 75int diva_bri_init_card(diva_os_xdi_adapter_t *a) 76{ 77 int bar; 78 dword bar2 = 0, bar2_length = 0xffffffff; 79 word cmd = 0, cmd_org; 80 byte Bus, Slot; 81 void *hdev; 82 byte __iomem *p; 83 84 /* 85 Set properties 86 */ 87 a->xdi_adapter.Properties = CardProperties[a->CardOrdinal]; 88 DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name)) 89 90 /* 91 Get resources 92 */ 93 for (bar = 0; bar < 3; bar++) { 94 a->resources.pci.bar[bar] = 95 divasa_get_pci_bar(a->resources.pci.bus, 96 a->resources.pci.func, bar, 97 a->resources.pci.hdev); 98 if (!a->resources.pci.bar[bar]) { 99 DBG_ERR(("A: can't get BAR[%d]", bar)) 100 return (-1); 101 } 102 } 103 104 a->resources.pci.irq = 105 (byte) divasa_get_pci_irq(a->resources.pci.bus, 106 a->resources.pci.func, 107 a->resources.pci.hdev); 108 if (!a->resources.pci.irq) { 109 DBG_ERR(("A: invalid irq")); 110 return (-1); 111 } 112 113 /* 114 Get length of I/O bar 2 - it is different by older 115 EEPROM version 116 */ 117 Bus = a->resources.pci.bus; 118 Slot = a->resources.pci.func; 119 hdev = a->resources.pci.hdev; 120 121 /* 122 Get plain original values of the BAR2 CDM registers 123 */ 124 PCIread(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev); 125 PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev); 126 /* 127 Disable device and get BAR2 length 128 */ 129 PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev); 130 PCIwrite(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev); 131 PCIread(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev); 132 /* 133 Restore BAR2 and CMD registers 134 */ 135 PCIwrite(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev); 136 PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev); 137 138 /* 139 Calculate BAR2 length 140 */ 141 bar2_length = (~(bar2_length & ~7)) + 1; 142 DBG_LOG(("BAR[2] length=%lx", bar2_length)) 143 144 /* 145 Map and register resources 146 */ 147 if (!(a->resources.pci.addr[0] = 148 divasa_remap_pci_bar(a, 0, a->resources.pci.bar[0], 149 bri_bar_length[0]))) { 150 DBG_ERR(("A: BRI, can't map BAR[0]")) 151 diva_bri_cleanup_adapter(a); 152 return (-1); 153 } 154 155 sprintf(&a->port_name[0], "BRI %02x:%02x", 156 a->resources.pci.bus, a->resources.pci.func); 157 158 if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1], 159 bri_bar_length[1], &a->port_name[0], 1)) { 160 DBG_ERR(("A: BRI, can't register BAR[1]")) 161 diva_bri_cleanup_adapter(a); 162 return (-1); 163 } 164 a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1]; 165 a->resources.pci.length[1] = bri_bar_length[1]; 166 167 if (diva_os_register_io_port(a, 1, a->resources.pci.bar[2], 168 bar2_length, &a->port_name[0], 2)) { 169 DBG_ERR(("A: BRI, can't register BAR[2]")) 170 diva_bri_cleanup_adapter(a); 171 return (-1); 172 } 173 a->resources.pci.addr[2] = (void *) (unsigned long) a->resources.pci.bar[2]; 174 a->resources.pci.length[2] = bar2_length; 175 176 /* 177 Set all memory areas 178 */ 179 diva_bri_set_addresses(a); 180 181 /* 182 Get Serial Number 183 */ 184 a->xdi_adapter.serialNo = diva_bri_get_serial_number(a); 185 186 /* 187 Register I/O ports with correct name now 188 */ 189 if (diva_bri_reregister_io(a)) { 190 diva_bri_cleanup_adapter(a); 191 return (-1); 192 } 193 194 /* 195 Initialize OS dependent objects 196 */ 197 if (diva_os_initialize_spin_lock 198 (&a->xdi_adapter.isr_spin_lock, "isr")) { 199 diva_bri_cleanup_adapter(a); 200 return (-1); 201 } 202 if (diva_os_initialize_spin_lock 203 (&a->xdi_adapter.data_spin_lock, "data")) { 204 diva_bri_cleanup_adapter(a); 205 return (-1); 206 } 207 208 strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasbrid"); 209 210 if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr, 211 DIDpcRoutine, &a->xdi_adapter)) { 212 diva_bri_cleanup_adapter(a); 213 return (-1); 214 } 215 /* 216 Do not initialize second DPC - only one thread will be created 217 */ 218 a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object; 219 220 /* 221 Create entity table 222 */ 223 a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels; 224 a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info; 225 a->xdi_adapter.e_tbl = diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO)); 226 if (!a->xdi_adapter.e_tbl) { 227 diva_bri_cleanup_adapter(a); 228 return (-1); 229 } 230 memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO)); 231 232 /* 233 Set up interface 234 */ 235 a->xdi_adapter.a.io = &a->xdi_adapter; 236 a->xdi_adapter.DIRequest = request; 237 a->interface.cleanup_adapter_proc = diva_bri_cleanup_adapter; 238 a->interface.cmd_proc = diva_bri_cmd_card_proc; 239 240 p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); 241 outpp(p, 0x41); 242 DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); 243 244 prepare_maestra_functions(&a->xdi_adapter); 245 246 a->dsp_mask = 0x00000003; 247 248 /* 249 Set IRQ handler 250 */ 251 a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq; 252 sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA BRI %ld", 253 (long) a->xdi_adapter.serialNo); 254 if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr, 255 a->xdi_adapter.irq_info.irq_name)) { 256 diva_bri_cleanup_adapter(a); 257 return (-1); 258 } 259 a->xdi_adapter.irq_info.registered = 1; 260 261 diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name, 262 a->resources.pci.irq, a->xdi_adapter.serialNo); 263 264 return (0); 265} 266 267 268static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t *a) 269{ 270 int i; 271 272 if (a->xdi_adapter.Initialized) { 273 diva_bri_stop_adapter(a); 274 } 275 276 /* 277 Remove ISR Handler 278 */ 279 if (a->xdi_adapter.irq_info.registered) { 280 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr); 281 } 282 a->xdi_adapter.irq_info.registered = 0; 283 284 if (a->resources.pci.addr[0] && a->resources.pci.bar[0]) { 285 divasa_unmap_pci_bar(a->resources.pci.addr[0]); 286 a->resources.pci.addr[0] = NULL; 287 a->resources.pci.bar[0] = 0; 288 } 289 290 for (i = 1; i < 3; i++) { 291 if (a->resources.pci.addr[i] && a->resources.pci.bar[i]) { 292 diva_os_register_io_port(a, 0, 293 a->resources.pci.bar[i], 294 a->resources.pci. 295 length[i], 296 &a->port_name[0], i); 297 a->resources.pci.addr[i] = NULL; 298 a->resources.pci.bar[i] = 0; 299 } 300 } 301 302 /* 303 Free OS objects 304 */ 305 diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr); 306 diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr); 307 308 diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr); 309 a->xdi_adapter.isr_soft_isr.object = NULL; 310 311 diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm"); 312 diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm"); 313 314 /* 315 Free memory 316 */ 317 if (a->xdi_adapter.e_tbl) { 318 diva_os_free(0, a->xdi_adapter.e_tbl); 319 a->xdi_adapter.e_tbl = NULL; 320 } 321 322 return (0); 323} 324 325void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter) 326{ 327} 328 329/* 330** Get serial number 331*/ 332static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t *a) 333{ 334 dword serNo = 0; 335 byte __iomem *confIO; 336 word serHi, serLo; 337 word __iomem *confMem; 338 339 confIO = DIVA_OS_MEM_ATTACH_CFG(&a->xdi_adapter); 340 serHi = (word) (inppw(&confIO[0x22]) & 0x0FFF); 341 serLo = (word) (inppw(&confIO[0x26]) & 0x0FFF); 342 serNo = ((dword) serHi << 16) | (dword) serLo; 343 DIVA_OS_MEM_DETACH_CFG(&a->xdi_adapter, confIO); 344 345 if ((serNo == 0) || (serNo == 0xFFFFFFFF)) { 346 DBG_FTL(("W: BRI use BAR[0] to get card serial number")) 347 348 confMem = (word __iomem *)DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter); 349 serHi = (word) (READ_WORD(&confMem[0x11]) & 0x0FFF); 350 serLo = (word) (READ_WORD(&confMem[0x13]) & 0x0FFF); 351 serNo = (((dword) serHi) << 16) | ((dword) serLo); 352 DIVA_OS_MEM_DETACH_RAM(&a->xdi_adapter, confMem); 353 } 354 355 DBG_LOG(("Serial Number=%ld", serNo)) 356 357 return (serNo); 358} 359 360/* 361** Unregister I/O and register it with new name, 362** based on Serial Number 363*/ 364static int diva_bri_reregister_io(diva_os_xdi_adapter_t *a) 365{ 366 int i; 367 368 for (i = 1; i < 3; i++) { 369 diva_os_register_io_port(a, 0, a->resources.pci.bar[i], 370 a->resources.pci.length[i], 371 &a->port_name[0], i); 372 a->resources.pci.addr[i] = NULL; 373 } 374 375 sprintf(a->port_name, "DIVA BRI %ld", 376 (long) a->xdi_adapter.serialNo); 377 378 for (i = 1; i < 3; i++) { 379 if (diva_os_register_io_port(a, 1, a->resources.pci.bar[i], 380 a->resources.pci.length[i], 381 &a->port_name[0], i)) { 382 DBG_ERR(("A: failed to reregister BAR[%d]", i)) 383 return (-1); 384 } 385 a->resources.pci.addr[i] = 386 (void *) (unsigned long) a->resources.pci.bar[i]; 387 } 388 389 return (0); 390} 391 392/* 393** Process command from user mode 394*/ 395static int 396diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, 397 diva_xdi_um_cfg_cmd_t *cmd, int length) 398{ 399 int ret = -1; 400 401 if (cmd->adapter != a->controller) { 402 DBG_ERR(("A: pri_cmd, invalid controller=%d != %d", 403 cmd->adapter, a->controller)) 404 return (-1); 405 } 406 407 switch (cmd->command) { 408 case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL: 409 a->xdi_mbox.data_length = sizeof(dword); 410 a->xdi_mbox.data = 411 diva_os_malloc(0, a->xdi_mbox.data_length); 412 if (a->xdi_mbox.data) { 413 *(dword *) a->xdi_mbox.data = 414 (dword) a->CardOrdinal; 415 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 416 ret = 0; 417 } 418 break; 419 420 case DIVA_XDI_UM_CMD_GET_SERIAL_NR: 421 a->xdi_mbox.data_length = sizeof(dword); 422 a->xdi_mbox.data = 423 diva_os_malloc(0, a->xdi_mbox.data_length); 424 if (a->xdi_mbox.data) { 425 *(dword *) a->xdi_mbox.data = 426 (dword) a->xdi_adapter.serialNo; 427 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 428 ret = 0; 429 } 430 break; 431 432 case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG: 433 a->xdi_mbox.data_length = sizeof(dword) * 9; 434 a->xdi_mbox.data = 435 diva_os_malloc(0, a->xdi_mbox.data_length); 436 if (a->xdi_mbox.data) { 437 int i; 438 dword *data = (dword *) a->xdi_mbox.data; 439 440 for (i = 0; i < 8; i++) { 441 *data++ = a->resources.pci.bar[i]; 442 } 443 *data++ = (dword) a->resources.pci.irq; 444 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 445 ret = 0; 446 } 447 break; 448 449 case DIVA_XDI_UM_CMD_GET_CARD_STATE: 450 a->xdi_mbox.data_length = sizeof(dword); 451 a->xdi_mbox.data = 452 diva_os_malloc(0, a->xdi_mbox.data_length); 453 if (a->xdi_mbox.data) { 454 dword *data = (dword *) a->xdi_mbox.data; 455 if (!a->xdi_adapter.port) { 456 *data = 3; 457 } else if (a->xdi_adapter.trapped) { 458 *data = 2; 459 } else if (a->xdi_adapter.Initialized) { 460 *data = 1; 461 } else { 462 *data = 0; 463 } 464 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; 465 ret = 0; 466 } 467 break; 468 469 case DIVA_XDI_UM_CMD_RESET_ADAPTER: 470 ret = diva_bri_reset_adapter(&a->xdi_adapter); 471 break; 472 473 case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK: 474 ret = diva_bri_write_sdram_block(&a->xdi_adapter, 475 cmd->command_data. 476 write_sdram.offset, 477 (byte *)&cmd[1], 478 cmd->command_data. 479 write_sdram.length); 480 break; 481 482 case DIVA_XDI_UM_CMD_START_ADAPTER: 483 ret = diva_bri_start_adapter(&a->xdi_adapter, 484 cmd->command_data.start. 485 offset, 486 cmd->command_data.start. 487 features); 488 break; 489 490 case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES: 491 a->xdi_adapter.features = 492 cmd->command_data.features.features; 493 a->xdi_adapter.a.protocol_capabilities = 494 a->xdi_adapter.features; 495 DBG_TRC( 496 ("Set raw protocol features (%08x)", 497 a->xdi_adapter.features)) ret = 0; 498 break; 499 500 case DIVA_XDI_UM_CMD_STOP_ADAPTER: 501 ret = diva_bri_stop_adapter(a); 502 break; 503 504 case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY: 505 ret = diva_card_read_xlog(a); 506 break; 507 508 default: 509 DBG_ERR( 510 ("A: A(%d) invalid cmd=%d", a->controller, 511 cmd->command))} 512 513 return (ret); 514} 515 516static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter) 517{ 518 byte __iomem *addrHi, *addrLo, *ioaddr; 519 dword i; 520 byte __iomem *Port; 521 522 if (!IoAdapter->port) { 523 return (-1); 524 } 525 if (IoAdapter->Initialized) { 526 DBG_ERR(("A: A(%d) can't reset BRI adapter - please stop first", 527 IoAdapter->ANum)) return (-1); 528 } 529 (*(IoAdapter->rstFnc)) (IoAdapter); 530 diva_os_wait(100); 531 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); 532 addrHi = Port + 533 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); 534 addrLo = Port + ADDR; 535 ioaddr = Port + DATA; 536 /* 537 recover 538 */ 539 outpp(addrHi, (byte) 0); 540 outppw(addrLo, (word) 0); 541 outppw(ioaddr, (word) 0); 542 /* 543 clear shared memory 544 */ 545 outpp(addrHi, 546 (byte) ( 547 (IoAdapter->MemoryBase + IoAdapter->MemorySize - 548 BRI_SHARED_RAM_SIZE) >> 16)); 549 outppw(addrLo, 0); 550 for (i = 0; i < 0x8000; outppw(ioaddr, 0), ++i); 551 diva_os_wait(100); 552 553 /* 554 clear signature 555 */ 556 outpp(addrHi, 557 (byte) ( 558 (IoAdapter->MemoryBase + IoAdapter->MemorySize - 559 BRI_SHARED_RAM_SIZE) >> 16)); 560 outppw(addrLo, 0x1e); 561 outpp(ioaddr, 0); 562 outpp(ioaddr, 0); 563 564 outpp(addrHi, (byte) 0); 565 outppw(addrLo, (word) 0); 566 outppw(ioaddr, (word) 0); 567 568 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); 569 570 /* 571 Forget all outstanding entities 572 */ 573 IoAdapter->e_count = 0; 574 if (IoAdapter->e_tbl) { 575 memset(IoAdapter->e_tbl, 0x00, 576 IoAdapter->e_max * sizeof(E_INFO)); 577 } 578 IoAdapter->head = 0; 579 IoAdapter->tail = 0; 580 IoAdapter->assign = 0; 581 IoAdapter->trapped = 0; 582 583 memset(&IoAdapter->a.IdTable[0], 0x00, 584 sizeof(IoAdapter->a.IdTable)); 585 memset(&IoAdapter->a.IdTypeTable[0], 0x00, 586 sizeof(IoAdapter->a.IdTypeTable)); 587 memset(&IoAdapter->a.FlowControlIdTable[0], 0x00, 588 sizeof(IoAdapter->a.FlowControlIdTable)); 589 memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00, 590 sizeof(IoAdapter->a.FlowControlSkipTable)); 591 memset(&IoAdapter->a.misc_flags_table[0], 0x00, 592 sizeof(IoAdapter->a.misc_flags_table)); 593 memset(&IoAdapter->a.rx_stream[0], 0x00, 594 sizeof(IoAdapter->a.rx_stream)); 595 memset(&IoAdapter->a.tx_stream[0], 0x00, 596 sizeof(IoAdapter->a.tx_stream)); 597 memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos)); 598 memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos)); 599 600 return (0); 601} 602 603static int 604diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter, 605 dword address, const byte *data, dword length) 606{ 607 byte __iomem *addrHi, *addrLo, *ioaddr; 608 byte __iomem *Port; 609 610 if (!IoAdapter->port) { 611 return (-1); 612 } 613 614 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); 615 addrHi = Port + 616 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); 617 addrLo = Port + ADDR; 618 ioaddr = Port + DATA; 619 620 while (length--) { 621 outpp(addrHi, (word) (address >> 16)); 622 outppw(addrLo, (word) (address & 0x0000ffff)); 623 outpp(ioaddr, *data++); 624 address++; 625 } 626 627 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); 628 return (0); 629} 630 631static int 632diva_bri_start_adapter(PISDN_ADAPTER IoAdapter, 633 dword start_address, dword features) 634{ 635 byte __iomem *Port; 636 dword i, test; 637 byte __iomem *addrHi, *addrLo, *ioaddr; 638 int started = 0; 639 ADAPTER *a = &IoAdapter->a; 640 641 if (IoAdapter->Initialized) { 642 DBG_ERR( 643 ("A: A(%d) bri_start_adapter, adapter already running", 644 IoAdapter->ANum)) return (-1); 645 } 646 if (!IoAdapter->port) { 647 DBG_ERR(("A: A(%d) bri_start_adapter, adapter not mapped", 648 IoAdapter->ANum)) return (-1); 649 } 650 651 sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum); 652 DBG_LOG(("A(%d) start BRI", IoAdapter->ANum)) 653 654 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); 655 addrHi = Port + 656 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); 657 addrLo = Port + ADDR; 658 ioaddr = Port + DATA; 659 660 outpp(addrHi, 661 (byte) ( 662 (IoAdapter->MemoryBase + IoAdapter->MemorySize - 663 BRI_SHARED_RAM_SIZE) >> 16)); 664 outppw(addrLo, 0x1e); 665 outppw(ioaddr, 0x00); 666 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); 667 668 /* 669 start the protocol code 670 */ 671 Port = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); 672 outpp(Port, 0x08); 673 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, Port); 674 675 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); 676 addrHi = Port + 677 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); 678 addrLo = Port + ADDR; 679 ioaddr = Port + DATA; 680 /* 681 wait for signature (max. 3 seconds) 682 */ 683 for (i = 0; i < 300; ++i) { 684 diva_os_wait(10); 685 outpp(addrHi, 686 (byte) ( 687 (IoAdapter->MemoryBase + 688 IoAdapter->MemorySize - 689 BRI_SHARED_RAM_SIZE) >> 16)); 690 outppw(addrLo, 0x1e); 691 test = (dword) inppw(ioaddr); 692 if (test == 0x4447) { 693 DBG_LOG( 694 ("Protocol startup time %d.%02d seconds", 695 (i / 100), (i % 100))) 696 started = 1; 697 break; 698 } 699 } 700 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); 701 702 if (!started) { 703 DBG_FTL(("A: A(%d) %s: Adapter selftest failed 0x%04X", 704 IoAdapter->ANum, IoAdapter->Properties.Name, 705 test)) 706 (*(IoAdapter->trapFnc)) (IoAdapter); 707 return (-1); 708 } 709 710 IoAdapter->Initialized = 1; 711 712 /* 713 Check Interrupt 714 */ 715 IoAdapter->IrqCount = 0; 716 a->ReadyInt = 1; 717 718 if (IoAdapter->reset) { 719 Port = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); 720 outpp(Port, 0x41); 721 DIVA_OS_MEM_DETACH_RESET(IoAdapter, Port); 722 } 723 724 a->ram_out(a, &PR_RAM->ReadyInt, 1); 725 for (i = 0; ((!IoAdapter->IrqCount) && (i < 100)); i++) { 726 diva_os_wait(10); 727 } 728 if (!IoAdapter->IrqCount) { 729 DBG_ERR( 730 ("A: A(%d) interrupt test failed", 731 IoAdapter->ANum)) 732 IoAdapter->Initialized = 0; 733 IoAdapter->stop(IoAdapter); 734 return (-1); 735 } 736 737 IoAdapter->Properties.Features = (word) features; 738 diva_xdi_display_adapter_features(IoAdapter->ANum); 739 DBG_LOG(("A(%d) BRI adapter successfully started", IoAdapter->ANum)) 740 /* 741 Register with DIDD 742 */ 743 diva_xdi_didd_register_adapter(IoAdapter->ANum); 744 745 return (0); 746} 747 748static void diva_bri_clear_interrupts(diva_os_xdi_adapter_t *a) 749{ 750 PISDN_ADAPTER IoAdapter = &a->xdi_adapter; 751 752 /* 753 clear any pending interrupt 754 */ 755 IoAdapter->disIrq(IoAdapter); 756 757 IoAdapter->tst_irq(&IoAdapter->a); 758 IoAdapter->clr_irq(&IoAdapter->a); 759 IoAdapter->tst_irq(&IoAdapter->a); 760 761 /* 762 kill pending dpcs 763 */ 764 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr); 765 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr); 766} 767 768/* 769** Stop card 770*/ 771static int diva_bri_stop_adapter(diva_os_xdi_adapter_t *a) 772{ 773 PISDN_ADAPTER IoAdapter = &a->xdi_adapter; 774 int i = 100; 775 776 if (!IoAdapter->port) { 777 return (-1); 778 } 779 if (!IoAdapter->Initialized) { 780 DBG_ERR(("A: A(%d) can't stop BRI adapter - not running", 781 IoAdapter->ANum)) 782 return (-1); /* nothing to stop */ 783 } 784 IoAdapter->Initialized = 0; 785 786 /* 787 Disconnect Adapter from DIDD 788 */ 789 diva_xdi_didd_remove_adapter(IoAdapter->ANum); 790 791 /* 792 Stop interrupts 793 */ 794 a->clear_interrupts_proc = diva_bri_clear_interrupts; 795 IoAdapter->a.ReadyInt = 1; 796 IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt); 797 do { 798 diva_os_sleep(10); 799 } while (i-- && a->clear_interrupts_proc); 800 if (a->clear_interrupts_proc) { 801 diva_bri_clear_interrupts(a); 802 a->clear_interrupts_proc = NULL; 803 DBG_ERR(("A: A(%d) no final interrupt from BRI adapter", 804 IoAdapter->ANum)) 805 } 806 IoAdapter->a.ReadyInt = 0; 807 808 /* 809 Stop and reset adapter 810 */ 811 IoAdapter->stop(IoAdapter); 812 813 return (0); 814} 815