/* 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; }
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); }
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; }