this repo has no description
at main 2975 lines 61 kB view raw
1/* 2 SCCEMDEV.c 3 4 Copyright (C) 2012 Philip Cummins, Weston Pawlowski, 5 Michael Fort, Paul C. Pratt 6 7 You can redistribute this file and/or modify it under the terms 8 of version 2 of the GNU General Public License as published by 9 the Free Software Foundation. You should have received a copy 10 of the license along with this file; see the file COPYING. 11 12 This file is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 license for more details. 16*/ 17 18/* 19 Serial Communications Controller EMulated DEVice 20 21 additions for LocalTalk networking support 22 Copyright 2011-2012, Michael Fort 23 enabled with "EmLocalTalk" 24 25 -- original description: -- 26 27 Emulates the Z8530 SCC found in the Mac Plus. 28 But only the minimum amount needed to emulate 29 normal operation in a Mac Plus with nothing 30 connected to the serial ports. 31 (and not even that much is complete yet) 32 33 This code adapted from "SCC.c" in vMac by Philip Cummins. 34 With additional code by Weston Pawlowski from the Windows 35 port of vMac. 36 37 Further information was found in the 38 "Zilog SCC/ESCC User's Manual". 39*/ 40 41#include "PICOMMON.h" 42 43#include "SCCEMDEV.h" 44 45/* 46 ReportAbnormalID unused 0x074D - 0x07FF 47*/ 48 49#define SCC_dolog (dbglog_HAVE && 0) 50#define SCC_TrackMore 0 51 52#if EmLocalTalk 53 54LOCALVAR blnr CTSpacketPending = falseblnr; 55LOCALVAR ui3r CTSpacketRxDA; 56LOCALVAR ui3r CTSpacketRxSA; 57 58LOCALVAR blnr IsFindingNode = falseblnr; 59 60/* 61 Function used when all the tx data is sent to the SCC as indicated 62 by resetting the TX underrun/EOM latch. If the transmit packet is 63 a unicast RTS LAPD packet, we fake the corresponding CTS LAPD 64 packet. This is okay because it is only a collision avoidance 65 mechanism and the Ethernet device itself and BPF automatically 66 handle collision detection and retransmission. Besides this is 67 what a standard AppleTalk (LocalTalk to EtherTalk) bridge does. 68*/ 69LOCALPROC LT_TransmitPacket1(void) 70{ 71 /* Check for LLAP RTS/CTS packets, which we won't send */ 72#if SCC_dolog 73 dbglog_WriteNote("SCC sending packet to UDP"); 74 dbglog_StartLine(); 75 dbglog_writelnNum("LT_TxBuffSz", LT_TxBuffSz); 76#endif 77 78 if (LT_TxBuffSz < 3) { 79 ReportAbnormalID(0x0721, 80 "packet too small in " 81 "in LT_TransmitPacket1"); 82 } else { 83 ui3r type = LT_TxBuffer[2]; 84 85#if SCC_dolog 86 dbglog_StartLine(); 87 dbglog_writelnNum("dst", LT_TxBuffer[0]); 88 dbglog_StartLine(); 89 dbglog_writelnNum("src", LT_TxBuffer[1]); 90 dbglog_StartLine(); 91 dbglog_writelnNum("type", type); 92#endif 93 94 if (type < 0x80) { 95 /* data packet */ 96#if LT_MayHaveEcho 97 IsFindingNode = falseblnr; 98#endif 99 LT_TransmitPacket(); 100 } else { 101 /* control packet */ 102 103 if (3 != LT_TxBuffSz) { 104 ReportAbnormalID(0x0722, 105 "unexpected size of control packet in " 106 "in LT_TransmitPacket1"); 107 } 108 109 if (0x81 == type) { 110#if SCC_dolog 111 dbglog_WriteNote( 112 "SCC LLAP packet lapENQ"); 113#endif 114#if LT_MayHaveEcho 115 IsFindingNode = trueblnr; 116#endif 117 LT_TransmitPacket(); 118 } else 119 if (0x82 == type) { 120#if SCC_dolog 121 dbglog_WriteNote( 122 "SCC LLAP packet lapACK"); 123#endif 124 LT_TransmitPacket(); 125 } else 126 if (0x84 == type) { 127 /* lapRTS - Request to send*/ 128 if (0xFF == LT_TxBuffer[0]) { 129#if SCC_dolog 130 dbglog_WriteNote( 131 "SCC LLAP packet ignore broadcast lapRTS"); 132#endif 133 } else 134 if (CTSpacketPending) { 135 ReportAbnormalID(0x0701, 136 "Already CTSpacketPending " 137 "in LT_TransmitPacket1"); 138 } else 139 { 140#if SCC_dolog 141 dbglog_WriteNote( 142 "SCC LLAP packet lapRTS"); 143#endif 144 CTSpacketRxDA = LT_TxBuffer[1]; /* rx da = tx sa */ 145 CTSpacketRxSA = LT_TxBuffer[0]; /* rx sa = tx da */ 146 CTSpacketPending = trueblnr; 147 } 148 } else 149 if (0x85 == type) { 150 /* ignore lapCTS - Clear To Send */ 151#if SCC_dolog 152 dbglog_WriteNote( 153 "SCC LLAP packet lapCTS"); 154#endif 155 } else 156 { 157#if SCC_dolog 158 dbglog_WriteNote( 159 "SCC LLAP packet unknown"); 160#endif 161 162 LT_TransmitPacket(); 163 } 164 } 165 } 166} 167 168LOCALVAR ui3b MyCTSBuffer[4]; 169 170LOCALPROC GetCTSpacket(void) 171{ 172 /* Get a single buffer worth of packets at a time */ 173 ui3p device_buffer = MyCTSBuffer; 174 175#if SCC_dolog 176 dbglog_WriteNote("SCC receiving CTS packet"); 177#endif 178 /* Create the fake response from the other node */ 179 device_buffer[0] = CTSpacketRxDA; 180 device_buffer[1] = CTSpacketRxSA; 181 device_buffer[2] = 0x85; /* llap cts */ 182 183 /* Start the receiver */ 184 LT_RxBuffer = device_buffer; 185 LT_RxBuffSz = 3; 186 187 CTSpacketPending = falseblnr; 188} 189 190/* LLAP/SDLC address */ 191LOCALVAR ui3b my_node_address = 0; 192 193LOCALVAR blnr LTAddrSrchMd = falseblnr; 194 195LOCALPROC GetNextPacketForMe(void) 196{ 197 ui3r dst; 198 ui3r src; 199 ui3r type; 200 201label_retry: 202 LT_ReceivePacket(); 203 204 if (nullpr != LT_RxBuffer) { 205 /* Is this packet destined for me? */ 206 dst = LT_RxBuffer[0]; 207 src = LT_RxBuffer[1]; 208 type = LT_RxBuffer[2]; 209 210#if SCC_dolog 211 dbglog_StartLine(); 212 dbglog_writeln("SCC receiving packet from UDP"); 213 dbglog_writelnNum("LT_RxBuffSz", LT_RxBuffSz); 214 dbglog_writelnNum("dst", dst); 215 dbglog_writelnNum("src", src); 216 dbglog_writelnNum("type", type); 217#endif 218 219 if ((dst != my_node_address) 220 && (dst != 0xFF) 221 && LTAddrSrchMd) 222 { 223#if SCC_dolog 224 dbglog_WriteNote("SCC ignore packet not for me"); 225#endif 226 LT_RxBuffer = nullpr; 227 goto label_retry; 228 } else 229#if LT_MayHaveEcho 230 if (CertainlyNotMyPacket) { 231#if SCC_dolog 232 dbglog_WriteNote("CertainlyNotMyPacket"); 233#endif 234 } else 235 if (src != my_node_address) { 236 /* we definitely did not send it, so ok */ 237 } else 238 /* 239 we should ignore packets "from" myself except ACK packets, 240 which tell me that we've got an address collision, 241 and ENQ packets which tell me I might be about to 242 */ 243 if (0x81 == type) { 244 if (! IsFindingNode) { 245 /* pass it on for lapACK reply */ 246#if SCC_dolog 247 dbglog_WriteNote("received lapENQ to us"); 248#endif 249 } else { 250 /* probably this is ourself, ignore */ 251#if SCC_dolog 252 dbglog_WriteNote("received lapENQ probably from us"); 253#endif 254 LT_RxBuffer = nullpr; 255 goto label_retry; 256 } 257 } else 258 if (0x82 == type) { 259 if (! IsFindingNode) { 260#if SCC_dolog 261 dbglog_WriteNote("received lapACK probably from us"); 262#endif 263 LT_RxBuffer = nullpr; 264 goto label_retry; 265 } else { 266 /* lapACK, pass it on handle collision */ 267#if SCC_dolog 268 dbglog_WriteNote("received lapACK to us"); 269#endif 270 } 271 } else 272 { 273#if SCC_dolog 274 dbglog_WriteNote("SCC ignore packet from myself"); 275#endif 276 LT_RxBuffer = nullpr; 277 goto label_retry; 278 } 279#else 280 { 281 /* 282 checking for own packets isn't needed, because of 283 packetIsOneISent check. if someone else is masquerading 284 as our address, it probably is more accurate emulation 285 to accept the packet. 286 */ 287 288 /* ok */ 289 } 290#endif 291 } 292} 293 294LOCALPROC LT_ReceivePacket1(void) 295{ 296 if (CTSpacketPending) { 297 GetCTSpacket(); 298 } else { 299 GetNextPacketForMe(); 300 } 301} 302 303LOCALPROC LT_AddrSrchMdSet(blnr v) 304{ 305#if SCC_dolog 306 dbglog_StartLine(); 307 dbglog_writelnNum("LT_AddrSrchMdSet", v); 308#endif 309 LTAddrSrchMd = v; 310} 311 312LOCALPROC LT_NodeAddressSet(ui3r v) 313{ 314#if SCC_dolog 315 dbglog_StartLine(); 316 dbglog_writelnNum("LT_NodeAddressSet", v); 317#endif 318 if (0 != v) { 319 my_node_address = v; 320 } 321} 322 323#endif /* EmLocalTalk */ 324 325/* Just to make things a little easier */ 326#define Bit0 1 327#define Bit1 2 328#define Bit2 4 329#define Bit3 8 330#define Bit4 16 331#define Bit5 32 332#define Bit6 64 333#define Bit7 128 334 335/* SCC Interrupts */ 336#define SCC_A_Rx 8 /* Rx Char Available */ 337#define SCC_A_Rx_Spec 7 /* Rx Special Condition */ 338#define SCC_A_Tx_Empty 6 /* Tx Buffer Empty */ 339#define SCC_A_Ext 5 /* External/Status Change */ 340#define SCC_B_Rx 4 /* Rx Char Available */ 341#define SCC_B_Rx_Spec 3 /* Rx Special Condition */ 342#define SCC_B_Tx_Empty 2 /* Tx Buffer Empty */ 343#define SCC_B_Ext 1 /* External/Status Change */ 344 345typedef struct { 346 blnr TxEnable; 347 blnr RxEnable; 348 blnr TxIE; /* Transmit Interrupt Enable */ 349 blnr TxUnderrun; 350 blnr SyncHunt; 351 blnr TxIP; /* Transmit Interrupt Pending */ 352#if EmLocalTalk 353 ui3r RxBuff; 354#endif 355#if EmLocalTalk 356 /* otherwise TxBufferEmpty always true */ 357 /* 358 though should behave as went false 359 for an instant when write to transmit buffer 360 */ 361 blnr TxBufferEmpty; 362#endif 363#if EmLocalTalk || SCC_TrackMore 364 blnr ExtIE; 365#endif 366#if SCC_TrackMore 367 blnr WaitRqstEnbl; 368#endif 369#if SCC_TrackMore 370 blnr WaitRqstSlct; 371#endif 372#if SCC_TrackMore 373 blnr WaitRqstRT; 374#endif 375#if SCC_TrackMore 376 blnr PrtySpclCond; 377#endif 378#if SCC_TrackMore 379 blnr PrtyEnable; 380#endif 381#if SCC_TrackMore 382 blnr PrtyEven; 383#endif 384#if SCC_TrackMore 385 blnr RxCRCEnbl; 386#endif 387#if SCC_TrackMore 388 blnr TxCRCEnbl; 389#endif 390#if SCC_TrackMore 391 blnr RTSctrl; 392#endif 393#if SCC_TrackMore 394 blnr SndBrkCtrl; 395#endif 396#if SCC_TrackMore 397 blnr DTRctrl; 398#endif 399#if EmLocalTalk || SCC_TrackMore 400 blnr AddrSrchMd; 401#endif 402#if SCC_TrackMore 403 blnr SyncChrLdInhb; 404#endif 405#if SCC_TrackMore 406 ui3r ClockRate; 407#endif 408#if SCC_TrackMore 409 ui3r DataEncoding; 410#endif 411#if SCC_TrackMore 412 ui3r TRxCsrc; 413#endif 414#if SCC_TrackMore 415 ui3r TClkSlct; 416#endif 417#if SCC_TrackMore 418 ui3r RClkSlct; 419#endif 420#if SCC_TrackMore 421 ui3r RBitsPerChar; 422#endif 423#if SCC_TrackMore 424 ui3r TBitsPerChar; 425#endif 426#if EmLocalTalk || SCC_TrackMore 427 ui3r RxIntMode; 428#endif 429#if EmLocalTalk || SCC_TrackMore 430 blnr FirstChar; 431#endif 432#if EmLocalTalk || SCC_TrackMore 433 ui3r SyncMode; 434#endif 435#if SCC_TrackMore 436 ui3r StopBits; 437#endif 438#if 0 /* AllSent always true */ 439 blnr AllSent; 440#endif 441#if 0 /* CTS always false */ 442 blnr CTS; /* input pin, unattached, so false? */ 443#endif 444#if 0 /* DCD always false */ 445 blnr DCD; /* Data Carrier Detect */ 446 /* 447 input pin for mouse interrupts. but since 448 not emulating mouse this way, leave false. 449 */ 450#endif 451#if EmLocalTalk 452 /* otherwise RxChrAvail always false */ 453 blnr RxChrAvail; 454#endif 455#if 0 /* RxOverrun always false */ 456 blnr RxOverrun; 457#endif 458#if 0 /* CRCFramingErr always false */ 459 blnr CRCFramingErr; 460#endif 461#if EmLocalTalk 462 /* otherwise EndOfFrame always false */ 463 blnr EndOfFrame; 464#endif 465#if 0 /* ParityErr always false */ 466 blnr ParityErr; 467#endif 468#if 0 /* ZeroCount always false */ 469 blnr ZeroCount; 470#endif 471#if 0 /* BreakAbort always false */ 472 blnr BreakAbort; 473#endif 474#if 0 /* SyncHuntIE usually false */ 475 blnr SyncHuntIE; 476#endif 477#if SCC_TrackMore /* don't care about CTS_IE */ 478 blnr CTS_IE; 479#endif 480#if SCC_TrackMore 481 blnr CRCPreset; 482#endif 483#if SCC_TrackMore 484 blnr BRGEnbl; 485#endif 486#if 0 /* don't care about DCD_IE, always true */ 487 blnr DCD_IE; 488#endif 489#if SCC_TrackMore /* don't care about BreakAbortIE */ 490 blnr BreakAbortIE; 491#endif 492#if SCC_TrackMore /* don't care about Baud */ 493 ui3r BaudLo; 494 ui3r BaudHi; 495#endif 496} Channel_Ty; 497 498typedef struct { 499 Channel_Ty a[2]; /* 0 = channel A, 1 = channel B */ 500 int SCC_Interrupt_Type; 501 int PointerBits; 502 ui3b InterruptVector; 503 blnr MIE; /* master interrupt enable */ 504#if SCC_TrackMore 505 blnr NoVectorSlct; 506#endif 507#if 0 /* StatusHiLo always false */ 508 blnr StatusHiLo; 509#endif 510} SCC_Ty; 511 512LOCALVAR SCC_Ty SCC; 513 514#if 0 515LOCALVAR int ReadPrint; 516LOCALVAR int ReadModem; 517#endif 518 519#if EmLocalTalk 520static int rx_data_offset = 0; 521 /* when data pending, this is used */ 522#endif 523 524EXPORTFUNC blnr SCC_InterruptsEnabled(void) 525{ 526 return SCC.MIE; 527} 528 529/* ---- */ 530 531/* Function used to update the interrupt state of the SCC */ 532LOCALPROC CheckSCCInterruptFlag(void) 533{ 534#if 0 /* ReceiveAInterrupt always false */ 535 blnr ReceiveAInterrupt = falseblnr 536 /* 537 also dependeds on WR1, bits 3 and 4, but 538 this doesn't change that it's all false 539 */ 540#if EmLocalTalk 541 /* otherwise RxChrAvail always false */ 542 | SCC.a[0].RxChrAvail 543#endif 544#if 0 /* RxOverrun always false */ 545 | SCC.a[0].RxOverrun 546#endif 547#if 0 /* CRCFramingErr always false */ 548 | SCC.a[0].CRCFramingErr 549#endif 550#if EmLocalTalk 551 /* otherwise EndOfFrame always false */ 552 | SCC.a[0].EndOfFrame 553#endif 554#if 0 /* ParityErr always false */ 555 | SCC.a[0].ParityErr 556#endif 557 ; 558#endif 559#if 0 560 blnr TransmitAInterrupt = SCC.a[0].TxBufferEmpty; 561 /* 562 but probably looking for transitions not 563 current value 564 */ 565#endif 566#if 0 567 blnr ExtStatusAInterrupt = 0 568#if 0 /* ZeroCount always false */ 569 | SCC.a[0].ZeroCount 570#endif 571 /* probably want transition for these, not value */ 572#if 0 /* DCD always false */ 573 | SCC.a[0].DCD /* DCD IE always true */ 574#endif 575#if 0 /* CTS always false */ 576 | SCC.a[0].CTS /* would depend on CTS_IE */ 577#endif 578 | SCC.a[0].SyncHunt /* SyncHuntIE usually false */ 579 | SCC.a[0].TxUnderrun /* Tx underrun/EOM IE always false */ 580#if 0 /* BreakAbort always false */ 581 | SCC.a[0].BreakAbort 582#endif 583 ; 584#endif 585 ui3b NewSCCInterruptRequest; 586 587#if EmLocalTalk 588 blnr ReceiveBInterrupt = falseblnr; 589 blnr RxSpclBInterrupt = falseblnr 590 /* otherwise EndOfFrame always false */ 591 | SCC.a[1].EndOfFrame 592 ; 593#endif 594 595#if EmLocalTalk 596 switch (SCC.a[1].RxIntMode) { 597 case 0: 598 /* disabled */ 599 RxSpclBInterrupt = falseblnr; 600 break; 601 case 1: 602 /* Rx INT on 1st char or special condition */ 603 if (SCC.a[1].RxChrAvail && SCC.a[1].FirstChar) { 604 ReceiveBInterrupt = trueblnr; 605 } 606 break; 607 case 2: 608 /* INT on all Rx char or special condition */ 609 if (SCC.a[1].RxChrAvail) { 610 ReceiveBInterrupt = trueblnr; 611 } 612 break; 613 case 3: 614 /* Rx INT on special condition only */ 615 break; 616 } 617#endif 618 619 /* Master Interrupt Enable */ 620 if (! SCC.MIE) { 621 SCC.SCC_Interrupt_Type = 0; 622 } else 623#if 0 624 /* External Interrupt Enable */ 625 if (SCC.a[1].ExtIE) { 626 /* DCD Interrupt Enable */ 627 if (SCC.a[1].DCD_IE && 0) { /* dcd unchanged */ 628 SCC.SCC_Interrupt_Type = ??; 629 } 630 } 631#endif 632 if (SCC.a[0].TxIP && SCC.a[0].TxIE) { 633 SCC.SCC_Interrupt_Type = SCC_A_Tx_Empty; 634 } else 635#if EmLocalTalk 636 if (ReceiveBInterrupt) { 637 SCC.SCC_Interrupt_Type = SCC_B_Rx; 638 } else 639 if (RxSpclBInterrupt) { 640 SCC.SCC_Interrupt_Type = SCC_B_Rx_Spec; 641 } else 642#endif 643 if (SCC.a[1].TxIP && SCC.a[1].TxIE) { 644 SCC.SCC_Interrupt_Type = SCC_B_Tx_Empty; 645 } else 646 { 647 SCC.SCC_Interrupt_Type = 0; 648 } 649 650 NewSCCInterruptRequest = (SCC.SCC_Interrupt_Type != 0) ? 1 : 0; 651 if (NewSCCInterruptRequest != SCCInterruptRequest) { 652#if SCC_dolog 653 dbglog_WriteSetBool("SCCInterruptRequest change", 654 NewSCCInterruptRequest); 655 656 dbglog_StartLine(); 657 dbglog_writeCStr("SCC.SCC_Interrupt_Type <- "); 658 dbglog_writeHex(SCC.SCC_Interrupt_Type); 659 dbglog_writeReturn(); 660#endif 661 SCCInterruptRequest = NewSCCInterruptRequest; 662#ifdef SCCinterruptChngNtfy 663 SCCinterruptChngNtfy(); 664#endif 665 } 666} 667 668LOCALPROC SCC_InitChannel(int chan) 669{ 670 /* anything not done by ResetChannel */ 671 672 SCC.a[chan].SyncHunt = trueblnr; 673#if 0 /* DCD always false */ 674 SCC.a[chan].DCD = falseblnr; /* input pin, reset doesn't change */ 675#endif 676#if 0 /* CTS always false */ 677 SCC.a[chan].CTS = falseblnr; /* input pin, reset doesn't change */ 678#endif 679#if 0 /* AllSent always true */ 680 SCC.a[chan].AllSent = trueblnr; 681#endif 682#if SCC_TrackMore /* don't care about Baud */ 683 SCC.a[chan].BaudLo = 0; 684 SCC.a[chan].BaudHi = 0; 685#endif 686#if 0 /* BreakAbort always false */ 687 SCC.a[chan].BreakAbort = falseblnr; 688#endif 689#if SCC_TrackMore 690 SCC.a[chan].BRGEnbl = falseblnr; 691#endif 692#if SCC_TrackMore 693 SCC.a[chan].TRxCsrc = 0; 694#endif 695#if SCC_TrackMore 696 SCC.a[chan].TClkSlct = 1; 697#endif 698#if SCC_TrackMore 699 SCC.a[chan].RClkSlct = 0; 700#endif 701} 702 703LOCALPROC SCC_ResetChannel(int chan) 704{ 705/* RR 0 */ 706#if EmLocalTalk 707 SCC.a[chan].RxBuff = 0; 708#endif 709#if EmLocalTalk 710 /* otherwise RxChrAvail always false */ 711 SCC.a[chan].RxChrAvail = falseblnr; 712#endif 713#if 0 /* ZeroCount always false */ 714 SCC.a[chan].ZeroCount = falseblnr; 715#endif 716#if EmLocalTalk 717 /* otherwise TxBufferEmpty always true */ 718 SCC.a[chan].TxBufferEmpty = trueblnr; 719#endif 720 SCC.a[chan].TxUnderrun = trueblnr; 721/* RR 1 */ 722#if 0 /* ParityErr always false */ 723 SCC.a[chan].ParityErr = falseblnr; 724#endif 725#if 0 /* RxOverrun always false */ 726 SCC.a[chan].RxOverrun = falseblnr; 727#endif 728#if 0 /* CRCFramingErr always false */ 729 SCC.a[chan].CRCFramingErr = falseblnr; 730#endif 731#if EmLocalTalk 732 /* otherwise EndOfFrame always false */ 733 SCC.a[chan].EndOfFrame = falseblnr; 734#endif 735/* RR 3 */ 736#if EmLocalTalk || SCC_TrackMore 737 SCC.a[chan].ExtIE = falseblnr; 738#endif 739#if SCC_TrackMore 740 SCC.a[chan].RxCRCEnbl = falseblnr; 741#endif 742#if SCC_TrackMore 743 SCC.a[chan].TxCRCEnbl = falseblnr; 744#endif 745#if SCC_TrackMore 746 SCC.a[chan].RTSctrl = falseblnr; 747#endif 748#if SCC_TrackMore 749 SCC.a[chan].SndBrkCtrl = falseblnr; 750#endif 751#if SCC_TrackMore 752 SCC.a[chan].DTRctrl = falseblnr; 753#endif 754#if EmLocalTalk || SCC_TrackMore 755 SCC.a[chan].AddrSrchMd = falseblnr; 756 if (0 != chan) { 757 LT_AddrSrchMdSet(falseblnr); 758 } 759#endif 760#if SCC_TrackMore 761 SCC.a[chan].SyncChrLdInhb = falseblnr; 762#endif 763#if SCC_TrackMore 764 SCC.a[chan].WaitRqstEnbl = falseblnr; 765#endif 766#if SCC_TrackMore 767 SCC.a[chan].WaitRqstSlct = falseblnr; 768#endif 769#if SCC_TrackMore 770 SCC.a[chan].WaitRqstRT = falseblnr; 771#endif 772#if SCC_TrackMore 773 SCC.a[chan].PrtySpclCond = falseblnr; 774#endif 775#if SCC_TrackMore 776 SCC.a[chan].PrtyEnable = falseblnr; 777#endif 778#if SCC_TrackMore 779 SCC.a[chan].PrtyEven = falseblnr; 780#endif 781#if SCC_TrackMore 782 SCC.a[chan].ClockRate = 0; 783#endif 784#if SCC_TrackMore 785 SCC.a[chan].DataEncoding = 0; 786#endif 787#if SCC_TrackMore 788 SCC.a[chan].RBitsPerChar = 0; 789#endif 790#if SCC_TrackMore 791 SCC.a[chan].TBitsPerChar = 0; 792#endif 793#if EmLocalTalk || SCC_TrackMore 794 SCC.a[chan].RxIntMode = 0; 795#endif 796#if EmLocalTalk || SCC_TrackMore 797 SCC.a[chan].FirstChar = falseblnr; 798#endif 799#if EmLocalTalk || SCC_TrackMore 800 SCC.a[chan].SyncMode = 0; 801#endif 802#if SCC_TrackMore 803 SCC.a[chan].StopBits = 0; 804#endif 805#if SCC_TrackMore 806 SCC.NoVectorSlct = falseblnr; 807#endif 808 SCC.a[chan].TxIP = falseblnr; 809 810 SCC.a[chan].TxEnable = falseblnr; 811 SCC.a[chan].RxEnable = falseblnr; 812 SCC.a[chan].TxIE = falseblnr; 813 814#if 0 /* don't care about DCD_IE, always true */ 815 SCC.a[chan].DCD_IE = trueblnr; 816#endif 817#if SCC_TrackMore /* don't care about CTS_IE */ 818 SCC.a[chan].CTS_IE = trueblnr; 819#endif 820#if SCC_TrackMore 821 SCC.a[chan].CRCPreset = falseblnr; 822#endif 823#if 0 /* SyncHuntIE usually false */ 824 SCC.a[chan].SyncHuntIE = trueblnr; 825#endif 826#if SCC_TrackMore /* don't care about BreakAbortIE */ 827 SCC.a[chan].BreakAbortIE = trueblnr; 828#endif 829 830 SCC.PointerBits = 0; 831 832#if 0 833 if (0 != chan) { 834 ReadPrint = 0; 835 } else { 836 ReadModem = 0; 837 } 838#endif 839} 840 841GLOBALPROC SCC_Reset(void) 842{ 843 SCCwaitrq = 1; 844 845 SCC.SCC_Interrupt_Type = 0; 846 847 SCCInterruptRequest = 0; 848 SCC.PointerBits = 0; 849 SCC.MIE = falseblnr; 850 SCC.InterruptVector = 0; 851#if 0 /* StatusHiLo always false */ 852 SCC.StatusHiLo = falseblnr; 853#endif 854 855 SCC_InitChannel(1); 856 SCC_InitChannel(0); 857 858 SCC_ResetChannel(1); 859 SCC_ResetChannel(0); 860} 861 862 863#if EmLocalTalk 864 865LOCALPROC SCC_TxBuffPut(ui3r Data) 866{ 867 /* Buffer the data in the transmit buffer */ 868 if (LT_TxBuffSz < LT_TxBfMxSz) { 869 LT_TxBuffer[LT_TxBuffSz] = Data; 870 ++LT_TxBuffSz; 871 } 872} 873 874/* 875 This function is called once all the normal packet bytes have been 876 received. 877*/ 878LOCALPROC rx_complete(void) 879{ 880 if (SCC.a[1].EndOfFrame) { 881 ReportAbnormalID(0x0702, "EndOfFrame true in rx_complete"); 882 } 883 if (! SCC.a[1].RxChrAvail) { 884 ReportAbnormalID(0x0703, "RxChrAvail false in rx_complete"); 885 } 886 if (SCC.a[1].SyncHunt) { 887 ReportAbnormalID(0x0704, "SyncHunt true in rx_complete"); 888 } 889 890 /* 891 Need to wait for rx_eof_pending (end of frame) to clear before 892 preparing the next packet for receive. 893 */ 894 LT_RxBuffer = nullpr; 895 896 SCC.a[1].EndOfFrame = trueblnr; 897} 898 899LOCALPROC SCC_RxBuffAdvance(void) 900{ 901 ui3r value; 902 903 /* 904 From the manual: 905 "If status is checked, it must be done before the data is read, 906 because the act of reading the data pops both the data and 907 error FIFOs." 908 */ 909 910 if (nullpr == LT_RxBuffer) { 911 value = 0x7E; 912 SCC.a[1].RxChrAvail = falseblnr; 913 } else { 914 if (rx_data_offset < LT_RxBuffSz) { 915 value = LT_RxBuffer[rx_data_offset]; 916 } else { 917 ui5r i = rx_data_offset - LT_RxBuffSz; 918 919 /* if i==0 in first byte of CRC, have not got EOF yet */ 920 if (i == 1) { 921 rx_complete(); 922 } 923 924 value = 0; 925 } 926 ++rx_data_offset; 927 } 928 929 SCC.a[1].RxBuff = value; 930} 931 932/* 933 External function, called periodically, to poll for any new LTOE 934 packets. Any new packets are queued into the packet receipt queue. 935*/ 936GLOBALPROC LocalTalkTick(void) 937{ 938 if (SCC.a[1].RxEnable 939 && (! SCC.a[1].RxChrAvail)) 940 { 941 if (nullpr != LT_RxBuffer) { 942#if SCC_dolog 943 dbglog_WriteNote("SCC recover abandoned packet"); 944#endif 945 } else { 946 LT_ReceivePacket1(); 947 } 948 949 if (nullpr != LT_RxBuffer) { 950 rx_data_offset = 0; 951 SCC.a[1].EndOfFrame = falseblnr; 952 SCC.a[1].RxChrAvail = trueblnr; 953 SCC.a[1].SyncHunt = falseblnr; 954 955 SCC_RxBuffAdvance(); 956 /* We can update the rx interrupt if enabled */ 957 CheckSCCInterruptFlag(); 958 } 959 } 960} 961 962#endif 963 964 965#if 0 966LOCALPROC SCC_Interrupt(int Type) 967{ 968 if (SCC.MIE) { /* Master Interrupt Enable */ 969 970 if (Type > SCC.SCC_Interrupt_Type) { 971 SCC.SCC_Interrupt_Type = Type; 972 } 973 974 CheckSCCInterruptFlag(); 975 } 976} 977#endif 978 979#if 0 980LOCALPROC SCC_Int(void) 981{ 982 /* This should be called at regular intervals */ 983 984 /* Turn off Sync/Hunt Mode */ 985 if (SCC.a[0].SyncHunt) { 986 SCC.a[0].SyncHunt = falseblnr; 987 988#ifdef _SCC_Debug2 989 vMac_Message("SCC_Int: Disable Sync/Hunt on A"); 990#endif 991 992#if 0 /* SyncHuntIE usually false */ 993 if (SCC.a[0].SyncHuntIE) { 994 SCC_Interrupt(SCC_A_Ext); 995 } 996#endif 997 } 998 if (SCC.a[1].SyncHunt) { 999 SCC.a[1].SyncHunt = falseblnr; 1000 1001#ifdef _SCC_Debug2 1002 vMac_Message("SCC_Int: Disable Sync/Hunt on B"); 1003#endif 1004 1005#if 0 /* SyncHuntIE usually false */ 1006 if (SCC.a[1].SyncHuntIE) { 1007 SCC_Interrupt(SCC_B_Ext); 1008 } 1009#endif 1010 } 1011 1012#if 0 1013 /* Check for incoming data */ 1014 if (ModemPort) 1015 { 1016 if (! SCC.a[0].RxEnable) { /* Rx Disabled */ 1017 ReadModem = 0; 1018 } 1019 1020 if ((ModemBytes > 0) && (ModemCount > ModemBytes - 1)) 1021 { 1022 SCC.a[0].RxChrAvail = falseblnr; 1023 ReadModem = ModemBytes = ModemCount = 0; 1024 } 1025 1026 if (ReadModem) { 1027 ReadModem = 2; 1028 1029 SCC.a[0].RxChrAvail = trueblnr; 1030 1031 if (SCC.a[0].WR[0] & Bit5 1032 && ! (SCC.a[0].WR[0] & (Bit4 | Bit3))) 1033 { 1034 /* Int on next Rx char */ 1035 SCC_Interrupt(SCC_A_Rx); 1036 } else if (SCC.a[0].WR[1] & Bit3 1037 && ! (SCC.a[0].WR[1] & Bit4)) 1038 { 1039 /* Int on first Rx char */ 1040 SCC_Interrupt(SCC_A_Rx); 1041 } else if (SCC.a[0].WR[1] & Bit4 1042 && ! (SCC.a[0].WR[1] & Bit3)) 1043 { 1044 /* Int on all Rx chars */ 1045 SCC_Interrupt(SCC_A_Rx); 1046 } 1047 } 1048 } 1049 if (PrintPort) { 1050 if (! SCC.a[1].RxEnable) { 1051 /* Rx Disabled */ 1052 ReadPrint = 0; 1053 } 1054 1055 if ((PrintBytes > 0) && (PrintCount > PrintBytes - 1)) { 1056 SCC.a[1].RxChrAvail = falseblnr; 1057 ReadPrint = PrintBytes = PrintCount = 0; 1058 } 1059 1060 if (ReadPrint) { 1061 ReadPrint = 2; 1062 1063 SCC.a[1].RxChrAvail = trueblnr; 1064 1065 if (SCC.a[1].WR[0] & Bit5 1066 && ! (SCC.a[1].WR[0] & (Bit4 | Bit3))) 1067 { 1068 /* Int on next Rx char */ 1069 SCC_Interrupt(SCC_B_Rx); 1070 } else if (SCC.a[1].WR[1] & Bit3 1071 && ! (SCC.a[1].WR[1] & Bit4)) 1072 { 1073 /* Int on first Rx char */ 1074 SCC_Interrupt(SCC_B_Rx); 1075 } else if (SCC.a[1].WR[1] & Bit4 1076 && ! (SCC.a[1].WR[1] & Bit3)) 1077 { 1078 /* Int on all Rx chars */ 1079 SCC_Interrupt(SCC_B_Rx); 1080 } 1081 } 1082 } 1083#endif 1084} 1085#endif 1086 1087#if SCC_dolog 1088LOCALPROC SCC_DbgLogChanStartLine(int chan) 1089{ 1090 dbglog_StartLine(); 1091 dbglog_writeCStr("SCC chan("); 1092 if (chan) { 1093 dbglog_writeCStr("B"); 1094 } else { 1095 dbglog_writeCStr("A"); 1096 } 1097 /* dbglog_writeHex(chan); */ 1098 dbglog_writeCStr(")"); 1099} 1100#endif 1101 1102LOCALFUNC ui3r SCC_GetRR0(int chan) 1103{ 1104 /* happens on boot always */ 1105 1106 return 0 1107#if 0 /* BreakAbort always false */ 1108 | (SCC.a[chan].BreakAbort ? (1 << 7) : 0) 1109#endif 1110 | (SCC.a[chan].TxUnderrun ? (1 << 6) : 0) 1111#if 0 /* CTS always false */ 1112 | (SCC.a[chan].CTS ? (1 << 5) : 0) 1113#endif 1114 | (SCC.a[chan].SyncHunt ? (1 << 4) : 0) 1115#if 0 /* DCD always false */ 1116 | (SCC.a[chan].DCD ? (1 << 3) : 0) 1117#endif 1118#if EmLocalTalk 1119 | (SCC.a[chan].TxBufferEmpty ? (1 << 2) : 0) 1120#else 1121 /* otherwise TxBufferEmpty always true */ 1122 | (1 << 2) 1123#endif 1124#if 0 /* ZeroCount always false */ 1125 | (SCC.a[chan].ZeroCount ? (1 << 1) : 0) 1126#endif 1127#if EmLocalTalk 1128 /* otherwise RxChrAvail always false */ 1129 | (SCC.a[chan].RxChrAvail ? (1 << 0) : 0) 1130#endif 1131 ; 1132} 1133 1134LOCALFUNC ui3r SCC_GetRR1(int chan) 1135{ 1136 /* happens in MacCheck */ 1137 1138 ui3r value; 1139#if ! EmLocalTalk 1140 UnusedParam(chan); 1141#endif 1142 1143 value = Bit2 | Bit1 1144#if 0 /* AllSent always true */ 1145 | (SCC.a[chan].AllSent ? (1 << 0) : 0) 1146#else 1147 | Bit0 1148#endif 1149#if 0 /* ParityErr always false */ 1150 | (SCC.a[chan].ParityErr ? (1 << 4) : 0) 1151#endif 1152#if 0 /* RxOverrun always false */ 1153 | (SCC.a[chan].RxOverrun ? (1 << 5) : 0) 1154#endif 1155#if 0 /* CRCFramingErr always false */ 1156 | (SCC.a[chan].CRCFramingErr ? (1 << 6) : 0) 1157#endif 1158#if EmLocalTalk 1159 /* otherwise EndOfFrame always false */ 1160 | (SCC.a[chan].EndOfFrame ? (1 << 7) : 0) 1161#endif 1162 ; 1163 1164 return value; 1165} 1166 1167LOCALFUNC ui3r SCC_GetRR2(int chan) 1168{ 1169 /* happens in MacCheck */ 1170 /* happens in Print to ImageWriter */ 1171 1172 ui3r value = SCC.InterruptVector; 1173 1174 if (0 != chan) { /* B Channel */ 1175#if 0 /* StatusHiLo always false */ 1176 if (SCC.StatusHiLo) { 1177 /* Status High */ 1178 value = value 1179 & (Bit0 | Bit1 | Bit2 | Bit3 | Bit7); 1180 1181 ReportAbnormalID(0x0705, "Status high/low"); 1182 switch (SCC.SCC_Interrupt_Type) { 1183 case SCC_A_Rx: 1184 value |= Bit4 | Bit5; 1185 break; 1186 1187 case SCC_A_Rx_Spec: 1188 value |= Bit4 | Bit5 | Bit6; 1189 break; 1190 1191 case SCC_A_Tx_Empty: 1192 value |= Bit4; 1193 break; 1194 1195 case SCC_A_Ext: 1196 value |= Bit4 | Bit6; 1197 break; 1198 1199 case SCC_B_Rx: 1200 value |= Bit5; 1201 break; 1202 1203 case SCC_B_Rx_Spec: 1204 value |= Bit5 | Bit6; 1205 break; 1206 1207 case SCC_B_Tx_Empty: 1208 value |= 0; 1209 break; 1210 1211 case SCC_B_Ext: 1212 value |= Bit6; 1213 break; 1214 1215 default: 1216 value |= Bit5 | Bit6; 1217 break; 1218 } 1219 } else 1220#endif 1221 { 1222 /* Status Low */ 1223 value = value 1224 & (Bit0 | Bit4 | Bit5 | Bit6 | Bit7); 1225 1226 switch (SCC.SCC_Interrupt_Type) { 1227 case SCC_A_Rx: 1228 value |= Bit3 | Bit2; 1229 break; 1230 1231 case SCC_A_Rx_Spec: 1232 value |= Bit3 | Bit2 | Bit1; 1233 break; 1234 1235 case SCC_A_Tx_Empty: 1236 value |= Bit3; 1237 break; 1238 1239 case SCC_A_Ext: 1240 value |= Bit3 | Bit1; 1241 break; 1242 1243 case SCC_B_Rx: 1244 value |= Bit2; 1245 break; 1246 1247 case SCC_B_Rx_Spec: 1248 value |= Bit2 | Bit1; 1249 break; 1250 1251 case SCC_B_Tx_Empty: 1252 value |= 0; 1253 break; 1254 1255 case SCC_B_Ext: 1256 value |= Bit1; 1257 break; 1258 1259 default: 1260 value |= Bit2 | Bit1; 1261 break; 1262 } 1263 } 1264 1265 /* SCC.SCC_Interrupt_Type = 0; */ 1266 } 1267 1268 return value; 1269} 1270 1271LOCALFUNC ui3r SCC_GetRR3(int chan) 1272{ 1273 ui3r value = 0; 1274 1275 UnusedParam(chan); 1276 ReportAbnormalID(0x0706, "RR 3"); 1277 1278#if 0 1279 if (chan == 0) { 1280 value = 0 1281 | (SCC.a[1].TxIP ? (1 << 1) : 0) 1282 | (SCC.a[0].TxIP ? (1 << 4) : 0) 1283 ; 1284 } else { 1285 value = 0; 1286 } 1287#endif 1288 1289 return value; 1290} 1291 1292LOCALFUNC ui3r SCC_GetRR8(int chan) 1293{ 1294 ui3r value = 0; 1295 1296 /* Receive Buffer */ 1297 /* happens on boot with appletalk on */ 1298 if (SCC.a[chan].RxEnable) { 1299#if EmLocalTalk 1300 if (0 != chan) { 1301 /* 1302 Check the receive state, handling a complete rx 1303 if necessary 1304 */ 1305 value = SCC.a[1].RxBuff; 1306 SCC.a[1].FirstChar = falseblnr; 1307 SCC_RxBuffAdvance(); 1308 } else { 1309 value = 0x7E; 1310 } 1311#else 1312 /* Rx Enable */ 1313#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) 1314 /* don't report */ 1315#else 1316 ReportAbnormalID(0x0707, "read rr8 when RxEnable"); 1317#endif 1318 1319 /* Input 1 byte from Modem Port/Printer into Data */ 1320#endif 1321 } else { 1322 /* happens on boot with appletalk on */ 1323 } 1324 1325 return value; 1326} 1327 1328LOCALFUNC ui3r SCC_GetRR10(int chan) 1329{ 1330 /* happens on boot with appletalk on */ 1331 1332 ui3r value = 0; 1333 UnusedParam(chan); 1334 1335#if 0 && EmLocalTalk 1336 value = 2; 1337#endif 1338 1339 return value; 1340} 1341 1342LOCALFUNC ui3r SCC_GetRR12(int chan) 1343{ 1344 ui3r value = 0; 1345 1346#if ! SCC_TrackMore 1347 UnusedParam(chan); 1348#endif 1349 ReportAbnormalID(0x0708, "RR 12"); 1350 1351#if SCC_TrackMore /* don't care about Baud */ 1352 value = SCC.a[chan].BaudLo; 1353#endif 1354 1355 return value; 1356} 1357 1358LOCALFUNC ui3r SCC_GetRR13(int chan) 1359{ 1360 ui3r value = 0; 1361 1362#if ! SCC_TrackMore 1363 UnusedParam(chan); 1364#endif 1365 ReportAbnormalID(0x0709, "RR 13"); 1366 1367#if SCC_TrackMore /* don't care about Baud */ 1368 value = SCC.a[chan].BaudHi; 1369#endif 1370 1371 return value; 1372} 1373 1374LOCALFUNC ui3r SCC_GetRR15(int chan) 1375{ 1376 ui3r value = 0; 1377 1378 UnusedParam(chan); 1379 ReportAbnormalID(0x070A, "RR 15"); 1380 1381#if 0 1382 value = 0 1383#if 0 /* don't care about DCD_IE, always true */ 1384 | (SCC.a[chan].DCD_IE ? Bit3 : 0) 1385#else 1386 | Bit3 1387#endif 1388#if 0 /* SyncHuntIE usually false */ 1389 | (SCC.a[chan].SyncHuntIE ? Bit4 : 0) 1390#endif 1391#if SCC_TrackMore /* don't care about CTS_IE */ 1392 | (SCC.a[chan].CTS_IE ? Bit5 : 0) 1393#endif 1394#if SCC_TrackMore /* don't care about BreakAbortIE */ 1395 | (SCC.a[chan].BreakAbortIE ? Bit7 : 0) 1396#endif 1397 ; 1398#endif 1399 1400 return value; 1401} 1402 1403#if SCC_dolog 1404LOCALPROC SCC_DbgLogChanCmnd(int chan, char *s) 1405{ 1406 SCC_DbgLogChanStartLine(chan); 1407 dbglog_writeCStr(" "); 1408 dbglog_writeCStr(s); 1409 dbglog_writeReturn(); 1410} 1411#endif 1412 1413#if SCC_dolog 1414LOCALPROC SCC_DbgLogChanChngBit(int chan, char *s, blnr v) 1415{ 1416 SCC_DbgLogChanStartLine(chan); 1417 dbglog_writeCStr(" "); 1418 dbglog_writeCStr(s); 1419 dbglog_writeCStr(" <- "); 1420 if (v) { 1421 dbglog_writeCStr("1"); 1422 } else { 1423 dbglog_writeCStr("0"); 1424 } 1425 dbglog_writeReturn(); 1426} 1427#endif 1428 1429LOCALPROC SCC_PutWR0(ui3r Data, int chan) 1430/* 1431 "CRC initialize, initialization commands for the various modes, 1432 Register Pointers" 1433*/ 1434{ 1435 switch ((Data >> 6) & 3) { 1436 case 1: 1437 ReportAbnormalID(0x070B, "Reset Rx CRC Checker"); 1438 break; 1439 case 2: 1440#if SCC_dolog 1441 SCC_DbgLogChanCmnd(chan, "Reset Tx CRC Generator"); 1442#endif 1443 /* happens on boot with appletalk on */ 1444 break; 1445 case 3: 1446#if SCC_dolog 1447 SCC_DbgLogChanCmnd(chan, 1448 "Reset Tx Underrun/EOM Latch"); 1449#endif 1450 /* happens on boot with appletalk on */ 1451#if EmLocalTalk 1452 /* 1453 This is the indication we are done transmitting 1454 data for the current packet. 1455 */ 1456 if (0 != chan) { 1457 LT_TransmitPacket1(); 1458 } 1459#endif 1460#if 0 /* It seems to work better without this */ 1461 if (SCC.a[chan].TxEnable) { 1462 /* Tx Enabled */ 1463 SCC.a[chan].TxUnderrun = falseblnr; 1464 1465 if (SCC.a[chan].WR[10] & Bit2) { 1466 /* Abort/Flag on Underrun */ 1467 /* Send Abort */ 1468 SCC.a[chan].TxUnderrun = trueblnr; 1469#if 0 /* TxBufferEmpty always true */ 1470 SCC.a[chan].TxBufferEmpty = trueblnr; 1471#endif 1472 1473 /* Send Flag */ 1474 } 1475 } 1476#endif 1477 break; 1478 case 0: 1479 default: 1480 /* Null Code */ 1481 break; 1482 } 1483 SCC.PointerBits = Data & 0x07; 1484 switch ((Data >> 3) & 7) { 1485 case 1: /* Point High */ 1486 SCC.PointerBits |= 8; 1487 break; 1488 case 2: 1489#if SCC_dolog 1490 SCC_DbgLogChanCmnd(chan, "Reset Ext/Status Ints"); 1491#endif 1492 /* happens on boot always */ 1493 SCC.a[chan].SyncHunt = falseblnr; 1494#if 0 /* only in sync mode */ 1495 SCC.a[chan].TxUnderrun = falseblnr; 1496#endif 1497#if 0 /* ZeroCount always false */ 1498 SCC.a[chan].ZeroCount = falseblnr; 1499#endif 1500#if 0 /* BreakAbort always false */ 1501 SCC.a[chan].BreakAbort = falseblnr; 1502#endif 1503 break; 1504 case 3: 1505 ReportAbnormalID(0x070C, "Send Abort (SDLC)"); 1506#if EmLocalTalk 1507 SCC.a[chan].TxBufferEmpty = trueblnr; 1508#endif 1509#if 0 1510 SCC.a[chan].TxUnderrun = trueblnr; 1511#if 0 /* TxBufferEmpty always true */ 1512 SCC.a[chan].TxBufferEmpty = trueblnr; 1513#endif 1514#endif 1515 break; 1516 case 4: 1517#if SCC_dolog 1518 SCC_DbgLogChanCmnd(chan, 1519 "Enable Int on next Rx char"); 1520#endif 1521#if EmLocalTalk || SCC_TrackMore 1522 SCC.a[chan].FirstChar = trueblnr; 1523#endif 1524 /* happens in MacCheck */ 1525 break; 1526 case 5: 1527#if SCC_dolog 1528 SCC_DbgLogChanCmnd(chan, "Reset Tx Int Pending"); 1529#endif 1530 /* happens in MacCheck */ 1531 /* happens in Print to ImageWriter */ 1532 SCC.a[chan].TxIP = falseblnr; 1533 CheckSCCInterruptFlag(); 1534 break; 1535 case 6: 1536#if SCC_dolog 1537 SCC_DbgLogChanCmnd(chan, "Error Reset"); 1538#endif 1539 /* happens on boot with appletalk on */ 1540#if EmLocalTalk 1541 SCC.a[chan].EndOfFrame = falseblnr; 1542#endif 1543#if 0 /* ParityErr always false */ 1544 SCC.a[chan].ParityErr = falseblnr; 1545#endif 1546#if 0 /* RxOverrun always false */ 1547 SCC.a[chan].RxOverrun = falseblnr; 1548#endif 1549#if 0 /* CRCFramingErr always false */ 1550 SCC.a[chan].CRCFramingErr = falseblnr; 1551#endif 1552 break; 1553 case 7: 1554 /* happens in "Network Watch" program (Cayman Systems) */ 1555#if SCC_dolog 1556 SCC_DbgLogChanCmnd(chan, "Reset Highest IUS"); 1557#endif 1558 break; 1559 case 0: 1560 default: 1561 /* Null Code */ 1562 break; 1563 } 1564} 1565 1566LOCALPROC SCC_PutWR1(ui3r Data, int chan) 1567/* 1568 "Transmit/Receive interrupt and data transfer mode definition" 1569*/ 1570{ 1571#if EmLocalTalk || SCC_TrackMore 1572 { 1573 blnr NewExtIE = (Data & Bit0) != 0; 1574 if (SCC.a[chan].ExtIE != NewExtIE) { 1575 SCC.a[chan].ExtIE = NewExtIE; 1576#if SCC_dolog 1577 SCC_DbgLogChanChngBit(chan, "EXT INT Enable", 1578 NewExtIE); 1579#endif 1580 /* 1581 set to 1 on start up, set to 0 in MacCheck 1582 and in Print to ImageWriter 1583 */ 1584 } 1585 } 1586#endif 1587 1588 { 1589 blnr NewTxIE = (Data & Bit1) != 0; 1590 if (SCC.a[chan].TxIE != NewTxIE) { 1591#if SCC_dolog 1592 SCC_DbgLogChanChngBit(chan, "Tx Int Enable", 1593 NewTxIE); 1594#endif 1595 /* happens in MacCheck */ 1596 /* happens in Print to ImageWriter */ 1597 SCC.a[chan].TxIE = NewTxIE; 1598 CheckSCCInterruptFlag(); 1599 } 1600 } 1601 1602#if SCC_TrackMore 1603 { 1604 blnr NewPrtySpclCond = (Data & Bit2) != 0; 1605 if (SCC.a[chan].PrtySpclCond != NewPrtySpclCond) { 1606 SCC.a[chan].PrtySpclCond = NewPrtySpclCond; 1607#if SCC_dolog 1608 SCC_DbgLogChanChngBit(chan, 1609 "Parity is special condition", NewPrtySpclCond); 1610#endif 1611 /* 1612 set to 1 in MacCheck 1613 and in Print to ImageWriter 1614 */ 1615 } 1616 } 1617#endif 1618 1619#if EmLocalTalk || SCC_TrackMore 1620 { 1621 ui3r NewRxIntMode = (Data >> 3) & 3; 1622 if (SCC.a[chan].RxIntMode != NewRxIntMode) { 1623 SCC.a[chan].RxIntMode = NewRxIntMode; 1624 1625 switch (NewRxIntMode) { 1626 case 0: 1627#if SCC_dolog 1628 SCC_DbgLogChanCmnd(chan, "Rx INT Disable"); 1629#endif 1630 /* happens on boot always */ 1631 break; 1632 case 1: 1633#if SCC_dolog 1634 SCC_DbgLogChanCmnd(chan, 1635 "Rx INT on 1st char" 1636 " or special condition"); 1637#endif 1638 SCC.a[chan].FirstChar = trueblnr; 1639 /* happens on boot with appletalk on */ 1640 break; 1641 case 2: 1642#if SCC_dolog 1643 SCC_DbgLogChanCmnd(chan, 1644 "INT on all Rx char" 1645 " or special condition"); 1646#endif 1647 /* happens in MacCheck */ 1648 /* happens in Print to ImageWriter */ 1649 break; 1650 case 3: 1651 ReportAbnormalID(0x070D, 1652 "Rx INT on special condition only"); 1653 break; 1654 } 1655 } 1656 } 1657#endif 1658 1659#if SCC_TrackMore 1660 { 1661 blnr NewWaitRqstRT = (Data & Bit5) != 0; 1662 if (SCC.a[chan].WaitRqstRT != NewWaitRqstRT) { 1663 SCC.a[chan].WaitRqstRT = NewWaitRqstRT; 1664#if SCC_dolog 1665 SCC_DbgLogChanChngBit(chan, 1666 "Wait/DMA request on receive/transmit", 1667 NewWaitRqstRT); 1668#endif 1669 /* happens in MacCheck */ 1670 } 1671 } 1672#endif 1673 1674#if SCC_TrackMore 1675 { 1676 blnr NewWaitRqstSlct = (Data & Bit6) != 0; 1677 if (SCC.a[chan].WaitRqstSlct != NewWaitRqstSlct) { 1678 SCC.a[chan].WaitRqstSlct = NewWaitRqstSlct; 1679#if SCC_dolog 1680 SCC_DbgLogChanChngBit(chan, 1681 "Wait/DMA request function", NewWaitRqstSlct); 1682#endif 1683 /* happens in MacCheck */ 1684 } 1685 } 1686#endif 1687 1688#if SCC_TrackMore 1689 { 1690 blnr NewWaitRqstEnbl = (Data & Bit7) != 0; 1691 if (SCC.a[chan].WaitRqstEnbl != NewWaitRqstEnbl) { 1692 SCC.a[chan].WaitRqstEnbl = NewWaitRqstEnbl; 1693#if SCC_dolog 1694 SCC_DbgLogChanChngBit(chan, 1695 "Wait/DMA request enable", NewWaitRqstEnbl); 1696#endif 1697 /* happens in MacCheck */ 1698 } 1699 } 1700#endif 1701} 1702 1703LOCALPROC SCC_PutWR2(ui3r Data, int chan) 1704/* "Interrupt Vector (accessed through either channel)" */ 1705{ 1706 /* 1707 Only 1 interrupt vector for the SCC, which 1708 is stored in channels A and B. B is modified 1709 when read. 1710 */ 1711 1712 /* happens on boot always */ 1713 1714#if ! SCC_dolog 1715 UnusedParam(chan); 1716#endif 1717 1718 if (SCC.InterruptVector != Data) { 1719#if SCC_dolog 1720 SCC_DbgLogChanStartLine(chan); 1721 dbglog_writeCStr(" InterruptVector <- "); 1722 dbglog_writeHex(Data); 1723 dbglog_writeReturn(); 1724#endif 1725 SCC.InterruptVector = Data; 1726 } 1727 if ((Data & Bit0) != 0) { /* interrupt vector 0 */ 1728 ReportAbnormalID(0x070E, "interrupt vector 0"); 1729 } 1730 if ((Data & Bit1) != 0) { /* interrupt vector 1 */ 1731 ReportAbnormalID(0x070F, "interrupt vector 1"); 1732 } 1733 if ((Data & Bit2) != 0) { /* interrupt vector 2 */ 1734 ReportAbnormalID(0x0710, "interrupt vector 2"); 1735 } 1736 if ((Data & Bit3) != 0) { /* interrupt vector 3 */ 1737 ReportAbnormalID(0x0711, "interrupt vector 3"); 1738 } 1739 if ((Data & Bit4) != 0) { /* interrupt vector 4 */ 1740 /* happens on boot with appletalk on */ 1741 } 1742 if ((Data & Bit5) != 0) { /* interrupt vector 5 */ 1743 /* happens on boot with appletalk on */ 1744 } 1745 if ((Data & Bit6) != 0) { /* interrupt vector 6 */ 1746 ReportAbnormalID(0x0712, "interrupt vector 6"); 1747 } 1748 if ((Data & Bit7) != 0) { /* interrupt vector 7 */ 1749 ReportAbnormalID(0x0713, "interrupt vector 7"); 1750 } 1751} 1752 1753LOCALPROC SCC_PutWR3(ui3r Data, int chan) 1754/* "Receive parameters and control" */ 1755{ 1756#if SCC_TrackMore 1757 { 1758 ui3r NewRBitsPerChar = (Data >> 6) & 3; 1759 if (SCC.a[chan].RBitsPerChar != NewRBitsPerChar) { 1760 SCC.a[chan].RBitsPerChar = NewRBitsPerChar; 1761 1762 switch (NewRBitsPerChar) { 1763 case 0: 1764#if SCC_dolog 1765 SCC_DbgLogChanCmnd(chan, 1766 "Rx Bits/Character <- 5"); 1767#endif 1768 break; 1769 case 1: 1770#if SCC_dolog 1771 SCC_DbgLogChanCmnd(chan, 1772 "Rx Bits/Character <- 7"); 1773#endif 1774 break; 1775 case 2: 1776#if SCC_dolog 1777 SCC_DbgLogChanCmnd(chan, 1778 "Rx Bits/Character <- 6"); 1779#endif 1780 break; 1781 case 3: 1782#if SCC_dolog 1783 SCC_DbgLogChanCmnd(chan, 1784 "Rx Bits/Character <- 8"); 1785#endif 1786 break; 1787 } 1788 } 1789 } 1790#endif 1791 1792 if ((Data & Bit5) != 0) { /* Auto Enables */ 1793 /* 1794 use DCD input as receiver enable, 1795 and set RTS output when transmit buffer empty 1796 */ 1797 ReportAbnormalID(0x0714, "Auto Enables"); 1798 } 1799 1800 if ((Data & Bit4) != 0) { /* Enter Hunt Mode */ 1801#if SCC_dolog 1802 SCC_DbgLogChanCmnd(chan, "Enter Hunt Mode"); 1803#endif 1804 /* happens on boot with appletalk on */ 1805 if (! (SCC.a[chan].SyncHunt)) { 1806 SCC.a[chan].SyncHunt = trueblnr; 1807 1808#if 0 /* SyncHuntIE usually false */ 1809 if (SCC.a[chan].SyncHuntIE) { 1810 SCC_Interrupt((chan == 0) 1811 ? SCC_A_Ext 1812 : SCC_B_Ext); 1813 } 1814#endif 1815 } 1816 } 1817 1818#if SCC_TrackMore 1819 { 1820 blnr NewRxCRCEnbl = (Data & Bit3) != 0; 1821 if (SCC.a[chan].RxCRCEnbl != NewRxCRCEnbl) { 1822 SCC.a[chan].RxCRCEnbl = NewRxCRCEnbl; 1823#if SCC_dolog 1824 SCC_DbgLogChanChngBit(chan, 1825 "Rx CRC Enable", NewRxCRCEnbl); 1826#endif 1827 /* happens on boot with appletalk on */ 1828 } 1829 } 1830#endif 1831 1832#if EmLocalTalk || SCC_TrackMore 1833 { 1834 blnr NewAddrSrchMd = (Data & Bit2) != 0; 1835 if (SCC.a[chan].AddrSrchMd != NewAddrSrchMd) { 1836 SCC.a[chan].AddrSrchMd = NewAddrSrchMd; 1837#if SCC_dolog 1838 SCC_DbgLogChanChngBit(chan, 1839 "Addr Search Mode (SDLC)", NewAddrSrchMd); 1840#endif 1841 /* happens on boot with appletalk on */ 1842 if (0 != chan) { 1843 LT_AddrSrchMdSet(NewAddrSrchMd); 1844 } 1845 } 1846 } 1847#endif 1848 1849#if SCC_TrackMore 1850 { 1851 blnr NewSyncChrLdInhb = (Data & Bit1) != 0; 1852 if (SCC.a[chan].SyncChrLdInhb != NewSyncChrLdInhb) { 1853 SCC.a[chan].SyncChrLdInhb = NewSyncChrLdInhb; 1854#if SCC_dolog 1855 SCC_DbgLogChanChngBit(chan, 1856 "Sync Char Load Inhibit", NewSyncChrLdInhb); 1857#endif 1858 /* happens on boot with appletalk on */ 1859 } 1860 } 1861#endif 1862 1863 { 1864 blnr NewRxEnable = (Data & Bit0) != 0; 1865 if (SCC.a[chan].RxEnable != NewRxEnable) { 1866 SCC.a[chan].RxEnable = NewRxEnable; 1867#if SCC_dolog 1868 SCC_DbgLogChanChngBit(chan, 1869 "Rx Enable", NewRxEnable); 1870#endif 1871 /* true on boot with appletalk on */ 1872 /* true on Print to ImageWriter */ 1873 1874#if EmLocalTalk 1875 if (! NewRxEnable) { 1876#if SCC_dolog 1877 if ((0 != chan) && (nullpr != LT_RxBuffer)) { 1878 dbglog_WriteNote("SCC abandon packet"); 1879 } 1880#endif 1881 1882 /* 1883 Go back into the idle state if we were 1884 waiting for EOF 1885 */ 1886 SCC.a[chan].EndOfFrame = falseblnr; 1887 SCC.a[chan].RxChrAvail = falseblnr; 1888 SCC.a[chan].SyncHunt = trueblnr; 1889 } else { 1890 /* look for a packet */ 1891 if (0 != chan) { 1892 LocalTalkTick(); 1893 } 1894 } 1895#endif 1896 } 1897 } 1898} 1899 1900LOCALPROC SCC_PutWR4(ui3r Data, int chan) 1901/* "Transmit/Receive miscellaneous parameters and modes" */ 1902{ 1903#if ! (EmLocalTalk || SCC_TrackMore) 1904 UnusedParam(Data); 1905 UnusedParam(chan); 1906#endif 1907 1908#if SCC_TrackMore 1909 { 1910 blnr NewPrtyEnable = (Data & Bit0) != 0; 1911 if (SCC.a[chan].PrtyEnable != NewPrtyEnable) { 1912 SCC.a[chan].PrtyEnable = NewPrtyEnable; 1913#if SCC_dolog 1914 SCC_DbgLogChanChngBit(chan, 1915 "Parity Enable", NewPrtyEnable); 1916#endif 1917 } 1918 } 1919#endif 1920 1921#if SCC_TrackMore 1922 { 1923 blnr NewPrtyEven = (Data & Bit1) != 0; 1924 if (SCC.a[chan].PrtyEven != NewPrtyEven) { 1925 SCC.a[chan].PrtyEven = NewPrtyEven; 1926#if SCC_dolog 1927 SCC_DbgLogChanChngBit(chan, 1928 "Parity Enable", NewPrtyEven); 1929#endif 1930 } 1931 } 1932#endif 1933 1934#if SCC_TrackMore 1935 { 1936 ui3r NewStopBits = (Data >> 2) & 3; 1937 if (SCC.a[chan].StopBits != NewStopBits) { 1938 SCC.a[chan].StopBits = NewStopBits; 1939 1940 /* SCC_SetStopBits(chan, NewStopBits); */ 1941 switch (NewStopBits) { 1942 case 0: 1943#if SCC_dolog 1944 SCC_DbgLogChanCmnd(chan, 1945 "Sync Modes Enable"); 1946#endif 1947 break; 1948 case 1: 1949#if SCC_dolog 1950 SCC_DbgLogChanCmnd(chan, "1 Stop Bit"); 1951#endif 1952 break; 1953 case 2: 1954#if SCC_dolog 1955 SCC_DbgLogChanCmnd(chan, "1 1/2 Stop Bits"); 1956#endif 1957 break; 1958 case 3: 1959#if SCC_dolog 1960 SCC_DbgLogChanCmnd(chan, "2 Stop Bits"); 1961#endif 1962 break; 1963 } 1964 } 1965 } 1966#endif 1967 1968#if EmLocalTalk || SCC_TrackMore 1969 { 1970 ui3r NewSyncMode = (Data >> 4) & 3; 1971 if (SCC.a[chan].SyncMode != NewSyncMode) { 1972 SCC.a[chan].SyncMode = NewSyncMode; 1973 1974 switch (NewSyncMode) { 1975 case 0: 1976#if SCC_dolog 1977 SCC_DbgLogChanCmnd(chan, "8 bit sync char"); 1978#endif 1979 /* happens on boot always */ 1980 break; 1981 case 1: 1982 ReportAbnormalID(0x0715, "16 bit sync char"); 1983 break; 1984 case 2: 1985#if SCC_dolog 1986 SCC_DbgLogChanCmnd(chan, "SDLC MODE"); 1987#endif 1988 /* happens on boot with appletalk on */ 1989#if EmLocalTalk 1990 SCC.a[chan].TxBufferEmpty = trueblnr; 1991#endif 1992 break; 1993 case 3: 1994 ReportAbnormalID(0x0716, "External sync mode"); 1995 break; 1996 } 1997 } 1998 } 1999#endif 2000 2001#if SCC_TrackMore 2002 { 2003 ui3r NewClockRate = (Data >> 6) & 3; 2004 if (SCC.a[chan].ClockRate != NewClockRate) { 2005 SCC.a[chan].ClockRate = NewClockRate; 2006 2007 switch (NewClockRate) { 2008 case 0: 2009#if SCC_dolog 2010 SCC_DbgLogChanCmnd(chan, 2011 "Clock Rate <- X1"); 2012#endif 2013 /* happens on boot with appletalk on */ 2014 break; 2015 case 1: 2016#if SCC_dolog 2017 SCC_DbgLogChanCmnd(chan, 2018 "Clock Rate <- X16"); 2019#endif 2020 /* happens on boot always */ 2021 break; 2022 case 2: 2023 ReportAbnormalID(0x0717, "Clock Rate <- X32"); 2024 break; 2025 case 3: 2026 ReportAbnormalID(0x0718, "Clock Rate <- X64"); 2027 break; 2028 } 2029 } 2030 } 2031#endif 2032} 2033 2034LOCALPROC SCC_PutWR5(ui3r Data, int chan) 2035/* "Transmit parameters and controls" */ 2036{ 2037 /* happens on boot with appletalk on */ 2038 /* happens in Print to ImageWriter */ 2039 2040#if SCC_TrackMore 2041 { 2042 blnr NewTxCRCEnbl = (Data & Bit0) != 0; 2043 if (SCC.a[chan].TxCRCEnbl != NewTxCRCEnbl) { 2044 SCC.a[chan].TxCRCEnbl = NewTxCRCEnbl; 2045#if SCC_dolog 2046 SCC_DbgLogChanChngBit(chan, 2047 "Tx CRC Enable", NewTxCRCEnbl); 2048#endif 2049 /* both values on boot with appletalk on */ 2050 } 2051 } 2052#endif 2053 2054#if SCC_TrackMore 2055 { 2056 blnr NewRTSctrl = (Data & Bit1) != 0; 2057 if (SCC.a[chan].RTSctrl != NewRTSctrl) { 2058 SCC.a[chan].RTSctrl = NewRTSctrl; 2059#if SCC_dolog 2060 SCC_DbgLogChanChngBit(chan, 2061 "RTS Control", NewRTSctrl); 2062#endif 2063 /* both values on boot with appletalk on */ 2064 /* 2065 value of Request To Send output pin, when 2066 Auto Enable is off 2067 */ 2068 } 2069 } 2070#endif 2071 2072 if ((Data & Bit2) != 0) { /* SDLC/CRC-16 */ 2073 ReportAbnormalID(0x0719, "SDLC/CRC-16"); 2074 } 2075 2076 { 2077 blnr NewTxEnable = (Data & Bit3) != 0; 2078 if (SCC.a[chan].TxEnable != NewTxEnable) { 2079 SCC.a[chan].TxEnable = NewTxEnable; 2080#if SCC_dolog 2081 SCC_DbgLogChanChngBit(chan, 2082 "Tx Enable", NewTxEnable); 2083#endif 2084 2085 if (NewTxEnable) { 2086 /* happens on boot with appletalk on */ 2087 /* happens in Print to ImageWriter */ 2088#if EmLocalTalk 2089 if (0 != chan) { 2090 LT_TxBuffSz = 0; 2091 } 2092#endif 2093 } else { 2094#if EmLocalTalk 2095 SCC.a[chan].TxBufferEmpty = trueblnr; 2096#endif 2097 } 2098 } 2099 } 2100 2101#if SCC_TrackMore 2102 { 2103 blnr NewSndBrkCtrl = (Data & Bit4) != 0; 2104 if (SCC.a[chan].SndBrkCtrl != NewSndBrkCtrl) { 2105 SCC.a[chan].SndBrkCtrl = NewSndBrkCtrl; 2106#if SCC_dolog 2107 SCC_DbgLogChanChngBit(chan, 2108 "Send Break Control", NewSndBrkCtrl); 2109#endif 2110 /* true in Print to LaserWriter 300 */ 2111 } 2112 } 2113#endif 2114 2115#if SCC_TrackMore 2116 { 2117 ui3r NewTBitsPerChar = (Data >> 5) & 3; 2118 if (SCC.a[chan].TBitsPerChar != NewTBitsPerChar) { 2119 SCC.a[chan].TBitsPerChar = NewTBitsPerChar; 2120 2121 switch (NewTBitsPerChar) { 2122 case 0: 2123 ReportAbnormalID(0x071A, "Tx Bits/Character <- 5"); 2124 break; 2125 case 1: 2126 ReportAbnormalID(0x071B, "Tx Bits/Character <- 7"); 2127 break; 2128 case 2: 2129 ReportAbnormalID(0x071C, "Tx Bits/Character <- 6"); 2130 break; 2131 case 3: 2132#if SCC_dolog 2133 SCC_DbgLogChanCmnd(chan, 2134 "Tx Bits/Character <- 8"); 2135#endif 2136 /* happens on boot with appletalk on */ 2137 /* happens in Print to ImageWriter */ 2138 break; 2139 } 2140 } 2141 } 2142#endif 2143 2144#if SCC_TrackMore 2145 { 2146 blnr NewDTRctrl = (Data & Bit7) != 0; 2147 if (SCC.a[chan].DTRctrl != NewDTRctrl) { 2148 SCC.a[chan].DTRctrl = NewDTRctrl; 2149#if SCC_dolog 2150 SCC_DbgLogChanChngBit(chan, 2151 "Data Terminal Ready Control", NewDTRctrl); 2152#endif 2153 /* zero happens in MacCheck */ 2154 /* 2155 value of Data Terminal Ready output pin, 2156 when WR14 D2 = 0 (DTR/request function) 2157 */ 2158 } 2159 } 2160#endif 2161} 2162 2163LOCALPROC SCC_PutWR6(ui3r Data, int chan) 2164/* "Sync characters or SDLC address field" */ 2165{ 2166 /* happens on boot with appletalk on */ 2167 2168#if ! (EmLocalTalk || SCC_dolog) 2169 UnusedParam(Data); 2170#endif 2171#if ! SCC_dolog 2172 UnusedParam(chan); 2173#endif 2174 2175#if SCC_dolog 2176 SCC_DbgLogChanStartLine(chan); 2177 dbglog_writeCStr(" Sync Char <- "); 2178 dbglog_writeHex(Data); 2179 dbglog_writeReturn(); 2180#endif 2181 2182#if EmLocalTalk 2183 if (0 != chan) { 2184 LT_NodeAddressSet(Data); 2185 } 2186#endif 2187} 2188 2189LOCALPROC SCC_PutWR7(ui3r Data, int chan) 2190/* "Sync character or SDLC flag" */ 2191{ 2192 /* happens on boot with appletalk on */ 2193 2194#if ! SCC_TrackMore 2195 UnusedParam(Data); 2196 UnusedParam(chan); 2197#endif 2198 2199#if SCC_TrackMore 2200 if (2 == SCC.a[chan].SyncMode) { 2201 if (0x7E != Data) { 2202 ReportAbnormalID(0x071D, 2203 "unexpect flag character for SDLC"); 2204 } 2205 } else { 2206 ReportAbnormalID(0x071E, "WR7 and not SDLC"); 2207 } 2208#endif 2209} 2210 2211LOCALPROC SCC_PutWR8(ui3r Data, int chan) 2212/* "Transmit Buffer" */ 2213{ 2214 /* happens on boot with appletalk on */ 2215 /* happens in Print to ImageWriter */ 2216 2217#if ! (EmLocalTalk || SCC_dolog) 2218 UnusedParam(Data); 2219#endif 2220 2221#if SCC_dolog 2222 SCC_DbgLogChanStartLine(chan); 2223 dbglog_writeCStr(" Transmit Buffer"); 2224 dbglog_writeCStr(" <- "); 2225 dbglog_writeHex(Data); 2226 dbglog_writeCStr(" '"); 2227 dbglog_writeMacChar(Data); 2228 dbglog_writeCStr("'"); 2229 dbglog_writeReturn(); 2230#endif 2231 2232 if (SCC.a[chan].TxEnable) { /* Tx Enable */ 2233 /* Output (Data) to Modem(B) or Printer(A) Port */ 2234 2235 /* happens on boot with appletalk on */ 2236#if EmLocalTalk 2237 if (0 != chan) { 2238 SCC_TxBuffPut(Data); 2239 } 2240#else 2241#if 0 /* TxBufferEmpty always true */ 2242 SCC.a[chan].TxBufferEmpty = trueblnr; 2243#endif 2244 SCC.a[chan].TxUnderrun = trueblnr; /* underrun ? */ 2245#endif 2246 2247 SCC.a[chan].TxIP = trueblnr; 2248 CheckSCCInterruptFlag(); 2249 } else { 2250 ReportAbnormalID(0x071F, 2251 "write when Transmit Buffer not Enabled"); 2252#if 0 /* TxBufferEmpty always true */ 2253 SCC.a[chan].TxBufferEmpty = falseblnr; 2254#endif 2255 } 2256} 2257 2258LOCALPROC SCC_PutWR9(ui3r Data, int chan) 2259/* 2260 "Master interrupt control and reset 2261 (accessed through either channel)" 2262*/ 2263{ 2264 /* Only 1 WR9 in the SCC */ 2265 2266 UnusedParam(chan); 2267 2268 if ((Data & Bit0) != 0) { /* VIS */ 2269 ReportAbnormalID(0x0720, "VIS"); 2270 } 2271 2272#if SCC_TrackMore 2273 { 2274 blnr NewNoVectorSlct = (Data & Bit1) != 0; 2275 if (SCC.NoVectorSlct != NewNoVectorSlct) { 2276 SCC.NoVectorSlct = NewNoVectorSlct; 2277#if SCC_dolog 2278 dbglog_WriteSetBool("SCC No Vector select", 2279 NewNoVectorSlct); 2280#endif 2281 /* has both values on boot always */ 2282 } 2283 } 2284#endif 2285 2286 if ((Data & Bit2) != 0) { /* DLC */ 2287 ReportAbnormalID(0x0723, "DLC"); 2288 } 2289 2290 { 2291 blnr NewMIE = (Data & Bit3) != 0; 2292 /* has both values on boot always */ 2293 if (SCC.MIE != NewMIE) { 2294 SCC.MIE = NewMIE; 2295#if SCC_dolog 2296 dbglog_WriteSetBool("SCC Master Interrupt Enable", 2297 NewMIE); 2298#endif 2299 CheckSCCInterruptFlag(); 2300 } 2301 } 2302 2303#if 0 /* StatusHiLo always false */ 2304 SCC.StatusHiLo = (Data & Bit4) != 0; 2305#else 2306 if ((Data & Bit4) != 0) { /* Status high/low */ 2307 ReportAbnormalID(0x0724, "Status high/low"); 2308 } 2309#endif 2310 if ((Data & Bit5) != 0) { /* WR9 b5 should be 0 */ 2311 ReportAbnormalID(0x0725, "WR9 b5 should be 0"); 2312 } 2313 2314 switch ((Data >> 6) & 3) { 2315 case 1: 2316#if SCC_dolog 2317 SCC_DbgLogChanCmnd(1, "Channel Reset"); 2318#endif 2319 /* happens on boot always */ 2320 SCC_ResetChannel(1); 2321 CheckSCCInterruptFlag(); 2322 break; 2323 case 2: 2324#if SCC_dolog 2325 SCC_DbgLogChanCmnd(0, "Channel Reset"); 2326#endif 2327 /* happens on boot always */ 2328 SCC_ResetChannel(0); 2329 CheckSCCInterruptFlag(); 2330 break; 2331 case 3: 2332#if SCC_dolog 2333 dbglog_WriteNote("SCC Force Hardware Reset"); 2334#endif 2335#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) 2336 /* don't report */ 2337#else 2338 ReportAbnormalID(0x0726, "SCC_Reset"); 2339#endif 2340 SCC_Reset(); 2341 CheckSCCInterruptFlag(); 2342 break; 2343 case 0: /* No Reset */ 2344 default: 2345 break; 2346 } 2347} 2348 2349LOCALPROC SCC_PutWR10(ui3r Data, int chan) 2350/* "Miscellaneous transmitter/receiver control bits" */ 2351{ 2352 /* happens on boot with appletalk on */ 2353 /* happens in Print to ImageWriter */ 2354 2355#if ! SCC_TrackMore 2356 UnusedParam(chan); 2357#endif 2358 2359 if ((Data & Bit0) != 0) { /* 6 bit/8 bit sync */ 2360 ReportAbnormalID(0x0727, "6 bit/8 bit sync"); 2361 } 2362 if ((Data & Bit1) != 0) { /* loop mode */ 2363 ReportAbnormalID(0x0728, "loop mode"); 2364 } 2365 if ((Data & Bit2) != 0) { /* abort/flag on underrun */ 2366 ReportAbnormalID(0x0729, "abort/flag on underrun"); 2367 } 2368 if ((Data & Bit3) != 0) { /* mark/flag idle */ 2369 ReportAbnormalID(0x072A, "mark/flag idle"); 2370 } 2371 if ((Data & Bit4) != 0) { /* go active on poll */ 2372 ReportAbnormalID(0x072B, "go active on poll"); 2373 } 2374 2375#if SCC_TrackMore 2376 { 2377 ui3r NewDataEncoding = (Data >> 5) & 3; 2378 if (SCC.a[chan].DataEncoding != NewDataEncoding) { 2379 SCC.a[chan].DataEncoding = NewDataEncoding; 2380 2381 switch (NewDataEncoding) { 2382 case 0: 2383#if SCC_dolog 2384 SCC_DbgLogChanCmnd(chan, 2385 "Data Encoding <- NRZ"); 2386#endif 2387 /* happens in MacCheck */ 2388 /* happens in Print to ImageWriter */ 2389 break; 2390 case 1: 2391 ReportAbnormalID(0x072C, "Data Encoding <- NRZI"); 2392 break; 2393 case 2: 2394 ReportAbnormalID(0x072D, "Data Encoding <- FM1"); 2395 break; 2396 case 3: 2397#if SCC_dolog 2398 SCC_DbgLogChanCmnd(chan, 2399 "Data Encoding <- FM0"); 2400#endif 2401 /* happens on boot with appletalk on */ 2402 break; 2403 } 2404 } 2405 } 2406#endif 2407 2408#if SCC_TrackMore 2409 { 2410 blnr NewCRCPreset = (Data & Bit7) != 0; 2411 if (SCC.a[chan].CRCPreset != NewCRCPreset) { 2412 SCC.a[chan].CRCPreset = NewCRCPreset; 2413#if SCC_dolog 2414 SCC_DbgLogChanChngBit(chan, 2415 "CRC preset I/O", NewCRCPreset); 2416#endif 2417 /* false happens in MacCheck */ 2418 /* true happens in Print to ImageWriter */ 2419 } 2420 } 2421#endif 2422} 2423 2424LOCALPROC SCC_PutWR11(ui3r Data, int chan) 2425/* "Clock mode control" */ 2426{ 2427 /* happens on boot with appletalk on */ 2428 /* happens in Print to ImageWriter */ 2429 /* happens in MacCheck */ 2430 2431#if ! SCC_TrackMore 2432 UnusedParam(chan); 2433#endif 2434 2435#if SCC_TrackMore 2436 /* Transmit External Control Selection */ 2437 { 2438 ui3r NewTRxCsrc = Data & 3; 2439 if (SCC.a[chan].TRxCsrc != NewTRxCsrc) { 2440 SCC.a[chan].TRxCsrc = NewTRxCsrc; 2441 2442 switch (NewTRxCsrc) { 2443 case 0: 2444#if SCC_dolog 2445 SCC_DbgLogChanCmnd(chan, 2446 "TRxC OUT = XTAL output"); 2447#endif 2448 /* happens on boot with appletalk on */ 2449 /* happens in Print to ImageWriter */ 2450 /* happens in MacCheck */ 2451 break; 2452 case 1: 2453 ReportAbnormalID(0x072E, 2454 "TRxC OUT = transmit clock"); 2455 break; 2456 case 2: 2457 ReportAbnormalID(0x072F, 2458 "TRxC OUT = BR generator output"); 2459 break; 2460 case 3: 2461 ReportAbnormalID(0x0730, "TRxC OUT = dpll output"); 2462 break; 2463 } 2464 } 2465 } 2466#endif 2467 2468 if ((Data & Bit2) != 0) { 2469 ReportAbnormalID(0x0731, "TRxC O/I"); 2470 } 2471 2472#if SCC_TrackMore 2473 { 2474 ui3r NewTClkSlct = (Data >> 3) & 3; 2475 if (SCC.a[chan].TClkSlct != NewTClkSlct) { 2476 SCC.a[chan].TClkSlct = NewTClkSlct; 2477 2478 switch (NewTClkSlct) { 2479 case 0: 2480 ReportAbnormalID(0x0732, 2481 "transmit clock = RTxC pin"); 2482 break; 2483 case 1: 2484#if SCC_dolog 2485 SCC_DbgLogChanCmnd(chan, 2486 "transmit clock = TRxC pin"); 2487#endif 2488 /* happens in Print to LaserWriter 300 */ 2489 break; 2490 case 2: 2491#if SCC_dolog 2492 SCC_DbgLogChanCmnd(chan, 2493 "transmit clock = BR generator output"); 2494#endif 2495 /* happens on boot with appletalk on */ 2496 /* happens in Print to ImageWriter */ 2497 /* happens in MacCheck */ 2498 break; 2499 case 3: 2500 ReportAbnormalID(0x0733, 2501 "transmit clock = dpll output"); 2502 break; 2503 } 2504 } 2505 } 2506#endif 2507 2508#if SCC_TrackMore 2509 { 2510 ui3r NewRClkSlct = (Data >> 5) & 3; 2511 if (SCC.a[chan].RClkSlct != NewRClkSlct) { 2512 SCC.a[chan].RClkSlct = NewRClkSlct; 2513 2514 switch (NewRClkSlct) { 2515 case 0: 2516 ReportAbnormalID(0x0734, 2517 "receive clock = RTxC pin"); 2518 break; 2519 case 1: 2520#if SCC_dolog 2521 SCC_DbgLogChanCmnd(chan, 2522 "receive clock = TRxC pin"); 2523#endif 2524 /* happens in Print to LaserWriter 300 */ 2525 break; 2526 case 2: 2527#if SCC_dolog 2528 SCC_DbgLogChanCmnd(chan, 2529 "receive clock = BR generator output"); 2530#endif 2531 /* happens in MacCheck */ 2532 /* happens in Print to ImageWriter */ 2533 break; 2534 case 3: 2535#if SCC_dolog 2536 SCC_DbgLogChanCmnd(chan, 2537 "receive clock = dpll output"); 2538#endif 2539 /* happens on boot with appletalk on */ 2540 break; 2541 } 2542 } 2543 } 2544#endif 2545 2546 if ((Data & Bit7) != 0) { 2547 ReportAbnormalID(0x0735, "RTxC XTAL/NO XTAL"); 2548 } 2549} 2550 2551LOCALPROC SCC_PutWR12(ui3r Data, int chan) 2552/* "Lower byte of baud rate generator time constant" */ 2553{ 2554 /* happens on boot with appletalk on */ 2555 /* happens in Print to ImageWriter */ 2556 2557#if ! SCC_TrackMore 2558 UnusedParam(Data); 2559 UnusedParam(chan); 2560#endif 2561 2562#if SCC_TrackMore /* don't care about Baud */ 2563 if (SCC.a[chan].BaudLo != Data) { 2564 SCC.a[chan].BaudLo = Data; 2565 2566#if SCC_dolog 2567 SCC_DbgLogChanStartLine(chan); 2568 dbglog_writeCStr(" BaudLo <- "); 2569 dbglog_writeHex(Data); 2570 dbglog_writeReturn(); 2571#endif 2572 } 2573#endif 2574 2575#if 0 2576 SCC_SetBaud(chan, 2577 SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8)); 2578 /* 380: BaudRate = 300 */ 2579 /* 94: BaudRate = 1200 */ 2580 /* 46: BaudRate = 2400 */ 2581 /* 22: BaudRate = 4800 */ 2582 /* 10: BaudRate = 9600 */ 2583 /* 4: BaudRate = 19200 */ 2584 /* 1: BaudRate = 38400 */ 2585 /* 0: BaudRate = 57600 */ 2586#endif 2587} 2588 2589LOCALPROC SCC_PutWR13(ui3r Data, int chan) 2590/* "Upper byte of baud rate generator time constant" */ 2591{ 2592 /* happens on boot with appletalk on */ 2593 /* happens in Print to ImageWriter */ 2594 2595#if ! SCC_TrackMore 2596 UnusedParam(Data); 2597 UnusedParam(chan); 2598#endif 2599 2600#if SCC_TrackMore /* don't care about Baud */ 2601 if (SCC.a[chan].BaudHi != Data) { 2602 SCC.a[chan].BaudHi = Data; 2603 2604#if SCC_dolog 2605 SCC_DbgLogChanStartLine(chan); 2606 dbglog_writeCStr(" BaudHi <- "); 2607 dbglog_writeHex(Data); 2608 dbglog_writeReturn(); 2609#endif 2610 } 2611#endif 2612 2613#if 0 2614 SCC_SetBaud(chan, 2615 SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8)); 2616#endif 2617} 2618 2619LOCALPROC SCC_PutWR14(ui3r Data, int chan) 2620/* "Miscellaneous control bits" */ 2621{ 2622 /* happens on boot with appletalk on */ 2623 2624#if ! (SCC_TrackMore || SCC_dolog) 2625 UnusedParam(chan); 2626#endif 2627 2628#if SCC_TrackMore 2629 { 2630 blnr NewBRGEnbl = (Data & Bit0) != 0; 2631 if (SCC.a[chan].BRGEnbl != NewBRGEnbl) { 2632 SCC.a[chan].BRGEnbl = NewBRGEnbl; 2633#if SCC_dolog 2634 SCC_DbgLogChanChngBit(chan, 2635 "BR generator enable", NewBRGEnbl); 2636#endif 2637 /* both values on boot with appletalk on */ 2638 /* true happens in Print to ImageWriter */ 2639 } 2640 } 2641#endif 2642 2643 if ((Data & Bit1) != 0) { /* BR generator source */ 2644 ReportAbnormalID(0x0736, "BR generator source"); 2645 } 2646 if ((Data & Bit2) != 0) { /* DTR/request function */ 2647 ReportAbnormalID(0x0737, "DTR/request function"); 2648 } 2649 if ((Data & Bit3) != 0) { /* auto echo */ 2650 ReportAbnormalID(0x0738, "auto echo"); 2651 } 2652 if ((Data & Bit4) != 0) { /* local loopback */ 2653 ReportAbnormalID(0x0739, "local loopback"); 2654 } 2655 2656 switch ((Data >> 5) & 7) { 2657 case 1: 2658#if SCC_dolog 2659 SCC_DbgLogChanCmnd(chan, "enter search mode"); 2660#endif 2661 /* happens on boot with appletalk on */ 2662 break; 2663 case 2: 2664#if SCC_dolog 2665 SCC_DbgLogChanCmnd(chan, "reset missing clock"); 2666#endif 2667 /* happens on boot with appletalk on */ 2668 /* 2669 should clear Bit 6 and Bit 7 of RR[10], but 2670 since these are never set, don't need 2671 to do anything 2672 */ 2673 break; 2674 case 3: 2675 ReportAbnormalID(0x073A, "disable dpll"); 2676 /* 2677 should clear Bit 6 and Bit 7 of RR[10], but 2678 since these are never set, don't need 2679 to do anything 2680 */ 2681 break; 2682 case 4: 2683 ReportAbnormalID(0x073B, "set source = br generator"); 2684 break; 2685 case 5: 2686 ReportAbnormalID(0x073C, "set source = RTxC"); 2687 break; 2688 case 6: 2689#if SCC_dolog 2690 SCC_DbgLogChanCmnd(chan, "set FM mode"); 2691#endif 2692 /* happens on boot with appletalk on */ 2693 break; 2694 case 7: 2695 ReportAbnormalID(0x073D, "set NRZI mode"); 2696 break; 2697 case 0: /* No Reset */ 2698 default: 2699 break; 2700 } 2701} 2702 2703LOCALPROC SCC_PutWR15(ui3r Data, int chan) 2704/* "External/Status interrupt control" */ 2705{ 2706 /* happens on boot always */ 2707 2708#if ! SCC_TrackMore 2709 UnusedParam(chan); 2710#endif 2711 2712 if ((Data & Bit0) != 0) { /* WR15 b0 should be 0 */ 2713 ReportAbnormalID(0x073E, "WR15 b0 should be 0"); 2714 } 2715 if ((Data & Bit1) != 0) { /* zero count IE */ 2716 ReportAbnormalID(0x073F, "zero count IE"); 2717 } 2718 if ((Data & Bit2) != 0) { /* WR15 b2 should be 0 */ 2719 ReportAbnormalID(0x0740, "WR15 b2 should be 0"); 2720 } 2721 2722#if 0 /* don't care about DCD_IE, always true */ 2723 SCC.a[chan].DCD_IE = (Data & Bit3) != 0; 2724#else 2725 if ((Data & Bit3) == 0) { /* DCD_IE */ 2726#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) 2727 /* don't report */ 2728#else 2729 ReportAbnormalID(0x0741, "not DCD IE"); 2730#endif 2731 } 2732#endif 2733 2734#if 0 /* SyncHuntIE usually false */ 2735 SCC.a[chan].SyncHuntIE = (Data & Bit4) != 0; 2736#else 2737 if ((Data & Bit4) != 0) { 2738 /* SYNC/HUNT IE */ 2739 ReportAbnormalID(0x0742, "SYNC/HUNT IE"); 2740 } 2741#endif 2742 2743#if SCC_TrackMore /* don't care about CTS_IE */ 2744 { 2745 blnr NewCTS_IE = (Data & Bit5) != 0; 2746 if (SCC.a[chan].CTS_IE != NewCTS_IE) { 2747 SCC.a[chan].CTS_IE = NewCTS_IE; 2748#if SCC_dolog 2749 SCC_DbgLogChanChngBit(chan, 2750 "CTS IE", NewCTS_IE); 2751#endif 2752 /* happens in MacCheck */ 2753 /* happens in Print to ImageWriter */ 2754 } 2755 } 2756#endif 2757 2758 if ((Data & Bit6) != 0) { /* Tx underrun/EOM IE */ 2759 ReportAbnormalID(0x0743, "Tx underrun/EOM IE"); 2760 } 2761 2762#if SCC_TrackMore 2763 { 2764 blnr NewBreakAbortIE = (Data & Bit7) != 0; 2765 if (SCC.a[chan].BreakAbortIE != NewBreakAbortIE) { 2766 SCC.a[chan].BreakAbortIE = NewBreakAbortIE; 2767#if SCC_dolog 2768 SCC_DbgLogChanChngBit(chan, 2769 "BreakAbort IE", NewBreakAbortIE); 2770#endif 2771 /* happens in MacCheck */ 2772 /* happens in Print to ImageWriter */ 2773 } 2774 } 2775#endif 2776} 2777 2778LOCALFUNC ui3r SCC_GetReg(int chan, ui3r SCC_Reg) 2779{ 2780 ui3r value; 2781 2782 switch (SCC_Reg) { 2783 case 0: 2784 value = SCC_GetRR0(chan); 2785 break; 2786 case 1: 2787 value = SCC_GetRR1(chan); 2788 break; 2789 case 2: 2790 value = SCC_GetRR2(chan); 2791 break; 2792 case 3: 2793 value = SCC_GetRR3(chan); 2794 break; 2795 case 4: 2796 ReportAbnormalID(0x0744, "RR 4"); /* same as RR0 */ 2797 value = SCC_GetRR0(chan); 2798 break; 2799 case 5: 2800 ReportAbnormalID(0x0745, "RR 5"); /* same as RR1 */ 2801 value = SCC_GetRR1(chan); 2802 break; 2803 case 6: 2804 ReportAbnormalID(0x0746, "RR 6"); /* same as RR2 */ 2805 value = SCC_GetRR2(chan); 2806 break; 2807 case 7: 2808 ReportAbnormalID(0x0747, "RR 7"); /* same as RR3 */ 2809 value = SCC_GetRR3(chan); 2810 break; 2811 case 8: 2812 value = SCC_GetRR8(chan); 2813 break; 2814 case 9: 2815 ReportAbnormalID(0x0748, "RR 9"); /* same as RR13 */ 2816 value = SCC_GetRR13(chan); 2817 break; 2818 case 10: 2819 value = SCC_GetRR10(chan); 2820 break; 2821 case 11: 2822 ReportAbnormalID(0x0749, "RR 11"); /* same as RR15 */ 2823 value = SCC_GetRR15(chan); 2824 break; 2825 case 12: 2826 value = SCC_GetRR12(chan); 2827 break; 2828 case 13: 2829 value = SCC_GetRR13(chan); 2830 break; 2831 case 14: 2832 ReportAbnormalID(0x074A, "RR 14"); 2833 value = 0; 2834 break; 2835 case 15: 2836 value = SCC_GetRR15(chan); 2837 break; 2838 default: 2839 ReportAbnormalID(0x074B, 2840 "unexpected SCC_Reg in SCC_GetReg"); 2841 value = 0; 2842 break; 2843 } 2844 2845#if EmLocalTalk 2846 /* 2847 Always check to see if interrupt state changed after 2848 ANY register access 2849 */ 2850 CheckSCCInterruptFlag(); 2851#endif 2852 2853#if SCC_dolog 2854 SCC_DbgLogChanStartLine(chan); 2855 dbglog_writeCStr(" RR["); 2856 dbglog_writeHex(SCC_Reg); 2857 dbglog_writeCStr("] -> "); 2858 dbglog_writeHex(value); 2859 dbglog_writeReturn(); 2860#endif 2861 2862 return value; 2863} 2864 2865LOCALPROC SCC_PutReg(ui3r Data, int chan, ui3r SCC_Reg) 2866{ 2867#if SCC_dolog && 0 2868 SCC_DbgLogChanStartLine(chan); 2869 dbglog_writeCStr(" WR["); 2870 dbglog_writeHex(SCC_Reg); 2871 dbglog_writeCStr("] <- "); 2872 dbglog_writeHex(Data); 2873 dbglog_writeReturn(); 2874#endif 2875 2876 switch (SCC_Reg) { 2877 case 0: 2878 SCC_PutWR0(Data, chan); 2879 break; 2880 case 1: 2881 SCC_PutWR1(Data, chan); 2882 break; 2883 case 2: 2884 SCC_PutWR2(Data, chan); 2885 break; 2886 case 3: 2887 SCC_PutWR3(Data, chan); 2888 break; 2889 case 4: 2890 SCC_PutWR4(Data, chan); 2891 break; 2892 case 5: 2893 SCC_PutWR5(Data, chan); 2894 break; 2895 case 6: 2896 SCC_PutWR6(Data, chan); 2897 break; 2898 case 7: 2899 SCC_PutWR7(Data, chan); 2900 break; 2901 case 8: 2902 SCC_PutWR8(Data, chan); 2903 break; 2904 case 9: 2905 SCC_PutWR9(Data, chan); 2906 break; 2907 case 10: 2908 SCC_PutWR10(Data, chan); 2909 break; 2910 case 11: 2911 SCC_PutWR11(Data, chan); 2912 break; 2913 case 12: 2914 SCC_PutWR12(Data, chan); 2915 break; 2916 case 13: 2917 SCC_PutWR13(Data, chan); 2918 break; 2919 case 14: 2920 SCC_PutWR14(Data, chan); 2921 break; 2922 case 15: 2923 SCC_PutWR15(Data, chan); 2924 break; 2925 default: 2926 ReportAbnormalID(0x074C, 2927 "unexpected SCC_Reg in SCC_PutReg"); 2928 break; 2929 } 2930 2931#if EmLocalTalk 2932 /* 2933 Always check to see if interrupt state changed after ANY 2934 register access 2935 */ 2936 CheckSCCInterruptFlag(); 2937#endif 2938} 2939 2940GLOBALFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr) 2941{ 2942#if EmLocalTalk 2943 /* 2944 Determine channel, data, and access type from address. The bus 2945 for the 8350 is non-standard, so the Macintosh connects address 2946 bus lines to various signals on the 8350 as shown below. The 2947 68K will use the upper byte of the data bus for odd addresses, 2948 and the 8350 is only wired to the upper byte, therefore use 2949 only odd addresses or you risk resetting the 8350. 2950 2951 68k 8350 2952 ----- ------ 2953 a1 a/b 2954 a2 d/c 2955 a21 wr/rd 2956 */ 2957#endif 2958 ui3b SCC_Reg; 2959 int chan = (~ addr) & 1; /* 0=modem, 1=printer */ 2960 if (((addr >> 1) & 1) == 0) { 2961 /* Channel Control */ 2962 SCC_Reg = SCC.PointerBits; 2963 SCC.PointerBits = 0; 2964 } else { 2965 /* Channel Data */ 2966 SCC_Reg = 8; 2967 } 2968 if (WriteMem) { 2969 SCC_PutReg(Data, chan, SCC_Reg); 2970 } else { 2971 Data = SCC_GetReg(chan, SCC_Reg); 2972 } 2973 2974 return Data; 2975}