this repo has no description
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}