Example #1
0
int lifepoll::inner_poll() {
  // AKT: bailIfCalculating() ;
  if (isCalculating()) {
    // AKT: better to simply ignore user event???
    // lifefatal("recursive poll called.") ;
    return interrupted ;
  }
  countdown = POLLINTERVAL ;
  calculating++ ;
  if (!interrupted)
    interrupted = checkevents() ;
  calculating-- ;
  return interrupted ;
}
Example #2
0
static int dev_do_io_2 (struct s2devstruct *dev, uaecptr request, int quick)
{
	uae_u8 flags = get_byte (request + 30);
	uae_u32 command = get_word (request + 28);
	uae_u32 packettype = get_long (request + 32 + 4);
	uaecptr data = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4);
	uae_u32 datalength = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2);
	uaecptr srcaddr = request + 32 + 4 + 4;
	uaecptr dstaddr = request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES;
	uaecptr statdata = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4);
	uaecptr buffermgmt = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4);
	uae_u32 io_error = 0;
	uae_u32 wire_error = 0;
	int i;
	int async = 0;
	struct priv_s2devstruct *pdev = getps2devstruct (request);

	if (log_net)
		write_log (_T("S2: C=%02d T=%04X S=%02X%02X%02X%02X%02X%02X D=%02X%02X%02X%02X%02X%02X L=%d D=%08X SD=%08X BM=%08X\n"),
		command, packettype,
		get_byte (srcaddr + 0), get_byte (srcaddr + 1), get_byte (srcaddr + 2), get_byte (srcaddr + 3), get_byte (srcaddr + 4), get_byte (srcaddr + 5),
		get_byte (dstaddr + 0), get_byte (dstaddr + 1), get_byte (dstaddr + 2), get_byte (dstaddr + 3), get_byte (dstaddr + 4), get_byte (dstaddr + 5), 
		datalength, data, statdata, buffermgmt);

	if (command == CMD_READ || command == S2_READORPHAN || command == CMD_WRITE || command == S2_BROADCAST || command == S2_MULTICAST) {
		if (!pdev->copyfrombuff || !pdev->copytobuff) {
			io_error = S2ERR_BAD_ARGUMENT;
			wire_error = S2WERR_BUFF_ERROR;
			goto end;
		}
	}

	switch (command)
	{
	case CMD_READ:
		if (!dev->online)
			goto offline;
		async = 1;
		break;

	case S2_READORPHAN:
		if (!dev->online)
			goto offline;
		async = 1;
		break;

	case S2_BROADCAST:
	case CMD_WRITE:
		if (!dev->online)
			goto offline;
		if (!checksize (request, dev))
			goto toobig;
		async = 1;
		break;

	case S2_MULTICAST:
		if (!dev->online)
			goto offline;
		if ((get_byte (dstaddr + 0) & 1) == 0) {
			io_error = S2ERR_BAD_ADDRESS;
			wire_error = S2WERR_BAD_MULTICAST;
			goto end;
		}
		if (!checksize (request, dev))
			goto toobig;
		async = 1;
		break;

	case CMD_FLUSH:
		dev->flush_timeout_cnt = 0;
		dev->flush_timeout = FLUSH_TIMEOUT;
		if (log_net)
			write_log (_T("CMD_FLUSH started %08x\n"), request);
		uae_sem_wait (&async_sem);
		flush (pdev);
		uae_sem_post (&async_sem);
		async = 1;
		uaenet_vsync_requested++;
		break;

	case S2_ADDMULTICASTADDRESS:
		addmulticastaddresses (dev, amigaaddrto64 (srcaddr), 0);
		break;
	case S2_DELMULTICASTADDRESS:
		if (!delmulticastaddresses (dev, amigaaddrto64 (srcaddr), 0)) {
			io_error = S2ERR_BAD_STATE;
			wire_error = S2WERR_BAD_MULTICAST;
		}
		break;
	case S2_ADDMULTICASTADDRESSES:
		addmulticastaddresses (dev, amigaaddrto64 (srcaddr), amigaaddrto64 (dstaddr));
		break;
	case S2_DELMULTICASTADDRESSES:
		if (!delmulticastaddresses (dev, amigaaddrto64 (srcaddr), amigaaddrto64 (dstaddr))) {
			io_error = S2ERR_BAD_STATE;
			wire_error = S2WERR_BAD_MULTICAST;
		}
		break;

	case S2_DEVICEQUERY:
		{
			int size = get_long (statdata);
			if (size > 30)
				size = 30;
			put_long (statdata + 4, size);
			if (size >= 12)
				put_long (statdata + 8, 0);
			if (size >= 16)
				put_long (statdata + 12, 0);
			if (size >= 18)
				put_word (statdata + 16, ADDR_SIZE * 8);
			if (size >= 22)
				put_long (statdata + 18, dev->td->mtu);
			if (size >= 26)
				put_long (statdata + 22, 10000000);
			if (size >= 30)
				put_long (statdata + 26, S2WireType_Ethernet);
		}
		break;

	case S2_GETTYPESTATS:
		if (pdev->trackcnt) {
			put_long (statdata + 0, pdev->packetssent);
			put_long (statdata + 4, pdev->packetsreceived);
			put_long (statdata + 8, pdev->bytessent);
			put_long (statdata + 12, pdev->bytesreceived);
			put_long (statdata + 16, pdev->packetsdropped);
		} else {
			io_error = S2ERR_BAD_STATE;
			wire_error = S2WERR_NOT_TRACKED;
		}
		break;

	case S2_GETGLOBALSTATS:
		put_long (statdata + 0, dev->packetsreceived);
		put_long (statdata + 4, dev->packetssent);
		put_long (statdata + 8, dev->baddata);
		put_long (statdata + 12, dev->overruns);
		put_long (statdata + 16, 0);
		put_long (statdata + 20, dev->unknowntypesreceived);
		put_long (statdata + 24, dev->reconfigurations);
		put_long (statdata + 28, dev->online_secs);
		put_long (statdata + 32, dev->online_micro);
		break;

	case S2_GETSPECIALSTATS:
		put_long (statdata + 1, 0);
		break;

	case S2_GETSTATIONADDRESS:
		for (i = 0; i < ADDR_SIZE; i++) {
			put_byte (srcaddr + i, dev->td->mac[i]);
			put_byte (dstaddr + i, dev->td->mac[i]);
		}
		break;

	case S2_CONFIGINTERFACE:
		if (dev->configured) {
			io_error = S2ERR_BAD_STATE;
			wire_error = S2WERR_IS_CONFIGURED;
		} else {
			dev->configured = TRUE;
		}
		break;

	case S2_ONLINE:
		if (!dev->configured) {
			io_error = S2ERR_BAD_STATE;
			wire_error = S2WERR_NOT_CONFIGURED;
		}
		if (!dev->adapter) {
			io_error = S2ERR_OUTOFSERVICE;
			wire_error = S2WERR_RCVREL_HDW_ERR;
		}
		if (!io_error) {
			uaenet_vsync_requested++;
			async = 1;
		}
		break;

	case S2_TRACKTYPE:
		if (packettype <= 65535) {
			if (pdev->tracks[packettype]) {
				io_error = S2ERR_BAD_STATE;
				wire_error = S2WERR_ALREADY_TRACKED;
			} else {
				pdev->tracks[packettype] = 1;
				pdev->trackcnt++;
			}
		} else {
			io_error = S2ERR_BAD_ARGUMENT;
		}
		break;
	case S2_UNTRACKTYPE:
		if (packettype <= 65535) {
			if (!pdev->tracks[packettype]) {
				io_error = S2ERR_BAD_STATE;
				wire_error = S2WERR_NOT_TRACKED;
			} else {
				pdev->tracks[packettype] = 0;
				pdev->trackcnt--;
			}
		} else {
			io_error = S2ERR_BAD_ARGUMENT;
		}
		break;

	case S2_OFFLINE:
		if (dev->online) {
			dev->online = 0;
			checkevents (dev, S2EVENT_OFFLINE, 1);
		}
		break;

	case S2_ONEVENT:
		{
			uae_u32 events;
			uae_u32 wanted_events = get_long (request + 32);
			if (wanted_events & ~KNOWN_EVENTS) {
				io_error = S2ERR_NOT_SUPPORTED;
				events = S2WERR_BAD_EVENT;
			} else {
				if (dev->online)
					events = S2EVENT_ONLINE;
				else
					events = S2EVENT_OFFLINE;
				events &= wanted_events;
				if (events) {
					wire_error = events;
				} else {
					async = 1;
				}
			}
		}
		break;

	default:
		io_error = IOERR_NOCMD;
		break;

offline:
		io_error = S2ERR_OUTOFSERVICE;
		wire_error = S2WERR_UNIT_OFFLINE;
		break;
toobig:
		io_error = S2ERR_MTU_EXCEEDED;
		wire_error = S2WERR_GENERIC_ERROR;
		break;

	}
end:
	if (log_net && (io_error || wire_error))
		write_log (_T("-> %d (%d)\n"), io_error, wire_error);
	put_long (request + 32, wire_error);
	put_byte (request + 31, io_error);
	return async;
}
Example #3
0
static uae_u32 REGPARAM2 uaenet_int_handler (TrapContext *ctx)
{
	int i, j;
	int gotit;
	struct asyncreq *ar;

	if (uae_sem_trywait (&async_sem)) {
		uaenet_int_requested = 0;
		uaenet_int_late = 1;
		return 0;
	}
	for (i = 0; i < MAX_OPEN_DEVICES; i++)
		pdevst[i].tmp = 0;

	for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) {
		struct s2devstruct *dev = &devst[i];
		struct s2packet *p;
		if (dev->online) {
			while (dev->readqueue) {
				uae_u16 type;
				p = dev->readqueue;
				type = (p->data[2 * ADDR_SIZE] << 8) | p->data[2 * ADDR_SIZE + 1];
				ar = dev->ar;
				gotit = 0;
				while (ar) {
					if (!ar->ready) {
						uaecptr request = ar->request;
						int command = get_word (request + 28);
						uae_u32 packettype = get_long (request + 32 + 4);
						if (command == CMD_READ && (packettype == type || (packettype <= 1500 && type <= 1500))) {
							struct priv_s2devstruct *pdev = getps2devstruct (request);
							if (pdev && pdev->tmp == 0) {
								if (handleread (ctx, pdev, request, p->data, p->len, command)) {
									if (log_net)
										write_log (_T("-> %p Accepted, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len);
									ar->ready = 1;
									write_comm_pipe_u32 (&dev->requests, request, 1);
									dev->packetsreceived++;
									gotit = 1;
									pdev->tmp = 1;
								} else {
									if (log_net)
										write_log (_T("-> %p PacketFilter() rejected, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len);
									pdev->tmp = -1;
								}
							}
						}
					}
					ar = ar->next;
				}
				ar = dev->ar;
				while (ar) {
					if (!ar->ready) {
						uaecptr request = ar->request;
						int command = get_word (request + 28);
						if (command == S2_READORPHAN) {
							struct priv_s2devstruct *pdev = getps2devstruct (request);
							if (pdev && pdev->tmp <= 0) {
								if (log_net)
									write_log (_T("-> %p Accepted, S2_READORPHAN, REQ=%08X LEN=%d\n"), p, request, p->len);
								handleread (ctx, pdev, request, p->data, p->len, command);
								ar->ready = 1;
								write_comm_pipe_u32 (&dev->requests, request, 1);
								dev->packetsreceived++;
								dev->unknowntypesreceived++;
								gotit = 1;
								pdev->tmp = 1;
							}
						}
					}
					ar = ar->next;
				}
				if (!gotit) {
					if (log_net)
						write_log (_T("-> %p packet dropped, LEN=%d\n"), p, p->len);
					for (j = 0; j < MAX_OPEN_DEVICES; j++) {
						if (pdevst[j].unit == dev->unit) {
							if (pdevst[j].tracks[type])
								pdevst[j].packetsdropped++;
						}
					}
				}
				dev->readqueue = dev->readqueue->next;
				freepacket (p);
			}
		} else {
			while (dev->readqueue) {
				p = dev->readqueue;
				dev->readqueue = dev->readqueue->next;
				freepacket (p);
			}
		}

		ar = dev->ar;
		while (ar) {
			if (!ar->ready) {
				uaecptr request = ar->request;
				int command = get_word (request + 28);
				if (command == S2_ONLINE) {
					struct priv_s2devstruct *pdev = getps2devstruct (request);
					dev->packetsreceived = 0;
					dev->packetssent = 0;
					dev->baddata = 0;
					dev->overruns = 0;
					dev->unknowntypesreceived = 0;
					dev->reconfigurations = 0;
					if (pdev && pdev->timerbase) {
						m68k_areg (regs, 0) = pdev->tempbuf;
						CallLib (ctx, pdev->timerbase, -0x42); /* GetSysTime() */
					} else {
						put_long (pdev->tempbuf + 0, 0);
						put_long (pdev->tempbuf + 4, 0);
					}
					dev->online_secs = get_long (pdev->tempbuf + 0);
					dev->online_micro = get_long (pdev->tempbuf + 4);
					checkevents (dev, S2EVENT_ONLINE, 0);
					dev->online = 1;
					ar->ready = 1;
					write_comm_pipe_u32 (&dev->requests, request, 1);
					uaenet_vsync_requested--;
				} else if (command == CMD_FLUSH) {
					/* do not reply CMD_FLUSH until all other requests are gone */
					if (dev->ar->next == NULL) {
						if (log_net)
							write_log (_T("CMD_FLUSH replied %08x\n"), request);
						ar->ready = 1;
						write_comm_pipe_u32 (&dev->requests, request, 1);
						uaenet_vsync_requested--;
					} else {
						struct priv_s2devstruct *pdev = getps2devstruct (request);
						if (pdev) {
							dev->flush_timeout--;
							if (dev->flush_timeout <= 0) {
								dev->flush_timeout = FLUSH_TIMEOUT;
								if (dev->flush_timeout_cnt > 1)
									write_log (_T("WARNING: %s:%d CMD_FLUSH possibly frozen..\n"), getdevname(), pdev->unit);
								dev->flush_timeout_cnt++;
								flush (pdev);
							}
						}
					}
				}
			}
			ar = ar->next;
		}
	}
	if (uaenet_int_late)
		uaenet_int_requested = 1;
	else
		uaenet_int_requested = 0;
	uaenet_int_late = 0;
	uae_sem_post (&async_sem);
	return 0;
}