Пример #1
0
/**
 * zd_mac_tx_to_dev - callback for USB layer
 * @skb: a &sk_buff pointer
 * @error: error value, 0 if transmission successful
 *
 * Informs the MAC layer that the frame has successfully transferred to the
 * device. If an ACK is required and the transfer to the device has been
 * successful, the packets are put on the @ack_wait_queue with
 * the control set removed.
 */
void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
{
	struct zd_tx_skb_control_block *cb =
		(struct zd_tx_skb_control_block *)skb->cb;
	struct ieee80211_hw *hw = cb->hw;

	if (likely(cb->control)) {
		skb_pull(skb, sizeof(struct zd_ctrlset));
		if (unlikely(error ||
		    (cb->control->flags & IEEE80211_TXCTL_NO_ACK)))
		{
			struct ieee80211_tx_status status;
			memset(&status, 0, sizeof(status));
			tx_status(hw, skb, &status, !error);
		} else {
			struct sk_buff_head *q =
				&zd_hw_mac(hw)->ack_wait_queue;

			skb_queue_tail(q, skb);
			while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
				zd_mac_tx_failed(hw);
		}
	} else {
		kfree_tx_skb(skb);
	}
}
Пример #2
0
/**
 * filter_ack - filters incoming packets for acknowledgements
 * @dev: the mac80211 device
 * @rx_hdr: received header
 * @stats: the status for the received packet
 *
 * This functions looks for ACK packets and tries to match them with the
 * frames in the tx queue. If a match is found the frame will be dequeued and
 * the upper layers is informed about the successful transmission. If
 * mac80211 queues have been stopped and the number of frames still to be
 * transmitted is low the queues will be opened again.
 *
 * Returns 1 if the frame was an ACK, 0 if it was ignored.
 */
static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
		      struct ieee80211_rx_status *stats)
{
	u16 fc = le16_to_cpu(rx_hdr->frame_control);
	struct sk_buff *skb;
	struct sk_buff_head *q;
	unsigned long flags;

	if ((fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) !=
	    (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK))
		return 0;

	q = &zd_hw_mac(hw)->ack_wait_queue;
	spin_lock_irqsave(&q->lock, flags);
	for (skb = q->next; skb != (struct sk_buff *)q; skb = skb->next) {
		struct ieee80211_hdr *tx_hdr;

		tx_hdr = (struct ieee80211_hdr *)skb->data;
		if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
		{
			struct ieee80211_tx_status status;

			memset(&status, 0, sizeof(status));
			status.flags = IEEE80211_TX_STATUS_ACK;
			status.ack_signal = stats->ssi;
			__skb_unlink(skb, q);
			tx_status(hw, skb, &status, 1);
			goto out;
		}
	}
out:
	spin_unlock_irqrestore(&q->lock, flags);
	return 1;
}
Пример #3
0
static int term_putchar(char c)
{
    u32 stat;

    stat = tx_status(term0_reg);
    if (stat != ST_READY && stat != ST_TRANSMITTED)
        return -1;

    term0_reg->transm_command = ((c << CHAR_OFFSET) | CMD_TRANSMIT);

    while ((stat = tx_status(term0_reg)) == ST_BUSY)
        ;

    term0_reg->transm_command = CMD_ACK;

    if (stat != ST_TRANSMITTED)
        return -1;
    else
        return 0;
}
Пример #4
0
/**
 * zd_mac_tx_failed - callback for failed frames
 * @dev: the mac80211 wireless device
 *
 * This function is called if a frame couldn't be succesfully be
 * transferred. The first frame from the tx queue, will be selected and
 * reported as error to the upper layers.
 */
void zd_mac_tx_failed(struct ieee80211_hw *hw)
{
	struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue;
	struct sk_buff *skb;
	struct ieee80211_tx_status status;

	skb = skb_dequeue(q);
	if (skb == NULL)
		return;

	memset(&status, 0, sizeof(status));

	tx_status(hw, skb, &status, 0);
}
Пример #5
0
Файл: spi.c Проект: longsleep/ec
/**
 * Get ready to receive a message from the master.
 *
 * Set up our RX DMA and disable our TX DMA. Set up the data output so that
 * we will send preamble bytes.
 */
static void setup_for_transaction(void)
{
	stm32_spi_regs_t *spi = STM32_SPI1_REGS;
	volatile uint8_t dummy __attribute__((unused));

	/* clear this as soon as possible */
	setup_transaction_later = 0;

	/* Not ready to receive yet */
	tx_status(EC_SPI_NOT_READY);

	/* We are no longer actively processing a transaction */
	state = SPI_STATE_PREPARE_RX;

	/* Stop sending response, if any */
	dma_disable(STM32_DMAC_SPI1_TX);

	/*
	 * Read dummy bytes in case there are some pending; this prevents the
	 * receive DMA from getting that byte right when we start it.
	 */
	dummy = spi->dr;
#ifdef CHIP_FAMILY_STM32F0
	/* 4 Bytes makes sure the RX FIFO on the F0 is empty as well. */
	dummy = spi->dr;
	dummy = spi->dr;
	dummy = spi->dr;
#endif

	/* Start DMA */
	dma_start_rx(&dma_rx_option, sizeof(in_msg), in_msg);

	/* Ready to receive */
	state = SPI_STATE_READY_TO_RX;
	tx_status(EC_SPI_OLD_READY);
}
Пример #6
0
static void usb_rx_data_complete(struct usb_request *req, unsigned actual, int status)
{
    if(status != 0) return;

    if(actual > rx_length) {
        actual = rx_length;
    }

    rx_addr += actual;
    rx_length -= actual;
    
    if(rx_length > 0) {
        rx_data();
    } else {
        tx_status("OKAY");
        rx_cmd();
    }
}
Пример #7
0
static void
ieee_mcpspt(MAC_McpsDcfmInd_s *ev)
  /* packet input and output thread */
{
  rimeaddr_t rime;
  switch(ev->u8Type)
  {
    case MAC_MCPS_IND_DATA:
      GDB2_PUTS(",");
      /* new frame received */
      packetbuf_clear();
      packetbuf_copyfrom(asdataframe(ev).au8Sdu,
          asdataframe(ev).u8SduLength);
      packetbuf_set_datalen(asdataframe(ev).u8SduLength);
      packetbuf_set_addr(PACKETBUF_ADDR_SENDER,
          asrimeaddr(&asdataframe(ev).sSrcAddr.uAddr.sExt, &rime));

      if(asdataframe(ev).sDstAddr.u8AddrMode==LONG) {
        /* addressed frame */
        packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER,
            asrimeaddr(&asdataframe(ev).sDstAddr.uAddr.sExt, &rime));
      } else if(asdataframe(ev).sDstAddr.u8AddrMode==SHORT &&
         asdataframe(ev).sDstAddr.u16PanId==BROADCAST_PANID &&
         asdataframe(ev).sDstAddr.uAddr.u16Short==BROADCAST_ADDR) {
        /* broadcast frame */
        packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null);
      }

      /* update lqi stuff and call lqi callback */
      packetbuf_set_attr(PACKETBUF_ATTR_RSSI, asdataframe(ev).u8LinkQuality);

      if (asdataframe(ev).sSrcAddr.u8AddrMode == LONG && lqicb)
        lqicb(asrimeaddr(&asdataframe(ev).sSrcAddr.uAddr.sExt, &rime),
              asdataframe(ev).u8LinkQuality);
      else if (lqicb)
        lqicb(NULL, asdataframe(ev).u8LinkQuality);

#if USE_TS
      current_timestamp = asdataframe(ev).timestamp;
#endif

      //{
      //  static char buf[512];
      //  uint8_t i;
      //  uint16_t j;
      //  printf("delay:%d len:%d data:", (int32_t) (clock_hrtime()-asdataframe(ev).timestamp), asdataframe(ev).u8SduLength);
      //  for (i=0,j=0; i<asdataframe(ev).u8SduLength; i++)
      //    j+=snprintf(buf+j,sizeof(buf)-j,"0x%x ",asdataframe(ev).au8Sdu[i]);
      //  buf[j]='\n';

      //  puts(buf);
      //}

      /* call upper layer */
      NETSTACK_NETWORK.input();
      break;
    case MAC_MCPS_DCFM_DATA:
      mac_call_sent_callback(mac_cb, mac_cb_ptr, tx_status(&asdataind(ev)), 1);
      break;
    case MAC_MCPS_DCFM_PURGE:
    default:
      HAL_BREAKPOINT();
      break;
  }
}
Пример #8
0
static void usb_rx_cmd_complete(struct usb_request *req, unsigned actual, int status)
{
    if(status != 0) return;
    
    if(actual > 4095) actual = 4095;    
    cmdbuf[actual] = 0;

    dprintf("\n> %s\n",cmdbuf);
    
//    dprintf("usb_rx_cmd_complete() '%s'\n", cmdbuf);  
    
    if(memcmp(cmdbuf, "reboot", 6) == 0) {
        tx_status("OKAY");
        rx_cmd();
        mdelay(100);
        board_reboot();
    }
#if 0
    if(memcmp(cmdbuf, "debug:", 6) == 0) {
        void debug(char *cmd, char *resp);
        memcpy(cmdbuf, "OKAY", 5);
        tx_status(cmdbuf);
        rx_cmd();
        mdelay(5000);
        dprintf("NOW!\n");
        debug(cmdbuf + 6, cmdbuf + 4);
        return;
    }
#endif
    if(memcmp(cmdbuf, "getvar:", 7) == 0) {
        char response[64];
        strcpy(response,"OKAY");
        
        if(!strcmp(cmdbuf + 7, "version")) {
            strcpy(response + 4, VERSION);
        } else if(!strcmp(cmdbuf + 7, "product")) {
            strcpy(response + 4, PRODUCTNAME);
        } else if(!strcmp(cmdbuf + 7, "serialno")) {
            strcpy(response + 4, serialno);
        } else {
            board_getvar(cmdbuf + 7, response + 4);
        }
        tx_status(response);
        rx_cmd();
        return;
    }

    if(memcmp(cmdbuf, "download:", 9) == 0) {
        char status[16];
        rx_addr = kernel_addr;
        rx_length = hex2unsigned(cmdbuf + 9);
        if (rx_length > (64*1024*1024)) {
            tx_status("FAILdata too large");
            rx_cmd();
            return;
        }
        kernel_size = rx_length;
        dprintf("recv data addr=%x size=%x\n", rx_addr, rx_length); 
        strcpy(status,"DATA");
        num_to_hex8(rx_length, status + 4);
        tx_status(status);
        rx_data();
        return;
    }

    if(memcmp(cmdbuf, "erase:", 6) == 0){
        struct ptentry *ptn;
        ptn = flash_find_ptn(cmdbuf + 6);
        if(ptn == 0) {
            tx_status("FAILpartition does not exist");
            rx_cmd();
            return;
        }
        dprintf("erasing '%s'\n", ptn->name);
        cprintf("erasing '%s'", ptn->name);
        if(flash_erase(ptn)) {
            tx_status("FAILfailed to erase partition");
            rx_cmd();
            cprintf(" - FAIL\n");
            return;
        } else {
            dprintf("partition '%s' erased\n", ptn->name);
            cprintf(" - OKAY\n");
        }
        tx_status("OKAY");
        rx_cmd();
        return;
    }

    if(memcmp(cmdbuf, "flash:", 6) == 0){
        struct ptentry *ptn;
        int extra = 0;
        ptn = flash_find_ptn(cmdbuf + 6);
        if(kernel_size == 0) {
            tx_status("FAILno image downloaded");
            rx_cmd();
            return;
        }
        if(ptn == 0) {
            tx_status("FAILpartition does not exist");
            rx_cmd();
            return;
        }
        if(!strcmp(ptn->name,"boot") || !strcmp(ptn->name,"recovery")) {
            if(memcmp((void*) kernel_addr, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
                tx_status("FAILimage is not a boot image");
                rx_cmd();
                return;
            }
        }
#if REQUIRE_SIGNATURE
        {
            unsigned char digest[DIGEST_SIZE];
            compute_digest((void*) kernel_addr, kernel_size, digest);
            if (is_signature_okay(digest, signature, key_engineering)) {
                dprintf("verified by engineering key\n");
            } else {
                tx_status("FAILsignature did not verify");
                rx_cmd();
                return;
            }
        }
#endif
        if(!strcmp(ptn->name,"system") || !strcmp(ptn->name,"userdata")) {
            extra = 64;
        } else {
            kernel_size = (kernel_size + 2047) & (~2047);
        }
        dprintf("writing %d bytes to '%s'\n", 
                kernel_size, ptn->name);
        cprintf("writing '%s' (%d bytes)", ptn->name, kernel_size);
        if(flash_write(ptn, extra, (void*) kernel_addr, kernel_size)) {
            tx_status("FAILflash write failure");
            rx_cmd();
            cprintf(" - FAIL\n");
            return;
        } else {
            dprintf("partition '%s' updated\n", ptn->name);
            cprintf(" - OKAY\n");
        }
        tx_status("OKAY");
        rx_cmd();
        return;
    }
    if(memcmp(cmdbuf, "boot", 4) == 0) {
        if(init_boot_linux()) {
            tx_status("FAILinvalid boot image");
            rx_cmd();
            return;
        }
        dprintf("booting linux...\n");
        cprintf("\nbooting linux...\n");
        tx_status("OKAY");
        mdelay(10);
        usb_shutdown();
        boot_linux();
        return;
    }
    if(memcmp(cmdbuf, "signature", 9) == 0) {
        if (kernel_size != SIGNATURE_SIZE) {
            tx_status("FAILsignature not 256 bytes long");
            rx_cmd();
            return;
        }
        memcpy(signature, (void*)kernel_addr, SIGNATURE_SIZE);
        tx_status("OKAY");
        rx_cmd();
        return;
    }

    tx_status("FAILinvalid command");
    rx_cmd();
}
Пример #9
0
Файл: spi.c Проект: longsleep/ec
/**
 * Handle an event on the NSS pin
 *
 * A falling edge of NSS indicates that the master is starting a new
 * transaction. A rising edge indicates that we have finsihed
 *
 * @param signal	GPIO signal for the NSS pin
 */
void spi_event(enum gpio_signal signal)
{
	stm32_dma_chan_t *rxdma;
	uint16_t *nss_reg;
	uint32_t nss_mask;
	uint16_t i;

	/* If not enabled, ignore glitches on NSS */
	if (!enabled)
		return;

	/* Check chip select.  If it's high, the AP ended a transaction. */
	nss_reg = gpio_get_level_reg(GPIO_SPI1_NSS, &nss_mask);
	if (REG16(nss_reg) & nss_mask) {
		enable_sleep(SLEEP_MASK_SPI);

		/*
		 * If the buffer is still used by the host command, postpone
		 * the DMA rx setup.
		 */
		if (state == SPI_STATE_PROCESSING) {
			setup_transaction_later = 1;
			return;
		}

		/* Set up for the next transaction */
		spi_init(); /* Fix for bug chrome-os-partner:31390 */
		return;
	}
	disable_sleep(SLEEP_MASK_SPI);

	/* Chip select is low = asserted */
	if (state != SPI_STATE_READY_TO_RX) {
		/*
		 * AP started a transaction but we weren't ready for it.
		 * Tell AP we weren't ready, and ignore the received data.
		 */
		CPRINTS("SPI not ready");
		tx_status(EC_SPI_NOT_READY);
		state = SPI_STATE_RX_BAD;
		return;
	}

	/* We're now inside a transaction */
	state = SPI_STATE_RECEIVING;
	tx_status(EC_SPI_RECEIVING);
	rxdma = dma_get_channel(STM32_DMAC_SPI1_RX);

	/* Wait for version, command, length bytes */
	if (wait_for_bytes(rxdma, 3, nss_reg, nss_mask))
		goto spi_event_error;

	if (in_msg[0] == EC_HOST_REQUEST_VERSION) {
		/* Protocol version 3 */
		struct ec_host_request *r = (struct ec_host_request *)in_msg;
		int pkt_size;

		/* Wait for the rest of the command header */
		if (wait_for_bytes(rxdma, sizeof(*r), nss_reg, nss_mask))
			goto spi_event_error;

		/*
		 * Check how big the packet should be.  We can't just wait to
		 * see how much data the host sends, because it will keep
		 * sending dummy data until we respond.
		 */
		pkt_size = host_request_expected_size(r);
		if (pkt_size == 0 || pkt_size > sizeof(in_msg))
			goto spi_event_error;

		/* Wait for the packet data */
		if (wait_for_bytes(rxdma, pkt_size, nss_reg, nss_mask))
			goto spi_event_error;

		spi_packet.send_response = spi_send_response_packet;

		spi_packet.request = in_msg;
		spi_packet.request_temp = NULL;
		spi_packet.request_max = sizeof(in_msg);
		spi_packet.request_size = pkt_size;

		/* Response must start with the preamble */
		memcpy(out_msg, out_preamble, sizeof(out_preamble));
		spi_packet.response = out_msg + sizeof(out_preamble);
		/* Reserve space for the preamble and trailing past-end byte */
		spi_packet.response_max = sizeof(out_msg)
			- sizeof(out_preamble) - EC_SPI_PAST_END_LENGTH;
		spi_packet.response_size = 0;

		spi_packet.driver_result = EC_RES_SUCCESS;

		/* Move to processing state */
		state = SPI_STATE_PROCESSING;
		tx_status(EC_SPI_PROCESSING);

		host_packet_receive(&spi_packet);
		return;

	} else if (in_msg[0] >= EC_CMD_VERSION0) {
		/*
		 * Protocol version 2
		 *
		 * TODO(crosbug.com/p/20257): Remove once kernel supports
		 * version 3.
		 */

#ifdef CHIP_FAMILY_STM32F0
		CPRINTS("WARNING: Protocol version 2 is not supported on the F0"
			" line due to crbug.com/31390");
#endif

		args.version = in_msg[0] - EC_CMD_VERSION0;
		args.command = in_msg[1];
		args.params_size = in_msg[2];

		/* Wait for parameters */
		if (wait_for_bytes(rxdma, 3 + args.params_size,
				   nss_reg, nss_mask))
			goto spi_event_error;

		/*
		 * Params are not 32-bit aligned in protocol version 2.  As a
		 * workaround, move them to the beginning of the input buffer
		 * so they are aligned.
		 */
		if (args.params_size)
			memmove(in_msg, in_msg + 3, args.params_size);

		args.params = in_msg;
		args.send_response = spi_send_response;

		/* Allow room for the header bytes */
		args.response = out_msg + SPI_PROTO2_OFFSET;
		args.response_max = sizeof(out_msg) - SPI_PROTO2_OVERHEAD;
		args.response_size = 0;
		args.result = EC_RES_SUCCESS;

		/* Move to processing state */
		state = SPI_STATE_PROCESSING;
		tx_status(EC_SPI_PROCESSING);

		host_command_received(&args);
		return;
	}

 spi_event_error:
	/* Error, timeout, or protocol we can't handle.  Ignore data. */
	tx_status(EC_SPI_RX_BAD_DATA);
	state = SPI_STATE_RX_BAD;
	CPRINTS("SPI rx bad data");

	CPRINTF("in_msg=[");
	for (i = 0; i < dma_bytes_done(rxdma, sizeof(in_msg)); i++)
		CPRINTF("%02x ", in_msg[i]);
	CPRINTF("]\n");
}