示例#1
0
文件: ethernet.c 项目: GNUHurdTR/hurd
/* Transmit an ethernet frame */
int
ethernet_xmit (struct sk_buff *skb, struct device *dev)
{
  error_t err;
  struct ether_device *edev = (struct ether_device *) dev->priv;
  u_int count;
  u_int tried = 0;

  do
    {
      tried++;
      err = device_write (edev->ether_port, D_NOWAIT, 0, skb->data, skb->len, &count);
      if (err == EMACH_SEND_INVALID_DEST || err == EMIG_SERVER_DIED)
	{
	  /* Device probably just died, try to reopen it.  */

	  if (tried == 2)
	    /* Too many tries, abort */
	    break;

	  ethernet_close (dev);
	  ethernet_open (dev);
	}
      else
	{
	  assert_perror (err);
	  assert (count == skb->len);
	}
    }
  while (err);

  dev_kfree_skb (skb);
  return 0;
}
示例#2
0
static uae_u32 REGPARAM2 dev_close_2 (TrapContext *context)
{
	uae_u32 request = m68k_areg (regs, 1);
	struct priv_s2devstruct *pdev = getps2devstruct (request);
	struct s2devstruct *dev;

	if (!pdev) {
		write_log (_T("%s close with unknown request %08X!?\n"), SANA2NAME, request);
		return 0;
	}
	dev = gets2devstruct (pdev->unit);
	if (!dev) {
		write_log (_T("%s:%d close with unknown request %08X!?\n"), SANA2NAME, pdev->unit, request);
		return 0;
	}
	if (log_net)
		write_log (_T("%s:%d close, open=%d req=%08X\n"), SANA2NAME, pdev->unit, dev->opencnt, request);
	put_long (request + 24, 0);
	dev->opencnt--;
	pdev->inuse = 0;
	if (!dev->opencnt) {
		dev->exclusive = 0;
		if (pdev->tempbuf) {
			m68k_areg (regs, 1) = pdev->tempbuf;
			m68k_dreg (regs, 0) = pdev->td->mtu + ETH_HEADER_SIZE + 2;
			CallLib (context, get_long (4), -0xD2); /* FreeMem */
			pdev->tempbuf = 0;
		}
		ethernet_close (pdev->td, dev->sysdata);
		xfree (dev->sysdata);
		dev->sysdata = NULL;
		write_comm_pipe_u32 (&dev->requests, 0, 1);
		write_log (_T("%s: opencnt == 0, all instances closed\n"), SANA2NAME);
	}
	put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) - 1);
	return 0;
}
示例#3
0
static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context)
{
	uaecptr ioreq = m68k_areg (regs, 1);
	uae_u32 unit = m68k_dreg (regs, 0);
	uae_u32 flags = m68k_dreg (regs, 1);
	uaecptr buffermgmt;
	struct s2devstruct *dev = gets2devstruct (unit);
	struct priv_s2devstruct *pdev = 0;
	int i;
	uaecptr tagp, tagpnext;

	if (!dev)
		return openfail (ioreq, IOERR_OPENFAIL);
	if (!initint(context))
		return openfail (ioreq, IOERR_SELFTEST);
	if (log_net)
		write_log (_T("opening %s:%d opencnt=%d ioreq=%08X\n"), SANA2NAME, unit, dev->opencnt, ioreq);
	if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE)
		return openfail (ioreq, IOERR_BADLENGTH);
	if ((flags & SANA2OPF_PROM) && dev->opencnt > 0)
		return openfail (ioreq, IOERR_UNITBUSY);

	for (i = 0; i < MAX_OPEN_DEVICES; i++) {
		pdev = &pdevst[i];
		if (pdev->inuse == 0)
			break;
	}
	if (i == MAX_OPEN_DEVICES)
		return openfail (ioreq, IOERR_UNITBUSY);

	put_long (ioreq + 24, pdev - pdevst);
	pdev->unit = unit;
	pdev->flags = flags;
	pdev->inuse = 1;
	pdev->td = td ? td[unit] : NULL;
	pdev->promiscuous = (flags & SANA2OPF_PROM) ? 1 : 0;

	if (pdev->td == NULL || pdev->td->active == 0)
		return openfail (ioreq, IOERR_OPENFAIL);

	if (dev->opencnt == 0) {
		dev->unit = unit;
		dev->sysdata = xcalloc (uae_u8, ethernet_getdatalenght (pdev->td));
		if (!ethernet_open (pdev->td, dev->sysdata, dev, uaenet_gotdata, uaenet_getdata, pdev->promiscuous)) {
			xfree (dev->sysdata);
			dev->sysdata = NULL;
			return openfail (ioreq, IOERR_OPENFAIL);
		}
		write_log (_T("%s: initializing unit %d\n"), getdevname (), unit);
		dev->td = pdev->td;
		dev->adapter = pdev->td ? pdev->td->active : 0;
		if (dev->adapter) {
			dev->online = 1;
			dev->configured = 1;
		}
		start_thread (dev);
	}

	if (kickstart_version >= 36) {
		m68k_areg (regs, 0) = get_long (4) + 350;
		m68k_areg (regs, 1) = timerdevname;
		CallLib (context, get_long (4), -0x114); /* FindName('timer.device') */
		pdev->timerbase = m68k_dreg (regs, 0);
	}

	pdev->copyfrombuff = pdev->copytobuff = pdev->packetfilter = 0;
	pdev->tempbuf = 0;
	if (get_word (ioreq + 0x12) >= SANA2_IOREQSIZE) {
		buffermgmt = get_long (ioreq + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4);
		tagpnext = buffermgmt;
		while (tagpnext) {
			uae_u32 tag = get_long (tagpnext);
			uae_u32 val = get_long (tagpnext + 4);
			tagp = tagpnext;
			tagpnext += 8;
			switch (tag)
			{
			case TAG_DONE:
				tagpnext = 0;
				break;
			case TAG_IGNORE:
				break;
			case TAG_MORE:
				tagpnext = val;
				break;
			case TAG_SKIP:
				tagpnext = tagp + val * 8;
				break;
			case S2_CopyToBuff:
				pdev->copytobuff = val;
				break;
			case S2_CopyFromBuff:
				pdev->copyfrombuff = val;
				break;
			case S2_PacketFilter:
				pdev->packetfilter = val;
				break;
			}
		}
		if (log_net)
			write_log (_T("%s:%d CTB=%08x CFB=%08x PF=%08x\n"),
			getdevname(), unit, pdev->copytobuff, pdev->copyfrombuff, pdev->packetfilter);
		m68k_dreg (regs, 0) = dev->td->mtu + ETH_HEADER_SIZE + 2;
		m68k_dreg (regs, 1) = 1;
		pdev->tempbuf = CallLib (context, get_long (4), -0xC6); /* AllocMem */
		if (!pdev->tempbuf) {
			if (dev->opencnt == 0) {
				ethernet_close (pdev->td, dev->sysdata);
				xfree (dev->sysdata);
				dev->sysdata = NULL;
			}
			return openfail (ioreq, S2ERR_BAD_ARGUMENT);
		}
		/* buffermanagement */
		put_long (ioreq + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4, pdev->tempbuf);
	}
	dev->exclusive = flags & SANA2OPF_MINE;
	dev->opencnt++;
	put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) + 1);
	put_byte (ioreq + 31, 0);
	put_byte (ioreq + 8, 7);
	return 0;
}