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); } } } }
// Dispatch packet to protocol handler static void ether_dispatch_packet(uint32 packet, uint32 length) { // Get packet type uint16 type = ReadMacInt16(packet + 12); // Look for protocol NetProtocol *prot = find_protocol(type); if (prot == NULL) return; // No default handler if (prot->handler == 0) return; // Copy header to RHA Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14); D(bug(" header %08lx%04lx %08lx%04lx %04lx\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12))); // Call protocol handler M68kRegisters r; r.d[0] = type; // Packet type r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket) r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket) r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", prot->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4])); Execute68k(prot->handler, &r); }
int16 RmvTime(uint32 tm) { D(bug("RmvTime %08lx\n", tm)); // Find descriptor int i = find_desc(tm); if (i < 0) { D(bug("WARNING: RmvTime(%08lx): 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 %ld\n", ReadMacInt32(tm + tmCount))); // Free descriptor free_desc(i); return 0; }
int16 PrimeTime(uint32 tm, int32 time) { D(bug("PrimeTime %08lx, time %ld\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("FATAL: Unsupported PrimeTime(0)\n"); return 0; } // 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; }
static __saveds __regargs LONG copy_from_buff(uint8 *to /*a0*/, char *wds /*a1*/, uint32 packet_len /*d0*/) { D(bug("CopyFromBuff to %08lx, wds %08lx, size %08lx\n", to, wds, packet_len)); #if MONITOR bug("Sending Ethernet packet:\n"); #endif for (;;) { int len = ReadMacInt16((uint32)wds); if (len == 0) break; #if MONITOR uint8 *adr = Mac2HostAddr(ReadMacInt32((uint32)wds + 2)); for (int i=0; i<len; i++) { bug("%02lx ", adr[i]); } #endif CopyMem(Mac2HostAddr(ReadMacInt32((uint32)wds + 2)), to, len); to += len; wds += 6; } #if MONITOR bug("\n"); #endif return 1; }
// Pass-through dirty areas to redraw functions static inline void NQD_set_dirty_area(uint32 p) { if (ReadMacInt32(p + acclDestBaseAddr) == screen_base) { int16 x = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); int16 y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); int16 w = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); int16 h = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); video_set_dirty_area(x, y, w, h); } }
static bool is_drive_number_free(int num) { uint32 e = ReadMacInt32(0x308 + qHead); while (e) { uint32 d = e - dsQLink; if ((int)ReadMacInt16(d + dsQDrive) == num) return false; e = ReadMacInt32(e + qLink); } return true; }
int16 InsTime(uint32 tm, uint16 trap) { D(bug("InsTime %08lx, trap %04x\n", tm, trap)); WriteMacInt16((uint32)tm + qType, ReadMacInt16((uint32)tm + qType) & 0x1fff | (trap << 4) & 0x6000); if (the_app->find_desc(tm)) printf("WARNING: InsTime(%08lx): Task re-inserted\n", tm); else { the_app->add_desc(tm); } return 0; }
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; }
int16 InsTime(uint32 tm, uint16 trap) { D(bug("InsTime %08lx, trap %04x\n", tm, trap)); WriteMacInt16((uint32)tm + qType, ReadMacInt16((uint32)tm + qType) & 0x1fff | (trap << 4) & 0x6000); if (find_desc(tm)) printf("WARNING: InsTime(%08lx): Task re-inserted\n", (long unsigned int)tm); else { TMDesc *desc = new TMDesc; desc->task = tm; desc->next = tmDescList; tmDescList = desc; } return 0; }
void ASERDPort::set_handshake(uint32 s, bool with_dtr) { D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\n", ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3), ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7))); err_mask = ReadMacInt8(s + shkErrs); if (is_parallel) { // Parallel handshake if (with_dtr) { if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR)) ((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE; else ((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE; } else { if (ReadMacInt8(s + shkFCTS)) ((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE; else ((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE; } set_par_params(); } else { // Serial handshake if (ReadMacInt8(s + shkFXOn) || ReadMacInt8(s + shkFInX)) control_io->io_SerFlags &= ~SERF_XDISABLED; else control_io->io_SerFlags |= SERF_XDISABLED; if (with_dtr) { if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR)) control_io->io_SerFlags |= SERF_7WIRE; else control_io->io_SerFlags &= ~SERF_7WIRE; } else { if (ReadMacInt8(s + shkFCTS)) control_io->io_SerFlags |= SERF_7WIRE; else control_io->io_SerFlags &= ~SERF_7WIRE; } control_io->io_CtlChar = ReadMacInt16(s + shkXOn) << 16; set_params(); } }
void NQD_invrect(uint32 p) { D(bug("accl_invrect %08x\n", p)); // Get inversion parameters int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); D(bug(" width %d, height %d, bytes_per_row %d\n", width, height, (int32)ReadMacInt32(p + acclDestRowBytes))); //!!?? pen_mode == 14 // And perform the inversion const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize)); const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp)); width *= bpp; switch (bpp) { case 1: for (int i = 0; i < height; i++) { do_invrect<8>(dest, width); dest += dest_row_bytes; } break; case 2: for (int i = 0; i < height; i++) { do_invrect<16>(dest, width); dest += dest_row_bytes; } break; case 4: for (int i = 0; i < height; i++) { do_invrect<32>(dest, width); dest += dest_row_bytes; } break; } }
void NQD_fillrect(uint32 p) { D(bug("accl_fillrect %08x\n", p)); // Get filling parameters int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); uint32 color = htonl(ReadMacInt32(p + acclPenMode) == 8 ? ReadMacInt32(p + acclForePen) : ReadMacInt32(p + acclBackPen)); D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); D(bug(" width %d, height %d\n", width, height)); D(bug(" bytes_per_row %d color %08x\n", (int32)ReadMacInt32(p + acclDestRowBytes), color)); // And perform the fill const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize)); const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp)); width *= bpp; switch (bpp) { case 1: for (int i = 0; i < height; i++) { memset(dest, color, width); dest += dest_row_bytes; } break; case 2: for (int i = 0; i < height; i++) { do_fillrect<16>(dest, color, width); dest += dest_row_bytes; } break; case 4: for (int i = 0; i < height; i++) { do_fillrect<32>(dest, color, width); dest += dest_row_bytes; } break; } }
void EtherInterrupt(void) { D(bug("EtherIRQ\n")); // Packet write done, enqueue DT to call IODone if (write_done) { EnqueueMac(ether_data + ed_DeferredTask, 0xd92); write_done = false; } // Call protocol handler for received packets IOSana2Req *io; while (io = (struct IOSana2Req *)GetMsg(read_port)) { // Get pointer to NetProtocol (hidden in node name) NetProtocol *p = (NetProtocol *)io->ios2_Req.io_Message.mn_Node.ln_Name; // No default handler if (p->handler == 0) continue; // Copy header to RHA Host2Mac_memcpy(ether_data + ed_RHA, io->ios2_Data, 14); D(bug(" header %08lx%04lx %08lx%04lx %04lx\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12))); // Call protocol handler M68kRegisters r; r.d[0] = *(uint16 *)((uint32)io->ios2_Data + 12); // Packet type r.d[1] = io->ios2_DataLength - 18; // Remaining packet length (without header, for ReadPacket) (-18 because the CRC is also included) r.a[0] = (uint32)io->ios2_Data + 14; // Pointer to packet (host address, for ReadPacket) r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", p->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4])); Execute68k(p->handler, &r); // Resend IORequest io->ios2_Req.io_Flags = SANA2IOF_RAW; BeginIO((struct IORequest *)io); } D(bug(" EtherIRQ done\n")); }
void EmulOp(M68kRegisters *r, uint32 pc, int selector) { D(bug("EmulOp %04x at %08x\n", selector, pc)); switch (selector) { case OP_BREAK: // Breakpoint printf("*** Breakpoint\n"); Dump68kRegs(r); break; case OP_XPRAM1: { // Read/write from/to XPRam uint32 len = r->d[3]; uint8 *adr = Mac2HostAddr(r->a[3]); D(bug("XPRAMReadWrite d3: %08lx, a3: %p\n", len, adr)); int ofs = len & 0xffff; len >>= 16; if (len & 0x8000) { len &= 0x7fff; for (uint32 i=0; i<len; i++) XPRAM[((ofs + i) & 0xff) + 0x1300] = *adr++; } else { for (uint32 i=0; i<len; i++) *adr++ = XPRAM[((ofs + i) & 0xff) + 0x1300]; } break; } case OP_XPRAM2: // Read from XPRam r->d[1] = XPRAM[(r->d[1] & 0xff) + 0x1300]; break; case OP_XPRAM3: // Write to XPRam XPRAM[(r->d[1] & 0xff) + 0x1300] = r->d[2]; break; case OP_NVRAM1: { // Read from NVRAM int ofs = r->d[0]; r->d[0] = XPRAM[ofs & 0x1fff]; bool localtalk = !(XPRAM[0x13e0] || XPRAM[0x13e1]); // LocalTalk enabled? switch (ofs) { case 0x13e0: // Disable LocalTalk (use EtherTalk instead) if (localtalk) r->d[0] = 0x00; break; case 0x13e1: if (localtalk) r->d[0] = 0x01; break; case 0x13e2: if (localtalk) r->d[0] = 0x00; break; case 0x13e3: if (localtalk) r->d[0] = 0x0a; break; } break; } case OP_NVRAM2: // Write to NVRAM XPRAM[r->d[0] & 0x1fff] = r->d[1]; break; case OP_NVRAM3: // Read/write from/to NVRAM if (r->d[3]) { r->d[0] = XPRAM[(r->d[4] + 0x1300) & 0x1fff]; } else { XPRAM[(r->d[4] + 0x1300) & 0x1fff] = r->d[5]; r->d[0] = 0; } break; case OP_FIX_MEMTOP: // Fixes MemTop in BootGlobs during startup D(bug("Fix MemTop\n")); WriteMacInt32(BootGlobsAddr - 20, RAMBase + RAMSize); // MemTop r->a[6] = RAMBase + RAMSize; break; case OP_FIX_MEMSIZE: { // Fixes physical/logical RAM size during startup D(bug("Fix MemSize\n")); uint32 diff = ReadMacInt32(0x1ef8) - ReadMacInt32(0x1ef4); WriteMacInt32(0x1ef8, RAMSize); // Physical RAM size WriteMacInt32(0x1ef4, RAMSize - diff); // Logical RAM size break; } case OP_FIX_BOOTSTACK: // Fixes boot stack pointer in boot 3 resource D(bug("Fix BootStack\n")); r->a[1] = r->a[7] = RAMBase + RAMSize * 3 / 4; break; case OP_SONY_OPEN: // Floppy driver functions r->d[0] = SonyOpen(r->a[0], r->a[1]); break; case OP_SONY_PRIME: r->d[0] = SonyPrime(r->a[0], r->a[1]); break; case OP_SONY_CONTROL: r->d[0] = SonyControl(r->a[0], r->a[1]); break; case OP_SONY_STATUS: r->d[0] = SonyStatus(r->a[0], r->a[1]); break; case OP_DISK_OPEN: // Disk driver functions r->d[0] = DiskOpen(r->a[0], r->a[1]); break; case OP_DISK_PRIME: r->d[0] = DiskPrime(r->a[0], r->a[1]); break; case OP_DISK_CONTROL: r->d[0] = DiskControl(r->a[0], r->a[1]); break; case OP_DISK_STATUS: r->d[0] = DiskStatus(r->a[0], r->a[1]); break; case OP_CDROM_OPEN: // CD-ROM driver functions r->d[0] = CDROMOpen(r->a[0], r->a[1]); break; case OP_CDROM_PRIME: r->d[0] = CDROMPrime(r->a[0], r->a[1]); break; case OP_CDROM_CONTROL: r->d[0] = CDROMControl(r->a[0], r->a[1]); break; case OP_CDROM_STATUS: r->d[0] = CDROMStatus(r->a[0], r->a[1]); break; case OP_AUDIO_DISPATCH: // Audio component functions r->d[0] = gMacAudio->Dispatch(r->a[3], r->a[4]); break; case OP_SOUNDIN_OPEN: // Sound input driver functions r->d[0] = gMacAudio->InOpen(r->a[0], r->a[1]); break; case OP_SOUNDIN_PRIME: r->d[0] = gMacAudio->InPrime(r->a[0], r->a[1]); break; case OP_SOUNDIN_CONTROL: r->d[0] = gMacAudio->InControl(r->a[0], r->a[1]); break; case OP_SOUNDIN_STATUS: r->d[0] = gMacAudio->InStatus(r->a[0], r->a[1]); break; case OP_SOUNDIN_CLOSE: r->d[0] = gMacAudio->InClose(r->a[0], r->a[1]); break; case OP_ADBOP: // ADBOp() replacement gADBInput->Op(r->d[0], Mac2HostAddr(ReadMacInt32(r->a[0]))); break; case OP_INSTIME: // InsTime() replacement r->d[0] = InsTime(r->a[0], r->d[1]); break; case OP_RMVTIME: // RmvTime() replacement r->d[0] = RmvTime(r->a[0]); break; case OP_PRIMETIME: // PrimeTime() replacement r->d[0] = PrimeTime(r->a[0], r->d[0]); break; case OP_MICROSECONDS: // Microseconds() replacement Microseconds(r->a[0], r->d[0]); break; case OP_PUT_SCRAP: // PutScrap() patch PutScrap(ReadMacInt32(r->a[7] + 8), Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 12)); break; case OP_GET_SCRAP: // GetScrap() patch GetScrap((void **)Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 12)); break; case OP_DEBUG_STR: // DebugStr() shows warning message if (PrefsFindBool("nogui")) { uint8 *pstr = Mac2HostAddr(ReadMacInt32(r->a[7] + 4)); char str[256]; int i; for (i=0; i<pstr[0]; i++) str[i] = pstr[i+1]; str[i] = 0; WarningAlert(str); } break; case OP_INSTALL_DRIVERS: { // Patch to install our own drivers during startup // Install drivers InstallDrivers(); // Patch MakeExecutable() MakeExecutableTvec = FindLibSymbol("\023PrivateInterfaceLib", "\016MakeExecutable"); D(bug("MakeExecutable TVECT at %08x\n", MakeExecutableTvec)); WriteMacInt32(MakeExecutableTvec, NativeFunction(NATIVE_MAKE_EXECUTABLE)); #if defined(__powerpc__) /* Native PowerPC */ WriteMacInt32(MakeExecutableTvec + 4, (uint32)TOC); #endif // Patch DebugStr() static const uint8 proc_template[] = { M68K_EMUL_OP_DEBUG_STR >> 8, M68K_EMUL_OP_DEBUG_STR & 0xFF, 0x4e, 0x74, // rtd #4 0x00, 0x04 }; BUILD_SHEEPSHAVER_PROCEDURE(proc); WriteMacInt32(0x1dfc, proc); break; } case OP_NAME_REGISTRY: // Patch Name Registry and initialize CallUniversalProc r->d[0] = (uint32)-1; PatchNameRegistry(); InitCallUniversalProc(); break; case OP_RESET: // Early in MacOS reset D(bug("*** RESET ***\n")); TimerReset(); MacOSUtilReset(); gMacAudio->Reset(); // Enable DR emulator (disabled for now) if (PrefsFindBool("jit68k") && 0) { D(bug("DR activated\n")); WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE); WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE); WriteMacInt32(KernelDataAddr + 0x1b04, DR_CACHE_BASE); WriteMacInt32(KernelDataAddr + 0x1b00, DR_EMULATOR_BASE); memcpy((void *)DR_EMULATOR_BASE, (void *)(ROMBase + 0x370000), DR_EMULATOR_SIZE); MakeExecutable(0, DR_EMULATOR_BASE, DR_EMULATOR_SIZE); } break; case OP_IRQ: // Level 1 interrupt WriteMacInt16(ReadMacInt32(KernelDataAddr + 0x67c), 0); // Clear interrupt r->d[0] = 0; if (HasMacStarted()) { if (InterruptFlags & INTFLAG_VIA) { ClearInterruptFlag(INTFLAG_VIA); #if !PRECISE_TIMING TimerInterrupt(); #endif ExecuteNative(NATIVE_VIDEO_VBL); static int tick_counter = 0; if (++tick_counter >= 60) { tick_counter = 0; SonyInterrupt(); DiskInterrupt(); CDROMInterrupt(); } r->d[0] = 1; // Flag: 68k interrupt routine executes VBLTasks etc. } if (InterruptFlags & INTFLAG_SERIAL) { ClearInterruptFlag(INTFLAG_SERIAL); SerialInterrupt(); } if (InterruptFlags & INTFLAG_ETHER) { ClearInterruptFlag(INTFLAG_ETHER); ExecuteNative(NATIVE_ETHER_IRQ); } if (InterruptFlags & INTFLAG_TIMER) { ClearInterruptFlag(INTFLAG_TIMER); TimerInterrupt(); } if (InterruptFlags & INTFLAG_AUDIO) { ClearInterruptFlag(INTFLAG_AUDIO); gMacAudio->Interrupt(); } if (InterruptFlags & INTFLAG_ADB) { ClearInterruptFlag(INTFLAG_ADB); gADBInput->Interrupt(); } } else r->d[0] = 1; break; case OP_SCSI_DISPATCH: { // SCSIDispatch() replacement uint32 ret = ReadMacInt32(r->a[7]); uint16 sel = ReadMacInt16(r->a[7] + 4); r->a[7] += 6; // D(bug("SCSIDispatch(%d)\n", sel)); int stack; switch (sel) { case 0: // SCSIReset WriteMacInt16(r->a[7], SCSIReset()); stack = 0; break; case 1: // SCSIGet WriteMacInt16(r->a[7], SCSIGet()); stack = 0; break; case 2: // SCSISelect case 11: // SCSISelAtn WriteMacInt16(r->a[7] + 2, SCSISelect(ReadMacInt8(r->a[7] + 1))); stack = 2; break; case 3: // SCSICmd WriteMacInt16(r->a[7] + 6, SCSICmd(ReadMacInt16(r->a[7]), Mac2HostAddr(ReadMacInt32(r->a[7] + 2)))); stack = 6; break; case 4: // SCSIComplete WriteMacInt16(r->a[7] + 12, SCSIComplete(ReadMacInt32(r->a[7]), ReadMacInt32(r->a[7] + 4), ReadMacInt32(r->a[7] + 8))); stack = 12; break; case 5: // SCSIRead case 8: // SCSIRBlind WriteMacInt16(r->a[7] + 4, SCSIRead(ReadMacInt32(r->a[7]))); stack = 4; break; case 6: // SCSIWrite case 9: // SCSIWBlind WriteMacInt16(r->a[7] + 4, SCSIWrite(ReadMacInt32(r->a[7]))); stack = 4; break; case 10: // SCSIStat WriteMacInt16(r->a[7], SCSIStat()); stack = 0; break; case 12: // SCSIMsgIn WriteMacInt16(r->a[7] + 4, 0); stack = 4; break; case 13: // SCSIMsgOut WriteMacInt16(r->a[7] + 2, 0); stack = 2; break; case 14: // SCSIMgrBusy WriteMacInt16(r->a[7], SCSIMgrBusy()); stack = 0; break; default: printf("FATAL: SCSIDispatch: illegal selector\n"); stack = 0; //!! SysError(12) } r->a[0] = ret; r->a[7] += stack; break; } case OP_SCSI_ATOMIC: // SCSIAtomic() replacement D(bug("SCSIAtomic\n")); r->d[0] = (uint32)-7887; break; case OP_CHECK_SYSV: { // Check we are not using MacOS < 8.1 with a NewWorld ROM r->a[1] = r->d[1]; r->a[0] = ReadMacInt32(r->d[1]); uint32 sysv = ReadMacInt16(r->a[0]); D(bug("Detected MacOS version %d.%d.%d\n", (sysv >> 8) & 0xf, (sysv >> 4) & 0xf, sysv & 0xf)); if (ROMType == ROMTYPE_NEWWORLD && sysv < 0x0801) r->d[1] = 0; break; } case OP_NTRB_17_PATCH: r->a[2] = ReadMacInt32(r->a[7]); r->a[7] += 4; if (ReadMacInt16(r->a[2] + 6) == 17) PatchNativeResourceManager(); break; case OP_NTRB_17_PATCH2: r->a[7] += 8; PatchNativeResourceManager(); break; case OP_NTRB_17_PATCH3: r->a[2] = ReadMacInt32(r->a[7]); r->a[7] += 4; D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6))); if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17) PatchNativeResourceManager(); break; case OP_NTRB_17_PATCH4: r->d[0] = ReadMacInt16(r->a[7]); r->a[7] += 2; D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6))); if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17) PatchNativeResourceManager(); break; case OP_CHECKLOAD: { // vCheckLoad() patch uint32 type = ReadMacInt32(r->a[7]); r->a[7] += 4; int16 id = ReadMacInt16(r->a[2]); if (r->a[0] == 0) break; uint32 adr = ReadMacInt32(r->a[0]); if (adr == 0) break; uint16 *p = (uint16 *)Mac2HostAddr(adr); uint32 size = ReadMacInt32(adr - 8) & 0xffffff; CheckLoad(type, id, p, size); break; } case OP_EXTFS_COMM: // External file system routines WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4))); break; case OP_EXTFS_HFS: WriteMacInt16(r->a[7] + 20, ExtFSHFS(ReadMacInt32(r->a[7] + 16), ReadMacInt16(r->a[7] + 14), ReadMacInt32(r->a[7] + 10), ReadMacInt32(r->a[7] + 6), ReadMacInt16(r->a[7] + 4))); break; case OP_IDLE_TIME: // Sleep if no events pending if (ReadMacInt32(0x14c) == 0) idle_wait(); r->a[0] = ReadMacInt32(0x2b6); break; case OP_IDLE_TIME_2: // Sleep if no events pending if (ReadMacInt32(0x14c) == 0) idle_wait(); r->d[0] = (uint32)-2; break; default: printf("FATAL: EMUL_OP called with bogus selector %08x\n", selector); QuitEmulator(); break; } }
int16 ASERDPort::control(uint32 pb, uint32 dce, uint16 code) { D(bug("control(%ld)\n", (uint32)code)); switch (code) { case 1: // KillIO send_to_proc(MSG_KILL_IO); return noErr; case kSERDConfiguration: if (configure(ReadMacInt16(pb + csParam))) return noErr; else return paramErr; case kSERDInputBuffer: { if (is_parallel) return noErr; int buf = ReadMacInt16(pb + csParam + 4) & 0xffffffc0; if (buf < 1024) // 1k minimum buf = 1024; D(bug(" buffer size is now %08lx\n", buf)); control_io->io_RBufLen = buf; return set_params() ? noErr : paramErr; } case kSERDSerHShake: set_handshake(pb + csParam, false); return noErr; case kSERDSetBreak: if (!is_parallel) send_to_proc(MSG_BREAK); return noErr; case kSERDClearBreak: return noErr; case kSERDBaudRate: if (is_parallel) return noErr; control_io->io_Baud = ReadMacInt16(pb + csParam); D(bug(" baud rate %ld\n", control_io->io_Baud)); return set_params() ? noErr : paramErr; case kSERDHandshake: case kSERDHandshakeRS232: set_handshake(pb + csParam, true); return noErr; case kSERDClockMIDI: if (is_parallel) return noErr; control_io->io_Baud = 31250; control_io->io_SerFlags = SERF_XDISABLED | SERF_SHARED; control_io->io_StopBits = 1; control_io->io_ReadLen = control_io->io_WriteLen = 8; return set_params() ? noErr : paramErr; case kSERDMiscOptions: case kSERDAssertDTR: case kSERDNegateDTR: case kSERDSetPEChar: case kSERDSetPEAltChar: case kSERDAssertRTS: case kSERDNegateRTS: return noErr; // Not supported under AmigaOS case kSERD115KBaud: if (is_parallel) return noErr; control_io->io_Baud = 115200; return set_params() ? noErr : paramErr; case kSERD230KBaud: case kSERDSetHighSpeed: if (is_parallel) return noErr; control_io->io_Baud = 230400; return set_params() ? noErr : paramErr; case kSERDResetChannel: send_to_proc(MSG_RESET); return noErr; default: printf("WARNING: SerialControl(): unimplemented control code %d\n", code); return controlErr; } }
void TimerInterrupt(void) { // D(bug("TimerIRQ\n")); // Look for active TMTasks that have expired tm_time_t now; timer_current_time(now); TMDesc *desc = tmDescList; while (desc) { TMDesc *next = desc->next; uint32 tm = desc->task; if ((ReadMacInt16(tm + qType) & 0x8000) && timer_cmp_time(desc->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(r.a[0], &r); D(bug(" returned from TimeTask\n")); } } desc = next; } #if PRECISE_TIMING // Look for next task to be called and set wakeup_time #if PRECISE_TIMING_BEOS while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; suspend_thread(timer_thread); #endif #if PRECISE_TIMING_MACH semaphore_wait(wakeup_time_sem); thread_suspend(timer_thread); #endif #if PRECISE_TIMING_POSIX timer_thread_suspend(); pthread_mutex_lock(&wakeup_time_lock); #endif wakeup_time = wakeup_time_max; for (TMDesc *d = tmDescList; d; d = d->next) if ((ReadMacInt16(d->task + qType) & 0x8000)) if (timer_cmp_time(d->wakeup, wakeup_time) < 0) wakeup_time = d->wakeup; #if PRECISE_TIMING_BEOS release_sem(wakeup_time_sem); thread_info info; do { resume_thread(timer_thread); // This will unblock the thread get_thread_info(timer_thread, &info); } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) #endif #if PRECISE_TIMING_MACH semaphore_signal(wakeup_time_sem); thread_abort(timer_thread); thread_resume(timer_thread); #endif #if PRECISE_TIMING_POSIX pthread_mutex_unlock(&wakeup_time_lock); timer_thread_resume(); assert(suspend_count == 0); #endif #endif }
int16 PrimeTime(uint32 tm, int32 time) { D(bug("PrimeTime %08lx, time %ld\n", tm, time)); // Find descriptor TMDesc *desc = find_desc(tm); if (!desc) { printf("FATAL: PrimeTime(%08lx): Descriptor not found\n", (long unsigned int)tm); return 0; } // Convert delay time tm_time_t delay; timer_mac2host_time(delay, time); // Extended task? if (ReadMacInt16(tm + qType) & 0x4000) { // Yes, tmWakeUp set? if (ReadMacInt32(tm + tmWakeUp)) { // PrimeTime(0) can either mean (a) "the task runs as soon as interrupts are enabled" // or (b) "continue previous delay" if an expired task was stopped via RmvTime() and // then re-installed using InsXTime(). Since tmWakeUp was set, this is case (b). // The remaining time was saved in tmCount by RmvTime(). if (time == 0) { timer_mac2host_time(delay, ReadMacInt16(tm + tmCount)); } // Yes, calculate wakeup time relative to last scheduled time tm_time_t wakeup; timer_add_time(wakeup, desc->wakeup, delay); desc->wakeup = wakeup; } else { // No, calculate wakeup time relative to current time tm_time_t now; timer_current_time(now); timer_add_time(desc->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 now; timer_current_time(now); timer_add_time(desc->wakeup, now, delay); } // Make task active and enqueue it in the Time Manager queue #if PRECISE_TIMING_BEOS while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; suspend_thread(timer_thread); #endif #ifdef PRECISE_TIMING_MACH semaphore_wait(wakeup_time_sem); thread_suspend(timer_thread); #endif #if PRECISE_TIMING_POSIX timer_thread_suspend(); pthread_mutex_lock(&wakeup_time_lock); #endif WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) | 0x8000); enqueue_tm(tm); #if PRECISE_TIMING // Look for next task to be called and set wakeup_time wakeup_time = wakeup_time_max; for (TMDesc *d = tmDescList; d; d = d->next) if ((ReadMacInt16(d->task + qType) & 0x8000)) if (timer_cmp_time(d->wakeup, wakeup_time) < 0) wakeup_time = d->wakeup; #ifdef PRECISE_TIMING_BEOS release_sem(wakeup_time_sem); thread_info info; do { resume_thread(timer_thread); // This will unblock the thread get_thread_info(timer_thread, &info); } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) #endif #ifdef PRECISE_TIMING_MACH semaphore_signal(wakeup_time_sem); thread_abort(timer_thread); thread_resume(timer_thread); #endif #ifdef PRECISE_TIMING_POSIX pthread_mutex_unlock(&wakeup_time_lock); timer_thread_resume(); assert(suspend_count == 0); #endif #endif return 0; }
int16 RmvTime(uint32 tm) { D(bug("RmvTime %08lx\n", tm)); // Find descriptor TMDesc *desc = find_desc(tm); if (!desc) { printf("WARNING: RmvTime(%08lx): Descriptor not found\n", (long unsigned int)tm); return 0; } // Task active? #if PRECISE_TIMING_BEOS while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; suspend_thread(timer_thread); #endif #ifdef PRECISE_TIMING_MACH semaphore_wait(wakeup_time_sem); thread_suspend(timer_thread); #endif #if PRECISE_TIMING_POSIX timer_thread_suspend(); pthread_mutex_lock(&wakeup_time_lock); #endif 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); #if PRECISE_TIMING // Look for next task to be called and set wakeup_time wakeup_time = wakeup_time_max; for (TMDesc *d = tmDescList; d; d = d->next) if ((ReadMacInt16(d->task + qType) & 0x8000)) if (timer_cmp_time(d->wakeup, wakeup_time) < 0) wakeup_time = d->wakeup; #endif // Compute remaining time tm_time_t remaining, current; timer_current_time(current); timer_sub_time(remaining, desc->wakeup, current); WriteMacInt32(tm + tmCount, timer_host2mac_time(remaining)); } else WriteMacInt32(tm + tmCount, 0); D(bug(" tmCount %ld\n", ReadMacInt32(tm + tmCount))); #if PRECISE_TIMING_BEOS release_sem(wakeup_time_sem); thread_info info; do { resume_thread(timer_thread); // This will unblock the thread get_thread_info(timer_thread, &info); } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) #endif #ifdef PRECISE_TIMING_MACH semaphore_signal(wakeup_time_sem); thread_abort(timer_thread); thread_resume(timer_thread); #endif #if PRECISE_TIMING_POSIX pthread_mutex_unlock(&wakeup_time_lock); timer_thread_resume(); assert(suspend_count == 0); #endif // Free descriptor free_desc(desc); return 0; }
int16 XSERDPort::control(uint32 pb, uint32 dce, uint16 code) { switch (code) { case 1: // KillIO io_killed = true; if (protocol == serial) tcflush(fd, TCIOFLUSH); while (read_pending || write_pending) usleep(10000); io_killed = false; return noErr; case kSERDConfiguration: if (configure(ReadMacInt16(pb + csParam))) return noErr; else return paramErr; case kSERDInputBuffer: return noErr; // Not supported under Unix case kSERDSerHShake: set_handshake(pb + csParam, false); return noErr; case kSERDSetBreak: if (protocol == serial) tcsendbreak(fd, 0); return noErr; case kSERDClearBreak: return noErr; case kSERDBaudRate: { if (protocol != serial) return noErr; uint16 rate = ReadMacInt16(pb + csParam); speed_t baud_rate; if (rate <= 50) { rate = 50; baud_rate = B50; } else if (rate <= 75) { rate = 75; baud_rate = B75; } else if (rate <= 110) { rate = 110; baud_rate = B110; } else if (rate <= 134) { rate = 134; baud_rate = B134; } else if (rate <= 150) { rate = 150; baud_rate = B150; } else if (rate <= 200) { rate = 200; baud_rate = B200; } else if (rate <= 300) { rate = 300; baud_rate = B300; } else if (rate <= 600) { rate = 600; baud_rate = B600; } else if (rate <= 1200) { rate = 1200; baud_rate = B1200; } else if (rate <= 1800) { rate = 1800; baud_rate = B1800; } else if (rate <= 2400) { rate = 2400; baud_rate = B2400; } else if (rate <= 4800) { rate = 4800; baud_rate = B4800; } else if (rate <= 9600) { rate = 9600; baud_rate = B9600; } else if (rate <= 19200) { rate = 19200; baud_rate = B19200; } else if (rate <= 38400) { rate = 38400; baud_rate = B38400; } else if (rate <= 57600) { rate = 57600; baud_rate = B57600; } else { // Just for safety in case someone wants a rate between 57600 and 65535 rate = 57600; baud_rate = B57600; } WriteMacInt16(pb + csParam, rate); cfsetispeed(&mode, baud_rate); cfsetospeed(&mode, baud_rate); tcsetattr(fd, TCSANOW, &mode); return noErr; } case kSERDHandshake: case kSERDHandshakeRS232: set_handshake(pb + csParam, true); return noErr; case kSERDMiscOptions: if (protocol != serial) return noErr; if (ReadMacInt8(pb + csParam) & kOptionPreserveDTR) mode.c_cflag &= ~HUPCL; else mode.c_cflag |= HUPCL; tcsetattr(fd, TCSANOW, &mode); return noErr; case kSERDAssertDTR: { if (protocol != serial) return noErr; unsigned int status = TIOCM_DTR; ioctl(fd, TIOCMBIS, &status); return noErr; } case kSERDNegateDTR: { if (protocol != serial) return noErr; unsigned int status = TIOCM_DTR; ioctl(fd, TIOCMBIC, &status); return noErr; } case kSERDSetPEChar: case kSERDSetPEAltChar: return noErr; // Not supported under Unix case kSERDResetChannel: if (protocol == serial) tcflush(fd, TCIOFLUSH); return noErr; case kSERDAssertRTS: { if (protocol != serial) return noErr; unsigned int status = TIOCM_RTS; ioctl(fd, TIOCMBIS, &status); return noErr; } case kSERDNegateRTS: { if (protocol != serial) return noErr; unsigned int status = TIOCM_RTS; ioctl(fd, TIOCMBIC, &status); return noErr; } case kSERD115KBaud: if (protocol != serial) return noErr; cfsetispeed(&mode, B115200); cfsetospeed(&mode, B115200); tcsetattr(fd, TCSANOW, &mode); return noErr; case kSERD230KBaud: case kSERDSetHighSpeed: if (protocol != serial) return noErr; cfsetispeed(&mode, B230400); cfsetospeed(&mode, B230400); tcsetattr(fd, TCSANOW, &mode); return noErr; default: printf("WARNING: SerialControl(): unimplemented control code %d\n", code); return controlErr; } }
} } // Set MACOS:CREATOR attribute uint32 creator = ReadMacInt32(finfo + fdCreator); if (creator) { tmp_buf[0] = creator >> 24; tmp_buf[1] = creator >> 16; tmp_buf[2] = creator >> 8; tmp_buf[3] = creator; fs_write_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4); } } // Write MACOS:HFS_FLAGS attribute uint16 flags = ReadMacInt16(finfo + fdFlags); if (flags != DEFAULT_FINDER_FLAGS) { tmp_buf[0] = flags >> 8; tmp_buf[1] = flags; fs_write_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2); } else fs_remove_attr(fd, "MACOS:HFS_FLAGS"); // Close file close(fd); } /* * Resource fork emulation functions */
int16 EtherControl(uint32 pb, uint32 dce) { uint16 code = ReadMacInt16(pb + csCode); D(bug("EtherControl %d\n", code)); switch (code) { case 1: // KillIO return -1; case kENetAddMulti: // Add multicast address D(bug("AddMulti %08lx%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4))); if (net_open) return ether_add_multicast(pb); else return noErr; case kENetDelMulti: // Delete multicast address D(bug("DelMulti %08lx%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4))); if (net_open) return ether_del_multicast(pb); else return noErr; case kENetAttachPH: // Attach protocol handler D(bug("AttachPH prot %04x, handler %08lx\n", ReadMacInt16(pb + eProtType), ReadMacInt32(pb + ePointer))); if (net_open) return ether_attach_ph(ReadMacInt16(pb + eProtType), ReadMacInt32(pb + ePointer)); else return noErr; case kENetDetachPH: // Detach protocol handler D(bug("DetachPH prot %04x\n", ReadMacInt16(pb + eProtType))); if (net_open) return ether_detach_ph(ReadMacInt16(pb + eProtType)); else return noErr; case kENetWrite: // Transmit raw Ethernet packet D(bug("EtherWrite\n")); if (ReadMacInt16(ReadMacInt32(pb + ePointer)) < 14) return eLenErr; // Header incomplete if (net_open) return ether_write(ReadMacInt32(pb + ePointer)); else return noErr; case kENetGetInfo: { // Get device information/statistics D(bug("GetInfo buf %08lx, size %d\n", ReadMacInt32(pb + ePointer), ReadMacInt16(pb + eBuffSize))); // Collect info (only ethernet address) uint8 buf[18]; memset(buf, 0, 18); memcpy(buf, ether_addr, 6); // Transfer info to supplied buffer int16 size = ReadMacInt16(pb + eBuffSize); if (size > 18) size = 18; WriteMacInt16(pb + eDataSize, size); // Number of bytes actually written Host2Mac_memcpy(ReadMacInt32(pb + ePointer), buf, size); return noErr; } case kENetSetGeneral: // Set general mode (always in general mode) D(bug("SetGeneral\n")); return noErr; default: printf("WARNING: Unknown EtherControl(%d)\n", code); return controlErr; } }
static __saveds void net_func(void) { const char *str; BYTE od_error; struct MsgPort *write_port = NULL, *control_port = NULL; struct IOSana2Req *write_io = NULL, *control_io = NULL; bool opened = false; ULONG read_mask = 0, write_mask = 0, proc_port_mask = 0; struct Sana2DeviceQuery query_data = {sizeof(Sana2DeviceQuery)}; ULONG buffer_tags[] = { S2_CopyToBuff, (uint32)copy_to_buff, S2_CopyFromBuff, (uint32)copy_from_buff, TAG_END }; // Default: error occured proc_error = true; // Create message port for communication with main task proc_port = CreateMsgPort(); if (proc_port == NULL) goto quit; proc_port_mask = 1 << proc_port->mp_SigBit; // Create message ports for device I/O read_port = CreateMsgPort(); if (read_port == NULL) goto quit; read_mask = 1 << read_port->mp_SigBit; write_port = CreateMsgPort(); if (write_port == NULL) goto quit; write_mask = 1 << write_port->mp_SigBit; control_port = CreateMsgPort(); if (control_port == NULL) goto quit; // Create control IORequest control_io = (struct IOSana2Req *)CreateIORequest(control_port, sizeof(struct IOSana2Req)); if (control_io == NULL) goto quit; control_io->ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug // Parse device name char dev_name[256]; ULONG dev_unit; str = PrefsFindString("ether"); if (str) { const char *FirstSlash = strchr(str, '/'); const char *LastSlash = strrchr(str, '/'); if (FirstSlash && FirstSlash && FirstSlash != LastSlash) { // Device name contains path, i.e. "Networks/xyzzy.device" const char *lp = str; char *dp = dev_name; while (lp != LastSlash) *dp++ = *lp++; *dp = '\0'; if (strlen(dev_name) < 1) goto quit; if (sscanf(LastSlash, "/%ld", &dev_unit) != 1) goto quit; } else { if (sscanf(str, "%[^/]/%ld", dev_name, &dev_unit) != 2) goto quit; } } else goto quit; // Open device control_io->ios2_BufferManagement = buffer_tags; od_error = OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)control_io, 0); if (od_error != 0 || control_io->ios2_Req.io_Device == 0) { printf("WARNING: OpenDevice(<%s>, unit=%d) returned error %d)\n", (UBYTE *)dev_name, dev_unit, od_error); goto quit; } opened = true; // Is it Ethernet? control_io->ios2_Req.io_Command = S2_DEVICEQUERY; control_io->ios2_StatData = (void *)&query_data; DoIO((struct IORequest *)control_io); if (control_io->ios2_Req.io_Error) goto quit; if (query_data.HardwareType != S2WireType_Ethernet) { WarningAlert(GetString(STR_NOT_ETHERNET_WARN)); goto quit; } // Yes, create IORequest for writing write_io = (struct IOSana2Req *)CreateIORequest(write_port, sizeof(struct IOSana2Req)); if (write_io == NULL) goto quit; memcpy(write_io, control_io, sizeof(struct IOSana2Req)); write_io->ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug write_io->ios2_Req.io_Message.mn_ReplyPort = write_port; // Configure Ethernet control_io->ios2_Req.io_Command = S2_GETSTATIONADDRESS; DoIO((struct IORequest *)control_io); memcpy(ether_addr, control_io->ios2_DstAddr, 6); memcpy(control_io->ios2_SrcAddr, control_io->ios2_DstAddr, 6); control_io->ios2_Req.io_Command = S2_CONFIGINTERFACE; DoIO((struct IORequest *)control_io); D(bug("Ethernet address %08lx %08lx\n", *(uint32 *)ether_addr, *(uint16 *)(ether_addr + 4))); // Initialization went well, inform main task proc_error = false; Signal(MainTask, SIGF_SINGLE); // Main loop for (;;) { // Wait for I/O and messages (CTRL_C is used for quitting the task) ULONG sig = Wait(proc_port_mask | read_mask | write_mask | SIGBREAKF_CTRL_C); // Main task wants to quit us if (sig & SIGBREAKF_CTRL_C) break; // Main task sent a command to us if (sig & proc_port_mask) { struct NetMessage *msg; while (msg = (NetMessage *)GetMsg(proc_port)) { D(bug("net_proc received %08lx\n", msg->what)); switch (msg->what) { case MSG_CLEANUP: remove_all_protocols(); break; case MSG_ADD_MULTI: control_io->ios2_Req.io_Command = S2_ADDMULTICASTADDRESS; Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6); DoIO((struct IORequest *)control_io); if (control_io->ios2_Req.io_Error == S2ERR_NOT_SUPPORTED) { WarningAlert(GetString(STR_NO_MULTICAST_WARN)); msg->result = noErr; } else if (control_io->ios2_Req.io_Error) msg->result = eMultiErr; else msg->result = noErr; break; case MSG_DEL_MULTI: control_io->ios2_Req.io_Command = S2_DELMULTICASTADDRESS; Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6); DoIO((struct IORequest *)control_io); if (control_io->ios2_Req.io_Error) msg->result = eMultiErr; else msg->result = noErr; break; case MSG_ATTACH_PH: { uint16 type = msg->type; uint32 handler = msg->pointer; // Protocol of that type already installed? NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next; while ((next = (NetProtocol *)p->ln_Succ) != NULL) { if (p->type == type) { msg->result = lapProtErr; goto reply; } p = next; } // Allocate NetProtocol, set type and handler p = (NetProtocol *)AllocMem(sizeof(NetProtocol), MEMF_PUBLIC); if (p == NULL) { msg->result = lapProtErr; goto reply; } p->type = type; p->handler = handler; // Set up and submit read requests for (int i=0; i<NUM_READ_REQUESTS; i++) { memcpy(p->read_io + i, control_io, sizeof(struct IOSana2Req)); p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Name = (char *)p; // Hide pointer to NetProtocol in node name p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug p->read_io[i].ios2_Req.io_Message.mn_ReplyPort = read_port; p->read_io[i].ios2_Req.io_Command = CMD_READ; p->read_io[i].ios2_PacketType = type; p->read_io[i].ios2_Data = p->read_buf[i]; p->read_io[i].ios2_Req.io_Flags = SANA2IOF_RAW; BeginIO((struct IORequest *)(p->read_io + i)); } // Add protocol to list AddTail(&prot_list, p); // Everything OK msg->result = noErr; break; } case MSG_DETACH_PH: { uint16 type = msg->type; msg->result = lapProtErr; NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next; while ((next = (NetProtocol *)p->ln_Succ) != NULL) { if (p->type == type) { remove_protocol(p); msg->result = noErr; break; } p = next; } break; } case MSG_WRITE: { // Get pointer to Write Data Structure uint32 wds = msg->pointer; write_io->ios2_Data = (void *)wds; // Calculate total packet length long len = 0; uint32 tmp = wds; for (;;) { int16 w = ReadMacInt16(tmp); if (w == 0) break; len += w; tmp += 6; } write_io->ios2_DataLength = len; // Get destination address uint32 hdr = ReadMacInt32(wds + 2); Mac2Host_memcpy(write_io->ios2_DstAddr, hdr, 6); // Get packet type uint32 type = ReadMacInt16(hdr + 12); if (type <= 1500) type = 0; // 802.3 packet write_io->ios2_PacketType = type; // Multicast/broadcard packet? if (write_io->ios2_DstAddr[0] & 1) { if (*(uint32 *)(write_io->ios2_DstAddr) == 0xffffffff && *(uint16 *)(write_io->ios2_DstAddr + 4) == 0xffff) write_io->ios2_Req.io_Command = S2_BROADCAST; else write_io->ios2_Req.io_Command = S2_MULTICAST; } else write_io->ios2_Req.io_Command = CMD_WRITE; // Send packet write_done = false; write_io->ios2_Req.io_Flags = SANA2IOF_RAW; BeginIO((IORequest *)write_io); break; } } reply: D(bug(" net_proc replying\n")); ReplyMsg(msg); } } // Packet received if (sig & read_mask) { D(bug(" packet received, triggering Ethernet interrupt\n")); SetInterruptFlag(INTFLAG_ETHER); TriggerInterrupt(); } // Packet write completed if (sig & write_mask) { GetMsg(write_port); WriteMacInt32(ether_data + ed_Result, write_io->ios2_Req.io_Error ? excessCollsns : 0); write_done = true; D(bug(" packet write done, triggering Ethernet interrupt\n")); SetInterruptFlag(INTFLAG_ETHER); TriggerInterrupt(); } } quit: // Close everything remove_all_protocols(); if (opened) { if (CheckIO((struct IORequest *)write_io) == 0) { AbortIO((struct IORequest *)write_io); WaitIO((struct IORequest *)write_io); } CloseDevice((struct IORequest *)control_io); } if (write_io) DeleteIORequest(write_io); if (control_io) DeleteIORequest(control_io); if (control_port) DeleteMsgPort(control_port); if (write_port) DeleteMsgPort(write_port); if (read_port) DeleteMsgPort(read_port); // Send signal to main task to confirm termination Forbid(); Signal(MainTask, SIGF_SINGLE); }
// !!UNC void init_posix_emu(void) { if(!validate_stat_struct) { ErrorAlert( "Invalid struct my_stat -- edit posix_emu.h" ); QuitEmulator(); } #if DEBUG_EXTFS debug_extfs = PrefsFindInt16("debugextfs"); debug_extfs = DB_EXTFS_LOUD; if(debug_extfs != DB_EXTFS_NONE) { extfs_log_open( EXTFS_LOG_FILE_NAME ); } #endif // We cannot use ExtFS "RootPath" because of the virtual desktop. if(PrefsFindBool("enableextfs")) { PrefsReplaceString("extfs", ""); } else { PrefsRemoveItem("extfs"); D(bug("extfs disabled by user\n")); #if DEBUG_EXTFS extfs_log_close(); #endif return; } const char *extdrives = PrefsFindString("extdrives"); // Set up drive list. size_t outinx = 0; for( TCHAR letter = TEXT('A'); letter <= TEXT('Z'); letter++ ) { if(extdrives && !strchr(extdrives,letter)) continue; TCHAR rootdir[20]; _sntprintf( rootdir, lengthof(rootdir), TEXT("%c:\\"), letter ); use_streams[ letter - 'A' ] = false; switch(GetDriveType(rootdir)) { case DRIVE_FIXED: case DRIVE_REMOTE: case DRIVE_RAMDISK: // TODO: NTFS AFP? // fall case DRIVE_REMOVABLE: case DRIVE_CDROM: if(outinx < lengthof(host_drive_list)) { host_drive_list[outinx] = letter; outinx += 2; } } } // Set up virtual desktop root. // TODO: this should be customizable. GetModuleFileName( NULL, virtual_root, lengthof(virtual_root) ); TCHAR *p = _tcsrchr( virtual_root, TEXT('\\') ); if(p) { _tcscpy( ++p, desktop_name ); } else { // should never happen _sntprintf( virtual_root, lengthof(virtual_root), TEXT("C:\\%s"), desktop_name ); } CreateDirectory( virtual_root, 0 ); // Set up an icon looking like "My Computer" // Can be overwritten just like any other folder custom icon. if(my_access(custom_icon_name,0) != 0) { int fd = my_creat( custom_icon_name, 0 ); if(fd >= 0) { my_close(fd); fd = open_rfork( custom_icon_name, O_RDWR|O_CREAT ); if(fd >= 0) { my_write( fd, my_comp_icon, sizeof(my_comp_icon) ); my_close(fd); static uint8 host_finfo[SIZEOF_FInfo]; uint32 finfo = Host2MacAddr(host_finfo); get_finfo(custom_icon_name, finfo, 0, false); WriteMacInt16(finfo + fdFlags, kIsInvisible); set_finfo(custom_icon_name, finfo, 0, false); get_finfo(my_computer, finfo, 0, true); WriteMacInt16(finfo + fdFlags, ReadMacInt16(finfo + fdFlags) | kHasCustomIcon); set_finfo(my_computer, finfo, 0, true); } else { my_remove(custom_icon_name); } } } }
void NQD_bitblt(uint32 p) { D(bug("accl_bitblt %08x\n", p)); // Get blitting parameters int16 src_X = (int16)ReadMacInt16(p + acclSrcRect + 2) - (int16)ReadMacInt16(p + acclSrcBoundsRect + 2); int16 src_Y = (int16)ReadMacInt16(p + acclSrcRect + 0) - (int16)ReadMacInt16(p + acclSrcBoundsRect + 0); int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); D(bug(" src addr %08x, dest addr %08x\n", ReadMacInt32(p + acclSrcBaseAddr), ReadMacInt32(p + acclDestBaseAddr))); D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y)); D(bug(" width %d, height %d\n", width, height)); // And perform the blit const int bpp = bytes_per_pixel(ReadMacInt32(p + acclSrcPixelSize)); width *= bpp; if ((int32)ReadMacInt32(p + acclSrcRowBytes) > 0) { const int src_row_bytes = (int32)ReadMacInt32(p + acclSrcRowBytes); const int dst_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); uint8 *src = Mac2HostAddr(ReadMacInt32(p + acclSrcBaseAddr) + (src_Y * src_row_bytes) + (src_X * bpp)); uint8 *dst = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dst_row_bytes) + (dest_X * bpp)); for (int i = 0; i < height; i++) { memmove(dst, src, width); src += src_row_bytes; dst += dst_row_bytes; } } else { const int src_row_bytes = -(int32)ReadMacInt32(p + acclSrcRowBytes); const int dst_row_bytes = -(int32)ReadMacInt32(p + acclDestRowBytes); uint8 *src = Mac2HostAddr(ReadMacInt32(p + acclSrcBaseAddr) + ((src_Y + height - 1) * src_row_bytes) + (src_X * bpp)); uint8 *dst = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + ((dest_Y + height - 1) * dst_row_bytes) + (dest_X * bpp)); for (int i = height - 1; i >= 0; i--) { memmove(dst, src, width); src -= src_row_bytes; dst -= dst_row_bytes; } } }