Exemplo n.º 1
0
void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
{
	// Open file
	int fd = open(path, O_WRONLY);
	if (fd < 0)
		return;

	if (!is_dir) {

		// Set BEOS:TYPE attribute
		uint32 type = ReadMacInt32(finfo + fdType);
		if (type) {
			for (int i=0; m2t_translation[i].mime; i++) {
				if (m2t_translation[i].type == type && m2t_translation[i].reversible) {
					fs_write_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, m2t_translation[i].mime, strlen(m2t_translation[i].mime) + 1);
					break;
				}
			}
		}

		// 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);
		}
	}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
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
}
Exemplo n.º 4
0
void Enqueue(uint32 elem, uint32 list)
{
	WriteMacInt32(elem + qLink, 0);
	if (!ReadMacInt32(list + qTail)) {
		WriteMacInt32(list + qHead, elem);
		WriteMacInt32(list + qTail, elem);
	} else {
		WriteMacInt32(ReadMacInt32(list + qTail) + qLink, elem);
		WriteMacInt32(list + qTail, elem);
	}
}
Exemplo n.º 5
0
void *XSERDPort::output_func(void *arg)
{
	XSERDPort *s = (XSERDPort *)arg;
	while (!s->output_thread_cancel) {

		// Wait for commands
		sem_wait(&s->output_signal);
		if (s->quitting)
			break;

		// Execute command
		void *buf = Mac2HostAddr(ReadMacInt32(s->output_pb + ioBuffer));
		uint32 length = ReadMacInt32(s->output_pb + ioReqCount);
		D(bug("output_func transmitting %ld bytes of data...\n", length));

#if MONITOR
		bug("Sending serial data:\n");
		uint8 *adr = (uint8 *)buf;
		for (int i=0; i<length; i++) {
			bug("%02x ", adr[i]);
		}
		bug("\n");
#endif

		int32 actual = write(s->fd, buf, length);
		D(bug(" %ld bytes transmitted\n", actual));

		// KillIO called? Then simply return
		if (s->io_killed) {

			WriteMacInt16(s->output_pb + ioResult, uint16(abortErr));
			WriteMacInt32(s->output_pb + ioActCount, 0);
			s->write_pending = s->write_done = false;

		} else {

			// Set error code
			if (actual >= 0) {
				WriteMacInt32(s->output_pb + ioActCount, actual);
				WriteMacInt32(s->output_dt + serdtResult, noErr);
			} else {
				WriteMacInt32(s->output_pb + ioActCount, 0);
				WriteMacInt32(s->output_dt + serdtResult, uint16(writErr));
			}

			// Trigger serial interrupt
			D(bug(" triggering serial interrupt\n"));
			s->write_done = true;
			SetInterruptFlag(INTFLAG_SERIAL);
			TriggerInterrupt();
		}
	}
	return NULL;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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
}
Exemplo n.º 8
0
int16 ether_write(uint32 wds)
{
	// Set source address
	uint32 hdr = ReadMacInt32(wds + 2);
	memcpy(Mac2HostAddr(hdr + 6), ether_addr, 6);
	return noErr;
}
Exemplo n.º 9
0
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);
				}
			}
		}
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
// 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);
}
Exemplo n.º 12
0
static DWORD WINAPI tick_func(void *arg)
{
	int tick_counter = 0;
	uint64 start = GetTicks_usec();
	int64 ticks = 0;
	uint64 next = GetTicks_usec();

	while (!tick_thread_cancel) {

		// Wait
		next += 16625;
		int64 delay = next - GetTicks_usec();
		if (delay > 0)
			Delay_usec(delay);
		else if (delay < -16625)
			next = GetTicks_usec();
		ticks++;

		// Pseudo Mac 1Hz interrupt, update local time
		if (++tick_counter > 60) {
			tick_counter = 0;
			WriteMacInt32(0x20c, TimerDateTime());
		}

		// Trigger 60Hz interrupt
		if (ReadMacInt32(XLM_IRQ_NEST) == 0) {
			SetInterruptFlag(INTFLAG_VIA);
			TriggerInterrupt();
		}
	}

	uint64 end = GetTicks_usec();
	D(bug("%lu ticks in %lu usec = %f ticks/sec\n", (unsigned long)ticks, (unsigned long)(end - start), ticks * 1000000.0 / (end - start)));
	return 0;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
// 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);
	}
}
Exemplo n.º 15
0
bool NQD_bitblt_hook(uint32 p)
{
	D(bug("accl_draw_hook %08x\n", p));
	NQD_set_dirty_area(p);

	// Check if we can accelerate this bitblt
	if (ReadMacInt32(p + 0x018) + ReadMacInt32(p + 0x128) == 0 &&
		ReadMacInt32(p + 0x130) == 0 &&
		ReadMacInt32(p + acclSrcPixelSize) >= 8 &&
		ReadMacInt32(p + acclSrcPixelSize) == ReadMacInt32(p + acclDestPixelSize) &&
		(int32)(ReadMacInt32(p + acclSrcRowBytes) ^ ReadMacInt32(p + acclDestRowBytes)) >= 0 &&	// same sign?
		ReadMacInt32(p + acclTransferMode) == 0 &&												// srcCopy?
		(int32)ReadMacInt32(p + 0x15c) > 0) {

		// Yes, set function pointer
		WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_NQD_BITBLT));
		return true;
	}
	return false;
}
Exemplo n.º 16
0
void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
{
	struct utimbuf times;
	times.actime = MacTimeToTime(ReadMacInt32(finfo - ioFlFndrInfo + ioFlCrDat));
	times.modtime = MacTimeToTime(ReadMacInt32(finfo - ioFlFndrInfo + ioFlMdDat));

	if (utime(path, &times) < 0) {
		D(bug("utime failed on %s\n", path));
	}

	// Open Finder info file
	int fd = open_finf(path, O_RDWR);
	if (fd < 0)
		return;

	// Write file
	write(fd, Mac2HostAddr(finfo), SIZEOF_FInfo);
	if (fxinfo)
		write(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo);
	close(fd);
}
Exemplo n.º 17
0
bool NQD_fillrect_hook(uint32 p)
{
	D(bug("accl_fillrect_hook %08x\n", p));
	NQD_set_dirty_area(p);

	// Check if we can accelerate this fillrect
	if (ReadMacInt32(p + 0x284) != 0 && ReadMacInt32(p + acclDestPixelSize) >= 8) {
		const int transfer_mode = ReadMacInt32(p + acclTransferMode);
		if (transfer_mode == 8) {
			// Fill
			WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_NQD_FILLRECT));
			return true;
		}
		else if (transfer_mode == 10) {
			// Invert
			WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_NQD_INVRECT));
			return true;
		}
	}
	return false;
}
Exemplo n.º 18
0
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;
	}
}
Exemplo n.º 19
0
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"));
}
Exemplo n.º 20
0
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;
	}
}
Exemplo n.º 21
0
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
}
Exemplo n.º 22
0
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;
}
Exemplo n.º 23
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;
}
Exemplo n.º 24
0
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;
	}
}
Exemplo n.º 25
0
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;
		}
	}
}
Exemplo n.º 26
0
void EnableInterrupt(void)
{
	WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) - 1);
}
Exemplo n.º 27
0
void DisableInterrupt(void)
{
	WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) + 1);
}
Exemplo n.º 28
0
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 {
Exemplo n.º 29
0
__saveds void ASERDPort::serial_func(void)
{
	struct ASERDPort *obj = (ASERDPort *)proc_arg;
	struct MsgPort *proc_port = NULL, *io_port = NULL, *control_port = NULL;
	struct IOExtSer *read_io = NULL, *write_io = NULL, *control_io = NULL;
	uint8 orig_params[sizeof(struct IOExtSer)];
	bool opened = false;
	ULONG io_mask = 0, proc_port_mask = 0;

	// Default: error occured
	obj->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 serial.device I/O
	io_port = CreateMsgPort();
	if (io_port == NULL)
		goto quit;
	io_mask = 1 << io_port->mp_SigBit;
	control_port = CreateMsgPort();
	if (control_port == NULL)
		goto quit;

	// Create IORequests
	read_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer));
	write_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer));
	control_io = (struct IOExtSer *)CreateIORequest(control_port, sizeof(struct IOExtSer));
	if (read_io == NULL || write_io == NULL || control_io == NULL)
		goto quit;
	read_io->IOSer.io_Message.mn_Node.ln_Type = 0;	// Avoid CheckIO() bug
	write_io->IOSer.io_Message.mn_Node.ln_Type = 0;
	control_io->IOSer.io_Message.mn_Node.ln_Type = 0;

	// Parse device name
	char dev_name[256];
	ULONG dev_unit;
	if (sscanf(obj->device_name, "%[^/]/%ld", dev_name, &dev_unit) < 2)
		goto quit;

	// Open device
	if (obj->is_parallel)
		((IOExtPar *)read_io)->io_ParFlags = PARF_SHARED;
	else
		read_io->io_SerFlags = SERF_SHARED | SERF_7WIRE;
	if (OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)read_io, 0) || read_io->IOSer.io_Device == NULL)
		goto quit;
	opened = true;

	// Copy IORequests
	memcpy(write_io, read_io, sizeof(struct IOExtSer));
	memcpy(control_io, read_io, sizeof(struct IOExtSer));

	// Attach control_io to control_port and set default values
	control_io->IOSer.io_Message.mn_ReplyPort = control_port;
	if (!obj->is_parallel) {
		control_io->io_CtlChar = SER_DEFAULT_CTLCHAR;
		control_io->io_RBufLen = 64;
		control_io->io_ExtFlags = 0;
		control_io->io_Baud = 9600;
		control_io->io_BrkTime = 250000;
		control_io->io_ReadLen = control_io->io_WriteLen = 8;
		control_io->io_StopBits = 1;
		control_io->io_SerFlags = SERF_SHARED;
		control_io->IOSer.io_Command = SDCMD_SETPARAMS;
		DoIO((struct IORequest *)control_io);
		memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
	}

	// Initialization went well, inform main task
	obj->proc_port = proc_port;
	obj->control_io = control_io;
	obj->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 | io_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 SerMessage *msg;
			while (msg = (SerMessage *)GetMsg(proc_port)) {
				D(bug("serial_proc received %08lx\n", msg->what));
				switch (msg->what) {
					case MSG_QUERY:
						control_io->IOSer.io_Command = SDCMD_QUERY;
						DoIO((struct IORequest *)control_io);
						D(bug(" query returned %08lx, actual %08lx\n", control_io->IOSer.io_Error, control_io->IOSer.io_Actual));
						break;

					case MSG_SET_PARAMS:
						// Only send SDCMD_SETPARAMS when configuration has changed
						if (memcmp(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar))) {
							memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
							memcpy(&(read_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
							memcpy(&(write_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
							control_io->IOSer.io_Command = SDCMD_SETPARAMS;
							D(bug(" params %08lx %08lx %08lx %08lx %08lx %08lx\n", control_io->io_CtlChar, control_io->io_RBufLen, control_io->io_ExtFlags, control_io->io_Baud, control_io->io_BrkTime, *(uint32 *)((uint8 *)control_io + 76)));
							DoIO((struct IORequest *)control_io);
							D(bug(" set_parms returned %08lx\n", control_io->IOSer.io_Error));
						}
						break;

					case MSG_SET_PAR_PARAMS:
						control_io->IOSer.io_Command = PDCMD_SETPARAMS;
						DoIO((struct IORequest *)control_io);
						D(bug(" set_par_parms returned %08lx\n", control_io->IOSer.io_Error));
						break;

					case MSG_BREAK:
						control_io->IOSer.io_Command = SDCMD_BREAK;
						DoIO((struct IORequest *)control_io);
						D(bug(" break returned %08lx\n", control_io->IOSer.io_Error));
						break;

					case MSG_RESET:
						control_io->IOSer.io_Command = CMD_RESET;
						DoIO((struct IORequest *)control_io);
						D(bug(" reset returned %08lx\n", control_io->IOSer.io_Error));
						break;

					case MSG_KILL_IO:
						AbortIO((struct IORequest *)read_io);
						AbortIO((struct IORequest *)write_io);
						WaitIO((struct IORequest *)read_io);
						WaitIO((struct IORequest *)write_io);
						obj->read_pending = obj->write_pending = false;
						obj->read_done = obj->write_done = false;
						break;

					case MSG_PRIME_IN:
						read_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb;
						read_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
						read_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount);
						read_io->IOSer.io_Actual = 0;
						read_io->IOSer.io_Command = CMD_READ;
						D(bug("serial_proc receiving %ld bytes from %08lx\n", read_io->IOSer.io_Length, read_io->IOSer.io_Data));
						SendIO((struct IORequest *)read_io);
						break;

					case MSG_PRIME_OUT: {
						write_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb;
						write_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
						write_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount);
						write_io->IOSer.io_Actual = 0;
						write_io->IOSer.io_Command = CMD_WRITE;
						D(bug("serial_proc transmitting %ld bytes from %08lx\n", write_io->IOSer.io_Length, write_io->IOSer.io_Data));
#if MONITOR
						bug("Sending serial data:\n");
						uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
						for (int i=0; i<len; i++) {
							bug("%02lx ", adr[i]);
						}
						bug("\n");
#endif
						SendIO((struct IORequest *)write_io);
						break;
					}
				}
				D(bug(" serial_proc replying\n"));
				ReplyMsg(msg);
			}
		}

		// I/O operation completed
		if (sig & io_mask) {
			struct IOExtSer *io;
			while (io = (struct IOExtSer *)GetMsg(io_port)) {
				if (io == read_io) {
					D(bug("read_io complete, %ld bytes received, error %ld\n", read_io->IOSer.io_Actual, read_io->IOSer.io_Error));
					uint32 pb = (uint32)read_io->IOSer.io_Message.mn_Node.ln_Name;
#if MONITOR
					bug("Receiving serial data:\n");
					uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
					for (int i=0; i<read_io->IOSer.io_Actual; i++) {
						bug("%02lx ", adr[i]);
					}
					bug("\n");
#endif
					WriteMacInt32(pb + ioActCount, read_io->IOSer.io_Actual);
					obj->conv_error(read_io, obj->input_dt);
					obj->read_done = true;
					SetInterruptFlag(INTFLAG_SERIAL);
					TriggerInterrupt();
				} else if (io == write_io) {
					D(bug("write_io complete, %ld bytes sent, error %ld\n", write_io->IOSer.io_Actual, write_io->IOSer.io_Error));
					uint32 pb = (uint32)write_io->IOSer.io_Message.mn_Node.ln_Name;
					WriteMacInt32(pb + ioActCount, write_io->IOSer.io_Actual);
					obj->conv_error(write_io, obj->output_dt);
					obj->write_done = true;
					SetInterruptFlag(INTFLAG_SERIAL);
					TriggerInterrupt();
				}
			}
		}
	}
quit:

	// Close everything
	if (opened) {
		if (CheckIO((struct IORequest *)write_io) == 0) {
			AbortIO((struct IORequest *)write_io);
			WaitIO((struct IORequest *)write_io);
		}
		if (CheckIO((struct IORequest *)read_io) == 0) {
			AbortIO((struct IORequest *)read_io);
			WaitIO((struct IORequest *)read_io);
		}
		CloseDevice((struct IORequest *)read_io);
	}
	if (control_io)
		DeleteIORequest(control_io);
	if (write_io)
		DeleteIORequest(write_io);
	if (read_io)
		DeleteIORequest(read_io);
	if (control_port)
		DeleteMsgPort(control_port);
	if (io_port)
		DeleteMsgPort(io_port);

	// Send signal to main task to confirm termination
	Forbid();
	Signal(MainTask, SIGF_SINGLE);
}
Exemplo n.º 30
0
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);
}