示例#1
0
static void
l4ser_shm_rx_chars(struct uart_port *port)
{
	struct l4ser_shm_uart_port *l4port = (struct l4ser_shm_uart_port *)port;
	struct tty_struct *tty = port->state->port.tty;

	struct chunk_head *chhead;
	struct ring_chunk_head *rph;
	unsigned long offs;

	chhead = (struct chunk_head *)l4shmc_chunk_ptr(&l4port->rx_chunk);
	offs = chhead->next_offs_to_read;

	while (1) {
		unsigned long l;

		rph = (struct ring_chunk_head *)(l4port->rx_ring_start + offs);
		if (!rph->size)
			break;
		offs += sizeof(struct ring_chunk_head);
		offs %= l4port->rx_ring_size;

		if (offs + rph->size > l4port->rx_ring_size)
			l = l4port->rx_ring_size - offs;
		else
			l = rph->size;


		port->icount.rx += rph->size;

		tty_insert_flip_string(tty,
		                       (const unsigned char *)l4port->rx_ring_start + offs,
		                       l);
		if (l != rph->size)
			tty_insert_flip_string(tty,
			                       (const unsigned char *)l4port->rx_ring_start,
			                       rph->size - l);


		offs = (offs + rph->size + sizeof(struct ring_chunk_head) - 1)
		       & ~(sizeof(struct ring_chunk_head) - 1);
		offs %= l4port->rx_ring_size;
		chhead->next_offs_to_read = offs;
		rph->size = 0;

	}
	tty_flip_buffer_push(tty);

	if (chhead->writer_blocked) {
		L4XV_V(f);
		L4XV_L(f);
		l4shmc_trigger(&l4port->tx_sig);
		L4XV_U(f);
	}

	chhead = (struct chunk_head *)l4shmc_chunk_ptr(&l4port->tx_chunk);
	chhead->writer_blocked = 0;

	return;
}
示例#2
0
static void *thread_consume(void *d)
{
  (void)d;
  l4shmc_area_t shmarea;
  l4shmc_chunk_t p_one;
  l4shmc_signal_t s_one, s_done;

  // attach to shared memory area
  CHK(l4shmc_attach("testshm", &shmarea));

  // get chunk 'one'
  CHK(l4shmc_get_chunk(&shmarea, "one", &p_one));

  // add a signal
  CHK(l4shmc_add_signal(&shmarea, "done", &s_done));

  // attach signal to this thread
  CHK(l4shmc_attach_signal_to(&shmarea, "prod",
                              pthread_l4_cap(pthread_self()), 10000, &s_one));

  // connect chunk and signal
  CHK(l4shmc_connect_chunk_signal(&p_one, &s_one));

  while (1)
    {
      CHK(l4shmc_wait_chunk(&p_one));

      printf("CONSUMER: Received from chunk one: %s\n",
             (char *)l4shmc_chunk_ptr(&p_one));
      memset(l4shmc_chunk_ptr(&p_one), 0, l4shmc_chunk_size(&p_one));

      CHK(l4shmc_chunk_consumed(&p_one));
      CHK(l4shmc_trigger(&s_done));
    }

  return NULL;
}
示例#3
0
static void *thread_producer(void *d)
{
  (void)d;
  l4shmc_chunk_t p_one;
  l4shmc_signal_t s_one, s_done;
  l4shmc_area_t shmarea;

  l4_debugger_set_object_name(pthread_getl4cap(pthread_self()), "prod");

  // attach this thread to the shm object
  CHK(l4shmc_attach("testshm", &shmarea));

  // add a chunk
  CHK(l4shmc_add_chunk(&shmarea, "one", 1024, &p_one));

  // add a signal
  CHK(l4shmc_add_signal(&shmarea, "prod", &s_one));

  // connect chunk and signal
  CHK(l4shmc_connect_chunk_signal(&p_one, &s_one));

  CHK(l4shmc_attach_signal_to(&shmarea, "done",
                              pthread_getl4cap(pthread_self()), 10000, &s_done));

  printf("PRODUCER: ready\n");

  while (1)
    {
      while (l4shmc_chunk_try_to_take(&p_one))
        printf("Uh, should not happen!\n"); //l4_thread_yield();

      set_some_data();

      memcpy(l4shmc_chunk_ptr(&p_one), some_data, sizeof(some_data));

      CHK(l4shmc_chunk_ready_sig(&p_one, sizeof(some_data)));

      printf("PRODUCER: Sent data %s\n", some_data);

      CHK(l4shmc_wait_signal(&s_done));

      l4_sleep(5000);
    }

  l4_sleep_forever();
  return NULL;
}
示例#4
0
static int __init l4ser_shm_init_port(int num, const char *name)
{
	int irq;
	struct chunk_head *ch;
	struct l4ser_shm_uart_port *p = &l4ser_shm_port[num];
	L4XV_V(f);

	if (p->inited)
		return 0;
	p->inited = 1;

	if (shmsize < PAGE_SIZE)
		shmsize = PAGE_SIZE;

	pr_info("l4ser_shm: Requesting, role %s, Shmsize %d Kbytes\n",
	        p->create ? "Creator" : "User", shmsize >> 10);

	L4XV_L(f);
	if (p->create) {
		if (l4shmc_create(name, shmsize)) {
			L4XV_U(f);
			pr_err("l4ser_shm/%s: Failed to create shm\n",
			       p->name);
			return -ENOMEM;
		}
	}

	if (l4shmc_attach_to(name, WAIT_TIMEOUT,
	                     &p->shmcarea)) {
		L4XV_U(f);
		pr_err("l4ser_shm/%s: Failed to attach to shm\n", p->name);
		return -ENOMEM;
	}

	if (l4shmc_add_chunk(&p->shmcarea, p->create ? "joe" : "bob",
	                     chunk_size(&p->shmcarea),
	                     &p->tx_chunk))
		goto unlock;

	if (l4shmc_add_signal(&p->shmcarea, p->create ? "joe" : "bob",
	                      &p->tx_sig))
		goto unlock;

	if (l4shmc_connect_chunk_signal(&p->tx_chunk,
	                                &p->tx_sig))
		goto unlock;

	/* Now get the receiving side */
	if (l4shmc_get_chunk_to(&p->shmcarea, p->create ? "bob" : "joe",
	                        WAIT_TIMEOUT, &p->rx_chunk))
		goto unlock;

	if (l4shmc_get_signal_to(&p->shmcarea, p->create ? "bob" : "joe",
	                         WAIT_TIMEOUT, &p->rx_sig))
		goto unlock;

	if (l4shmc_connect_chunk_signal(&p->rx_chunk,
	                                &p->rx_sig))
		goto unlock;
	L4XV_U(f);

	if ((irq = l4x_register_irq(l4shmc_signal_cap(&p->rx_sig))) < 0)
		return -ENOMEM;

	ch = (struct chunk_head *)l4shmc_chunk_ptr(&p->tx_chunk);
	ch->next_offs_to_write = 0;
	ch->next_offs_to_read  = 0;
	ch->writer_blocked     = 0;

	p->tx_ring_size = l4shmc_chunk_capacity(&p->tx_chunk)
	                       - sizeof(struct chunk_head);
        p->rx_ring_size = l4shmc_chunk_capacity(&p->rx_chunk)
                               - sizeof(struct chunk_head);

        p->tx_ring_start = (char *)l4shmc_chunk_ptr(&p->tx_chunk)
                               + sizeof(struct chunk_head);
        p->rx_ring_start = (char *)l4shmc_chunk_ptr(&p->rx_chunk)
                               + sizeof(struct chunk_head);


	p->port.uartclk   = 3686400;
	p->port.ops       = &l4ser_shm_pops;
	p->port.fifosize  = 8;
	p->port.line      = num;
	p->port.iotype    = UPIO_MEM;
	p->port.membase   = (void *)1;
	p->port.mapbase   = 1;
	p->port.flags     = UPF_BOOT_AUTOCONF;
	p->port.irq       = irq;

	return 0;

unlock:
	L4XV_U(f);
	return -ENOMEM;
}
示例#5
0
static unsigned long tx_buf(struct uart_port *port, const char *chunk, int length)
{
	struct l4ser_shm_uart_port *l4port = (struct l4ser_shm_uart_port *)port;
	struct chunk_head *chhead;
	struct ring_chunk_head *rph;
	unsigned long l, offs, nextoffs, free_bytes;
	unsigned long flags;
	struct tty_struct *tty = port->state->port.tty;

	spin_lock_irqsave(&txlock, flags);

	chhead = (struct chunk_head *)l4shmc_chunk_ptr(&l4port->tx_chunk);
	offs = chhead->next_offs_to_write;

	rph = (struct ring_chunk_head *)(l4port->tx_ring_start + offs);
	BUILD_BUG_ON(sizeof(struct ring_chunk_head) & (sizeof(struct ring_chunk_head) - 1));

	// get max free space
	if (chhead->next_offs_to_write >= chhead->next_offs_to_read)
		free_bytes = l4port->tx_ring_size - (chhead->next_offs_to_write - chhead->next_offs_to_read);
	else
		free_bytes = chhead->next_offs_to_read - chhead->next_offs_to_write;

	if (free_bytes <= sizeof(struct ring_chunk_head) * 2) {
		chhead->writer_blocked = 1;
		spin_unlock_irqrestore(&txlock, flags);
		tty->hw_stopped = 1;
		tty->stopped = 1;
		l4shmc_trigger(&l4port->tx_sig);
		return 0;
	}

	if (length > free_bytes - sizeof(struct ring_chunk_head) * 2)
		length = free_bytes - sizeof(struct ring_chunk_head) * 2;

	nextoffs = (offs + length + sizeof(struct ring_chunk_head) + sizeof(struct ring_chunk_head) - 1)
	           & ~(sizeof(struct ring_chunk_head) - 1);

	nextoffs %= l4port->tx_ring_size;

	offs += sizeof(struct ring_chunk_head);
	offs %= l4port->tx_ring_size;

	if (offs + length > l4port->tx_ring_size)
		l = l4port->tx_ring_size - offs;
	else
		l = length;

	memcpy(l4port->tx_ring_start + offs, chunk, l);
	if (l != length)
		memcpy(l4port->tx_ring_start, chunk + l, length - l);

	// now write header
	((struct ring_chunk_head *)(l4port->tx_ring_start + nextoffs))->size = 0;
	smp_wmb();
	rph->size = length;
	chhead->next_offs_to_write = nextoffs;

	spin_unlock_irqrestore(&txlock, flags);
	return length;
}