1/* 2 * Copyright (C) Eicon Technology Corporation, 2000. 3 * 4 * Eicon File Revision : 1.15 5 * 6 * This software may be used and distributed according to the terms 7 * of the GNU General Public License, incorporated herein by reference. 8 * 9 */ 10 11#include "eicon.h" 12#include "sys.h" 13#include "idi.h" 14#include "constant.h" 15#include "divas.h" 16#include "pc.h" 17#include "pr_pc.h" 18 19#include "uxio.h" 20 21#define DIVAS_LOAD_CMD 0x02 22#define DIVAS_START_CMD 0x03 23#define DIVAS_IRQ_RESET 0xC18 24#define DIVAS_IRQ_RESET_VAL 0xFE 25 26#define TEST_INT_DIVAS 0x11 27#define TEST_INT_DIVAS_BRI 0x12 28#define TEST_INT_DIVAS_Q 0x13 29 30#define DIVAS_RESET 0x81 31#define DIVAS_LED1 0x04 32#define DIVAS_LED2 0x08 33#define DIVAS_LED3 0x20 34#define DIVAS_LED4 0x40 35 36#define DIVAS_SIGNATURE 0x4447 37 38#define MP_PROTOCOL_ADDR 0xA0011000 39 40#define PLX_IOBASE 0 41#define DIVAS_IOBASE 1 42 43typedef struct { 44 dword cmd; 45 dword addr; 46 dword len; 47 dword err; 48 dword live; 49 dword reserved[(0x1020>>2)-6]; 50 dword signature; 51 byte data[1]; 52} diva_server_boot_t; 53 54int DivasCardNext; 55card_t DivasCards[MAX_CARDS]; 56 57dia_config_t *DivasConfig(card_t *, dia_config_t *); 58 59static 60DESCRIPTOR DIDD_Table[32]; 61 62void DIVA_DIDD_Read( DESCRIPTOR *table, int tablelength ) 63{ 64 memset(table, 0, tablelength); 65 66 if (tablelength > sizeof(DIDD_Table)) 67 tablelength = sizeof(DIDD_Table); 68 69 if(tablelength % sizeof(DESCRIPTOR)) { 70 tablelength /= sizeof(DESCRIPTOR); 71 tablelength *= sizeof(DESCRIPTOR); 72 } 73 74 if (tablelength > 0) 75 memcpy((void *)table, (void *)DIDD_Table, tablelength); 76 77 return; 78} 79 80void DIVA_DIDD_Write(DESCRIPTOR *table, int tablelength) 81{ 82 if (tablelength > sizeof(DIDD_Table)) 83 tablelength = sizeof(DIDD_Table); 84 85 memcpy((void *)DIDD_Table, (void *)table, tablelength); 86 87 return; 88} 89 90static 91void init_idi_tab(void) 92{ 93 DESCRIPTOR d[32]; 94 95 memset(d, 0, sizeof(d)); 96 97 d[0].type = IDI_DIMAINT; /* identify the DIMAINT entry */ 98 d[0].channels = 0; /* zero channels associated with dimaint*/ 99 d[0].features = 0; /* no features associated with dimaint */ 100 d[0].request = (IDI_CALL) DivasPrintf; 101 102 DIVA_DIDD_Write(d, sizeof(d)); 103 104 return; 105} 106 107/* 108 * I/O routines for memory mapped cards 109 */ 110 111byte mem_in(ADAPTER *a, void *adr) 112{ 113 card_t *card = a->io; 114 unsigned char *b, *m; 115 byte value; 116 117 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 118 119 m += (unsigned int) adr; 120 121 value = UxCardMemIn(card->hw, m); 122 123 UxCardMemDetach(card->hw, b); 124 125 return value; 126} 127 128word mem_inw(ADAPTER *a, void *adr) 129{ 130 card_t *card = a->io; 131 unsigned char *b, *m; 132 word value; 133 134 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 135 136 m += (unsigned int) adr; 137 138 value = UxCardMemInW(card->hw, m); 139 140 UxCardMemDetach(card->hw, b); 141 142 return value; 143} 144 145void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length) 146{ 147 card_t *card = a->io; 148 unsigned char *b, *m; 149 150 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 151 152 m += (unsigned int) adr; 153 154 UxCardMemInBuffer(card->hw, m, P, length); 155 156 UxCardMemDetach(card->hw, b); 157 158 return; 159} 160 161void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e) 162{ 163 card_t *card = a->io; 164 unsigned char *b, *m; 165 166 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 167 168 m += (dword) &RBuffer->length; 169 card->RBuffer.length = UxCardMemInW(card->hw, m); 170 171 m = b; 172 m += (dword) &RBuffer->P; 173 UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length); 174 175 e->RBuffer = (DBUFFER *) &card->RBuffer; 176 177 UxCardMemDetach(card->hw, b); 178 179 return; 180} 181 182void mem_out(ADAPTER *a, void *adr, byte data) 183{ 184 card_t *card = a->io; 185 unsigned char *b, *m; 186 187 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 188 189 m += (unsigned int) adr; 190 191 UxCardMemOut(card->hw, m, data); 192 193 UxCardMemDetach(card->hw, b); 194 195 return; 196} 197 198void mem_outw(ADAPTER *a, void *adr, word data) 199{ 200 card_t *card = a->io; 201 unsigned char *b, *m; 202 203 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 204 205 m += (unsigned int) adr; 206 207 UxCardMemOutW(card->hw, m, data); 208 209 UxCardMemDetach(card->hw, b); 210 211 return; 212} 213 214void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length) 215{ 216 card_t *card = a->io; 217 unsigned char *b, *m; 218 219 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 220 221 m += (unsigned int) adr; 222 223 UxCardMemOutBuffer(card->hw, m, P, length); 224 225 UxCardMemDetach(card->hw, b); 226 227 return; 228} 229 230void mem_inc(ADAPTER *a, void *adr) 231{ 232 word value; 233 card_t *card = a->io; 234 unsigned char *b, *m; 235 236 m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 237 238 m += (unsigned int) adr; 239 240 value = UxCardMemInW(card->hw, m); 241 value++; 242 UxCardMemOutW(card->hw, m, value); 243 244 UxCardMemDetach(card->hw, b); 245 246 return; 247} 248 249/* 250 * I/O routines for I/O mapped cards 251 */ 252 253byte io_in(ADAPTER *a, void *adr) 254{ 255 card_t *card = a->io; 256 byte value; 257 byte *DivasIOBase = NULL; 258 259 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 260 261 value = UxCardIoIn(card->hw, DivasIOBase, adr); 262 263 UxCardMemDetach(card->hw, DivasIOBase); 264 265 return value; 266} 267 268word io_inw(ADAPTER *a, void *adr) 269{ 270 card_t *card = a->io; 271 word value; 272 byte *DivasIOBase = NULL; 273 274 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 275 276 value = UxCardIoInW(card->hw, DivasIOBase, adr); 277 278 UxCardMemDetach(card->hw, DivasIOBase); 279 280 return value; 281} 282 283void io_in_buffer(ADAPTER *a, void *adr, void *P, word length) 284{ 285 card_t *card = a->io; 286 byte *DivasIOBase = NULL; 287 288 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 289 290 UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length); 291 292 UxCardMemDetach(card->hw, DivasIOBase); 293 294 return; 295} 296 297void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e) 298{ 299 card_t *card = a->io; 300 byte *DivasIOBase = NULL; 301 302 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 303 304 card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer); 305 306 UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length); 307 308 UxCardMemDetach(card->hw, DivasIOBase); 309 310 e->RBuffer = (DBUFFER *) &card->RBuffer; 311 312 return; 313} 314 315void io_out(ADAPTER *a, void *adr, byte data) 316{ 317 card_t *card = a->io; 318 byte *DivasIOBase = NULL; 319 320 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 321 322 UxCardIoOut(card->hw, DivasIOBase, adr, data); 323 324 UxCardMemDetach(card->hw, DivasIOBase); 325 326 return; 327} 328 329void io_outw(ADAPTER *a, void *adr, word data) 330{ 331 card_t *card = a->io; 332 byte *DivasIOBase = NULL; 333 334 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 335 336 UxCardIoOutW(card->hw, DivasIOBase, adr, data); 337 338 UxCardMemDetach(card->hw, DivasIOBase); 339 340 return; 341} 342 343void io_out_buffer(ADAPTER *a, void *adr, void *P, word length) 344{ 345 card_t *card = a->io; 346 byte *DivasIOBase = NULL; 347 348 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 349 350 UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length); 351 352 UxCardMemDetach(card->hw, DivasIOBase); 353 354 return; 355} 356 357void io_inc(ADAPTER *a, void *adr) 358{ 359 word value; 360 card_t *card = a->io; 361 byte *DivasIOBase; 362 363 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 364 365 value = UxCardIoInW(card->hw, DivasIOBase, adr); 366 367 value++; 368 369 UxCardIoOutW(card->hw, DivasIOBase, adr, value); 370 371 UxCardMemDetach(card->hw, DivasIOBase); 372 373 return; 374} 375 376static 377void test_int(card_t *card) 378 379{ 380 byte *shared, *DivasIOBase; 381 382 switch (card->test_int_pend) 383 { 384 case TEST_INT_DIVAS: 385 DPRINTF(("divas: test interrupt pending")); 386 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 387 388 if (UxCardMemIn(card->hw, &shared[0x3FE])) 389 { 390 UxCardMemOut(card->hw, 391 &(((struct pr_ram *)shared)->RcOutput), 0); 392 UxCardMemDetach(card->hw, shared); 393 (*card->reset_int)(card); 394 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 395 UxCardMemOut(card->hw, &shared[0x3FE], 0); 396 DPRINTF(("divas: test interrupt cleared")); 397 } 398 399 UxCardMemDetach(card->hw, shared); 400 401 card->test_int_pend = 0; 402 break; 403 404 case TEST_INT_DIVAS_BRI: 405 DPRINTF(("divas: BRI test interrupt pending")); 406 (*card->reset_int)(card); 407 DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); 408 UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0); 409 UxCardMemDetach(card->hw, DivasIOBase); 410 DPRINTF(("divas: test interrupt cleared")); 411 card->test_int_pend = 0; 412 break; 413 414 case TEST_INT_DIVAS_Q: 415 DPRINTF(("divas: 4BRI test interrupt pending")); 416 (*card->reset_int)(card); 417 card->test_int_pend = 0; 418 break; 419 420 default: 421 DPRINTF(("divas: unknown test interrupt pending")); 422 return; 423 } 424 return; 425} 426 427void card_isr (void *dev_id) 428{ 429 card_t *card = (card_t *) dev_id; 430 ADAPTER *a = &card->a; 431 int ipl; 432 433 if (card->test_int_pend) 434 { 435 ipl = UxCardLock(card->hw); 436 card->int_pend=0; 437 test_int(card); 438 UxCardUnlock(card->hw,ipl); 439 return; 440 } 441 442 if(card->card_isr) 443 { 444 (*(card->card_isr))(card); 445 } 446 else 447 { 448 ipl = UxCardLock(card->hw); 449 450 if ((card->test_int)(a)) 451 { 452 (card->reset_int)(card); 453 } 454 455 UxCardUnlock(card->hw,ipl); 456 457 } 458 459} 460 461int DivasCardNew(dia_card_t *card_info) 462{ 463 card_t *card; 464 static boolean_t first_call = TRUE; 465 boolean_t NeedISRandReset = FALSE; 466 467 DPRINTF(("divas: new card ")); 468 469 if (first_call) 470 { 471 first_call = FALSE; 472 init_idi_tab(); 473 } 474 475 DivasConfigGet(card_info); 476 477 if (DivasCardNext == DIM(DivasCards)) 478 { 479 KDPRINTF((KERN_WARNING "Divas: no space available for new card")); 480 return -1; 481 } 482 483 card = &DivasCards[DivasCardNext]; 484 485 card->state = DIA_UNKNOWN; 486 487 card->cfg = *card_info; 488 489 card->a.io = card; 490 491 if (UxCardHandleGet(&card->hw, card_info)) 492 { 493 KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card")); 494 return -1; 495 } 496 497 if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B) 498 { 499 DivasBriPatch(card); 500 card_info->io_base = card->cfg.io_base; 501 } 502 503 switch (card_info->card_type) 504 { 505 case DIA_CARD_TYPE_DIVA_SERVER: 506 if (DivasPriInit(card, card_info)) 507 { 508 return -1; 509 } 510 NeedISRandReset = TRUE; 511 break; 512 513 case DIA_CARD_TYPE_DIVA_SERVER_B: 514 if (DivasBriInit(card, card_info)) 515 { 516 return -1; 517 } 518 NeedISRandReset = TRUE; 519 break; 520 521 case DIA_CARD_TYPE_DIVA_SERVER_Q: 522 if (Divas4BriInit(card, card_info)) 523 { 524 return -1; 525 } 526 527 if (card_info->name[6] == '0') 528 { 529 NeedISRandReset = TRUE; 530 } 531 else // Need to set paramater for ISR anyway 532 { 533 card->hw->user_isr_arg = card; 534 card->hw->user_isr = card_isr; 535 } 536 break; 537 538 default: 539 KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type)); 540 return -1; 541 } 542 543 if (NeedISRandReset) 544 { 545 if (UxIsrInstall(card->hw, card_isr, card)) 546 { 547 KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq)); 548 UxCardHandleFree(card->hw); 549 return -1; 550 } 551 552 if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q) 553 { 554 if ((*card->card_reset)(card)) 555 { 556 KDPRINTF((KERN_WARNING "Divas: Adapter reset failed")); 557 return -1; 558 } 559 card->state = DIA_RESET; 560 } 561 562 NeedISRandReset = FALSE; 563 } 564 565 DivasCardNext++; 566 567 return 0; 568} 569 570void *get_card(int card_id) 571{ 572 int i; 573 574 for (i=0; i < DivasCardNext; i++) 575 { 576 if (DivasCards[i].cfg.card_id == card_id) 577 { 578 return(&DivasCards[i]); 579 } 580 } 581 582 DPRINTF(("divas: get_card() : no such card id (%d)", card_id)); 583 584 return NULL; 585} 586 587int DivasCardConfig(dia_config_t *config) 588{ 589 card_t *card; 590 int status; 591 592 DPRINTF(("divas: configuring card")); 593 594 card = get_card(config->card_id); 595 if (!card) 596 { 597 return -1; 598 } 599 600 config = DivasConfig(card, config); 601 602 status = (*card->card_config)(card, config); 603 604 if (!status) 605 { 606 card->state = DIA_CONFIGURED; 607 } 608 return status; 609} 610 611int DivasCardLoad(dia_load_t *load) 612{ 613 card_t *card; 614 int status; 615 616 card = get_card(load->card_id); 617 if (!card) 618 { 619 return -1; 620 } 621 622 if (card->state == DIA_RUNNING) 623 { 624 (*card->card_reset)(card); 625 } 626 627 status = (*card->card_load)(card, load); 628 if (!status) 629 { 630 card->state = DIA_LOADED; 631 } 632 return status; 633} 634 635static int idi_register(card_t *card, byte channels) 636{ 637 DESCRIPTOR d[32]; 638 int length, num_entities; 639 640 DPRINTF(("divas: registering card with IDI")); 641 642 num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES; 643 card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities); 644 645 if (!card->e_tbl) 646 { 647 KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available")); 648 return -1; 649 } 650 651 memset(card->e_tbl, 0, sizeof(E_INFO) * num_entities); 652 card->e_max = num_entities; 653 654 DIVA_DIDD_Read(d, sizeof(d)); 655 656 for(length=0; length < DIM(d); length++) 657 if (d[length].type == 0) break; 658 659 if (length >= DIM(d)) 660 { 661 KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full")); 662 return -1; 663 } 664 665 switch (card->cfg.card_type) 666 { 667 case DIA_CARD_TYPE_DIVA_SERVER: 668 d[length].type = IDI_ADAPTER_PR; 669 /* d[length].serial = card->serial_no; */ 670 break; 671 672 case DIA_CARD_TYPE_DIVA_SERVER_B: 673 d[length].type = IDI_ADAPTER_MAESTRA; 674 /* d[length].serial = card->serial_no; */ 675 break; 676 677 // 4BRI is treated as 4 BRI adapters 678 case DIA_CARD_TYPE_DIVA_SERVER_Q: 679 d[length].type = IDI_ADAPTER_MAESTRA; 680 /* d[length].serial = card->cfg.serial; */ 681 } 682 683 d[length].features = 0; 684 d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120; 685 686 if ( card->hw->features & PROTCAP_MANIF ) 687 { 688 d[length].features |= DI_MANAGE ; 689 } 690 if ( card->hw->features & PROTCAP_V_42 ) 691 { 692 d[length].features |= DI_V_42 ; 693 } 694 if ( card->hw->features & PROTCAP_EXTD_FAX ) 695 { 696 d[length].features |= DI_EXTD_FAX ; 697 } 698 699 d[length].channels = channels; 700 d[length].request = DivasIdiRequest[card - DivasCards]; 701 702 length++; 703 704 DIVA_DIDD_Write(d, sizeof(d)); 705 706 return 0; 707} 708 709int DivasCardStart(int card_id) 710{ 711 card_t *card; 712 byte channels; 713 int status; 714 715 DPRINTF(("divas: starting card")); 716 717 card = get_card(card_id); 718 if (!card) 719 { 720 return -1; 721 } 722 723 status = (*card->card_start)(card, &channels); 724 if (status) 725 { 726 return status; 727 } 728 729 /* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */ 730 if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q) 731 { 732 int i; 733 card_t *FourBRISlave; 734 735 for (i=3; i >= 0; i--) 736 { 737 FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */ 738 if (FourBRISlave) 739 { 740 idi_register(FourBRISlave, 2); 741 FourBRISlave->state = DIA_RUNNING; 742 } 743 } 744 card->serial_no = card->cfg.serial; 745 746 DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels", 747 card_id - 3, card->serial_no, (int) channels)); 748 } 749 else 750 { 751 status = idi_register(card, channels); 752 if (!status) 753 { 754 card->state = DIA_RUNNING; 755 DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels", 756 card_id, card->serial_no, (int) channels)); 757 } 758 } 759 760 return status; 761} 762 763int DivasGetMem(mem_block_t *mem_block) 764{ 765 card_t *card; 766 word card_id = mem_block->card_id; 767 768 card = get_card(card_id); 769 if (!card) 770 { 771 return 0; 772 } 773 774 return (*card->card_mem_get)(card, mem_block); 775} 776 777 778/* 779 * Deleyed Procedure Call for handling interrupts from card 780 */ 781 782void DivaDoCardDpc(card_t *card) 783{ 784 ADAPTER *a; 785 786 a = &card->a; 787 788 if(UxInterlockedIncrement(card->hw, &card->dpc_reentered) > 1) 789 { 790 return; 791 } 792 793 do{ 794 if((*(card->test_int))(a)) 795 { 796 (*(card->dpc))(a); 797 (*(card->clear_int))(a); 798 } 799 (*(card->out))(a); 800 }while(UxInterlockedDecrement(card->hw, &card->dpc_reentered)); 801 802} 803 804void DivasDoDpc(void *pData) 805{ 806 card_t *card = DivasCards; 807 int i = DivasCardNext; 808 809 while(i--) 810 { 811 if (card->state == DIA_RUNNING) 812 DivaDoCardDpc(card); 813 card++; 814 } 815} 816 817void DivasDoRequestDpc(void *pData) 818{ 819 DivasDoDpc(pData); 820} 821 822/* 823 * DivasGetNum 824 * Returns the number of active adapters 825 */ 826 827int DivasGetNum(void) 828{ 829 return(DivasCardNext); 830} 831 832/* 833 * DivasGetList 834 * Returns a list of active adapters 835 */ 836int DivasGetList(dia_card_list_t *card_list) 837{ 838 int i; 839 840 memset(card_list, 0, sizeof(dia_card_list_t)); 841 842 for(i = 0; i < DivasCardNext; i++) 843 { 844 card_list->card_type = DivasCards[i].cfg.card_type; 845 card_list->card_slot = DivasCards[i].cfg.slot; 846 card_list->state = DivasCards[i].state; 847 card_list++; 848 } 849 850 return 0; 851 852} 853 854/* 855 * control logging for specified card 856 */ 857 858void DivasLog(dia_log_t *log) 859{ 860 card_t *card; 861 862 card = get_card(log->card_id); 863 if (!card) 864 { 865 return; 866 } 867 868 card->log_types = log->log_types; 869 870 return; 871} 872 873