/
githubmirror
/
libslirp
Обзор
Документация
Войти
/
githubmirror
/
libslirp
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
20201217
BasiliskII/src/timer.cpp
316 строк
6 KB
jvernet
Some Warning removed and 64bits
03 окт 2017, 22:37
03 окт 2017, 22:37
1316b64
Код
Авторство
О чём код?
/* * timer.cpp - Time Manager emulation * * Basilisk II (C) 1997-2008 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * SEE ALSO * Inside Macintosh: Processes, chapter 3 "Time Manager" * Technote 1063: "Inside Macintosh: Processes: Time Manager Addenda" */ #include <stdio.h> #include "sysdeps.h" #include "cpu_emulation.h" #include "main.h" #include "macos_util.h" #include "timer.h" #define DEBUG 0 #include "debug.h" // Set this to 1 to enable TMQueue management (doesn't work) #define TM_QUEUE 0 // Definitions for Time Manager enum { // TMTask struct tmAddr = 6, tmCount = 10, tmWakeUp = 14, tmReserved = 18 }; // Array of additional info for each installed TMTask struct TMDesc { uint32 task; // Mac address of associated TMTask tm_time_t wakeup; // Time this task is scheduled for execution bool in_use; // Flag: descriptor in use }; const int NUM_DESCS = 64; // Maximum number of descriptors static TMDesc desc[NUM_DESCS]; /* * Allocate descriptor for given TMTask in list */ static int alloc_desc(uint32 tm) { // Search for first free descriptor for (int i=0; i<NUM_DESCS; i++) if (!desc[i].in_use) { desc[i].task = tm; desc[i].in_use = true; return i; } return -1; } /* * Free descriptor in list */ inline static void free_desc(int i) { desc[i].in_use = false; } /* * Find descriptor associated with given TMTask */ inline static int find_desc(uint32 tm) { for (int i=0; i<NUM_DESCS; i++) if (desc[i].in_use && desc[i].task == tm) return i; return -1; } /* * Enqueue task in Time Manager queue */ static void enqueue_tm(uint32 tm) { #if TM_QUEUE uint32 tm_var = ReadMacInt32(0xb30); WriteMacInt32(tm + qLink, ReadMacInt32(tm_var)); WriteMacInt32(tm_var, tm); #endif } /* * Remove task from Time Manager queue */ static void dequeue_tm(uint32 tm) { #if TM_QUEUE uint32 p = ReadMacInt32(0xb30); while (p) { uint32 next = ReadMacInt32(p + qLink); if (next == tm) { WriteMacInt32(p + qLink, ReadMacInt32(next + qLink)); return; } } #endif } /* * Initialize Time Manager */ void TimerInit(void) { // Mark all descriptors as inactive for (int i=0; i<NUM_DESCS; i++) free_desc(i); } /* * Exit Time Manager */ void TimerExit(void) { } /* * Emulator reset, remove all timer tasks */ void TimerReset(void) { // Mark all descriptors as inactive for (int i=0; i<NUM_DESCS; i++) free_desc(i); } /* * Insert timer task */ int16 InsTime(uint32 tm, uint16 trap) { D(bug("InsTime %08lx, trap %04x\n", tm, trap)); WriteMacInt16(tm + qType, (ReadMacInt16(tm + qType) & 0x1fff) | ((trap << 4) & 0x6000)); if (find_desc(tm) >= 0) printf("WARNING: InsTime(): Task re-inserted\n"); else { int i = alloc_desc(tm); if (i < 0) printf("FATAL: InsTime(): No free Time Manager descriptor\n"); } return 0; } /* * Remove timer task */ int16 RmvTime(uint32 tm) { D(bug("RmvTime %08lx\n", tm)); // Find descriptor int i = find_desc(tm); if (i < 0) { printf("WARNING: RmvTime(%08x): Descriptor not found\n", tm); return 0; } // Task active? if (ReadMacInt16(tm + qType) & 0x8000) { // Yes, make task inactive and remove it from the Time Manager queue WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff); dequeue_tm(tm); // Compute remaining time tm_time_t remaining, current; timer_current_time(current); timer_sub_time(remaining, desc[i].wakeup, current); WriteMacInt32(tm + tmCount, timer_host2mac_time(remaining)); } else WriteMacInt32(tm + tmCount, 0); D(bug(" tmCount %d\n", ReadMacInt32(tm + tmCount))); // Free descriptor free_desc(i); return 0; } /* * Start timer task */ int16 PrimeTime(uint32 tm, int32 time) { D(bug("PrimeTime %08x, time %d\n", tm, time)); // Find descriptor int i = find_desc(tm); if (i < 0) { printf("FATAL: PrimeTime(): Descriptor not found\n"); return 0; } // Extended task? if (ReadMacInt16(tm + qType) & 0x4000) { // Convert delay time tm_time_t delay; timer_mac2host_time(delay, time); // Yes, tmWakeUp set? if (ReadMacInt32(tm + tmWakeUp)) { //!! PrimeTime(0) means continue previous delay // (save wakeup time in RmvTime?) if (time == 0) printf("WARNING: Unsupported PrimeTime(0)\n"); // Yes, calculate wakeup time relative to last scheduled time tm_time_t wakeup; timer_add_time(wakeup, desc[i].wakeup, delay); desc[i].wakeup = wakeup; } else { // No, calculate wakeup time relative to current time tm_time_t now; timer_current_time(now); timer_add_time(desc[i].wakeup, now, delay); } // Set tmWakeUp to indicate that task was scheduled WriteMacInt32(tm + tmWakeUp, 0x12345678); } else { // Not extended task, calculate wakeup time relative to current time tm_time_t delay; timer_mac2host_time(delay, time); timer_current_time(desc[i].wakeup); timer_add_time(desc[i].wakeup, desc[i].wakeup, delay); } // Make task active and enqueue it in the Time Manager queue WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) | 0x8000); enqueue_tm(tm); return 0; } /* * Timer interrupt function (executed as part of 60Hz interrupt) */ void TimerInterrupt(void) { // Look for active TMTasks that have expired tm_time_t now; timer_current_time(now); for (int i=0; i<NUM_DESCS; i++) if (desc[i].in_use) { uint32 tm = desc[i].task; if ((ReadMacInt16(tm + qType) & 0x8000) && timer_cmp_time(desc[i].wakeup, now) < 0) { // Found one, mark as inactive and remove it from the Time Manager queue WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff); dequeue_tm(tm); // Call timer function uint32 addr = ReadMacInt32(tm + tmAddr); if (addr) { D(bug("Calling TimeTask %08lx, addr %08lx\n", tm, addr)); M68kRegisters r; r.a[0] = addr; r.a[1] = tm; Execute68k(addr, &r); } } } }