Beispiel #1
0
int
rtk_intr(void *arg)
{
	struct rtk_softc *sc;
	struct ifnet *ifp;
	uint16_t status;
	int handled;

	sc = arg;
	ifp = &sc->ethercom.ec_if;

	if (!device_has_power(sc->sc_dev))
		return 0;

	/* Disable interrupts. */
	CSR_WRITE_2(sc, RTK_IMR, 0x0000);

	handled = 0;
	for (;;) {

		status = CSR_READ_2(sc, RTK_ISR);

		if (status == 0xffff)
			break; /* Card is gone... */

		if (status)
			CSR_WRITE_2(sc, RTK_ISR, status);

		if ((status & RTK_INTRS) == 0)
			break;

		handled = 1;

		if (status & RTK_ISR_RX_OK)
			rtk_rxeof(sc);

		if (status & RTK_ISR_RX_ERR)
			rtk_rxeof(sc);

		if (status & (RTK_ISR_TX_OK|RTK_ISR_TX_ERR))
			rtk_txeof(sc);

		if (status & RTK_ISR_SYSTEM_ERR) {
			rtk_reset(sc);
			rtk_init(ifp);
		}
	}

	/* Re-enable interrupts. */
	CSR_WRITE_2(sc, RTK_IMR, RTK_INTRS);

	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
		rtk_start(ifp);

	rnd_add_uint32(&sc->rnd_source, status);

	return handled;
}
Beispiel #2
0
// Main
int main(int argc, char **argv)
{
  playerc_client_t *client;
  rtk_app_t *app;
  mainwnd_t *mainwnd;
  opt_t *opt;
  const char *host;
  int port;
  int i;
  int count;
  double rate;
  char section[256];
  int device_count;
  device_t devices[PLAYER_MAX_DEVICES];
  device_t *device;
  struct timeval tv, tc = {0, 0};
  struct timespec st = {0, (1.0/GUI_UPDATE_RATE) * 1e9};

  printf("PlayerViewer %s\n", PLAYER_VERSION);

  // Initialise rtk lib (after we have read the program options we
  // want).
  rtk_init(&argc, &argv);

  // Register signal handlers
  signal(SIGINT, sig_quit);
  signal(SIGQUIT, sig_quit);

  // Load program options
  opt = opt_init(argc, argv, NULL);
  if (!opt)
  {
    print_usage();
    return -1;
  }

  // Pick out some important program options
  host = opt_get_string(opt, "", "host", NULL);
  if (!host)
    host = opt_get_string(opt, "", "h", "localhost");

  port = opt_get_int(opt, "", "port", -1);
  if (port < 0)
    port = opt_get_int(opt, "", "p", 6665);

  rate = opt_get_double(opt, "", "rate", 5.0);
  if(rate < 0.0)
    rate = 0.0;

  // Connect to the server
  printf("Connecting to [%s:%d]\n", host, port);
  client = playerc_client_create(NULL, host, port);
  if (playerc_client_connect(client) != 0)
  {
    PRINT_ERR1("%s", playerc_error_str());
    print_usage();
    return -1;
  }

  if(rate == 0.0)
  {
    printf("Setting delivery mode to PLAYER_DATAMODE_PUSH\n");
    // Change the server's data delivery mode.
    if (playerc_client_set_replace_rule(client, -1, -1, -1, -1, 0) != 0)
    {
      PRINT_ERR1("%s", playerc_error_str());
      return -1;
    }

    // Change the server's data delivery mode.
    // PLAYERC_DATAMODE_PUSH, PLAYERC_DATAMODE_PULL
    if (playerc_client_datamode(client, PLAYERC_DATAMODE_PUSH) != 0)
    {
      PRINT_ERR1("%s", playerc_error_str());
      return -1;
    }
  }

  // Get the available devices.
  if (playerc_client_get_devlist(client) != 0)
  {
    PRINT_ERR1("%s", playerc_error_str());
    return -1;
  }

  // Create gui
  app = rtk_app_create();

  // Create a window for most of the sensor data
  mainwnd = mainwnd_create(app, host, port);
  if (!mainwnd)
    return -1;

  // Create a list of available devices, with their gui proxies.
  device_count = 0;
  for (i = 0; i < client->devinfo_count; i++)
  {
    device = devices + device_count;

    device->addr = client->devinfos[i].addr;
    device->drivername = strdup(client->devinfos[i].drivername);

    // See if the device should be subscribed immediately.
    snprintf(section, sizeof(section), "%s:%d",
             interf_to_str(device->addr.interf), device->addr.index);
    device->subscribe = opt_get_int(opt, section, "", 0);
    device->subscribe = opt_get_int(opt, section, "subscribe", device->subscribe);
    if (device->addr.index == 0)
    {
      snprintf(section, sizeof(section), "%s",
               interf_to_str(device->addr.interf));
      device->subscribe = opt_get_int(opt, section, "", device->subscribe);
      device->subscribe = opt_get_int(opt, section, "subscribe", device->subscribe);
    }

    // Allow for --position instead of --position2d
    if(device->addr.interf == PLAYER_POSITION2D_CODE)
    {
      snprintf(section, sizeof(section), "%s:%d",
               PLAYER_POSITION2D_STRING, device->addr.index);
      device->subscribe = opt_get_int(opt, section, "", device->subscribe);
      device->subscribe = opt_get_int(opt, section, "subscribe", device->subscribe);
      if (device->addr.index == 0)
      {
        snprintf(section, sizeof(section), "%s", PLAYER_POSITION2D_STRING);
        device->subscribe = opt_get_int(opt, section, "", device->subscribe);
        device->subscribe = opt_get_int(opt, section, "subscribe", device->subscribe);
      }
    }

    // Create the GUI proxy for this device.
    create_proxy(device, opt, mainwnd, client);

    device_count++;
  }

  // Print the list of available devices.
  printf("Available devices: %s:%d\n", host, port);
  for (i = 0; i < device_count; i++)
  {
    device = devices + i;
    snprintf(section, sizeof(section), "%s:%d",
             interf_to_str(device->addr.interf), device->addr.index);
    printf("%-16s %-40s", section, device->drivername);
    if (device->proxy)
    {
      if (device->subscribe)
        printf("subscribed");
      else
        printf("ready");
    }
    else
      printf("unsupported");
    printf("\n");
  }

  // Print out a list of unused options.
  opt_warn_unused(opt);

  // Start the gui; dont run in a separate thread and dont let it do
  // its own updates.
  rtk_app_main_init(app);

  // start out timer if in pull mode
  if(rate > 0.0)
    gettimeofday(&tv, NULL);

  while (!quit)
  {
    // Let gui process messages
    rtk_app_main_loop(app);

    if(rate == 0.0)  // if we're in push mode
    {
      // see if there's data
      count = playerc_client_peek(client, 50);
      if (count < 0)
      {
        PRINT_ERR1("%s", playerc_error_str());
        break;
      }
      if (count > 0)
      {
        /*proxy = */playerc_client_read_nonblock(client);
      }
    }
    else // we're in pull mode
    {
      // we only want to request new data at the target rate
      gettimeofday(&tc, NULL);
      if(((tc.tv_sec - tv.tv_sec) + (tc.tv_usec - tv.tv_usec)/1e6) > 1.0/rate)
      {
        tv = tc;
        // this requests a round of data from the server to be read
        playerc_client_requestdata(client);
        playerc_client_read_nonblock(client);
       }
       else
       {
        // sleep for the minimum time we can, so we don't use up too much
        // processor
        nanosleep(&st, NULL);
       }
    }


    // Update the devices
    for (i = 0; i < device_count; i++)
    {
      device = devices + i;
      if(device->proxy)
        (*(device->fnupdate)) (device->proxy);
    }
    // Update the main window
    if (mainwnd_update(mainwnd) != 0)
      break;
  }

  // Stop the gui
  rtk_app_main_term(app);

  // Destroy devices
  for (i = 0; i < device_count; i++)
  {
    device = devices + i;
    if (device->proxy)
      (*(device->fndestroy)) (device->proxy);
    free(device->drivername);
  }

  // Disconnect from server
  if (playerc_client_disconnect(client) != 0)
  {
    PRINT_ERR1("%s", playerc_error_str());
    return -1;
  }
  playerc_client_destroy(client);

  // For some reason, either of the following calls makes the program
  // segfault on exit.  I haven't figured out why, so I'm commenting them out.  - BPG

  // Destroy the windows
  //mainwnd_destroy(mainwnd);

  // Destroy the gui
  //rtk_app_destroy(app);

  opt_term(opt);

  return 0;
}
Beispiel #3
0
/*
 * A frame has been uploaded: pass the resulting mbuf chain up to
 * the higher level protocols.
 *
 * You know there's something wrong with a PCI bus-master chip design.
 *
 * The receive operation is badly documented in the datasheet, so I'll
 * attempt to document it here. The driver provides a buffer area and
 * places its base address in the RX buffer start address register.
 * The chip then begins copying frames into the RX buffer. Each frame
 * is preceded by a 32-bit RX status word which specifies the length
 * of the frame and certain other status bits. Each frame (starting with
 * the status word) is also 32-bit aligned. The frame length is in the
 * first 16 bits of the status word; the lower 15 bits correspond with
 * the 'rx status register' mentioned in the datasheet.
 *
 * Note: to make the Alpha happy, the frame payload needs to be aligned
 * on a 32-bit boundary. To achieve this, we copy the data to mbuf
 * shifted forward 2 bytes.
 */
static void
rtk_rxeof(struct rtk_softc *sc)
{
	struct mbuf *m;
	struct ifnet *ifp;
	uint8_t *rxbufpos, *dst;
	u_int total_len, wrap;
	uint32_t rxstat;
	uint16_t cur_rx, new_rx;
	uint16_t limit;
	uint16_t rx_bytes, max_bytes;

	ifp = &sc->ethercom.ec_if;

	cur_rx = (CSR_READ_2(sc, RTK_CURRXADDR) + 16) % RTK_RXBUFLEN;

	/* Do not try to read past this point. */
	limit = CSR_READ_2(sc, RTK_CURRXBUF) % RTK_RXBUFLEN;

	if (limit < cur_rx)
		max_bytes = (RTK_RXBUFLEN - cur_rx) + limit;
	else
		max_bytes = limit - cur_rx;
	rx_bytes = 0;

	while ((CSR_READ_1(sc, RTK_COMMAND) & RTK_CMD_EMPTY_RXBUF) == 0) {
		rxbufpos = sc->rtk_rx_buf + cur_rx;
		bus_dmamap_sync(sc->sc_dmat, sc->recv_dmamap, cur_rx,
		    RTK_RXSTAT_LEN, BUS_DMASYNC_POSTREAD);
		rxstat = le32toh(*(uint32_t *)rxbufpos);
		bus_dmamap_sync(sc->sc_dmat, sc->recv_dmamap, cur_rx,
		    RTK_RXSTAT_LEN, BUS_DMASYNC_PREREAD);

		/*
		 * Here's a totally undocumented fact for you. When the
		 * RealTek chip is in the process of copying a packet into
		 * RAM for you, the length will be 0xfff0. If you spot a
		 * packet header with this value, you need to stop. The
		 * datasheet makes absolutely no mention of this and
		 * RealTek should be shot for this.
		 */
		total_len = rxstat >> 16;
		if (total_len == RTK_RXSTAT_UNFINISHED)
			break;

		if ((rxstat & RTK_RXSTAT_RXOK) == 0 ||
		    total_len < ETHER_MIN_LEN ||
		    total_len > (MCLBYTES - RTK_ETHER_ALIGN)) {
			ifp->if_ierrors++;

			/*
			 * submitted by:[netbsd-pcmcia:00484]
			 *	Takahiro Kambe <*****@*****.**>
			 * obtain from:
			 *     FreeBSD if_rl.c rev 1.24->1.25
			 *
			 */
#if 0
			if (rxstat & (RTK_RXSTAT_BADSYM|RTK_RXSTAT_RUNT|
			    RTK_RXSTAT_GIANT|RTK_RXSTAT_CRCERR|
			    RTK_RXSTAT_ALIGNERR)) {
				CSR_WRITE_2(sc, RTK_COMMAND, RTK_CMD_TX_ENB);
				CSR_WRITE_2(sc, RTK_COMMAND,
				    RTK_CMD_TX_ENB|RTK_CMD_RX_ENB);
				CSR_WRITE_4(sc, RTK_RXCFG, RTK_RXCFG_CONFIG);
				CSR_WRITE_4(sc, RTK_RXADDR,
				    sc->recv_dmamap->dm_segs[0].ds_addr);
				cur_rx = 0;
			}
			break;
#else
			rtk_init(ifp);
			return;
#endif
		}

		/* No errors; receive the packet. */
		rx_bytes += total_len + RTK_RXSTAT_LEN;

		/*
		 * Avoid trying to read more bytes than we know
		 * the chip has prepared for us.
		 */
		if (rx_bytes > max_bytes)
			break;

		/*
		 * Skip the status word, wrapping around to the beginning
		 * of the Rx area, if necessary.
		 */
		cur_rx = (cur_rx + RTK_RXSTAT_LEN) % RTK_RXBUFLEN;
		rxbufpos = sc->rtk_rx_buf + cur_rx;

		/*
		 * Compute the number of bytes at which the packet
		 * will wrap to the beginning of the ring buffer.
		 */
		wrap = RTK_RXBUFLEN - cur_rx;

		/*
		 * Compute where the next pending packet is.
		 */
		if (total_len > wrap)
			new_rx = total_len - wrap;
		else
			new_rx = cur_rx + total_len;
		/* Round up to 32-bit boundary. */
		new_rx = roundup2(new_rx, sizeof(uint32_t)) % RTK_RXBUFLEN;

		/*
		 * The RealTek chip includes the CRC with every
		 * incoming packet; trim it off here.
		 */
		total_len -= ETHER_CRC_LEN;

		/*
		 * Now allocate an mbuf (and possibly a cluster) to hold
		 * the packet. Note we offset the packet 2 bytes so that
		 * data after the Ethernet header will be 4-byte aligned.
		 */
		MGETHDR(m, M_DONTWAIT, MT_DATA);
		if (m == NULL) {
			printf("%s: unable to allocate Rx mbuf\n",
			    device_xname(sc->sc_dev));
			ifp->if_ierrors++;
			goto next_packet;
		}
		if (total_len > (MHLEN - RTK_ETHER_ALIGN)) {
			MCLGET(m, M_DONTWAIT);
			if ((m->m_flags & M_EXT) == 0) {
				printf("%s: unable to allocate Rx cluster\n",
				    device_xname(sc->sc_dev));
				ifp->if_ierrors++;
				m_freem(m);
				m = NULL;
				goto next_packet;
			}
		}
		m->m_data += RTK_ETHER_ALIGN;	/* for alignment */
		m->m_pkthdr.rcvif = ifp;
		m->m_pkthdr.len = m->m_len = total_len;
		dst = mtod(m, void *);

		/*
		 * If the packet wraps, copy up to the wrapping point.
		 */
		if (total_len > wrap) {
			bus_dmamap_sync(sc->sc_dmat, sc->recv_dmamap,
			    cur_rx, wrap, BUS_DMASYNC_POSTREAD);
			memcpy(dst, rxbufpos, wrap);
			bus_dmamap_sync(sc->sc_dmat, sc->recv_dmamap,
			    cur_rx, wrap, BUS_DMASYNC_PREREAD);
			cur_rx = 0;
			rxbufpos = sc->rtk_rx_buf;
			total_len -= wrap;
			dst += wrap;
		}

		/*
		 * ...and now the rest.
		 */
		bus_dmamap_sync(sc->sc_dmat, sc->recv_dmamap,
		    cur_rx, total_len, BUS_DMASYNC_POSTREAD);
		memcpy(dst, rxbufpos, total_len);
		bus_dmamap_sync(sc->sc_dmat, sc->recv_dmamap,
		    cur_rx, total_len, BUS_DMASYNC_PREREAD);

 next_packet:
		CSR_WRITE_2(sc, RTK_CURRXADDR, (new_rx - 16) % RTK_RXBUFLEN);
		cur_rx = new_rx;

		if (m == NULL)
			continue;

		ifp->if_ipackets++;

		bpf_mtap(ifp, m);
		/* pass it on. */
		(*ifp->if_input)(ifp, m);
	}
}