minivmac4ios/Mini vMac/mnvm_core/ADBEMDEV.c

1 line
5.1 KiB
C
Raw Normal View History

/* ADBEMDEV.c Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Apple Desktop Bus EMulated DEVice */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "ADBEMDEV.h" #ifdef _VIA_Debug #include <stdio.h> #endif /* ReportAbnormalID unused 0x0C06 - 0x0CFF */ IMPORTPROC ADB_ShiftOutData(ui3b v); IMPORTFUNC ui3b ADB_ShiftInData(void); #include "ADBSHARE.h" LOCALVAR blnr ADB_ListenDatBuf; LOCALVAR ui3b ADB_IndexDatBuf; GLOBALPROC ADB_DoNewState(void) { ui3b state = ADB_st1 * 2 + ADB_st0; #ifdef _VIA_Debug fprintf(stderr, "ADB_DoNewState: %d\n", state); #endif { ADB_Int = 1; switch (state) { case 0: /* Start a new command */ if (ADB_ListenDatBuf) { ADB_ListenDatBuf = falseblnr; ADB_SzDatBuf = ADB_IndexDatBuf; ADB_EndListen(); } ADB_TalkDatBuf = falseblnr; ADB_IndexDatBuf = 0; ADB_CurCmd = ADB_ShiftInData(); /* which sets interrupt, acknowleding command */ #ifdef _VIA_Debug fprintf(stderr, "in: %d\n", ADB_CurCmd); #endif switch ((ADB_CurCmd >> 2) & 3) { case 0: /* reserved */ switch (ADB_CurCmd & 3) { case 0: /* Send Reset */ ADB_DoReset(); break; case 1: /* Flush */ ADB_Flush(); break; case 2: /* reserved */ case 3: /* reserved */ ReportAbnormalID(0x0C01, "Reserved ADB command"); break; } break; case 1: /* reserved */ ReportAbnormalID(0x0C02, "Reserved ADB command"); break; case 2: /* listen */ ADB_ListenDatBuf = trueblnr; #ifdef _VIA_Debug fprintf(stderr, "*** listening\n"); #endif break; case 3: /* talk */ ADB_DoTalk(); break; } break; case 1: /* Transfer date byte (even) */ case 2: /* Transfer date byte (odd) */ if (! ADB_ListenDatBuf) { /* will get here even if no pending talk data, when there is pending event from device other than the one polled by the last talk command. this probably indicates a bug. */ if ((! ADB_TalkDatBuf) || (ADB_IndexDatBuf >= ADB_SzDatBuf)) { ADB_ShiftOutData(0xFF); ADB_Data = 1; ADB_Int = 0; } else { #ifdef _VIA_Debug fprintf(stderr, "*** talk one\n"); #endif ADB_ShiftOutData(ADB_DatBuf[ADB_IndexDatBuf]); ADB_Data = 1; ADB_IndexDatBuf += 1; } } else { if (ADB_IndexDatBuf >= ADB_MaxSzDatBuf) { ReportAbnormalID(0x0C03, "ADB listen too much"); /* ADB_MaxSzDatBuf isn't big enough */ (void) ADB_ShiftInData(); } else { #ifdef _VIA_Debug fprintf(stderr, "*** listen one\n"); #endif ADB_DatBuf[ADB_IndexDatBuf] = ADB_ShiftInData(); ADB_IndexDatBuf += 1; } } break; case 3: /* idle */ if (ADB_ListenDatBuf) { ReportAbnormalID(0x0C04, "ADB idle follows listen"); /* apparently doesn't happen */ } if (ADB_TalkDatBuf) { if (ADB_IndexDatBuf != 0) { ReportAbnormalID(0x0C05, "idle when not done talking"); } ADB_ShiftOutData(0xFF); /* ADB_Int = 0; */ } else if (CheckForADBanyEvt()) { if (((ADB_CurCmd >> 2) & 3) == 3) { ADB_DoTalk(); } ADB_ShiftOutData(0xFF); /* ADB_Int = 0; */ } break; } } } GLOBALPROC ADBstate_ChangeNtfy(void) { #ifdef _VIA_Debug fprintf(stderr, "ADBstate_ChangeNtfy: %d, %d, %d\n", ADB_st1, ADB_st0, GetCuriCount()); #endif ICT_add(kICT_ADB_NewState, 348160UL * kCycleScale / 64 * kMyClockMult); /* Macintosh Family Hardware Reference say device "must res