fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 972 lines 17 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/chipset/e6522.c * 7 * Created: 2007-11-09 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2007-2023 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <stdlib.h> 24#include <stdio.h> 25 26#include "e6522.h" 27 28 29#define DEBUG_VIA 0 30 31 32#define E6522_IFR_CA2 0x01 33#define E6522_IFR_CA1 0x02 34#define E6522_IFR_SR 0x04 35#define E6522_IFR_CB2 0x08 36#define E6522_IFR_CB1 0x10 37#define E6522_IFR_T2 0x20 38#define E6522_IFR_T1 0x40 39#define E6522_IFR_SET 0x80 40 41 42void e6522_init (e6522_t *via, unsigned addr_shift) 43{ 44 via->addr_shift = addr_shift; 45 46 via->ora = 0x00; 47 via->orb = 0x00; 48 49 via->ira = 0x00; 50 via->irb = 0x00; 51 52 via->ddra = 0x00; 53 via->ddrb = 0x00; 54 55 via->shift_val = 0; 56 via->shift_cnt = 0; 57 58 via->acr = 0x00; 59 via->pcr = 0x00; 60 61 via->ifr = 0x00; 62 via->ier = 0x00; 63 64 via->t1_latch = 0; 65 via->t1_val = 0; 66 via->t1_hot = 0; 67 68 via->t2_latch = 0; 69 via->t2_val = 0; 70 via->t2_hot = 0; 71 72 via->ca1_inp = 0; 73 via->ca2_inp = 0; 74 75 via->cb1_inp = 0; 76 via->cb2_inp = 0; 77 78 via->set_ora_ext = NULL; 79 via->set_ora = NULL; 80 via->set_ora_val = 0; 81 82 via->set_orb_ext = NULL; 83 via->set_orb = NULL; 84 via->set_orb_val = 0; 85 86 via->set_ca2_ext = NULL; 87 via->set_ca2 = NULL; 88 via->set_ca2_val = 0; 89 90 via->set_cb2_ext = NULL; 91 via->set_cb2 = NULL; 92 via->set_cb2_val = 0; 93 94 via->set_shift_out_ext = NULL; 95 via->set_shift_out = NULL; 96 97 via->irq_ext = NULL; 98 via->irq = NULL; 99 via->irq_val = 0; 100} 101 102void e6522_free (e6522_t *via) 103{ 104} 105 106void e6522_set_ora_fct (e6522_t *via, void *ext, void *fct) 107{ 108 via->set_ora_ext = ext; 109 via->set_ora = fct; 110} 111 112void e6522_set_orb_fct (e6522_t *via, void *ext, void *fct) 113{ 114 via->set_orb_ext = ext; 115 via->set_orb = fct; 116} 117 118void e6522_set_ca2_fct (e6522_t *via, void *ext, void *fct) 119{ 120 via->set_ca2_ext = ext; 121 via->set_ca2 = fct; 122} 123 124void e6522_set_cb2_fct (e6522_t *via, void *ext, void *fct) 125{ 126 via->set_cb2_ext = ext; 127 via->set_cb2 = fct; 128} 129 130void e6522_set_shift_out_fct (e6522_t *via, void *ext, void *fct) 131{ 132 via->set_shift_out_ext = ext; 133 via->set_shift_out = fct; 134} 135 136void e6522_set_irq_fct (e6522_t *via, void *ext, void *fct) 137{ 138 via->irq_ext = ext; 139 via->irq = fct; 140} 141 142 143static 144void e6522_set_ora_out (e6522_t *via) 145{ 146 unsigned char val; 147 148 val = via->ora & via->ddra; 149 val |= via->ira & ~via->ddra; 150 151 if (via->set_ora != NULL) { 152 via->set_ora (via->set_ora_ext, val); 153 } 154} 155 156static 157void e6522_set_orb_out (e6522_t *via) 158{ 159 unsigned char val; 160 161 val = via->orb & via->ddrb; 162 val |= via->irb & ~ via->ddrb; 163 164 if (via->set_orb != NULL) { 165 via->set_orb (via->set_orb_ext, val); 166 } 167} 168 169/* 170 * Set the CA2 output according to the VIA's state 171 */ 172static 173void e6522_set_ca2_out (e6522_t *via) 174{ 175 unsigned char val; 176 177 if ((via->pcr & 0x08) == 0) { 178 /* CA2 is input */ 179 val = 1; 180 } 181 else if ((via->pcr & 0x06) == 0x06) { 182 /* manual output mode (1) */ 183 val = 1; 184 } 185 else if ((via->pcr & 0x06) == 0x04) { 186 /* manual output mode (0) */ 187 val = 0; 188 } 189 else { 190 /* not implemented */ 191 val = 1; 192 } 193 194 195 if (val == via->set_ca2_val) { 196 return; 197 } 198 199 via->set_ca2_val = val; 200 201 if (via->set_ca2 != NULL) { 202 via->set_ca2 (via->set_ca2_ext, val); 203 } 204} 205 206/* 207 * Set the CB2 output according to the VIA's state 208 */ 209static 210void e6522_set_cb2_out (e6522_t *via) 211{ 212 unsigned char val; 213 214 if ((via->acr & 0x1c) != 0) { 215 /* shift register enabled */ 216 217 if (via->acr & 0x10) { 218 val = ((via->shift_val & 1) != 0); 219 } 220 else { 221 /* shift register input */ 222 val = 1; 223 } 224 } 225 else if ((via->pcr & 0x80) == 0) { 226 /* CB2 is input */ 227 val = 1; 228 } 229 else if ((via->pcr & 0x60) == 0x60) { 230 /* manual output mode (1) */ 231 val = 1; 232 } 233 else if ((via->pcr & 0x60) == 0x40) { 234 /* manual output mode (0) */ 235 val = 0; 236 } 237 else { 238 /* not implemented */ 239 val = 1; 240 } 241 242 243 if (val == via->set_cb2_val) { 244 return; 245 } 246 247 via->set_cb2_val = val; 248 249 if (via->set_cb2 != NULL) { 250 via->set_cb2 (via->set_cb2_ext, val); 251 } 252} 253 254static 255void e6522_set_shift_out (e6522_t *via, unsigned char val) 256{ 257 if (via->set_shift_out != NULL) { 258 via->set_shift_out (via->set_shift_out_ext, val); 259 } 260} 261 262/* 263 * Set the IRQ output 264 */ 265static 266void e6522_set_irq (e6522_t *via, unsigned char val) 267{ 268 if (via->irq_val == val) { 269 return; 270 } 271 272 via->irq_val = val; 273 274 if (via->irq != NULL) { 275 via->irq (via->irq_ext, val); 276 } 277} 278 279/* 280 * Set the IFR and trigger an interrupt if necessary 281 */ 282static 283void e6522_set_ifr (e6522_t *via, unsigned char val) 284{ 285 val &= 0x7f; 286 287 if (val & via->ier) { 288 val |= 0x80; 289 } 290 291 via->ifr = val; 292 293 e6522_set_irq (via, (via->ifr & 0x80) != 0); 294} 295 296/* 297 * Set the IER and trigger an interrupt if necessary 298 */ 299static 300void e6522_set_ier (e6522_t *via, unsigned char val) 301{ 302 if (val & 0x80) { 303 via->ier |= (val & 0x7f); 304 } 305 else { 306 via->ier &= (~val & 0x7f); 307 } 308 309 e6522_set_ifr (via, via->ifr); 310} 311 312 313unsigned char e6522_shift_out (e6522_t *via) 314{ 315 unsigned char val; 316 317 if ((via->acr & 0x1c) != 0x1c) { 318 return (0); 319 } 320 321 val = (via->shift_val >> 7) & 1; 322 323 via->shift_val = ((via->shift_val << 1) | (via->shift_val >> 7)) & 0xff; 324 via->shift_cnt = (via->shift_cnt + 1) & 7; 325 326 if (via->shift_cnt == 0) { 327 e6522_set_ifr (via, via->ifr | E6522_IFR_SR); 328 } 329 330 return (val); 331} 332 333void e6522_shift_in (e6522_t *via, unsigned char val) 334{ 335 if ((via->acr & 0x1c) != 0x0c) { 336 return; 337 } 338 339 via->shift_val = ((via->shift_val << 1) | (val != 0)) & 0xff; 340 via->shift_cnt = (via->shift_cnt + 1) & 7; 341 342 if (via->shift_cnt == 0) { 343 e6522_set_ifr (via, via->ifr | E6522_IFR_SR); 344 } 345 346 e6522_set_ifr (via, via->ifr | E6522_IFR_CB1); 347} 348 349 350static 351unsigned char e6522_get_ora (e6522_t *via, int handshake) 352{ 353 unsigned char val; 354 355 if (handshake) { 356 e6522_set_ifr (via, via->ifr & ~(E6522_IFR_CA1 | E6522_IFR_CA2)); 357 } 358 359 val = via->ora & via->ddra; 360 val |= via->ira & ~via->ddra; 361 362 return (val); 363} 364 365static 366unsigned char e6522_get_orb (e6522_t *via) 367{ 368 unsigned char val; 369 370 e6522_set_ifr (via, via->ifr & ~(E6522_IFR_CB1 | E6522_IFR_CB2)); 371 372 val = via->orb & via->ddrb; 373 val |= via->irb & ~via->ddrb; 374 375 return (val); 376} 377 378static 379unsigned char e6522_get_t1_counter_low (e6522_t *via) 380{ 381 e6522_set_ifr (via, via->ifr & ~E6522_IFR_T1); 382 383 return (via->t1_val & 0xff); 384} 385 386static 387unsigned char e6522_get_t1_counter_high (e6522_t *via) 388{ 389 return ((via->t1_val >> 8) & 0xff); 390} 391 392static 393unsigned char e6522_get_t1_latch_low (e6522_t *via) 394{ 395 return (via->t1_latch & 0xff); 396} 397 398static 399unsigned char e6522_get_t1_latch_high (e6522_t *via) 400{ 401 return ((via->t1_latch >> 8) & 0xff); 402} 403 404static 405unsigned char e6522_get_t2_counter_low (e6522_t *via) 406{ 407 e6522_set_ifr (via, via->ifr & ~E6522_IFR_T2); 408 409 return (via->t2_val & 0xff); 410} 411 412static 413unsigned char e6522_get_t2_counter_high (e6522_t *via) 414{ 415 return ((via->t2_val >> 8) & 0xff); 416} 417 418static 419unsigned char e6522_get_shift (e6522_t *via) 420{ 421 e6522_set_ifr (via, via->ifr & ~E6522_IFR_SR); 422 423 via->shift_cnt = 0; 424 425 return (via->shift_val); 426} 427 428static 429unsigned char e6522_get_acr (e6522_t *via) 430{ 431 return (via->acr); 432} 433 434static 435unsigned char e6522_get_pcr (e6522_t *via) 436{ 437 return (via->pcr); 438} 439 440static 441void e6522_set_ora (e6522_t *via, unsigned char val, int handshake) 442{ 443 via->ora = val; 444 445 e6522_set_ora_out (via); 446 447 if (handshake) { 448 e6522_set_ifr (via, via->ifr & ~(E6522_IFR_CA1 | E6522_IFR_CA2)); 449 } 450} 451 452static 453void e6522_set_ddra (e6522_t *via, unsigned char val) 454{ 455 via->ddra = val; 456 457 e6522_set_ora_out (via); 458} 459 460static 461void e6522_set_orb (e6522_t *via, unsigned char val) 462{ 463 via->orb = val; 464 465 e6522_set_orb_out (via); 466 e6522_set_ifr (via, via->ifr & ~(E6522_IFR_CB1 | E6522_IFR_CB2)); 467} 468 469static 470void e6522_set_ddrb (e6522_t *via, unsigned char val) 471{ 472 via->ddrb = val; 473 474 e6522_set_orb_out (via); 475} 476 477static 478void e6522_set_t1_latch_low (e6522_t *via, unsigned char val) 479{ 480 via->t1_latch &= 0xff00; 481 via->t1_latch |= (val & 0xff); 482} 483 484static 485void e6522_set_t1_counter_high (e6522_t *via, unsigned char val) 486{ 487 via->t1_latch &= 0x00ff; 488 via->t1_latch |= (val & 0xff) << 8; 489 490 via->t1_reload = 1; 491 492 if ((via->acr & 0x40) == 0) { 493 via->t1_hot = 1; 494 } 495 496 e6522_set_ifr (via, via->ifr & ~E6522_IFR_T1); 497} 498 499static 500void e6522_set_t1_latch_high (e6522_t *via, unsigned char val) 501{ 502 via->t1_latch &= 0x00ff; 503 via->t1_latch |= (val & 0xff) << 8; 504} 505 506static 507void e6522_set_t2_latch_low (e6522_t *via, unsigned char val) 508{ 509 via->t2_latch &= 0xff00; 510 via->t2_latch |= (val & 0xff); 511} 512 513static 514void e6522_set_t2_counter_high (e6522_t *via, unsigned char val) 515{ 516 via->t2_latch &= 0x00ff; 517 via->t2_latch |= (val & 0xff) << 8; 518 519 via->t2_val = via->t2_latch; 520 521 if ((via->acr & 0x20) == 0) { 522 via->t2_hot = 1; 523 } 524 525 e6522_set_ifr (via, via->ifr & ~E6522_IFR_T2); 526} 527 528static 529void e6522_set_shift (e6522_t *via, unsigned char val) 530{ 531 e6522_set_ifr (via, via->ifr & ~E6522_IFR_SR); 532 533 via->shift_val = val; 534 via->shift_cnt = 0; 535 536 if ((via->acr & 0x1c) == 0x1c) { 537 /* shift out with external clock */ 538 if (via->set_shift_out != NULL) { 539 e6522_set_shift_out (via, via->shift_val); 540 e6522_set_ifr (via, via->ifr | E6522_IFR_SR); 541 } 542 } 543} 544 545static 546void e6522_set_acr (e6522_t *via, unsigned char val) 547{ 548 via->acr = val; 549 550 if ((via->acr & 0x1c) == 0) { 551 /* shift register disabled */ 552 via->shift_cnt = 0; 553 } 554 555 e6522_set_cb2_out (via); 556} 557 558static 559void e6522_set_pcr (e6522_t *via, unsigned char val) 560{ 561 via->pcr = val; 562 563 e6522_set_ca2_out (via); 564 e6522_set_cb2_out (via); 565} 566 567 568void e6522_set_ca1_inp (e6522_t *via, unsigned char val) 569{ 570 unsigned char old; 571 572 old = (via->ca1_inp != 0); 573 val = (val != 0); 574 575 via->ca1_inp = val; 576 577 if (old != val) { 578 if ((val != 0) == ((via->pcr & 0x01) != 0)) { 579 e6522_set_ifr (via, via->ifr | E6522_IFR_CA1); 580 } 581 } 582} 583 584void e6522_set_ca2_inp (e6522_t *via, unsigned char val) 585{ 586 unsigned char old; 587 588 old = (via->ca2_inp != 0); 589 val = (val != 0); 590 591 via->ca2_inp = val; 592 593 if (via->pcr & 0x08) { 594 /* CA2 is output */ 595 return; 596 } 597 598 if (old != val) { 599 if ((val != 0) == ((via->pcr & 0x04) != 0)) { 600 e6522_set_ifr (via, via->ifr | E6522_IFR_CA2); 601 } 602 } 603} 604 605void e6522_set_cb1_inp (e6522_t *via, unsigned char val) 606{ 607 unsigned char old; 608 609 old = (via->cb1_inp != 0); 610 val = (val != 0); 611 612 via->cb1_inp = val; 613 614 if (old != val) { 615 if ((val != 0) == ((via->pcr & 0x10) != 0)) { 616 e6522_set_ifr (via, via->ifr | E6522_IFR_CB1); 617 } 618 } 619} 620 621void e6522_set_cb2_inp (e6522_t *via, unsigned char val) 622{ 623 unsigned char old; 624 625 old = (via->cb2_inp != 0); 626 val = (val != 0); 627 628 via->cb2_inp = val; 629 630 if ((via->acr & 0x1c) != 0) { 631 /* shift register enabled */ 632 return; 633 } 634 635 if (via->pcr & 0x80) { 636 /* CB2 is output */ 637 return; 638 } 639 640 if (old != val) { 641 if ((val != 0) == ((via->pcr & 0x40) != 0)) { 642 e6522_set_ifr (via, via->ifr | E6522_IFR_CB2); 643 } 644 } 645} 646 647void e6522_set_ira_inp (e6522_t *via, unsigned char val) 648{ 649 if (via->ira == val) { 650 return; 651 } 652 653 via->ira = val; 654 655 e6522_set_ora_out (via); 656} 657 658void e6522_set_irb_inp (e6522_t *via, unsigned char val) 659{ 660 if (via->irb == val) { 661 return; 662 } 663 664 via->irb = val; 665 666 e6522_set_orb_out (via); 667} 668 669void e6522_set_shift_inp (e6522_t *via, unsigned char val) 670{ 671 if ((via->acr & 0x1c) == 0x0c) { 672 /* shift in with external clock */ 673 via->shift_val = val; 674 via->shift_cnt = 0; 675 e6522_set_ifr (via, via->ifr | E6522_IFR_SR); 676 } 677} 678 679 680static 681unsigned long e6522_addr_decode (e6522_t *via, unsigned long addr) 682{ 683 return (addr >> via->addr_shift); 684} 685 686unsigned char e6522_get_uint8 (e6522_t *via, unsigned long addr) 687{ 688 unsigned char val; 689 690 addr = e6522_addr_decode (via, addr); 691 692 switch (addr) { 693 case 0x00: 694 val = e6522_get_orb (via); 695 break; 696 697 case 0x01: 698 val = e6522_get_ora (via, 1); 699 break; 700 701 case 0x02: 702 val = via->ddrb; 703 break; 704 705 case 0x03: 706 val = via->ddra; 707 break; 708 709 case 0x04: 710 val = e6522_get_t1_counter_low (via); 711 break; 712 713 case 0x05: 714 val = e6522_get_t1_counter_high (via); 715 break; 716 717 case 0x06: 718 val = e6522_get_t1_latch_low (via); 719 break; 720 721 case 0x07: 722 val = e6522_get_t1_latch_high (via); 723 break; 724 725 case 0x08: 726 val = e6522_get_t2_counter_low (via); 727 break; 728 729 case 0x09: 730 val = e6522_get_t2_counter_high (via); 731 break; 732 733 case 0x0a: 734 val = e6522_get_shift (via); 735 break; 736 737 case 0x0b: 738 val = e6522_get_acr (via); 739 break; 740 741 case 0x0c: 742 val = e6522_get_pcr (via); 743 break; 744 745 case 0x0d: 746 val = via->ifr; 747 break; 748 749 case 0x0e: 750 val = via->ier | 0x80; 751 break; 752 753 case 0x0f: 754 val = e6522_get_ora (via, 0); 755 break; 756 757 default: 758 val = 0xaa; 759 break; 760 } 761 762#if DEBUG_VIA 763 fprintf (stderr, "via: get %04lX -> %02X\n", addr, val); 764#endif 765 766 return (val); 767} 768 769unsigned short e6522_get_uint16 (e6522_t *via, unsigned long addr) 770{ 771 return (e6522_get_uint8 (via, addr)); 772} 773 774unsigned long e6522_get_uint32 (e6522_t *via, unsigned long addr) 775{ 776 return (e6522_get_uint8 (via, addr)); 777} 778 779 780void e6522_set_uint8 (e6522_t *via, unsigned long addr, unsigned char val) 781{ 782 addr = e6522_addr_decode (via, addr); 783 784#if DEBUG_VIA 785 fprintf (stderr, "via: set %04lX <- %02X\n", addr, val); 786#endif 787 788 switch (addr) { 789 case 0x00: 790 e6522_set_orb (via, val); 791 break; 792 793 case 0x01: 794 e6522_set_ora (via, val, 1); 795 break; 796 797 case 0x02: 798 e6522_set_ddrb (via, val); 799 break; 800 801 case 0x03: 802 e6522_set_ddra (via, val); 803 break; 804 805 case 0x04: 806 e6522_set_t1_latch_low (via, val); 807 break; 808 809 case 0x05: 810 e6522_set_t1_counter_high (via, val); 811 break; 812 813 case 0x06: 814 e6522_set_t1_latch_low (via, val); 815 break; 816 817 case 0x07: 818 e6522_set_t1_latch_high (via, val); 819 break; 820 821 case 0x08: 822 e6522_set_t2_latch_low (via, val); 823 break; 824 825 case 0x09: 826 e6522_set_t2_counter_high (via, val); 827 break; 828 829 case 0x0a: 830 e6522_set_shift (via, val); 831 break; 832 833 case 0x0b: 834 e6522_set_acr (via, val); 835 break; 836 837 case 0x0c: 838 e6522_set_pcr (via, val); 839 break; 840 841 case 0x0d: 842 e6522_set_ifr (via, via->ifr & ~val & 0x7f); 843 break; 844 845 case 0x0e: 846 e6522_set_ier (via, val); 847 break; 848 849 case 0x0f: 850 e6522_set_ora (via, val, 0); 851 break; 852 853 } 854} 855 856void e6522_set_uint16 (e6522_t *via, unsigned long addr, unsigned short val) 857{ 858 e6522_set_uint8 (via, addr, val & 0xff); 859} 860 861void e6522_set_uint32 (e6522_t *via, unsigned long addr, unsigned long val) 862{ 863 e6522_set_uint8 (via, addr, val & 0xff); 864} 865 866void e6522_reset (e6522_t *via) 867{ 868 via->ora = 0x00; 869 via->orb = 0x00; 870 871 via->ddra = 0x00; 872 via->ddrb = 0x00; 873 874 via->shift_val = 0; 875 via->shift_cnt = 0; 876 877 via->pcr = 0x00; 878 via->acr = 0x00; 879 880 via->ifr = 0x00; 881 via->ier = 0x00; 882 883 via->t1_reload = 0; 884 via->t1_timeout = 0; 885 via->t1_hot = 0; 886 via->t1_latch = 0; 887 via->t1_val = 0; 888 889 via->t2_timeout = 0; 890 via->t2_hot = 0; 891 via->t2_latch = 0; 892 via->t2_val = 0; 893 894 e6522_set_ora_out (via); 895 e6522_set_orb_out (via); 896 897 e6522_set_ifr (via, via->ifr); 898 899#if DEBUG_VIA 900 fprintf (stderr, "via: reset\n"); 901#endif 902} 903 904static 905void e6522_clock_t1 (e6522_t *via) 906{ 907 if (via->t1_reload) { 908 via->t1_reload = 0; 909 via->t1_timeout = 0; 910 via->t1_val = via->t1_latch; 911 return; 912 } 913 914 via->t1_val = (via->t1_val - 1) & 0xffff; 915 916 if (via->t1_val == 0) { 917 via->t1_timeout = 1; 918 } 919 else if (via->t1_timeout) { 920 via->t1_timeout = 0; 921 922 if (via->acr & 0x40) { 923 /* free running */ 924 925 e6522_set_ifr (via, via->ifr | E6522_IFR_T1); 926 927 via->t1_reload = 1; 928 } 929 else { 930 /* one shot */ 931 932 if (via->t1_hot) { 933 via->t1_hot = 0; 934 e6522_set_ifr (via, via->ifr | E6522_IFR_T1); 935 } 936 } 937 } 938} 939 940static 941void e6522_clock_t2 (e6522_t *via) 942{ 943 via->t2_val = (via->t2_val - 1) & 0xffff; 944 945 if (via->t2_val == 0) { 946 via->t2_timeout = 1; 947 } 948 else if (via->t2_timeout) { 949 via->t2_timeout = 0; 950 951 if (via->acr & 0x20) { 952 /* free running */ 953 ; 954 } 955 else { 956 /* one shot */ 957 958 if (via->t2_hot) { 959 via->t2_hot = 0; 960 e6522_set_ifr (via, via->ifr | E6522_IFR_T2); 961 } 962 } 963 } 964} 965 966void e6522_clock (e6522_t *via, unsigned n) 967{ 968 while (n-- > 0) { 969 e6522_clock_t1 (via); 970 e6522_clock_t2 (via); 971 } 972}