int emac_initialize(int intf) { struct lpc17_driver_s *priv; /* Get the interface structure associated with this interface number. */ DEBUGASSERT(inf < CONFIG_HCS12_NINTERFACES); priv = &g_ethdrvr[intf]; /* Check if a Ethernet chip is recognized at its I/O base */ /* Attach the IRQ to the driver */ if (irq_attach(CONFIG_HCS12_IRQ, emac_interrupt)) { /* We could not attach the ISR to the interrupt */ return -EAGAIN; } /* Initialize the driver structure */ memset(priv, 0, sizeof(struct emac_driver_s)); priv->d_dev.d_ifup = emac_ifup; /* I/F down callback */ priv->d_dev.d_ifdown = emac_ifdown; /* I/F up (new IP address) callback */ priv->d_dev.d_txavail = emac_txavail; /* New TX data callback */ #ifdef CONFIG_NET_IGMP priv->d_dev.d_addmac = emac_addmac; /* Add multicast MAC address */ priv->d_dev.d_rmmac = emac_rmmac; /* Remove multicast MAC address */ #endif priv->d_dev.d_private = (void*)g_emac; /* Used to recover private state from dev */ /* Create a watchdog for timing polling for and timing of transmisstions */ priv->d_txpoll = wd_create(); /* Create periodic poll timer */ priv->d_txtimeout = wd_create(); /* Create TX timeout timer */ /* Put the interface in the down state. This usually amounts to resetting * the device and/or calling emac_ifdown(). */ /* Read the MAC address from the hardware into priv->d_dev.d_mac.ether_addr_octet */ /* Register the device with the OS so that socket IOCTLs can be performed */ (void)netdev_register(&priv->d_dev, NET_LL_ETHERNET); return OK; }
void arp_timer_initialize(void) { /* Create and start the ARP timer */ g_arptimer = wd_create(); (void)wd_start(g_arptimer, ARPTIMER_WDINTERVAL, arptimer_poll, 0); }
int timer_create(clockid_t clockid, FAR struct sigevent *evp, FAR timer_t *timerid) { struct posix_timer_s *ret; WDOG_ID wdog; /* Sanity checks. Also, we support only CLOCK_REALTIME */ if (!timerid || clockid != CLOCK_REALTIME) { set_errno(EINVAL); return ERROR; } /* Allocate a watchdog to provide the underling CLOCK_REALTIME timer */ wdog = wd_create(); if (!wdog) { set_errno(EAGAIN); return ERROR; } /* Allocate a timer instance to contain the watchdog */ ret = timer_allocate(); if (!ret) { set_errno(EAGAIN); return ERROR; } /* Initialize the timer instance */ ret->pt_crefs = 1; ret->pt_owner = getpid(); ret->pt_delay = 0; ret->pt_wdog = wdog; if (evp) { ret->pt_signo = evp->sigev_signo; #ifdef CONFIG_CAN_PASS_STRUCTS ret->pt_value = evp->sigev_value; #else ret->pt_value.sival_ptr = evp->sigev_value.sival_ptr; #endif } else { ret->pt_signo = SIGALRM; ret->pt_value.sival_ptr = ret; } /* Return the timer */ *timerid = ret; return OK; }
int bcmf_netdev_register(FAR struct bcmf_dev_s *priv) { uint32_t out_len; /* Initialize network driver structure */ memset(&priv->bc_dev, 0, sizeof(priv->bc_dev)); priv->bc_dev.d_ifup = bcmf_ifup; /* I/F up (new IP address) callback */ priv->bc_dev.d_ifdown = bcmf_ifdown; /* I/F down callback */ priv->bc_dev.d_txavail = bcmf_txavail; /* New TX data callback */ #ifdef CONFIG_NET_IGMP priv->bc_dev.d_addmac = bcmf_addmac; /* Add multicast MAC address */ priv->bc_dev.d_rmmac = bcmf_rmmac; /* Remove multicast MAC address */ #endif #ifdef CONFIG_NETDEV_IOCTL priv->bc_dev.d_ioctl = bcmf_ioctl; /* Handle network IOCTL commands */ #endif priv->bc_dev.d_private = (FAR void *)priv; /* Used to recover private state from dev */ /* Create a watchdog for timing polling */ priv->bc_txpoll = wd_create(); /* Create periodic poll timer */ DEBUGASSERT(priv->bc_txpoll != NULL); /* Initialize network stack interface buffer */ priv->cur_tx_frame = NULL; priv->bc_dev.d_buf = NULL; /* Put the interface in the down state. This usually amounts to resetting * the device and/or calling bcmf_ifdown(). */ /* Enable chip */ if (bcmf_wl_enable(priv, true) != OK) { return -EIO; } /* Query MAC address */ out_len = ETHER_ADDR_LEN; if (bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, false, IOVAR_STR_CUR_ETHERADDR, priv->bc_dev.d_mac.ether.ether_addr_octet, &out_len) != OK) { return -EIO; } /* Register the device with the OS so that socket IOCTLs can be performed */ (void)netdev_register(&priv->bc_dev, NET_LL_IEEE80211); return OK; }
int localhost_initialize(void) { FAR struct lo_driver_s *priv; /* Get the interface structure associated with this interface number. */ priv = &g_loopback; /* Initialize the driver structure */ memset(priv, 0, sizeof(struct lo_driver_s)); priv->lo_dev.d_ifup = lo_ifup; /* I/F up (new IP address) callback */ priv->lo_dev.d_ifdown = lo_ifdown; /* I/F down callback */ priv->lo_dev.d_txavail = lo_txavail; /* New TX data callback */ #ifdef CONFIG_NET_IGMP priv->lo_dev.d_addmac = lo_addmac; /* Add multicast MAC address */ priv->lo_dev.d_rmmac = lo_rmmac; /* Remove multicast MAC address */ #endif #ifdef CONFIG_NET_MULTIBUFFER priv->lo_dev.d_buf = g_iobuffer; /* Attach the IO buffer */ #endif priv->lo_dev.d_private = (FAR void *)priv; /* Used to recover private state from dev */ /* Create a watchdog for timing polling for and timing of transmissions */ priv->lo_polldog = wd_create(); /* Create periodic poll timer */ /* Register the loopabck device with the OS so that socket IOCTLs can b * performed. */ (void)netdev_register(&priv->lo_dev, NET_LL_LOOPBACK); /* Set the local loopback IP address */ #ifdef CONFIG_NET_IPv4 net_ipv4addr_copy(priv->lo_dev.d_ipaddr, g_lo_ipv4addr); net_ipv4addr_copy(priv->lo_dev.d_draddr, g_lo_ipv4addr); net_ipv4addr_copy(priv->lo_dev.d_netmask, g_lo_ipv4mask); #endif #ifdef CONFIG_NET_IPv6 net_ipv6addr_copy(priv->lo_dev.d_ipv6addr, g_lo_ipv6addr); net_ipv6addr_copy(priv->lo_dev.d_ipv6draddr, g_lo_ipv6addr); net_ipv6addr_copy(priv->lo_dev.d_ipv6netmask, g_ipv6_alloneaddr); #endif /* Put the network in the UP state */ priv->lo_dev.d_flags = IFF_UP; return lo_ifup(&priv->lo_dev); }
FAR struct igmp_group_s *igmp_grpalloc(FAR struct net_driver_s *dev, FAR const in_addr_t *addr) { FAR struct igmp_group_s *group; net_lock_t flags; nllvdbg("addr: %08x dev: %p\n", *addr, dev); if (up_interrupt_context()) { #if CONFIG_PREALLOC_IGMPGROUPS > 0 grplldbg("Use a pre-allocated group entry\n"); group = igmp_grpprealloc(); #else grplldbg("Cannot allocate from interrupt handler\n"); group = NULL; #endif } else { grplldbg("Allocate from the heap\n"); group = igmp_grpheapalloc(); } grplldbg("group: %p\n", group); /* Check if we successfully allocated a group structure */ if (group) { /* Initialize the non-zero elements of the group structure */ net_ipv4addr_copy(group->grpaddr, *addr); sem_init(&group->sem, 0, 0); /* Initialize the group timer (but don't start it yet) */ group->wdog = wd_create(); DEBUGASSERT(group->wdog); /* Interrupts must be disabled in order to modify the group list */ flags = net_lock(); /* Add the group structure to the list in the device structure */ sq_addfirst((FAR sq_entry_t *)group, &dev->grplist); net_unlock(flags); } return group; }
int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout) { WDOG_ID wdog; sem_t sem; int count = 0; int ret; sem_init(&sem, 0, 0); ret = poll_setup(fds, nfds, &sem); if (ret >= 0) { if (timeout >= 0) { /* Wait for the poll event with a timeout. Note that the * millisecond timeout has to be converted to system clock * ticks for wd_start */ wdog = wd_create(); wd_start(wdog, MSEC2TICK(timeout), poll_timeout, 1, (uint32_t)&sem); poll_semtake(&sem); wd_delete(wdog); } else { /* Wait for the poll event with no timeout */ poll_semtake(&sem); } /* Teardown the poll operation and get the count of events */ ret = poll_teardown(fds, nfds, &count); } sem_destroy(&sem); /* Check for errors */ if (ret < 0) { set_errno(-ret); return ERROR; } return count; }
int vnet_init(struct rgmp_vnet *vnet) { struct vnet_driver_s *priv; static int i = 0; if (i >= CONFIG_VNET_NINTERFACES) { return -1; } priv = &g_vnet[i++]; /* Initialize the driver structure */ memset(priv, 0, sizeof(struct vnet_driver_s)); priv->sk_dev.d_ifup = vnet_ifup; /* I/F down callback */ priv->sk_dev.d_ifdown = vnet_ifdown; /* I/F up (new IP address) callback */ priv->sk_dev.d_txavail = vnet_txavail; /* New TX data callback */ #ifdef CONFIG_NET_IGMP priv->sk_dev.d_addmac = vnet_addmac; /* Add multicast MAC address */ priv->sk_dev.d_rmmac = vnet_rmmac; /* Remove multicast MAC address */ #endif priv->sk_dev.d_private = (FAR void *)priv; /* Used to recover private state from dev */ /* Create a watchdog for timing polling for and timing of transmisstions */ priv->sk_txpoll = wd_create(); /* Create periodic poll timer */ priv->vnet = vnet; vnet->priv = priv; /* Register the device with the OS */ (void)netdev_register(&priv->sk_dev), NET_LL_ETHERNET; return 0; }
void vnet_initialize(void) { struct vnet_driver_s *priv; struct rgmp_vnet *vnet = vnet_list.next; int i; for (i=0; i<CONFIG_VNET_NINTERFACES; i++) { if (vnet == NULL) break; priv = &g_vnet[i]; /* Initialize the driver structure */ memset(priv, 0, sizeof(struct vnet_driver_s)); priv->sk_dev.d_ifup = vnet_ifup; /* I/F down callback */ priv->sk_dev.d_ifdown = vnet_ifdown; /* I/F up (new IP address) callback */ priv->sk_dev.d_txavail = vnet_txavail; /* New TX data callback */ #ifdef CONFIG_NET_IGMP priv->sk_dev.d_addmac = vnet_addmac; /* Add multicast MAC address */ priv->sk_dev.d_rmmac = vnet_rmmac; /* Remove multicast MAC address */ #endif priv->sk_dev.d_private = (void*)g_vnet; /* Used to recover private state from dev */ /* Create a watchdog for timing polling for and timing of transmisstions */ priv->sk_txpoll = wd_create(); /* Create periodic poll timer */ //priv->sk_txtimeout = wd_create(); /* Create TX timeout timer */ priv->vnet = vnet; /* Register the device with the OS */ (void)netdev_register(&priv->sk_dev); vnet = vnet->next; } }
int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio, const struct timespec *abstime) { WDOG_ID wdog; FAR msgq_t *msgq; FAR mqmsg_t *mqmsg = NULL; irqstate_t saved_state; int ret = ERROR; DEBUGASSERT(up_interrupt_context() == false); /* Verify the input parameters -- setting errno appropriately * on any failures to verify. */ if (mq_verifysend(mqdes, msg, msglen, prio) != OK) { return ERROR; } if (!abstime || abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) { set_errno(EINVAL); return ERROR; } /* Get a pointer to the message queue */ msgq = mqdes->msgq; /* Create a watchdog. We will not actually need this watchdog * unless the queue is full, but we will reserve it up front * before we enter the following critical section. */ wdog = wd_create(); if (!wdog) { set_errno(EINVAL); return ERROR; } /* Allocate a message structure: * - If we are called from an interrupt handler, or * - If the message queue is not full, or */ sched_lock(); saved_state = irqsave(); if (up_interrupt_context() || /* In an interrupt handler */ msgq->nmsgs < msgq->maxmsgs) /* OR Message queue not full */ { /* Allocate the message */ irqrestore(saved_state); mqmsg = mq_msgalloc(); } else { int ticks; /* We are not in an interupt handler and the message queue is full. * set up a timed wait for the message queue to become non-full. * * Convert the timespec to clock ticks. We must have interrupts * disabled here so that this time stays valid until the wait begins. */ int result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired and the message queue is empty, * return immediately. */ if (result == OK && ticks <= 0) { result = ETIMEDOUT; } /* Handle any time-related errors */ if (result != OK) { set_errno(result); ret = ERROR; } /* Start the watchdog and begin the wait for MQ not full */ if (result == OK) { /* Start the watchdog */ wd_start(wdog, ticks, (wdentry_t)mq_sndtimeout, 1, getpid()); /* And wait for the message queue to be non-empty */ ret = mq_waitsend(mqdes); /* This may return with an error and errno set to either EINTR * or ETIMEOUT. Cancel the watchdog timer in any event. */ wd_cancel(wdog); } /* That is the end of the atomic operations */ irqrestore(saved_state); /* If any of the above failed, set the errno. Otherwise, there should * be space for another message in the message queue. NOW we can allocate * the message structure. */ if (ret == OK) { mqmsg = mq_msgalloc(); } } /* Check if we were able to get a message structure -- this can fail * either because we cannot send the message (and didn't bother trying * to allocate it) or because the allocation failed. */ if (mqmsg) { /* Yes, peform the message send. */ ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); } sched_unlock(); wd_delete(wdog); return ret; }
int ads7843e_register(FAR struct spi_dev_s *spi, FAR struct ads7843e_config_s *config, int minor) { FAR struct ads7843e_dev_s *priv; char devname[DEV_NAMELEN]; #ifdef CONFIG_ADS7843E_MULTIPLE irqstate_t flags; #endif int ret; ivdbg("spi: %p minor: %d\n", spi, minor); /* Debug-only sanity checks */ DEBUGASSERT(spi != NULL && config != NULL && minor >= 0 && minor < 100); /* Create and initialize a ADS7843E device driver instance */ #ifndef CONFIG_ADS7843E_MULTIPLE priv = &g_ads7843e; #else priv = (FAR struct ads7843e_dev_s *)kmalloc(sizeof(struct ads7843e_dev_s)); if (!priv) { idbg("kmalloc(%d) failed\n", sizeof(struct ads7843e_dev_s)); return -ENOMEM; } #endif /* Initialize the ADS7843E device driver instance */ memset(priv, 0, sizeof(struct ads7843e_dev_s)); priv->spi = spi; /* Save the SPI device handle */ priv->config = config; /* Save the board configuration */ priv->wdog = wd_create(); /* Create a watchdog timer */ priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */ priv->threshy = INVALID_THRESHOLD; /* Initialize thresholding logic */ sem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */ sem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */ /* Make sure that interrupts are disabled */ config->clear(config); config->enable(config, false); /* Attach the interrupt handler */ ret = config->attach(config, ads7843e_interrupt); if (ret < 0) { idbg("Failed to attach interrupt\n"); goto errout_with_priv; } idbg("Mode: %d Bits: 8 Frequency: %d\n", CONFIG_ADS7843E_SPIMODE, CONFIG_ADS7843E_FREQUENCY); /* Lock the SPI bus so that we have exclusive access */ ads7843e_lock(spi); /* Configure the SPI interface */ ads7843e_configspi(spi); /* Enable the PEN IRQ */ ads7843e_sendcmd(priv, ADS7843_CMD_ENABPENIRQ); /* Unlock the bus */ ads7843e_unlock(spi); /* Register the device as an input device */ (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); ivdbg("Registering %s\n", devname); ret = register_driver(devname, &ads7843e_fops, 0666, priv); if (ret < 0) { idbg("register_driver() failed: %d\n", ret); goto errout_with_priv; } /* If multiple ADS7843E devices are supported, then we will need to add * this new instance to a list of device instances so that it can be * found by the interrupt handler based on the recieved IRQ number. */ #ifdef CONFIG_ADS7843E_MULTIPLE priv->flink = g_ads7843elist; g_ads7843elist = priv; irqrestore(flags); #endif /* Schedule work to perform the initial sampling and to set the data * availability conditions. */ ret = work_queue(HPWORK, &priv->work, ads7843e_worker, priv, 0); if (ret != 0) { idbg("Failed to queue work: %d\n", ret); goto errout_with_priv; } /* And return success (?) */ return OK; errout_with_priv: sem_destroy(&priv->devsem); #ifdef CONFIG_ADS7843E_MULTIPLE kfree(priv); #endif return ret; }
/** * Initialise an I2C device */ struct i2c_dev_s *up_i2cinitialize(int port) { irqstate_t flags; int retval; i2cvdbg("Init I2C port %d\n", port); /* Only one I2C port on TSB */ if (port > 0) return NULL; flags = irqsave(); if (refcount++) goto out; retval = tsb_request_pinshare(TSB_PIN_GPIO21 | TSB_PIN_GPIO22); if (retval) { lowsyslog("I2C: cannot get ownership of I2C pins\n"); goto err_req_pinshare; } sem_init(&g_mutex, 0, 1); sem_init(&g_wait, 0, 0); /* enable I2C pins */ tsb_clr_pinshare(TSB_PIN_GPIO21); tsb_clr_pinshare(TSB_PIN_GPIO22); /* enable I2C clocks */ tsb_clk_enable(TSB_CLK_I2CP); tsb_clk_enable(TSB_CLK_I2CS); /* reset I2C module */ tsb_reset(TSB_RST_I2CP); tsb_reset(TSB_RST_I2CS); /* Initialize the I2C controller */ tsb_i2c_init(); /* Allocate a watchdog timer */ g_timeout = wd_create(); DEBUGASSERT(g_timeout != 0); /* Attach Interrupt Handler */ irq_attach(TSB_IRQ_I2C, i2c_interrupt); /* Enable Interrupt Handler */ up_enable_irq(TSB_IRQ_I2C); /* Install our operations */ g_dev.ops = &dev_i2c_ops; out: irqrestore(flags); return &g_dev; err_req_pinshare: refcount--; irqrestore(flags); return NULL; }
int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, FAR const struct timespec *abstime) { FAR struct tcb_s *rtcb = this_task(); int ticks; int mypid = (int)getpid(); irqstate_t int_state; int ret = OK; int status; sdbg("cond=0x%p mutex=0x%p abstime=0x%p\n", cond, mutex, abstime); DEBUGASSERT(rtcb->waitdog == NULL); /* Make sure that non-NULL references were provided. */ if (!cond || !mutex) { ret = EINVAL; } /* Make sure that the caller holds the mutex */ else if (mutex->pid != mypid) { ret = EPERM; } /* If no wait time is provided, this function degenerates to * the same behavior as pthread_cond_wait(). */ else if (!abstime) { ret = pthread_cond_wait(cond, mutex); } else { /* Create a watchdog */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { ret = EINVAL; } else { sdbg("Give up mutex...\n"); /* We must disable pre-emption and interrupts here so that * the time stays valid until the wait begins. This adds * complexity because we assure that interrupts and * pre-emption are re-enabled correctly. */ sched_lock(); int_state = irqsave(); /* Convert the timespec to clock ticks. We must disable pre-emption * here so that this time stays valid until the wait begins. */ ret = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); if (ret) { /* Restore interrupts (pre-emption will be enabled when * we fall through the if/then/else */ irqrestore(int_state); } else { /* Check the absolute time to wait. If it is now or in the past, then * just return with the timedout condition. */ if (ticks <= 0) { /* Restore interrupts and indicate that we have already timed out. * (pre-emption will be enabled when we fall through the * if/then/else */ irqrestore(int_state); ret = ETIMEDOUT; } else { /* Give up the mutex */ mutex->pid = -1; ret = pthread_givesemaphore((FAR sem_t *)&mutex->sem); if (ret) { /* Restore interrupts (pre-emption will be enabled when * we fall through the if/then/else) */ irqrestore(int_state); } else { /* Start the watchdog */ wd_start(rtcb->waitdog, ticks, (wdentry_t)pthread_condtimedout, 2, (uint32_t)mypid, (uint32_t)SIGCONDTIMEDOUT); /* Take the condition semaphore. Do not restore interrupts * until we return from the wait. This is necessary to * make sure that the watchdog timer and the condition wait * are started atomically. */ status = sem_wait((FAR sem_t *)&cond->sem); /* Did we get the condition semaphore. */ if (status != OK) { /* NO.. Handle the special case where the semaphore wait was * awakened by the receipt of a signal -- presumably the * signal posted by pthread_condtimedout(). */ if (get_errno() == EINTR) { sdbg("Timedout!\n"); ret = ETIMEDOUT; } else { ret = EINVAL; } } /* The interrupts stay disabled until after we sample the errno. * This is because when debug is enabled and the console is used * for debug output, then the errno can be altered by interrupt * handling! (bad) */ irqrestore(int_state); } /* Reacquire the mutex (retaining the ret). */ sdbg("Re-locking...\n"); status = pthread_takesemaphore((FAR sem_t *)&mutex->sem); if (!status) { mutex->pid = mypid; } else if (!ret) { ret = status; } } /* Re-enable pre-emption (It is expected that interrupts * have already been re-enabled in the above logic) */ sched_unlock(); } /* We no longer need the watchdog */ wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; } } sdbg("Returning %d\n", ret); return ret; }
int misoc_net_initialize(int intf) { FAR struct misoc_net_driver_s *priv; /* Get the interface structure associated with this interface number. */ DEBUGASSERT(intf < CONFIG_MISOC_NET_NINTERFACES); priv = &g_misoc_net[intf]; /* Check if a Ethernet chip is recognized at its I/O base */ /* Attach the IRQ to the driver */ if (irq_attach(ETHMAC_INTERRUPT, misoc_net_interrupt, NULL)) { /* We could not attach the ISR to the interrupt */ return -EAGAIN; } /* clear pending int */ ethmac_sram_writer_ev_pending_write(1); ethmac_sram_reader_ev_pending_write(1); /* Initialize the driver structure */ memset(priv, 0, sizeof(struct misoc_net_driver_s)); priv->rx0_buf = (uint8_t *)ETHMAC_RX0_BASE; priv->rx1_buf = (uint8_t *)ETHMAC_RX1_BASE; priv->tx0_buf = (uint8_t *)ETHMAC_TX0_BASE; priv->tx1_buf = (uint8_t *)ETHMAC_TX1_BASE; priv->tx_buf = priv->tx0_buf; priv->tx_slot=0; priv->misoc_net_dev.d_buf = g_pktbuf; /* Single packet buffer */ priv->misoc_net_dev.d_ifup = misoc_net_ifup; /* I/F up (new IP address) callback */ priv->misoc_net_dev.d_ifdown = misoc_net_ifdown; /* I/F down callback */ priv->misoc_net_dev.d_txavail = misoc_net_txavail; /* New TX data callback */ #ifdef CONFIG_NET_IGMP priv->misoc_net_dev.d_addmac = misoc_net_addmac; /* Add multicast MAC address */ priv->misoc_net_dev.d_rmmac = misoc_net_rmmac; /* Remove multicast MAC address */ #endif priv->misoc_net_dev.d_private = (FAR void *)g_misoc_net; /* Used to recover private state from dev */ /* Create a watchdog for timing polling for and timing of transmissions */ priv->misoc_net_txpoll = wd_create(); /* Create periodic poll timer */ priv->misoc_net_txtimeout = wd_create(); /* Create TX timeout timer */ /* Put the interface in the down state. This usually amounts to resetting * the device and/or calling misoc_net_ifdown(). */ /* Read the MAC address from the hardware into * priv->misoc_net_dev.d_mac.ether.ether_addr_octet */ /* Register the device with the OS so that socket IOCTLs can be performed */ (void)netdev_register(&priv->misoc_net_dev, NET_LL_ETHERNET); return OK; }
int sem_tickwait(FAR sem_t *sem, systime_t start, uint32_t delay) { FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head; irqstate_t flags; systime_t elapsed; int ret; DEBUGASSERT(sem != NULL && up_interrupt_context() == false && rtcb->waitdog == NULL); /* Create a watchdog. We will not actually need this watchdog * unless the semaphore is unavailable, but we will reserve it up * front before we enter the following critical section. */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { return -ENOMEM; } /* We will disable interrupts until we have completed the semaphore * wait. We need to do this (as opposed to just disabling pre-emption) * because there could be interrupt handlers that are asynchronously * posting semaphores and to prevent race conditions with watchdog * timeout. This is not too bad because interrupts will be re- * enabled while we are blocked waiting for the semaphore. */ flags = enter_critical_section(); /* Try to take the semaphore without waiting. */ ret = sem_trywait(sem); if (ret == OK) { /* We got it! */ goto success_with_irqdisabled; } /* We will have to wait for the semaphore. Make sure that we were provided * with a valid timeout. */ if (delay == 0) { /* Return the errno from sem_trywait() */ ret = -get_errno(); goto errout_with_irqdisabled; } /* Adjust the delay for any time since the delay was calculated */ elapsed = clock_systimer() - start; if (/* elapsed >= (UINT32_MAX / 2) || */ elapsed >= delay) { ret = -ETIMEDOUT; goto errout_with_irqdisabled; } delay -= elapsed; /* Start the watchdog with interrupts still disabled */ (void)wd_start(rtcb->waitdog, delay, (wdentry_t)sem_timeout, 1, getpid()); /* Now perform the blocking wait */ ret = sem_wait(sem); if (ret < 0) { /* Return the errno from sem_wait() */ ret = -get_errno(); goto errout_with_irqdisabled; } /* Stop the watchdog timer */ wd_cancel(rtcb->waitdog); /* We can now restore interrupts and delete the watchdog */ /* Success exits */ success_with_irqdisabled: /* Error exits */ errout_with_irqdisabled: leave_critical_section(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; return ret; }
int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info, FAR const struct timespec *timeout) { FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head; sigset_t intersection; FAR sigpendq_t *sigpend; irqstate_t saved_state; int32_t waitticks; int ret = ERROR; DEBUGASSERT(rtcb->waitdog == NULL); sched_lock(); /* Not necessary */ /* Several operations must be performed below: We must determine if any * signal is pending and, if not, wait for the signal. Since signals can * be posted from the interrupt level, there is a race condition that * can only be eliminated by disabling interrupts! */ saved_state = irqsave(); /* Check if there is a pending signal corresponding to one of the * signals in the pending signal set argument. */ intersection = *set & sig_pendingset(rtcb); if (intersection != NULL_SIGNAL_SET) { /* One or more of the signals in intersections is sufficient to cause * us to not wait. Pick the lowest numbered signal and mark it not * pending. */ sigpend = sig_removependingsignal(rtcb, sig_lowest(&intersection)); ASSERT(sigpend); /* Return the signal info to the caller if so requested */ if (info) { memcpy(info, &sigpend->info, sizeof(struct siginfo)); } /* Then dispose of the pending signal structure properly */ sig_releasependingsignal(sigpend); irqrestore(saved_state); /* The return value is the number of the signal that awakened us */ ret = sigpend->info.si_signo; } /* We will have to wait for a signal to be posted to this task. */ else { /* Save the set of pending signals to wait for */ rtcb->sigwaitmask = *set; /* Check if we should wait for the timeout */ if (timeout) { /* Convert the timespec to system clock ticks, making sure that * the resulting delay is greater than or equal to the requested * time in nanoseconds. */ #ifdef CONFIG_HAVE_LONG_LONG uint64_t waitticks64 = ((uint64_t)timeout->tv_sec * NSEC_PER_SEC + (uint64_t)timeout->tv_nsec + NSEC_PER_TICK - 1) / NSEC_PER_TICK; DEBUGASSERT(waitticks64 <= UINT32_MAX); waitticks = (uint32_t)waitticks64; #else uint32_t waitmsec; DEBUGASSERT(timeout->tv_sec < UINT32_MAX / MSEC_PER_SEC); waitmsec = timeout->tv_sec * MSEC_PER_SEC + (timeout->tv_nsec + NSEC_PER_MSEC - 1) / NSEC_PER_MSEC; waitticks = MSEC2TICK(waitmsec); #endif /* Create a watchdog */ rtcb->waitdog = wd_create(); DEBUGASSERT(rtcb->waitdog); if (rtcb->waitdog) { /* This little bit of nonsense is necessary for some * processors where sizeof(pointer) < sizeof(uint32_t). * see wdog.h. */ wdparm_t wdparm; wdparm.pvarg = (FAR void *)rtcb; /* Start the watchdog */ wd_start(rtcb->waitdog, waitticks, (wdentry_t)sig_timeout, 1, wdparm.dwarg); /* Now wait for either the signal or the watchdog */ up_block_task(rtcb, TSTATE_WAIT_SIG); /* We no longer need the watchdog */ wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; } /* REVISIT: And do what if there are no watchdog timers? The wait * will fail and we will return something bogus. */ } /* No timeout, just wait */ else { /* And wait until one of the unblocked signals is posted */ up_block_task(rtcb, TSTATE_WAIT_SIG); } /* We are running again, clear the sigwaitmask */ rtcb->sigwaitmask = NULL_SIGNAL_SET; /* When we awaken, the cause will be in the TCB. Get the signal number * or timeout) that awakened us. */ if (GOOD_SIGNO(rtcb->sigunbinfo.si_signo)) { /* We were awakened by a signal... but is it one of the signals that * we were waiting for? */ if (sigismember(set, rtcb->sigunbinfo.si_signo)) { /* Yes.. the return value is the number of the signal that * awakened us. */ ret = rtcb->sigunbinfo.si_signo; } else { /* No... then set EINTR and report an error */ set_errno(EINTR); ret = ERROR; } } else { /* Otherwise, we must have been awakened by the timeout. Set EGAIN * and return an error. */ DEBUGASSERT(rtcb->sigunbinfo.si_signo == SIG_WAIT_TIMEOUT); set_errno(EAGAIN); ret = ERROR; } /* Return the signal info to the caller if so requested */ if (info) { memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo)); } irqrestore(saved_state); } sched_unlock(); return ret; }
ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen, int *prio, const struct timespec *abstime) { FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head; FAR mqmsg_t *mqmsg; irqstate_t saved_state; int ret = ERROR; DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL); /* Verify the input parameters and, in case of an error, set * errno appropriately. */ if (mq_verifyreceive(mqdes, msg, msglen) != OK) { return ERROR; } if (!abstime || abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) { set_errno(EINVAL); return ERROR; } /* Create a watchdog. We will not actually need this watchdog * unless the queue is not empty, but we will reserve it up front * before we enter the following critical section. */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { set_errno(EINVAL); return ERROR; } /* Get the next mesage from the message queue. We will disable * pre-emption until we have completed the message received. This * is not too bad because if the receipt takes a long time, it will * be because we are blocked waiting for a message and pre-emption * will be re-enabled while we are blocked */ sched_lock(); /* Furthermore, mq_waitreceive() expects to have interrupts disabled * because messages can be sent from interrupt level. */ saved_state = irqsave(); /* Check if the message queue is empty. If it is NOT empty, then we * will not need to start timer. */ if (mqdes->msgq->msglist.head == NULL) { int ticks; /* Convert the timespec to clock ticks. We must have interrupts * disabled here so that this time stays valid until the wait begins. */ int result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired and the message queue is empty, * return immediately. */ if (result == OK && ticks <= 0) { result = ETIMEDOUT; } /* Handle any time-related errors */ if (result != OK) { set_errno(result); irqrestore(saved_state); sched_unlock(); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; return ERROR; } /* Start the watchdog */ wd_start(rtcb->waitdog, ticks, (wdentry_t)mq_rcvtimeout, 1, getpid()); } /* Get the message from the message queue */ mqmsg = mq_waitreceive(mqdes); /* Stop the watchdog timer (this is not harmful in the case where * it was never started) */ wd_cancel(rtcb->waitdog); /* We can now restore interrupts */ irqrestore(saved_state); /* Check if we got a message from the message queue. We might * not have a message if: * * - The message queue is empty and O_NONBLOCK is set in the mqdes * - The wait was interrupted by a signal * - The watchdog timeout expired */ if (mqmsg) { ret = mq_doreceive(mqdes, mqmsg, msg, prio); } sched_unlock(); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; return ret; }
int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio, FAR const struct timespec *abstime) { FAR struct tcb_s *rtcb = this_task(); FAR struct mqueue_inode_s *msgq; FAR struct mqueue_msg_s *mqmsg = NULL; irqstate_t saved_state; int ticks; int result; int ret = ERROR; DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL); /* Verify the input parameters -- setting errno appropriately * on any failures to verify. */ if (mq_verifysend(mqdes, msg, msglen, prio) != OK) { /* mq_verifysend() will set the errno appropriately */ return ERROR; } /* Pre-allocate a message structure */ mqmsg = mq_msgalloc(); if (!mqmsg) { /* Failed to allocate the message */ set_errno(ENOMEM); return ERROR; } /* Get a pointer to the message queue */ sched_lock(); msgq = mqdes->msgq; /* OpenGroup.org: "Under no circumstance shall the operation fail with a * timeout if there is sufficient room in the queue to add the message * immediately. The validity of the abstime parameter need not be checked * when there is sufficient room in the queue." * * Also ignore the time value if for some crazy reason we were called from * an interrupt handler. This probably really should be an assertion. * * NOTE: There is a race condition here: What if a message is added by * interrupt related logic so that queue again becomes non-empty. That * is handled because mq_dosend() will permit the maxmsgs limit to be * exceeded in that case. */ if (msgq->nmsgs < msgq->maxmsgs || up_interrupt_context()) { /* Do the send with no further checks (possibly exceeding maxmsgs) * Currently mq_dosend() always returns OK. */ ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); sched_unlock(); return ret; } /* The message queue is full... We are going to wait. Now we must have a * valid time value. */ if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { result = EINVAL; goto errout_with_mqmsg; } /* Create a watchdog. We will not actually need this watchdog * unless the queue is full, but we will reserve it up front * before we enter the following critical section. */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { result = EINVAL; goto errout_with_mqmsg; } /* We are not in an interrupt handler and the message queue is full. * Set up a timed wait for the message queue to become non-full. * * Convert the timespec to clock ticks. We must have interrupts * disabled here so that this time stays valid until the wait begins. */ saved_state = irqsave(); result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired and the message queue is empty, * return immediately. */ if (result == OK && ticks <= 0) { result = ETIMEDOUT; } /* Handle any time-related errors */ if (result != OK) { goto errout_with_irqsave; } /* Start the watchdog and begin the wait for MQ not full */ wd_start(rtcb->waitdog, ticks, (wdentry_t)mq_sndtimeout, 1, getpid()); /* And wait for the message queue to be non-empty */ ret = mq_waitsend(mqdes); /* This may return with an error and errno set to either EINTR * or ETIMEOUT. Cancel the watchdog timer in any event. */ wd_cancel(rtcb->waitdog); /* Check if mq_waitsend() failed */ if (ret < 0) { /* mq_waitsend() will set the errno, but the error exit will reset it */ result = get_errno(); goto errout_with_irqsave; } /* That is the end of the atomic operations */ irqrestore(saved_state); /* If any of the above failed, set the errno. Otherwise, there should * be space for another message in the message queue. NOW we can allocate * the message structure. * * Currently mq_dosend() always returns OK. */ ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); sched_unlock(); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; return ret; /* Exit here with (1) the scheduler locked, (2) a message allocated, (3) a * wdog allocated, and (4) interrupts disabled. The error code is in * 'result' */ errout_with_irqsave: irqrestore(saved_state); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; /* Exit here with (1) the scheduler locked and 2) a message allocated. The * error code is in 'result' */ errout_with_mqmsg: mq_msgfree(mqmsg); sched_unlock(); set_errno(result); return ERROR; }
int max11802_register(FAR struct spi_dev_s *spi, FAR struct max11802_config_s *config, int minor) { FAR struct max11802_dev_s *priv; char devname[DEV_NAMELEN]; #ifdef CONFIG_MAX11802_MULTIPLE irqstate_t flags; #endif int ret; iinfo("spi: %p minor: %d\n", spi, minor); /* Debug-only sanity checks */ DEBUGASSERT(spi != NULL && config != NULL && minor >= 0 && minor < 100); /* Create and initialize a MAX11802 device driver instance */ #ifndef CONFIG_MAX11802_MULTIPLE priv = &g_max11802; #else priv = (FAR struct max11802_dev_s *)kmm_malloc(sizeof(struct max11802_dev_s)); if (!priv) { ierr("ERROR: kmm_malloc(%d) failed\n", sizeof(struct max11802_dev_s)); return -ENOMEM; } #endif /* Initialize the MAX11802 device driver instance */ memset(priv, 0, sizeof(struct max11802_dev_s)); priv->spi = spi; /* Save the SPI device handle */ priv->config = config; /* Save the board configuration */ priv->wdog = wd_create(); /* Create a watchdog timer */ priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */ priv->threshy = INVALID_THRESHOLD; /* Initialize thresholding logic */ /* Initialize semaphores */ sem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */ sem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */ /* The pen event semaphore is used for signaling and, hence, should not * have priority inheritance enabled. */ sem_setprotocol(&priv->waitsem, SEM_PRIO_NONE); /* Make sure that interrupts are disabled */ config->clear(config); config->enable(config, false); /* Attach the interrupt handler */ ret = config->attach(config, max11802_interrupt); if (ret < 0) { ierr("ERROR: Failed to attach interrupt\n"); goto errout_with_priv; } iinfo("Mode: %d Bits: 8 Frequency: %d\n", CONFIG_MAX11802_SPIMODE, CONFIG_MAX11802_FREQUENCY); /* Lock the SPI bus so that we have exclusive access */ max11802_lock(spi); /* Configure MAX11802 registers */ SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true); (void)SPI_SEND(priv->spi, MAX11802_CMD_MODE_WR); (void)SPI_SEND(priv->spi, MAX11802_MODE); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true); (void)SPI_SEND(priv->spi, MAX11802_CMD_AVG_WR); (void)SPI_SEND(priv->spi, MAX11802_AVG); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true); (void)SPI_SEND(priv->spi, MAX11802_CMD_TIMING_WR); (void)SPI_SEND(priv->spi, MAX11802_TIMING); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true); (void)SPI_SEND(priv->spi, MAX11802_CMD_DELAY_WR); (void)SPI_SEND(priv->spi, MAX11802_DELAY); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false); /* Test that the device access was successful. */ SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true); (void)SPI_SEND(priv->spi, MAX11802_CMD_MODE_RD); ret = SPI_SEND(priv->spi, 0); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false); /* Unlock the bus */ max11802_unlock(spi); if (ret != MAX11802_MODE) { ierr("ERROR: max11802 mode readback failed: %02x\n", ret); goto errout_with_priv; } /* Register the device as an input device */ (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); iinfo("Registering %s\n", devname); ret = register_driver(devname, &max11802_fops, 0666, priv); if (ret < 0) { ierr("ERROR: register_driver() failed: %d\n", ret); goto errout_with_priv; } /* If multiple MAX11802 devices are supported, then we will need to add * this new instance to a list of device instances so that it can be * found by the interrupt handler based on the recieved IRQ number. */ #ifdef CONFIG_MAX11802_MULTIPLE flags = enter_critical_section(); priv->flink = g_max11802list; g_max11802list = priv; leave_critical_section(flags); #endif /* Schedule work to perform the initial sampling and to set the data * availability conditions. */ ret = work_queue(HPWORK, &priv->work, max11802_worker, priv, 0); if (ret != 0) { ierr("ERROR: Failed to queue work: %d\n", ret); goto errout_with_priv; } /* And return success (?) */ return OK; errout_with_priv: sem_destroy(&priv->devsem); #ifdef CONFIG_MAX11802_MULTIPLE kmm_free(priv); #endif return ret; }
int stmpe811_register(STMPE811_HANDLE handle, int minor) { FAR struct stmpe811_dev_s *priv = (FAR struct stmpe811_dev_s *)handle; char devname[DEV_NAMELEN]; int ret; iinfo("handle=%p minor=%d\n", handle, minor); DEBUGASSERT(priv); /* Get exclusive access to the device structure */ ret = sem_wait(&priv->exclsem); if (ret < 0) { int errval = errno; ierr("ERROR: sem_wait failed: %d\n", errval); return -errval; } /* Make sure that the pins (4-7) need by the TSC are not already in use */ if ((priv->inuse & TSC_PIN_SET) != 0) { ierr("ERROR: TSC pins is already in-use: %02x\n", priv->inuse); sem_post(&priv->exclsem); return -EBUSY; } /* Initialize the TS structure fields to their default values */ priv->minor = minor; priv->penchange = false; priv->threshx = 0; priv->threshy = 0; /* Create a timer for catching missed pen up conditions */ priv->wdog = wd_create(); if (!priv->wdog) { ierr("ERROR: Failed to create a watchdog\n", errno); sem_post(&priv->exclsem); return -ENOSPC; } /* Register the character driver */ snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); ret = register_driver(devname, &g_stmpe811fops, 0666, priv); if (ret < 0) { ierr("ERROR: Failed to register driver %s: %d\n", devname, ret); sem_post(&priv->exclsem); return ret; } /* Initialize the touchscreen controller */ stmpe811_tscinitialize(priv); /* Inidicate that the touchscreen controller was successfully initialized */ priv->inuse |= TSC_PIN_SET; /* Pins 4-7 are now in-use */ priv->flags |= STMPE811_FLAGS_TSC_INITIALIZED; /* TSC function is initialized */ sem_post(&priv->exclsem); return ret; }
static int e1000_probe(uint16_t addr, pci_id_t id) { uint32_t mmio_base, mmio_size; uint32_t size; int err; void *kmem, *omem; struct e1000_dev *dev; // alloc e1000_dev memory if ((dev = kzalloc(sizeof(struct e1000_dev))) == NULL) return -1; // save pci addr dev->pci_addr = addr; // enable device if ((err = pci_enable_device(addr, PCI_BUS_MASTER)) < 0) goto error; // get e1000 device type dev->pci_dev_id = id.join; // remap the controller's i/o-memory into kernel's address-space mmio_base = pci_resource_start(addr, 0); mmio_size = pci_resource_len(addr, 0); err = rgmp_memmap_nocache(mmio_base, mmio_size, mmio_base); if (err) goto error; dev->phy_mem_base = mmio_base; dev->io_mem_base = mmio_base; dev->mem_size = mmio_size; // MAC address memset(dev->dst_mac, 0xFF, 6); memcpy(dev->src_mac, (void *)(dev->io_mem_base+E1000_RA), 6); // IRQ setup dev->int_desc.handler = e1000_interrupt_handler; dev->int_desc.dev_id = dev; if ((err = pci_request_irq(addr, &dev->int_desc, 0)) < 0) goto err0; // Here we alloc a big block of memory once and make it // aligned to page boundary and multiple of page size. This // is because the memory can be modified by E1000 DMA and // should be mapped no-cache which will hugely reduce memory // access performance. The page size alloc will restrict // this bad effect only within the memory we alloc here. // // NEED FIX: the memalign may alloc memory continous in // virtual address but dis-continous in physical address // due to RGMP memory setup. size = CONFIG_E1000_N_TX_DESC * sizeof(struct tx_desc) + CONFIG_E1000_N_TX_DESC * CONFIG_E1000_BUFF_SIZE + CONFIG_E1000_N_RX_DESC * sizeof(struct rx_desc) + CONFIG_E1000_N_RX_DESC * CONFIG_E1000_BUFF_SIZE; size = ROUNDUP(size, PGSIZE); omem = kmem = memalign(PGSIZE, size); if (kmem == NULL) { err = -ENOMEM; goto err1; } rgmp_memremap_nocache((uintptr_t)kmem, size); // alloc memory for tx ring dev->tx_ring.desc = (struct tx_desc*)kmem; kmem += CONFIG_E1000_N_TX_DESC * sizeof(struct tx_desc); dev->tx_ring.buf = kmem; kmem += CONFIG_E1000_N_TX_DESC * CONFIG_E1000_BUFF_SIZE; // alloc memory for rx rings dev->rx_ring.desc = (struct rx_desc*)kmem; kmem += CONFIG_E1000_N_RX_DESC * sizeof(struct rx_desc); dev->rx_ring.buf = kmem; /* Initialize the driver structure */ dev->uip_dev.d_ifup = e1000_ifup; /* I/F up (new IP address) callback */ dev->uip_dev.d_ifdown = e1000_ifdown; /* I/F down callback */ dev->uip_dev.d_txavail = e1000_txavail; /* New TX data callback */ #ifdef CONFIG_NET_IGMP dev->uip_dev.d_addmac = e1000_addmac; /* Add multicast MAC address */ dev->uip_dev.d_rmmac = e1000_rmmac; /* Remove multicast MAC address */ #endif dev->uip_dev.d_private = dev; /* Used to recover private state from dev */ /* Create a watchdog for timing polling for and timing of transmisstions */ dev->txpoll = wd_create(); /* Create periodic poll timer */ dev->txtimeout = wd_create(); /* Create TX timeout timer */ // Put the interface in the down state. // e1000 reset e1000_reset(dev); /* Read the MAC address from the hardware */ memcpy(dev->uip_dev.d_mac.ether_addr_octet, (void *)(dev->io_mem_base+E1000_RA), 6); /* Register the device with the OS so that socket IOCTLs can be performed */ err = netdev_register(&dev->uip_dev); if (err) goto err2; // insert into e1000_list dev->next = e1000_list.next; e1000_list.next = dev; cprintf("bring up e1000 device: %04x %08x\n", addr, id.join); return 0; err2: rgmp_memremap((uintptr_t)omem, size); free(omem); err1: pci_free_irq(addr); err0: rgmp_memunmap(mmio_base, mmio_size); error: kfree(dev); cprintf("e1000 device probe fail: %d\n", err); return err; }
int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) { FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head; irqstate_t flags; int ticks; int err; int ret = ERROR; DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL); /* Verify the input parameters and, in case of an error, set * errno appropriately. */ #ifdef CONFIG_DEBUG if (!abstime || !sem) { err = EINVAL; goto errout; } #endif /* Create a watchdog. We will not actually need this watchdog * unless the the semaphore is unavailable, but we will reserve it up * front before we enter the following critical section. */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { err = ENOMEM; goto errout; } /* We will disable interrupts until we have completed the semaphore * wait. We need to do this (as opposed to just disabling pre-emption) * because there could be interrupt handlers that are asynchronoulsy * posting semaphores and to prevent race conditions with watchdog * timeout. This is not too bad because interrupts will be re- * enabled while we are blocked waiting for the semaphore. */ flags = irqsave(); /* Try to take the semaphore without waiting. */ ret = sem_trywait(sem); if (ret == 0) { /* We got it! */ irqrestore(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; return OK; } /* We will have to wait for the semphore. Make sure that we were provided * with a valid timeout. */ if (abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) { err = EINVAL; goto errout_disabled; } /* Convert the timespec to clock ticks. We must have interrupts * disabled here so that this time stays valid until the wait begins. */ err = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired return immediately. */ if (err == OK && ticks <= 0) { err = ETIMEDOUT; goto errout_disabled; } /* Handle any time-related errors */ if (err != OK) { goto errout_disabled; } /* Start the watchdog */ err = OK; wd_start(rtcb->waitdog, ticks, (wdentry_t)sem_timeout, 1, getpid()); /* Now perform the blocking wait */ ret = sem_wait(sem); /* Stop the watchdog timer */ wd_cancel(rtcb->waitdog); /* We can now restore interrupts and delete the watchdog */ irqrestore(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; /* We are either returning success or an error detected by sem_wait() * or the timeout detected by sem_timeout(). The 'errno' value has * been set appropriately by sem_wait() or sem_timeout() in those * cases. */ return ret; /* Error exits */ errout_disabled: irqrestore(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; errout: set_errno(err); return ERROR; }