io_return_t sceopen( dev_t dev, dev_mode_t flag, io_req_t ior) { struct ifnet *ifp; int i, unit; sce_softc_t ssc; scsit_return_t sr; TR_DECL("sceopen"); tr4("enter: dev = 0x%x flag = 0x%x ior = 0x%x", dev, flag, ior); unit = minor(dev); if (scegetssc(unit) != NULL_SSC) { tr1("exit: D_ALREADY_OPEN"); return (D_ALREADY_OPEN); } for(i=0;i<NSCE;i++) { ssc = &sce_softc[i]; if (!ssc->inuse) break; } if (ssc->inuse) { tr1("exit: D_WOULD_BLOCK"); return (D_WOULD_BLOCK); } ssc->inuse = TRUE; ssc->node = unit; sr = scsit_handle_alloc(&ssc->recv_handle); assert(sr == SCSIT_SUCCESS); sr = scsit_handle_mismatch(ssc->recv_handle); assert(sr == SCSIT_SUCCESS); ifp = &(ssc->sce_if); ifp->if_unit = unit; ifp->if_mtu = SCE_MTU; ifp->if_flags = IFF_UP | IFF_RUNNING | IFF_BROADCAST; ifp->if_header_size = sizeof(struct ether_header); ifp->if_header_format = HDR_ETHERNET; ifp->if_address_size = 6; ifp->if_address = sce_fake_addr; if_init_queues(ifp); (void)sce_prime(ssc, IKM_NULL); tr1("exit: D_SUCCESS"); return (D_SUCCESS); }
static io_return_t device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type, dev_mode_t mode, char *name, device_t *devp) { io_return_t err = D_SUCCESS; ipc_port_t notify; struct ifnet *ifp; struct linux_device *dev; struct net_data *nd; /* Search for the device. */ for (dev = dev_base; dev; dev = dev->next) if (dev->base_addr && dev->base_addr != 0xffe0 && !strcmp (name, dev->name)) break; if (!dev) return D_NO_SUCH_DEVICE; /* Allocate and initialize device data if this is the first open. */ nd = dev->net_data; if (!nd) { dev->net_data = nd = ((struct net_data *) kalloc (sizeof (struct net_data))); if (!nd) { err = D_NO_MEMORY; goto out; } nd->dev = dev; nd->device.emul_data = nd; nd->device.emul_ops = &linux_net_emulation_ops; nd->port = ipc_port_alloc_kernel (); if (nd->port == IP_NULL) { err = KERN_RESOURCE_SHORTAGE; goto out; } ipc_kobject_set (nd->port, (ipc_kobject_t) & nd->device, IKOT_DEVICE); notify = ipc_port_make_sonce (nd->port); ip_lock (nd->port); ipc_port_nsrequest (nd->port, 1, notify, ¬ify); assert (notify == IP_NULL); ifp = &nd->ifnet; ifp->if_unit = dev->name[strlen (dev->name) - 1] - '0'; ifp->if_flags = IFF_UP | IFF_RUNNING; ifp->if_mtu = dev->mtu; ifp->if_header_size = dev->hard_header_len; ifp->if_header_format = dev->type; ifp->if_address_size = dev->addr_len; ifp->if_address = dev->dev_addr; if_init_queues (ifp); if (dev->open) { linux_intr_pri = SPL6; if ((*dev->open) (dev)) err = D_NO_SUCH_DEVICE; } out: if (err) { if (nd) { if (nd->port != IP_NULL) { ipc_kobject_set (nd->port, IKO_NULL, IKOT_NONE); ipc_port_dealloc_kernel (nd->port); } kfree ((vm_offset_t) nd, sizeof (struct net_data)); nd = NULL; dev->net_data = NULL; } } else { /* IPv6 heavily relies on multicasting (especially router and neighbor solicits and advertisements), so enable reception of those multicast packets by setting `LINUX_IFF_ALLMULTI'. */ dev->flags |= LINUX_IFF_UP | LINUX_IFF_RUNNING | LINUX_IFF_ALLMULTI; skb_queue_head_init (&dev->buffs[0]); if (dev->set_multicast_list) dev->set_multicast_list (dev); } if (IP_VALID (reply_port)) ds_device_open_reply (reply_port, reply_port_type, err, dev_to_port (nd)); return MIG_NO_REPLY; } *devp = &nd->device; return D_SUCCESS; }