// 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); }
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); } } } }
void GetScrap(void **handle, uint32 type, int32 offset) { #if defined(__LP64__) D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset)); #warning Carbon scrapbook function are not implemented in 64-bit mode #else D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset)); ScrapRef theScrap; if (GetCurrentScrap(&theScrap) != noErr) { D(bug(" could not open scrap\n")); return; } Size byteCount; if (GetScrapFlavorSize(theScrap, type, &byteCount) == noErr) { // Allocate space for new scrap in MacOS side M68kRegisters r; r.d[0] = byteCount; Execute68kTrap(0xa71e, &r); // NewPtrSysClear() uint32 scrap_area = r.a[0]; // Get the native clipboard data if (scrap_area) { uint8 * const data = Mac2HostAddr(scrap_area); if (GetScrapFlavorData(theScrap, type, &byteCount, data) == noErr) { SwapScrapData(type, data, byteCount, FALSE); // Add new data to clipboard static uint8 proc[] = { 0x59, 0x8f, // subq.l #4,sp 0xa9, 0xfc, // ZeroScrap() 0x2f, 0x3c, 0, 0, 0, 0, // move.l #length,-(sp) 0x2f, 0x3c, 0, 0, 0, 0, // move.l #type,-(sp) 0x2f, 0x3c, 0, 0, 0, 0, // move.l #outbuf,-(sp) 0xa9, 0xfe, // PutScrap() 0x58, 0x8f, // addq.l #4,sp M68K_RTS >> 8, M68K_RTS & 0xff }; r.d[0] = sizeof(proc); Execute68kTrap(0xa71e, &r); // NewPtrSysClear() uint32 proc_area = r.a[0]; if (proc_area) { Host2Mac_memcpy(proc_area, proc, sizeof(proc)); WriteMacInt32(proc_area + 6, byteCount); WriteMacInt32(proc_area + 12, type); WriteMacInt32(proc_area + 18, scrap_area); we_put_this_data = true; Execute68k(proc_area, &r); r.a[0] = proc_area; Execute68kTrap(0xa01f, &r); // DisposePtr } } r.a[0] = scrap_area; Execute68kTrap(0xa01f, &r); // DisposePtr }
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 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 }
uint32 FindLibSymbol(const char *lib_str, const char *sym_str) { SheepVar32 conn_id = 0; SheepVar32 main_addr = 0; SheepArray<256> err; WriteMacInt8(err.addr(), 0); SheepVar32 sym_addr = 0; SheepVar32 sym_class = 0; SheepString lib(lib_str); SheepString sym(sym_str); D(bug("FindLibSymbol %s in %s...\n", sym.value()+1, lib.value()+1)); if (ReadMacInt32(XLM_RUN_MODE) == MODE_EMUL_OP) { M68kRegisters r; // Find shared library static const uint8 proc1_template[] = { 0x55, 0x8f, // subq.l #2,a7 0x2f, 0x08, // move.l a0,-(a7) 0x2f, 0x3c, 0x70, 0x77, 0x70, 0x63, // move.l #'pwpc',-(a7) 0x2f, 0x3c, 0x00, 0x00, 0x00, 0x01, // move.l #kReferenceCFrag,-(a7) 0x2f, 0x09, // move.l a1,-(a7) 0x2f, 0x0a, // move.l a2,-(a7) 0x2f, 0x0b, // move.l a3,-(a7) 0x3f, 0x3c, 0x00, 0x01, // (GetSharedLibrary) 0xaa, 0x5a, // CFMDispatch 0x30, 0x1f, // move.w (a7)+,d0 M68K_RTS >> 8, M68K_RTS & 0xff }; BUILD_SHEEPSHAVER_PROCEDURE(proc1); r.a[0] = lib.addr(); r.a[1] = conn_id.addr(); r.a[2] = main_addr.addr(); r.a[3] = err.addr(); Execute68k(proc1, &r); D(bug(" GetSharedLibrary: ret %d, connection ID %ld, main %p\n", (int16)r.d[0], conn_id.value(), main_addr.value())); if (r.d[0]) return 0; // Find symbol static const uint8 proc2_template[] = { 0x55, 0x8f, // subq.l #2,a7 0x2f, 0x00, // move.l d0,-(a7) 0x2f, 0x08, // move.l a0,-(a7) 0x2f, 0x09, // move.l a1,-(a7) 0x2f, 0x0a, // move.l a2,-(a7) 0x3f, 0x3c, 0x00, 0x05, // (FindSymbol) 0xaa, 0x5a, // CFMDispatch 0x30, 0x1f, // move.w (a7)+,d0 M68K_RTS >> 8, M68K_RTS & 0xff }; BUILD_SHEEPSHAVER_PROCEDURE(proc2); r.d[0] = conn_id.value(); r.a[0] = sym.addr(); r.a[1] = sym_addr.addr(); r.a[2] = sym_class.addr(); Execute68k(proc2, &r); D(bug(" FindSymbol1: ret %d, sym_addr %p, sym_class %ld\n", (int16)r.d[0], sym_addr.value(), sym_class.value())); //!! CloseConnection()? if (r.d[0]) return 0; else return sym_addr.value(); } else {
void ExecuteNative(int selector) { M68kRegisters r; Execute68k(NativeRoutineDescriptor(selector), &r); }
void GetScrap(void **handle, uint32 type, int32 offset) { M68kRegisters r; D(bug("GetScrap handle %p, type %08lx, offset %ld\n", handle, type, offset)); return; //!! GetScrap is currently broken (should use Clipboard Manager) //!! replace with clipboard notification in BeOS R4.1 switch (type) { case 'TEXT': D(bug(" clipping TEXT\n")); if (be_clipboard->Lock()) { BMessage *clipper = be_clipboard->Data(); char *clip; ssize_t length; // Check if we already copied this data if (clipper->HasData("application/x-SheepShaver-cookie", B_MIME_TYPE)) return; bigtime_t cookie = system_time(); clipper->AddData("application/x-SheepShaver-cookie", B_MIME_TYPE, &cookie, sizeof(bigtime_t)); // No, is there text in it? if (clipper->FindData("text/plain", B_MIME_TYPE, &clip, &length) == B_OK) { D(bug(" text/plain found\n")); // Convert text from UTF-8 to Mac charset int32 src_length = length; int32 dest_length = length; int32 state = 0; char *outbuf = new char[dest_length]; if (convert_from_utf8(B_MAC_ROMAN_CONVERSION, clip, &src_length, outbuf, &dest_length, &state) == B_OK) { for (int i=0; i<dest_length; i++) if (outbuf[i] == 10) outbuf[i] = 13; // Add text to Mac clipboard static uint16 proc[] = { 0x598f, // subq.l #4,sp 0xa9fc, // ZeroScrap() 0x2f3c, 0, 0, // move.l #length,-(sp) 0x2f3c, 'TE', 'XT', // move.l #'TEXT',-(sp) 0x2f3c, 0, 0, // move.l #outbuf,-(sp) 0xa9fe, // PutScrap() 0x588f, // addq.l #4,sp M68K_RTS }; *(int32 *)(proc + 3) = dest_length; *(char **)(proc + 9) = outbuf; we_put_this_data = true; Execute68k((uint32)proc, &r); } else { D(bug(" text conversion failed\n")); } delete[] outbuf; } be_clipboard->Commit(); be_clipboard->Unlock(); } break; case 'PICT': D(bug(" clipping PICT\n")); if (be_clipboard->Lock()) { BMessage *clipper = be_clipboard->Data(); char *clip; ssize_t length; // Check if we already copied this data if (clipper->HasData("application/x-SheepShaver-cookie", B_MIME_TYPE)) return; bigtime_t cookie = system_time(); clipper->AddData("application/x-SheepShaver-cookie", B_MIME_TYPE, &cookie, sizeof(bigtime_t)); static uint16 proc2[] = { 0x598f, // subq.l #4,sp 0xa9fc, // ZeroScrap() 0x2f3c, 0, 0, // move.l #length,-(sp) 0x2f3c, 'PI', 'CT', // move.l #'PICT',-(sp) 0x2f3c, 0, 0, // move.l #buf,-(sp) 0xa9fe, // PutScrap() 0x588f, // addq.l #4,sp M68K_RTS }; // No, is there a pict ? if (clipper->FindData("image/pict", B_MIME_TYPE, &clip, &length) == B_OK ) { D(bug(" image/pict found\n")); // Add pict to Mac clipboard *(int32 *)(proc2 + 3) = length; *(char **)(proc2 + 9) = clip; we_put_this_data = true; Execute68k((uint32)proc2, &r); #if 0 // No, is there a bitmap ? } else if (clipper->FindData("image/x-be-bitmap", B_MIME_TYPE, &clip, &length) == B_OK || output_cap > 0) { D(bug(" image/x-be-bitmap found\nstarting conversion to PICT\n")); BMemoryIO *in_buffer = new BMemoryIO(clip, length); BMallocIO *out_buffer = new BMallocIO(); status_t result=roster->Translate(output_trans,in_buffer,NULL,out_buffer,'PICT'); D(bug("result of conversion:%08x buffer_size:%d\n",result,out_buffer->BufferLength())); // Add pict to Mac clipboard *(int32 *)(proc2 + 3) = out_buffer->BufferLength(); *(char **)(proc2 + 9) = (char *)out_buffer->Buffer(); we_put_this_data = true; Execute68k(proc2, &r); delete in_buffer; delete out_buffer; #endif } be_clipboard->Commit(); be_clipboard->Unlock(); } break; } }