Beispiel #1
0
/* 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;
}
Beispiel #2
0
void
setup_ethernet_device (char *name, struct device **device)
{
  struct net_status netstat;
  size_t count;
  int net_address[2];
  error_t err;
  struct ether_device *edev;
  struct device *dev;

  edev = calloc (1, sizeof (struct ether_device));
  if (!edev)
    error (2, ENOMEM, "%s", name);
  edev->next = ether_dev;
  ether_dev = edev;

  *device = dev = &edev->dev;

  dev->name = strdup (name);
  /* Functions.  These ones are the true "hardware layer" in Linux.  */
  dev->open = 0;		/* We set up before calling dev_open.  */
  dev->stop = ethernet_stop;
  dev->hard_start_xmit = ethernet_xmit;
  dev->get_stats = ethernet_get_stats;
  dev->set_multicast_list = ethernet_set_multi;

  /* These are the ones set by drivers/net/net_init.c::ether_setup.  */
  dev->hard_header = eth_header;
  dev->rebuild_header = eth_rebuild_header;
  dev->hard_header_cache = eth_header_cache;
  dev->header_cache_update = eth_header_cache_update;
  dev->hard_header_parse = eth_header_parse;
  /* We can't do these two (and we never try anyway).  */
  /* dev->change_mtu = eth_change_mtu; */
  /* dev->set_mac_address = eth_mac_addr; */

  /* Some more fields */
  dev->priv = edev;         /* For reverse lookup.  */
  dev->type = ARPHRD_ETHER;
  dev->hard_header_len = ETH_HLEN;
  dev->addr_len = ETH_ALEN;
  memset (dev->broadcast, 0xff, ETH_ALEN);
  dev->flags = IFF_BROADCAST | IFF_MULTICAST;

  /* FIXME: Receive all multicast to fix IPv6, until we implement
     ethernet_set_multi.  */
  dev->flags |= IFF_ALLMULTI;

  dev->change_flags = ethernet_change_flags;

  dev_init_buffers (dev);

  ethernet_open (dev);

  /* Fetch hardware information */
  count = NET_STATUS_COUNT;
  err = device_get_status (edev->ether_port, NET_STATUS,
			   (dev_status_t) &netstat, &count);
  if (err)
    error (2, err, "%s: Cannot get device status", name);
  dev->mtu = netstat.max_packet_size - dev->hard_header_len;
  assert (netstat.header_format == HDR_ETHERNET);
  assert (netstat.header_size == ETH_HLEN);
  assert (netstat.address_size == ETH_ALEN);

  count = 2;
  assert (count * sizeof (int) >= ETH_ALEN);
  err = device_get_status (edev->ether_port, NET_ADDRESS, net_address, &count);
  if (err)
    error (2, err, "%s: Cannot get hardware Ethernet address", name);
  net_address[0] = ntohl (net_address[0]);
  net_address[1] = ntohl (net_address[1]);
  memcpy (dev->dev_addr, net_address, ETH_ALEN);

  /* That should be enough.  */

  /* This call adds the device to the `dev_base' chain,
     initializes its `ifindex' member (which matters!),
     and tells the protocol stacks about the device.  */
  err = - register_netdevice (dev);
  assert_perror (err);
}
Beispiel #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;
}