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;
}
Beispiel #2
0
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);
}
Beispiel #3
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
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;
  }
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
/**
 * 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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
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;
}
Beispiel #21
0
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;
}
Beispiel #22
0
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;
}