コード例 #1
0
void zmq::stream_engine_t::in_event ()
{
    zmq_assert (!io_error);

    //  If still handshaking, receive and process the greeting message.
    if (unlikely (handshaking))
        if (!handshake ())
            return;

    zmq_assert (decoder);

    //  If there has been an I/O error, stop polling.
    if (input_stopped) {
        rm_fd (handle);
        io_error = true;
        return;
    }

    //  If there's no data to process in the buffer...
    if (!insize) {

        //  Retrieve the buffer and read as much data as possible.
        //  Note that buffer can be arbitrarily large. However, we assume
        //  the underlying TCP layer has fixed buffer size and thus the
        //  number of bytes read will be always limited.
        size_t bufsize = 0;
        decoder->get_buffer (&inpos, &bufsize);

        const int rc = tcp_read (s, inpos, bufsize);

        if (rc == 0) {
            error (connection_error);
            return;
        }
        if (rc == -1) {
            if (errno != EAGAIN)
                error (connection_error);
            return;
        }

        //  Adjust input size
        insize = static_cast <size_t> (rc);
        // Adjust buffer size to received bytes
        decoder->resize_buffer(insize);
    }

    int rc = 0;
    size_t processed = 0;

    while (insize > 0) {
        rc = decoder->decode (inpos, insize, processed);
        zmq_assert (processed <= insize);
        inpos += processed;
        insize -= processed;
        if (rc == 0 || rc == -1)
            break;
        rc = (this->*process_msg) (decoder->msg ());
        if (rc == -1)
            break;
    }

    //  Tear down the connection if we have failed to decode input data
    //  or the session has rejected the message.
    if (rc == -1) {
        if (errno != EAGAIN) {
            error (protocol_error);
            return;
        }
        input_stopped = true;
        reset_pollin (handle);
    }

    session->flush ();
}
コード例 #2
0
ファイル: gtls.c プロジェクト: DarkSpiritNET/NeoStats
/*
 * This function is called after the TCP connect has completed. Setup the TLS
 * layer and do all necessary magic.
 */
CURLcode
Curl_gtls_connect(struct connectdata *conn,
                  int sockindex)

{
  static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
  struct SessionHandle *data = conn->data;
  gnutls_session session;
  int rc;
  unsigned int cert_list_size;
  const gnutls_datum *chainp;
  unsigned int verify_status;
  gnutls_x509_crt x509_cert;
  char certbuf[256]; /* big enough? */
  size_t size;
  unsigned int algo;
  unsigned int bits;
  time_t clock;
  const char *ptr;
  void *ssl_sessionid;
  size_t ssl_idsize;

  if (!gtls_inited) _Curl_gtls_init();
  /* GnuTLS only supports TLSv1 (and SSLv3?) */
  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    failf(data, "GnuTLS does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* allocate a cred struct */
  rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
  if(rc < 0) {
    failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
    return CURLE_SSL_CONNECT_ERROR;
  }

  if(data->set.ssl.CAfile) {
    /* set the trusted CA cert bundle file */
    gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);

    rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
                                                data->set.ssl.CAfile,
                                                GNUTLS_X509_FMT_PEM);
    if(rc < 0) {
      infof(data, "error reading ca cert file %s (%s)\n",
            data->set.ssl.CAfile, gnutls_strerror(rc));
      if (data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
    else
      infof(data, "found %d certificates in %s\n",
            rc, data->set.ssl.CAfile);
  }

  /* Initialize TLS session as a client */
  rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
  if(rc) {
    failf(data, "gnutls_init() failed: %d", rc);
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* convenient assign */
  session = conn->ssl[sockindex].session;

  /* Use default priorities */
  rc = gnutls_set_default_priority(session);
  if(rc < 0)
    return CURLE_SSL_CONNECT_ERROR;

  /* Sets the priority on the certificate types supported by gnutls. Priority
     is higher for types specified before others. After specifying the types
     you want, you must append a 0. */
  rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
  if(rc < 0)
    return CURLE_SSL_CONNECT_ERROR;

  if(data->set.str[STRING_CERT]) {
    if( gnutls_certificate_set_x509_key_file(
          conn->ssl[sockindex].cred,
          data->set.str[STRING_CERT],
          data->set.str[STRING_KEY] ?
          data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
          do_file_type(data->set.str[STRING_CERT_TYPE]) ) ) {
      failf(data, "error reading X.509 key or certificate file");
      return CURLE_SSL_CONNECT_ERROR;
    }
  }

  /* put the credentials to the current session */
  rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
                              conn->ssl[sockindex].cred);

  /* set the connection handle (file descriptor for the socket) */
  gnutls_transport_set_ptr(session,
                           (gnutls_transport_ptr)conn->sock[sockindex]);

  /* register callback functions to send and receive data. */
  gnutls_transport_set_push_function(session, Curl_gtls_push);
  gnutls_transport_set_pull_function(session, Curl_gtls_pull);

  /* lowat must be set to zero when using custom push and pull functions. */
  gnutls_transport_set_lowat(session, 0);

  /* This might be a reconnect, so we check for a session ID in the cache
     to speed up things */

  if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
    /* we got a session id, use it! */
    gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);

    /* Informational message */
    infof (data, "SSL re-using session ID\n");
  }

  rc = handshake(conn, session, sockindex, TRUE);
  if(rc)
    /* handshake() sets its own error message with failf() */
    return rc;

  /* This function will return the peer's raw certificate (chain) as sent by
     the peer. These certificates are in raw format (DER encoded for
     X.509). In case of a X.509 then a certificate list may be present. The
     first certificate in the list is the peer's certificate, following the
     issuer's certificate, then the issuer's issuer etc. */

  chainp = gnutls_certificate_get_peers(session, &cert_list_size);
  if(!chainp) {
    if(data->set.ssl.verifyhost) {
      failf(data, "failed to get server cert");
      return CURLE_PEER_FAILED_VERIFICATION;
    }
    infof(data, "\t common name: WARNING couldn't obtain\n");
  }

  /* This function will try to verify the peer's certificate and return its
     status (trusted, invalid etc.). The value of status should be one or more
     of the gnutls_certificate_status_t enumerated elements bitwise or'd. To
     avoid denial of service attacks some default upper limits regarding the
     certificate key size and chain size are set. To override them use
     gnutls_certificate_set_verify_limits(). */

  rc = gnutls_certificate_verify_peers2(session, &verify_status);
  if (rc < 0) {
    failf(data, "server cert verify failed: %d", rc);
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* verify_status is a bitmask of gnutls_certificate_status bits */
  if(verify_status & GNUTLS_CERT_INVALID) {
    if (data->set.ssl.verifypeer) {
      failf(data, "server certificate verification failed. CAfile: %s",
            data->set.ssl.CAfile?data->set.ssl.CAfile:"none");
      return CURLE_SSL_CACERT;
    }
    else
      infof(data, "\t server certificate verification FAILED\n");
  }
  else
      infof(data, "\t server certificate verification OK\n");

  /* initialize an X.509 certificate structure. */
  gnutls_x509_crt_init(&x509_cert);

  /* convert the given DER or PEM encoded Certificate to the native
     gnutls_x509_crt_t format */
  gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);

  size=sizeof(certbuf);
  rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
                                     0, /* the first and only one */
                                     FALSE,
                                     certbuf,
                                     &size);
  if(rc) {
    infof(data, "error fetching CN from cert:%s\n",
          gnutls_strerror(rc));
  }

  /* This function will check if the given certificate's subject matches the
     given hostname. This is a basic implementation of the matching described
     in RFC2818 (HTTPS), which takes into account wildcards, and the subject
     alternative name PKIX extension. Returns non zero on success, and zero on
     failure. */
  rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);

  if(!rc) {
    if (data->set.ssl.verifyhost > 1) {
      failf(data, "SSL: certificate subject name (%s) does not match "
            "target host name '%s'", certbuf, conn->host.dispname);
      gnutls_x509_crt_deinit(x509_cert);
      return CURLE_PEER_FAILED_VERIFICATION;
    }
    else
      infof(data, "\t common name: %s (does not match '%s')\n",
            certbuf, conn->host.dispname);
  }
  else
    infof(data, "\t common name: %s (matched)\n", certbuf);

  /* Check for time-based validity */
  clock = gnutls_x509_crt_get_expiration_time(x509_cert);

  if(clock == (time_t)-1) {
    failf(data, "server cert expiration date verify failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  if(clock < time(NULL)) {
    if (data->set.ssl.verifypeer) {
      failf(data, "server certificate expiration date has passed.");
      return CURLE_PEER_FAILED_VERIFICATION;
    }
    else
      infof(data, "\t server certificate expiration date FAILED\n");
  }
  else
    infof(data, "\t server certificate expiration date OK\n");

  clock = gnutls_x509_crt_get_activation_time(x509_cert);

  if(clock == (time_t)-1) {
    failf(data, "server cert activation date verify failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  if(clock > time(NULL)) {
    if (data->set.ssl.verifypeer) {
      failf(data, "server certificate not activated yet.");
      return CURLE_PEER_FAILED_VERIFICATION;
    }
    else
      infof(data, "\t server certificate activation date FAILED\n");
  }
  else
    infof(data, "\t server certificate activation date OK\n");

  /* Show:

  - ciphers used
  - subject
  - start date
  - expire date
  - common name
  - issuer

  */

  /* public key algorithm's parameters */
  algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
  infof(data, "\t certificate public key: %s\n",
        gnutls_pk_algorithm_get_name(algo));

  /* version of the X.509 certificate. */
  infof(data, "\t certificate version: #%d\n",
        gnutls_x509_crt_get_version(x509_cert));


  size = sizeof(certbuf);
  gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
  infof(data, "\t subject: %s\n", certbuf);

  clock = gnutls_x509_crt_get_activation_time(x509_cert);
  showtime(data, "start date", clock);

  clock = gnutls_x509_crt_get_expiration_time(x509_cert);
  showtime(data, "expire date", clock);

  size = sizeof(certbuf);
  gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
  infof(data, "\t issuer: %s\n", certbuf);

  gnutls_x509_crt_deinit(x509_cert);

  /* compression algorithm (if any) */
  ptr = gnutls_compression_get_name(gnutls_compression_get(session));
  /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
  infof(data, "\t compression: %s\n", ptr);

  /* the name of the cipher used. ie 3DES. */
  ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
  infof(data, "\t cipher: %s\n", ptr);

  /* the MAC algorithms name. ie SHA1 */
  ptr = gnutls_mac_get_name(gnutls_mac_get(session));
  infof(data, "\t MAC: %s\n", ptr);

  if(!ssl_sessionid) {
    /* this session was not previously in the cache, add it now */

    /* get the session ID data size */
    gnutls_session_get_data(session, NULL, &ssl_idsize);
    ssl_sessionid = malloc(ssl_idsize); /* get a buffer for it */

    if(ssl_sessionid) {
      /* extract session ID to the allocated buffer */
      gnutls_session_get_data(session, ssl_sessionid, &ssl_idsize);

      /* store this session id */
      return Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_idsize);
    }
  }

  return CURLE_OK;
}
コード例 #3
0
 void
 RTMPSession::dataReceived()
 {
     
     static uint8_t buffer[4096] = {0};
     bool stop1 = false;
     bool stop2 = false;
     do {
         
         size_t maxlen = m_streamInBuffer->total() - m_streamInBuffer->size();
         size_t len = m_streamSession->read(buffer, maxlen);
         
         m_streamInBuffer->put(&buffer[0], len);
         
         while(m_streamInBuffer->size() > 0 && !stop1) {
             
             switch(m_state) {
                 case kClientStateHandshake1s0:
                 {
                     uint8_t s0 ;
                     m_streamInBuffer->get(&s0, 1);
                     
                     if(s0 == 0x03) {
                         setClientState(kClientStateHandshake1s1);
                     }
                 }
                     break;
                     
                 case kClientStateHandshake1s1:
                 {
                     if(m_streamInBuffer->size() >= kRTMPSignatureSize) {
                         
                         uint8_t buf[kRTMPSignatureSize];
                         size_t size = m_streamInBuffer->get(buf, kRTMPSignatureSize);
                         m_s1.resize(size);
                         m_s1.put(buf, size);
                         handshake();
                     } else {
                         stop1 = true;
                     }
                 }
                     break;
                 case kClientStateHandshake2:
                 {
                     if(m_streamInBuffer->size() >= kRTMPSignatureSize) {
                         uint8_t buf[kRTMPSignatureSize];
                         m_streamInBuffer->get(buf, kRTMPSignatureSize);
                         
                         setClientState(kClientStateHandshakeComplete);
                         handshake();
                         sendConnectPacket();
                     } else {
                         stop1 = true;
                     }
                 }
                     break;
                 default:
                 {
                     if(!parseCurrentData()) {
                         // the buffer seems corrupted.
                         stop1 = stop2 = true;
                     }
                 }
             }
         }
         
     } while((m_streamSession->status() & kStreamStatusReadBufferHasBytes) && !stop2);
 }
コード例 #4
0
static jdwpTransportError JNICALL
socketTransport_attach(jdwpTransportEnv* env, const char* addressString, jlong attachTimeout,
		       jlong handshakeTimeout)
{
    struct sockaddr_in sa;
    int err;

    if (addressString == NULL || addressString[0] == '\0') {
	RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "address is missing");
    }
     
    err = parseAddress(addressString, &sa, 0x7f000001);
    if (err != JDWPTRANSPORT_ERROR_NONE) {
        return err;
    }

    socketFD = dbgsysSocket(AF_INET, SOCK_STREAM, 0);
    if (socketFD < 0) {
	RETURN_IO_ERROR("unable to create socket");
    }

    err = setOptions(socketFD);
    if (err) {
        return err;
    }

    /* 
     * To do a timed connect we make the socket non-blocking
     * and poll with a timeout;
     */
    if (attachTimeout > 0) {
        dbgsysConfigureBlocking(socketFD, JNI_FALSE);
    }

    err = dbgsysConnect(socketFD, (struct sockaddr *)&sa, sizeof(sa));
    if (err == DBG_EINPROGRESS && attachTimeout > 0) {
	err = dbgsysFinishConnect(socketFD, (long)attachTimeout);

	if (err == DBG_ETIMEOUT) {
	    dbgsysConfigureBlocking(socketFD, JNI_TRUE);
	    RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "connect timed out");
	}
    }

    if (err < 0) {
	RETURN_IO_ERROR("connect failed");
    }

    if (attachTimeout > 0) {
	dbgsysConfigureBlocking(socketFD, JNI_TRUE); 
    }

    err = handshake(socketFD, handshakeTimeout);
    if (err) {
	dbgsysSocketClose(socketFD);
	socketFD = -1;
 	return err;
    }

    return JDWPTRANSPORT_ERROR_NONE;
}
コード例 #5
0
ファイル: dsp56k.c プロジェクト: dmgerman/linux-pre-history
static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
			    loff_t *ppos)
{
	struct inode *inode = file->f_dentry->d_inode;
	int dev = MINOR(inode->i_rdev) & 0x0f;

	switch(dev)
	{
	case DSP56K_DEV_56001:
	{
		long n;

		/* Don't do anything if nothing is to be done */
		if (!count) return 0;

		n = 0;
		switch (dsp56k.tx_wsize) {
		case 1:  /* 8 bit */
		{
			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
				  get_user(dsp56k_host_interface.data.b[3], buf+n++));
			return n;
		}
		case 2:  /* 16 bit */
		{
			short *data;

			count /= 2;
			data = (short*) buf;
			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
				  get_user(dsp56k_host_interface.data.w[1], data+n++));
			return 2*n;
		}
		case 3:  /* 24 bit */
		{
			count /= 3;
			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
				  get_user(dsp56k_host_interface.data.b[1], buf+n++);
				  get_user(dsp56k_host_interface.data.b[2], buf+n++);
				  get_user(dsp56k_host_interface.data.b[3], buf+n++));
			return 3*n;
		}
		case 4:  /* 32 bit */
		{
			long *data;

			count /= 4;
			data = (long*) buf;
			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
				  get_user(dsp56k_host_interface.data.l, data+n++));
			return 4*n;
		}
		}

		return -EFAULT;
	}
	default:
		printk("DSP56k driver: Unknown minor device: %d\n", dev);
		return -ENXIO;
	}
}
コード例 #6
0
static int tegra_ehci_hub_control(
	struct usb_hcd	*hcd,
	u16		typeReq,
	u16		wValue,
	u16		wIndex,
	char		*buf,
	u16		wLength
)
{
	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
	int		ports = HCS_N_PORTS(ehci->hcs_params);
	u32		temp, status;
	u32 __iomem	*status_reg;
	u32		usbsts_reg;

	unsigned long	flags;
	int		retval = 0;
	unsigned	selector;
	struct		tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	bool		hsic = false;
	bool do_post_resume = false;

	//mutex_lock(&tegra->tegra_ehci_hcd_mutex);
	if (!tegra->host_resumed) {
		if (buf)
			memset (buf, 0, wLength);
		//mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
		return retval;
	}

	hsic = (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC);

	status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];

	spin_lock_irqsave(&ehci->lock, flags);

	/*
	 * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
	 * that are write on clear, by writing back the register read value, so
	 * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
	 */
	if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
		temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
		ehci_writel(ehci, temp & ~PORT_PE, status_reg);
		goto done;
	} else if (typeReq == GetPortStatus) {
		temp = ehci_readl(ehci, status_reg);
		if (tegra->port_resuming && !(temp & PORT_SUSPEND) &&
			time_after_eq(jiffies, ehci->reset_done[wIndex-1])) {
			clear_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
			ehci->reset_done[wIndex-1] = 0;
			do_post_resume = true;
		} else if (tegra->port_resuming && (temp & PORT_RESUME) &&
			time_after_eq(jiffies, ehci->reset_done[wIndex-1]) ) {
			do_post_resume = true;
		}

		if (do_post_resume) {
			tegra->port_resuming = 0;
			tegra_usb_phy_postresume(tegra->phy, false);
			if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
				ehci->command |= CMD_RUN;
				/*
				 * ehci run bit is disabled to avoid SOF.
				 * 2LS WAR is executed by now enable the run bit.
				 */
				ehci_writel(ehci, ehci->command,
					&ehci->regs->command);
				/* Now we can safely re-enable irqs */
				ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
			}
		}

	} else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
		temp = ehci_readl(ehci, status_reg);
		if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
			retval = -EPIPE;
			goto done;
		}

		temp &= ~PORT_WKCONN_E;
		temp |= PORT_WKDISC_E | PORT_WKOC_E;
		ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);

		/* Need a 4ms delay before the controller goes to suspend */
		mdelay(4);

		/*
		 * If a transaction is in progress, there may be a delay in
		 * suspending the port. Poll until the port is suspended.
		 */
		if (handshake(ehci, status_reg, PORT_SUSPEND,
						PORT_SUSPEND, 5000))
			pr_err("%s: timeout waiting for SUSPEND\n", __func__);

		set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);

		if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
			/* Disable RUN bit. */
			ehci->command &= ~CMD_RUN;
			ehci_writel(ehci, ehci->command,
				&ehci->regs->command);
		}

		tegra_usb_phy_postsuspend(tegra->phy, false);

		goto done;
	}

	/*
	 * Tegra host controller will time the resume operation to clear the bit
	 * when the port control state switches to HS or FS Idle. This behavior
	 * is different from EHCI where the host controller driver is required
	 * to set this bit to a zero after the resume duration is timed in the
	 * driver.
	 */
	else if (typeReq == ClearPortFeature &&
					wValue == USB_PORT_FEAT_SUSPEND) {
		temp = ehci_readl(ehci, status_reg);
		if ((temp & PORT_RESET) || !(temp & PORT_PE)) {
			retval = -EPIPE;
			goto done;
		}

		if (!(temp & PORT_SUSPEND))
			goto done;

		tegra->port_resuming = 1;

		if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
			/* disable interrupts */
			ehci_writel(ehci, 0, &ehci->regs->intr_enable);
			/* Disable RUN bit. */
			ehci->command &= ~CMD_RUN;
			ehci_writel(ehci, ehci->command,
				&ehci->regs->command);
		}

		/* Disable disconnect detection during port resume */
		tegra_usb_phy_preresume(tegra->phy, false);
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
		if (tegra->phy->usb_phy_type != TEGRA_USB_PHY_TYPE_UTMIP) {
#endif
		ehci_dbg(ehci, "%s:USBSTS = 0x%x", __func__,
			ehci_readl(ehci, &ehci->regs->status));
		usbsts_reg = ehci_readl(ehci, &ehci->regs->status);
		ehci_writel(ehci, usbsts_reg, &ehci->regs->status);
		usbsts_reg = ehci_readl(ehci, &ehci->regs->status);
		udelay(20);

		if (handshake(ehci, &ehci->regs->status, STS_SRI, STS_SRI, 2000))
			pr_err("%s: timeout set for STS_SRI\n", __func__);

		usbsts_reg = ehci_readl(ehci, &ehci->regs->status);
		ehci_writel(ehci, usbsts_reg, &ehci->regs->status);

		if (handshake(ehci, &ehci->regs->status, STS_SRI, 0, 2000))
			pr_err("%s: timeout clear STS_SRI\n", __func__);

		if (handshake(ehci, &ehci->regs->status, STS_SRI, STS_SRI, 2000))
			pr_err("%s: timeout set STS_SRI\n", __func__);

		udelay(20);
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
		}
#endif
		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
		/* start resume signaling */
		ehci_writel(ehci, temp | PORT_RESUME, status_reg);

		ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
		/* whoever resumes must GetPortStatus to complete it!! */
		goto done;
	}

	/* Handle port reset here */
	if ((hsic) && (typeReq == SetPortFeature) &&
		((wValue == USB_PORT_FEAT_RESET) || (wValue == USB_PORT_FEAT_POWER))) {
		selector = wIndex >> 8;
		wIndex &= 0xff;
		if (!wIndex || wIndex > ports) {
			retval = -EPIPE;
			goto done;
		}
		wIndex--;
		status = 0;
		temp = ehci_readl(ehci, status_reg);
		if (temp & PORT_OWNER)
			goto done;
		temp &= ~PORT_RWC_BITS;

		switch (wValue) {
		case USB_PORT_FEAT_RESET:
		{
			if (temp & PORT_RESUME) {
				retval = -EPIPE;
				goto done;
			}
			/* line status bits may report this as low speed,
			* which can be fine if this root hub has a
			* transaction translator built in.
			*/
			if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
					&& !ehci_is_TDI(ehci) && PORT_USB11 (temp)) {
				ehci_dbg (ehci, "port %d low speed --> companion\n", wIndex + 1);
				temp |= PORT_OWNER;
				ehci_writel(ehci, temp, status_reg);
			} else {
				ehci_vdbg(ehci, "port %d reset\n", wIndex + 1);
				temp &= ~PORT_PE;
				/*
				* caller must wait, then call GetPortStatus
				* usb 2.0 spec says 50 ms resets on root
				*/
				ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(50);
				ehci_writel(ehci, temp, status_reg);
				if (hsic && (wIndex == 0))
					tegra_usb_phy_bus_reset(tegra->phy);
			}

			break;
		}
		case USB_PORT_FEAT_POWER:
		{
			if (HCS_PPC(ehci->hcs_params))
				ehci_writel(ehci, temp | PORT_POWER, status_reg);
			if (hsic && (wIndex == 0))
				tegra_usb_phy_bus_connect(tegra->phy);
			break;
		}
		}
		goto done;
	}
コード例 #7
0
 void handshake(handshake_type type, const ConstBufferSequence& buffers)
 {
   asio::error_code ec;
   handshake(type, buffers, ec);
   asio::detail::throw_error(ec, "handshake");
 }
コード例 #8
0
static int ehci_hub_control (
	struct usb_hcd	*hcd,
	u16		typeReq,
	u16		wValue,
	u16		wIndex,
	char		*buf,
	u16		wLength
) {
	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
	int		ports = HCS_N_PORTS (ehci->hcs_params);
	u32		temp, status;
	unsigned long	flags;
	int		retval = 0;

	/*
	 * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
	 * HCS_INDICATOR may say we can change LEDs to off/amber/green.
	 * (track current state ourselves) ... blink for diagnostics,
	 * power, "this is the one", etc.  EHCI spec supports this.
	 */

	spin_lock_irqsave (&ehci->lock, flags);
	switch (typeReq) {
	case ClearHubFeature:
		switch (wValue) {
		case C_HUB_LOCAL_POWER:
		case C_HUB_OVER_CURRENT:
			/* no hub-wide feature/status flags */
			break;
		default:
			goto error;
		}
		break;
	case ClearPortFeature:
		if (!wIndex || wIndex > ports)
			goto error;
		wIndex--;
		temp = readl (&ehci->regs->port_status [wIndex]);
		if (temp & PORT_OWNER)
			break;

		switch (wValue) {
		case USB_PORT_FEAT_ENABLE:
			writel (temp & ~PORT_PE,
				&ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_C_ENABLE:
			writel((temp & ~PORT_RWC_BITS) | PORT_PEC,
				&ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_SUSPEND:
			if (temp & PORT_RESET)
				goto error;
			if (temp & PORT_SUSPEND) {
				if ((temp & PORT_PE) == 0)
					goto error;
				/* resume signaling for 20 msec */
				temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
				writel (temp | PORT_RESUME,
					&ehci->regs->port_status [wIndex]);
				ehci->reset_done [wIndex] = jiffies
						+ msecs_to_jiffies (20);
			}
			break;
		case USB_PORT_FEAT_C_SUSPEND:
			/* we auto-clear this feature */
			break;
		case USB_PORT_FEAT_POWER:
			if (HCS_PPC (ehci->hcs_params))
				writel (temp & ~(PORT_RWC_BITS | PORT_POWER),
					&ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_C_CONNECTION:
			writel ((temp & ~PORT_RWC_BITS) | PORT_CSC,
				&ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_C_OVER_CURRENT:
			writel ((temp & ~PORT_RWC_BITS) | PORT_OCC,
				&ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_C_RESET:
			/* GetPortStatus clears reset */
			break;
		default:
			goto error;
		}
		readl (&ehci->regs->command);	/* unblock posted write */
		break;
	case GetHubDescriptor:
		ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
			buf);
		break;
	case GetHubStatus:
		/* no hub-wide feature/status flags */
		memset (buf, 0, 4);
		//cpu_to_le32s ((u32 *) buf);
		break;
	case GetPortStatus:
		if (!wIndex || wIndex > ports)
			goto error;
		wIndex--;
		status = 0;
		temp = readl (&ehci->regs->port_status [wIndex]);

		// wPortChange bits
		if (temp & PORT_CSC)
			status |= 1 << USB_PORT_FEAT_C_CONNECTION;
		if (temp & PORT_PEC)
			status |= 1 << USB_PORT_FEAT_C_ENABLE;
		if (temp & PORT_OCC)
			status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;

		/* whoever resumes must GetPortStatus to complete it!! */
		if ((temp & PORT_RESUME)
				&& time_after (jiffies,
					ehci->reset_done [wIndex])) {
			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
			ehci->reset_done [wIndex] = 0;

			/* stop resume signaling */
			temp = readl (&ehci->regs->port_status [wIndex]);
			writel (temp & ~(PORT_RWC_BITS | PORT_RESUME),
				&ehci->regs->port_status [wIndex]);
			retval = handshake (
					&ehci->regs->port_status [wIndex],
					PORT_RESUME, 0, 2000 /* 2msec */);
			if (retval != 0) {
				ehci_err (ehci, "port %d resume error %d\n",
					wIndex + 1, retval);
				goto error;
			}
			temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
		}

		/* whoever resets must GetPortStatus to complete it!! */
		if ((temp & PORT_RESET)
				&& time_after (jiffies,
					ehci->reset_done [wIndex])) {
			status |= 1 << USB_PORT_FEAT_C_RESET;
			ehci->reset_done [wIndex] = 0;

			/* force reset to complete */
			writel (temp & ~(PORT_RWC_BITS | PORT_RESET),
					&ehci->regs->port_status [wIndex]);
			retval = handshake (
					&ehci->regs->port_status [wIndex],
					PORT_RESET, 0, 500);
			if (retval != 0) {
				ehci_err (ehci, "port %d reset error %d\n",
					wIndex + 1, retval);
				goto error;
			}

			/* see what we found out */
			temp = check_reset_complete (ehci, wIndex,
				readl (&ehci->regs->port_status [wIndex]));
		}

		// don't show wPortStatus if it's owned by a companion hc
		if (!(temp & PORT_OWNER)) {
			if (temp & PORT_CONNECT) {
				status |= 1 << USB_PORT_FEAT_CONNECTION;
				// status may be from integrated TT
				status |= ehci_port_speed(ehci, temp);
			}
			if (temp & PORT_PE)
				status |= 1 << USB_PORT_FEAT_ENABLE;
			if (temp & (PORT_SUSPEND|PORT_RESUME))
				status |= 1 << USB_PORT_FEAT_SUSPEND;
			if (temp & PORT_OC)
				status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
			if (temp & PORT_RESET)
				status |= 1 << USB_PORT_FEAT_RESET;
			if (temp & PORT_POWER)
				status |= 1 << USB_PORT_FEAT_POWER;
		}

#ifndef	EHCI_VERBOSE_DEBUG
	if (status & ~0xffff)	/* only if wPortChange is interesting */
#endif
		dbg_port (ehci, "GetStatus", wIndex + 1, temp);
		// we "know" this alignment is good, caller used kmalloc()...
		*((__le32 *) buf) = cpu_to_le32 (status);
		break;
	case SetHubFeature:
		switch (wValue) {
		case C_HUB_LOCAL_POWER:
		case C_HUB_OVER_CURRENT:
			/* no hub-wide feature/status flags */
			break;
		default:
			goto error;
		}
		break;
	case SetPortFeature:
		if (!wIndex || wIndex > ports)
			goto error;
		wIndex--;
		temp = readl (&ehci->regs->port_status [wIndex]);
		if (temp & PORT_OWNER)
			break;

		temp &= ~PORT_RWC_BITS;
		switch (wValue) {
		case USB_PORT_FEAT_SUSPEND:
			if ((temp & PORT_PE) == 0
					|| (temp & PORT_RESET) != 0)
				goto error;
			if (ehci->hcd.remote_wakeup)
				temp |= PORT_WAKE_BITS;
			writel (temp | PORT_SUSPEND,
				&ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_POWER:
			if (HCS_PPC (ehci->hcs_params))
				writel (temp | PORT_POWER,
					&ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_RESET:
			if (temp & PORT_RESUME)
				goto error;
			/* line status bits may report this as low speed,
			 * which can be fine if this root hub has a
			 * transaction translator built in.
			 */
			if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
					&& !ehci_is_ARC(ehci)
					&& PORT_USB11 (temp)) {
				ehci_dbg (ehci,
					"port %d low speed --> companion\n",
					wIndex + 1);
				temp |= PORT_OWNER;
			} else {
				ehci_vdbg (ehci, "port %d reset\n", wIndex + 1);
				temp |= PORT_RESET;
				temp &= ~PORT_PE;

				/*
				 * caller must wait, then call GetPortStatus
				 * usb 2.0 spec says 50 ms resets on root
				 */
				ehci->reset_done [wIndex] = jiffies
						+ msecs_to_jiffies (50);
			}
			writel (temp, &ehci->regs->port_status [wIndex]);
			break;
		default:
			goto error;
		}
		readl (&ehci->regs->command);	/* unblock posted writes */
		break;

	default:
error:
		/* "stall" on error */
		retval = -EPIPE;
	}
	spin_unlock_irqrestore (&ehci->lock, flags);
	return retval;
}
コード例 #9
0
ファイル: ehci-hcd.c プロジェクト: tomstokes/u-boot
static int
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
		   int length, struct devrequest *req)
{
	ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN);
	struct qTD *qtd;
	int qtd_count = 0;
	int qtd_counter = 0;
	volatile struct qTD *vtd;
	unsigned long ts;
	uint32_t *tdp;
	uint32_t endpt, maxpacket, token, usbsts;
	uint32_t c, toggle;
	uint32_t cmd;
	int timeout;
	int ret = 0;
	struct ehci_ctrl *ctrl = dev->controller;

	debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
	      buffer, length, req);
	if (req != NULL)
		debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n",
		      req->request, req->request,
		      req->requesttype, req->requesttype,
		      le16_to_cpu(req->value), le16_to_cpu(req->value),
		      le16_to_cpu(req->index));

#define PKT_ALIGN	512
	/*
	 * The USB transfer is split into qTD transfers. Eeach qTD transfer is
	 * described by a transfer descriptor (the qTD). The qTDs form a linked
	 * list with a queue head (QH).
	 *
	 * Each qTD transfer starts with a new USB packet, i.e. a packet cannot
	 * have its beginning in a qTD transfer and its end in the following
	 * one, so the qTD transfer lengths have to be chosen accordingly.
	 *
	 * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to
	 * single pages. The first data buffer can start at any offset within a
	 * page (not considering the cache-line alignment issues), while the
	 * following buffers must be page-aligned. There is no alignment
	 * constraint on the size of a qTD transfer.
	 */
	if (req != NULL)
		/* 1 qTD will be needed for SETUP, and 1 for ACK. */
		qtd_count += 1 + 1;
	if (length > 0 || req == NULL) {
		/*
		 * Determine the qTD transfer size that will be used for the
		 * data payload (not considering the first qTD transfer, which
		 * may be longer or shorter, and the final one, which may be
		 * shorter).
		 *
		 * In order to keep each packet within a qTD transfer, the qTD
		 * transfer size is aligned to PKT_ALIGN, which is a multiple of
		 * wMaxPacketSize (except in some cases for interrupt transfers,
		 * see comment in submit_int_msg()).
		 *
		 * By default, i.e. if the input buffer is aligned to PKT_ALIGN,
		 * QT_BUFFER_CNT full pages will be used.
		 */
		int xfr_sz = QT_BUFFER_CNT;
		/*
		 * However, if the input buffer is not aligned to PKT_ALIGN, the
		 * qTD transfer size will be one page shorter, and the first qTD
		 * data buffer of each transfer will be page-unaligned.
		 */
		if ((uint32_t)buffer & (PKT_ALIGN - 1))
			xfr_sz--;
		/* Convert the qTD transfer size to bytes. */
		xfr_sz *= EHCI_PAGE_SIZE;
		/*
		 * Approximate by excess the number of qTDs that will be
		 * required for the data payload. The exact formula is way more
		 * complicated and saves at most 2 qTDs, i.e. a total of 128
		 * bytes.
		 */
		qtd_count += 2 + length / xfr_sz;
	}
/*
 * Threshold value based on the worst-case total size of the allocated qTDs for
 * a mass-storage transfer of 65535 blocks of 512 bytes.
 */
#if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024
#warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI
#endif
	qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD));
	if (qtd == NULL) {
		printf("unable to allocate TDs\n");
		return -1;
	}

	memset(qh, 0, sizeof(struct QH));
	memset(qtd, 0, qtd_count * sizeof(*qtd));

	toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));

	/*
	 * Setup QH (3.6 in ehci-r10.pdf)
	 *
	 *   qh_link ................. 03-00 H
	 *   qh_endpt1 ............... 07-04 H
	 *   qh_endpt2 ............... 0B-08 H
	 * - qh_curtd
	 *   qh_overlay.qt_next ...... 13-10 H
	 * - qh_overlay.qt_altnext
	 */
	qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH);
	c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe);
	maxpacket = usb_maxpacket(dev, pipe);
	endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
		QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) |
		QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) |
		QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) |
		QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) |
		QH_ENDPT1_DEVADDR(usb_pipedevice(pipe));
	qh->qh_endpt1 = cpu_to_hc32(endpt);
	endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0);
	qh->qh_endpt2 = cpu_to_hc32(endpt);
	ehci_update_endpt2_dev_n_port(dev, qh);
	qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
	qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);

	tdp = &qh->qh_overlay.qt_next;

	if (req != NULL) {
		/*
		 * Setup request qTD (3.5 in ehci-r10.pdf)
		 *
		 *   qt_next ................ 03-00 H
		 *   qt_altnext ............. 07-04 H
		 *   qt_token ............... 0B-08 H
		 *
		 *   [ buffer, buffer_hi ] loaded with "req".
		 */
		qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
		qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
		token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) |
			QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
			QT_TOKEN_PID(QT_TOKEN_PID_SETUP) |
			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
		if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) {
			printf("unable to construct SETUP TD\n");
			goto fail;
		}
		/* Update previous qTD! */
		*tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]);
		tdp = &qtd[qtd_counter++].qt_next;
		toggle = 1;
	}

	if (length > 0 || req == NULL) {
		uint8_t *buf_ptr = buffer;
		int left_length = length;

		do {
			/*
			 * Determine the size of this qTD transfer. By default,
			 * QT_BUFFER_CNT full pages can be used.
			 */
			int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE;
			/*
			 * However, if the input buffer is not page-aligned, the
			 * portion of the first page before the buffer start
			 * offset within that page is unusable.
			 */
			xfr_bytes -= (uint32_t)buf_ptr & (EHCI_PAGE_SIZE - 1);
			/*
			 * In order to keep each packet within a qTD transfer,
			 * align the qTD transfer size to PKT_ALIGN.
			 */
			xfr_bytes &= ~(PKT_ALIGN - 1);
			/*
			 * This transfer may be shorter than the available qTD
			 * transfer size that has just been computed.
			 */
			xfr_bytes = min(xfr_bytes, left_length);

			/*
			 * Setup request qTD (3.5 in ehci-r10.pdf)
			 *
			 *   qt_next ................ 03-00 H
			 *   qt_altnext ............. 07-04 H
			 *   qt_token ............... 0B-08 H
			 *
			 *   [ buffer, buffer_hi ] loaded with "buffer".
			 */
			qtd[qtd_counter].qt_next =
					cpu_to_hc32(QT_NEXT_TERMINATE);
			qtd[qtd_counter].qt_altnext =
					cpu_to_hc32(QT_NEXT_TERMINATE);
			token = QT_TOKEN_DT(toggle) |
				QT_TOKEN_TOTALBYTES(xfr_bytes) |
				QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) |
				QT_TOKEN_CERR(3) |
				QT_TOKEN_PID(usb_pipein(pipe) ?
					QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) |
				QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
			qtd[qtd_counter].qt_token = cpu_to_hc32(token);
			if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr,
						xfr_bytes)) {
				printf("unable to construct DATA TD\n");
				goto fail;
			}
			/* Update previous qTD! */
			*tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]);
			tdp = &qtd[qtd_counter++].qt_next;
			/*
			 * Data toggle has to be adjusted since the qTD transfer
			 * size is not always an even multiple of
			 * wMaxPacketSize.
			 */
			if ((xfr_bytes / maxpacket) & 1)
				toggle ^= 1;
			buf_ptr += xfr_bytes;
			left_length -= xfr_bytes;
		} while (left_length > 0);
	}

	if (req != NULL) {
		/*
		 * Setup request qTD (3.5 in ehci-r10.pdf)
		 *
		 *   qt_next ................ 03-00 H
		 *   qt_altnext ............. 07-04 H
		 *   qt_token ............... 0B-08 H
		 */
		qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
		qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
		token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) |
			QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
			QT_TOKEN_PID(usb_pipein(pipe) ?
				QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) |
			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
		/* Update previous qTD! */
		*tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]);
		tdp = &qtd[qtd_counter++].qt_next;
	}

	ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);

	/* Flush dcache */
	flush_dcache_range((uint32_t)&ctrl->qh_list,
		ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
	flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1));
	flush_dcache_range((uint32_t)qtd,
			   ALIGN_END_ADDR(struct qTD, qtd, qtd_count));

	/* Set async. queue head pointer. */
	ehci_writel(&ctrl->hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list);

	usbsts = ehci_readl(&ctrl->hcor->or_usbsts);
	ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f));

	/* Enable async. schedule. */
	cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
	cmd |= CMD_ASE;
	ehci_writel(&ctrl->hcor->or_usbcmd, cmd);

	ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS,
			100 * 1000);
	if (ret < 0) {
		printf("EHCI fail timeout STS_ASS set\n");
		goto fail;
	}

	/* Wait for TDs to be processed. */
	ts = get_timer(0);
	vtd = &qtd[qtd_counter - 1];
	timeout = USB_TIMEOUT_MS(pipe);
	do {
		/* Invalidate dcache */
		invalidate_dcache_range((uint32_t)&ctrl->qh_list,
			ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
		invalidate_dcache_range((uint32_t)qh,
			ALIGN_END_ADDR(struct QH, qh, 1));
		invalidate_dcache_range((uint32_t)qtd,
			ALIGN_END_ADDR(struct qTD, qtd, qtd_count));

		token = hc32_to_cpu(vtd->qt_token);
		if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE))
			break;
		WATCHDOG_RESET();
	} while (get_timer(ts) < timeout);

	/*
	 * Invalidate the memory area occupied by buffer
	 * Don't try to fix the buffer alignment, if it isn't properly
	 * aligned it's upper layer's fault so let invalidate_dcache_range()
	 * vow about it. But we have to fix the length as it's actual
	 * transfer length and can be unaligned. This is potentially
	 * dangerous operation, it's responsibility of the calling
	 * code to make sure enough space is reserved.
	 */
	invalidate_dcache_range((uint32_t)buffer,
		ALIGN((uint32_t)buffer + length, ARCH_DMA_MINALIGN));

	/* Check that the TD processing happened */
	if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)
		printf("EHCI timed out on TD - token=%#x\n", token);

	/* Disable async schedule. */
	cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
	cmd &= ~CMD_ASE;
	ehci_writel(&ctrl->hcor->or_usbcmd, cmd);

	ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0,
			100 * 1000);
	if (ret < 0) {
		printf("EHCI fail timeout STS_ASS reset\n");
		goto fail;
	}

	token = hc32_to_cpu(qh->qh_overlay.qt_token);
	if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) {
		debug("TOKEN=%#x\n", token);
		switch (QT_TOKEN_GET_STATUS(token) &
			~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) {
		case 0:
			toggle = QT_TOKEN_GET_DT(token);
			usb_settoggle(dev, usb_pipeendpoint(pipe),
				       usb_pipeout(pipe), toggle);
			dev->status = 0;
			break;
		case QT_TOKEN_STATUS_HALTED:
			dev->status = USB_ST_STALLED;
			break;
		case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR:
		case QT_TOKEN_STATUS_DATBUFERR:
			dev->status = USB_ST_BUF_ERR;
			break;
		case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET:
		case QT_TOKEN_STATUS_BABBLEDET:
			dev->status = USB_ST_BABBLE_DET;
			break;
		default:
			dev->status = USB_ST_CRC_ERR;
			if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED)
				dev->status |= USB_ST_STALLED;
			break;
		}
		dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token);
	} else {
		dev->act_len = 0;
#ifndef CONFIG_USB_EHCI_FARADAY
		debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
		      dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts),
		      ehci_readl(&ctrl->hcor->or_portsc[0]),
		      ehci_readl(&ctrl->hcor->or_portsc[1]));
#endif
	}

	free(qtd);
	return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;

fail:
	free(qtd);
	return -1;
}
コード例 #10
0
static int omap_ehci_hub_control(
	struct usb_hcd	*hcd,
	u16		typeReq,
	u16		wValue,
	u16		wIndex,
	char		*buf,
	u16		wLength
) {
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	u32 __iomem	*status_reg = &ehci->regs->port_status[
				(wIndex & 0xff) - 1];
	u32 __iomem	*hostpc_reg = NULL;
	u32		temp, temp1, status;
	unsigned long	flags;
	int		retval = 0;
	u32		runstop, temp_reg;

	spin_lock_irqsave(&ehci->lock, flags);
	switch (typeReq) {
	case GetPortStatus:
		wIndex--;
		status = 0;
		temp = ehci_readl(ehci, status_reg);

		/* wPortChange bits */
		if (temp & PORT_CSC)
			status |= USB_PORT_STAT_C_CONNECTION << 16;
		if (temp & PORT_PEC)
			status |= USB_PORT_STAT_C_ENABLE << 16;

		if ((temp & PORT_OCC) && !ignore_oc) {
			status |= USB_PORT_STAT_C_OVERCURRENT << 16;

			/*
			 * Hubs should disable port power on over-current.
			 * However, not all EHCI implementations do this
			 * automatically, even if they _do_ support per-port
			 * power switching; they're allowed to just limit the
			 * current.  khubd will turn the power back on.
			 */
			if (HCS_PPC(ehci->hcs_params)) {
				ehci_writel(ehci,
					temp & ~(PORT_RWC_BITS | PORT_POWER),
					status_reg);
			}
		}

		/* whoever resumes must GetPortStatus to complete it!! */
		if (temp & PORT_RESUME) {

			/* Remote Wakeup received? */
			if (!ehci->reset_done[wIndex]) {
				/* resume signaling for 20 msec */
				ehci->reset_done[wIndex] = jiffies
						+ msecs_to_jiffies(20);
				/* check the port again */
				mod_timer(&ehci_to_hcd(ehci)->rh_timer,
						ehci->reset_done[wIndex]);
			}

			/* resume completed? */
			else if (time_after_eq(jiffies,
					ehci->reset_done[wIndex])) {
				clear_bit(wIndex, &ehci->suspended_ports);
				set_bit(wIndex, &ehci->port_c_suspend);
				ehci->reset_done[wIndex] = 0;

				/*
				 * Workaround for OMAP errata:
				 * To Stop Resume Signalling, it is required
				 * to Stop the Host Controller and disable the
				 * TLL Functional Clock.
				 */

				/* Stop the Host Controller */
				runstop = ehci_readl(ehci,
							&ehci->regs->command);
				ehci_writel(ehci, (runstop & ~CMD_RUN),
							&ehci->regs->command);
				(void) ehci_readl(ehci, &ehci->regs->command);
				handshake(ehci, &ehci->regs->status,
							STS_HALT,
							STS_HALT,
							2000);

				temp_reg = omap_readl(L3INIT_HSUSBTLL_CLKCTRL);
				temp_reg &= ~(1 << 9);

				/* stop resume signaling */
				temp = ehci_readl(ehci, status_reg);
				ehci_writel(ehci,
					temp & ~(PORT_RWC_BITS | PORT_RESUME),
					status_reg);

				/* Disable the Channel 1 Optional Fclk */
				omap_writel(temp_reg, L3INIT_HSUSBTLL_CLKCTRL);

				retval = handshake(ehci, status_reg,
					   PORT_RESUME, 0, 2000 /* 2msec */);

				/*
				 * Enable the Host Controller and start the
				 * Channel 1 Optional Fclk since resume has
				 * finished.
				 */
				udelay(2);
				omap_writel((temp_reg | (1 << 9)),
						L3INIT_HSUSBTLL_CLKCTRL);
				ehci_writel(ehci, (runstop),
						&ehci->regs->command);
				(void) ehci_readl(ehci, &ehci->regs->command);

				if (retval != 0) {
					ehci_err(ehci,
						"port %d resume error %d\n",
						wIndex + 1, retval);
					spin_unlock_irqrestore(&ehci->lock,
									flags);
					return -EPIPE;
				}
				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
			}
		}

		/* whoever resets must GetPortStatus to complete it!! */
		if ((temp & PORT_RESET)
				&& time_after_eq(jiffies,
					ehci->reset_done[wIndex])) {
			status |= USB_PORT_STAT_C_RESET << 16;
			ehci->reset_done[wIndex] = 0;

			/* force reset to complete */
			ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
					status_reg);
			/* REVISIT:  some hardware needs 550+ usec to clear
			 * this bit; seems too long to spin routinely...
			 */
			retval = handshake(ehci, status_reg,
					PORT_RESET, 0, 1000);
			if (retval != 0) {
				ehci_err(ehci, "port %d reset error %d\n",
					wIndex + 1, retval);
				spin_unlock_irqrestore(&ehci->lock, flags);
				return -EPIPE;
			}

			/* see what we found out */
			temp = check_reset_complete(ehci, wIndex, status_reg,
					ehci_readl(ehci, status_reg));
		}

		if (!(temp & (PORT_RESUME|PORT_RESET)))
			ehci->reset_done[wIndex] = 0;

		/* transfer dedicated ports to the companion hc */
		if ((temp & PORT_CONNECT) &&
				test_bit(wIndex, &ehci->companion_ports)) {
			temp &= ~PORT_RWC_BITS;
			temp |= PORT_OWNER;
			ehci_writel(ehci, temp, status_reg);
			ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1);
			temp = ehci_readl(ehci, status_reg);
		}

		/*
		 * Even if OWNER is set, there's no harm letting khubd
		 * see the wPortStatus values (they should all be 0 except
		 * for PORT_POWER anyway).
		 */

		if (temp & PORT_CONNECT) {
			status |= USB_PORT_STAT_CONNECTION;
			/* status may be from integrated TT */
			if (ehci->has_hostpc) {
				temp1 = ehci_readl(ehci, hostpc_reg);
				status |= ehci_port_speed(ehci, temp1);
			} else
				status |= ehci_port_speed(ehci, temp);
		}
		if (temp & PORT_PE)
			status |= USB_PORT_STAT_ENABLE;

		/* maybe the port was unsuspended without our knowledge */
		if (temp & (PORT_SUSPEND|PORT_RESUME)) {
			status |= USB_PORT_STAT_SUSPEND;
		} else if (test_bit(wIndex, &ehci->suspended_ports)) {
			clear_bit(wIndex, &ehci->suspended_ports);
			ehci->reset_done[wIndex] = 0;
			if (temp & PORT_PE)
				set_bit(wIndex, &ehci->port_c_suspend);
		}

		if (temp & PORT_OC)
			status |= USB_PORT_STAT_OVERCURRENT;
		if (temp & PORT_RESET)
			status |= USB_PORT_STAT_RESET;
		if (temp & PORT_POWER)
			status |= USB_PORT_STAT_POWER;
		if (test_bit(wIndex, &ehci->port_c_suspend))
			status |= USB_PORT_STAT_C_SUSPEND << 16;

#ifndef	VERBOSE_DEBUG
	if (status & ~0xffff)	/* only if wPortChange is interesting */
#endif
		dbg_port(ehci, "GetStatus", wIndex + 1, temp);
		put_unaligned_le32(status, buf);
		break;
	default:
		spin_unlock_irqrestore(&ehci->lock, flags);
		retval = ehci_hub_control(hcd, typeReq, wValue, wIndex,
								buf, wLength);
		spin_lock_irqsave(&ehci->lock, flags);
	}
	spin_unlock_irqrestore(&ehci->lock, flags);
	return retval;
}
コード例 #11
0
int main(int argc, char **argv) {
    int sockfd; /* socket */
    int portno; /* port to listen on */
    struct sockaddr_in clientaddr; /* client addr */
    socklen_t clientlen; /* byte size of client's address */
    struct sockaddr_in serveraddr; /* server's addr */
    int optval; /* flag value for setsockopt */
    int fd;
    long file_size;
    long total_read = 0;
    unsigned char file_buf[MAX_SEQ_NUM_HALF];
    unsigned long lastbyteSent, lastbyteAcked, maxbyte;
    unsigned char *lastbyteSentPtr, *lastbyteAckedPtr, *maxbytePtr;
    clock_t clock_start, clock_end;
    bool eof = false;
    int dupAck = 0;
    map<uint16_t, clock_t> time_map;
    
    /* check command line arguments */
    if (argc != 3)
        error("Usage: ./server PORT-NUMBER FILE-NAME");
    portno = atoi(argv[1]);
    
    /* socket: create the parent socket */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
        error("ERROR opening socket");
    
    optval = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) == -1){
        perror("setsockopt");
        return 1;
    };
    
    /* build the server's Internet address */
    bzero((char *) &serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons((unsigned short)portno);
    
    /* bind: associate the parent socket with a port */
    if (::bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) == -1){
        perror("bind");
        return 2;
    }
    
    clientlen = sizeof(clientaddr);
    
    if (handshake(sockfd, clientaddr, clientlen) == USHRT_MAX)
        return 3;
    
    if ((fd = open(argv[2], O_RDONLY, 0644)) == -1){
        perror("open");
        return 4;
    }
    if ((file_size = lseek(fd, 0, SEEK_END)) == -1){
        perror("lseek");
        return 5;
    }
    if (lseek(fd, 0, SEEK_SET) == -1){
        perror("lseek");
        return 6;
    }
    
    maxbyte = lastbyteSent = lastbyteAcked = 0;
    maxbytePtr = lastbyteSentPtr = lastbyteAckedPtr = file_buf;
    clock_start = clock_end = clock();
    
    bool firstRTT = true;
    
    while (!(eof && lastbyteAcked == maxbyte))
    {
        for ( ; (lastbyteSent < maxbyte) && (unackedPackets < cwndPackets);
             (lastbyteSent += BUFSIZE) && (unackedPackets++))
        {
            segment seg;
            seg.setSeqnum(server_seq);
            int send_size;
            if ((maxbyte-lastbyteSent)/BUFSIZE >= 1)
                send_size = BUFSIZE;
            else
                send_size = (int)(maxbyte - lastbyteSent);
            
            if (lastbyteSentPtr + send_size > file_buf + MAX_SEQ_NUM_HALF)
            {
                unsigned char temp[BUFSIZE];
                long send_part2 = (lastbyteSentPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF);
                long send_part1 = send_size - send_part2;
                memcpy((char*)temp, (char*)lastbyteSentPtr, send_part1);
                memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2);
                unsigned char *send_buf = seg.encode(temp, send_size);
                sendto(sockfd, send_buf, send_size+HEADERSIZE, 0, (struct sockaddr *)&clientaddr, clientlen);
                lastbyteSentPtr = lastbyteSentPtr + send_size - MAX_SEQ_NUM_HALF;
            }
            else
            {
                unsigned char *send_buf = seg.encode(lastbyteSentPtr, send_size);
                sendto(sockfd, send_buf, send_size+HEADERSIZE, 0, (struct sockaddr *)&clientaddr, clientlen);
                lastbyteSentPtr = lastbyteSentPtr + send_size;
            }
            
            clock_t now = clock();
            time_map[server_seq] = now;
            
            cout << "Sending packet " << server_seq << " " << cwnd << " " << ssthresh << endl;
            server_seq = (server_seq + send_size) % MAX_SEQ_NUM;
        }
        
        while (true)
        {
            unsigned char recv_buf[HEADERSIZE];
            long recv_len;
            if ((recv_len = recvfrom(sockfd, recv_buf, HEADERSIZE, MSG_DONTWAIT,
                                     (struct sockaddr *) &clientaddr, &clientlen)) == -1)
            {
                if (errno != EWOULDBLOCK && errno != EAGAIN)
                    perror("recvfrom");
                break;
            }
            
            segment ack;
            ack.decode(recv_buf, HEADERSIZE);
            if (ack.getFlagack())
            {
                cout << "Receiving packet " << ack.getAcknum() << endl;
                
                if (ack.getAcknum() != server_ack)
                {
                    map<uint16_t, clock_t>::iterator it = time_map.find(server_ack);
                    if (it != time_map.end())
                    {
                        clock_t now, then;
                        now = clock();
                        then = it->second;
                        time_map.erase(server_ack);
                        
                        double sampleRTT = double(now - then) / CLOCKS_PER_SEC;
                        
                        if (firstRTT)
                        {
                            estimatedRTT = sampleRTT;
                            devRTT = sampleRTT / 2;
                            adaptiveRTO = estimatedRTT + 4 * devRTT;
                            timeout = adaptiveRTO;
                            firstRTT = false;
                        }
                        else
                        {
                            double difference = sampleRTT - estimatedRTT >= 0 ?
                                                sampleRTT - estimatedRTT : estimatedRTT - sampleRTT;
                            estimatedRTT = 0.875 * estimatedRTT + 0.125 * sampleRTT;
                            devRTT = 0.75 * devRTT + 0.25 * difference;
                            adaptiveRTO = estimatedRTT + 4 * devRTT;
                            timeout = adaptiveRTO;
                        }
                    }
                    
                    uint16_t diff;
                    if (ack.getAcknum() > server_ack)
                        diff = ack.getAcknum() - server_ack;
                    else
                        diff = MAX_SEQ_NUM - server_ack + ack.getAcknum();
                    
                    lastbyteAcked += diff;
                    if (lastbyteAckedPtr + diff > file_buf + MAX_SEQ_NUM_HALF)
                        lastbyteAckedPtr = lastbyteAckedPtr + diff - MAX_SEQ_NUM_HALF;
                    else
                        lastbyteAckedPtr = lastbyteAckedPtr + diff;
                    
                    server_ack = ack.getAcknum();
                    int num_acked = diff/BUFSIZE;
                    unackedPackets -= num_acked;
                    for (int i = 0; i < num_acked; i++)
                        updateCwnd();
                    
                    clock_start = clock_end = clock();
                    dupAck = 0;
                }
                else
                {
                    if (state != FASTRECOVERY)
                    {
                        dupAck++;
                        if (dupAck == 3)
                        {
                            state = FASTRECOVERY;
                            dupAck = 0;
                            
                            ssthresh = cwnd/2 < BUFSIZE ? BUFSIZE : cwnd/2;
                            ssthreshPackets = ssthresh / BUFSIZE;
                            cwnd = ssthresh + BUFSIZE*3;
                            cwndPackets = cwnd / BUFSIZE;
                            
                            segment seg;
                            seg.setSeqnum(server_ack);
                            int send_size;
                            if ((maxbyte-lastbyteAcked)/BUFSIZE >= 1)
                                send_size = BUFSIZE;
                            else
                                send_size = (int)(maxbyte - lastbyteAcked);
                            
                            if (lastbyteAckedPtr + send_size > file_buf + MAX_SEQ_NUM_HALF)
                            {
                                unsigned char temp[BUFSIZE];
                                long send_part2 = (lastbyteAckedPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF);
                                long send_part1 = send_size - send_part2;
                                memcpy((char*)temp, (char*)lastbyteAckedPtr, send_part1);
                                memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2);
                                unsigned char *send_buf = seg.encode(temp, send_size);
                                sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen);
                            }
                            else
                            {
                                unsigned char *send_buf = seg.encode(lastbyteAckedPtr, send_size);
                                sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen);
                            }
                            
                            cout << "Sending packet " << server_ack << " " << cwnd << " "
                            << ssthresh << " Retransmission" << endl;
                            clock_start = clock_end = clock();
                            time_map.erase(server_ack);
                        }
                    }
                    else
                    {
                        cwnd += BUFSIZE;
                        cwndPackets += 1;
                    }
                }
            }
        }
        
        clock_end = clock();
        double elapsed_secs = double(clock_end - clock_start) / CLOCKS_PER_SEC;
        if (elapsed_secs >= timeout)
        {
            state = SLOWSTART;
            dupAck = 0;
            
            ssthresh = cwnd/2 < BUFSIZE ? BUFSIZE : cwnd/2;
            ssthreshPackets = ssthresh / BUFSIZE;
            cwnd = BUFSIZE;
            cwndPackets = 1;
            
            segment seg;
            seg.setSeqnum(server_ack);
            int send_size;
            if ((maxbyte-lastbyteAcked)/BUFSIZE >= 1)
                send_size = BUFSIZE;
            else
                send_size = (int)(maxbyte - lastbyteAcked);
            
            if (lastbyteAckedPtr + send_size > file_buf + MAX_SEQ_NUM_HALF)
            {
                unsigned char temp[BUFSIZE];
                long send_part2 = (lastbyteAckedPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF);
                long send_part1 = send_size - send_part2;
                memcpy((char*)temp, (char*)lastbyteAckedPtr, send_part1);
                memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2);
                unsigned char *send_buf = seg.encode(temp, send_size);
                sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen);
            }
            else
            {
                unsigned char *send_buf = seg.encode(lastbyteAckedPtr, send_size);
                sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen);
            }
            
            cout << "Sending packet " << server_ack << " " << cwnd << " "
            << ssthresh << " Retransmission" << endl;
            clock_start = clock_end = clock();
            
            timeout *= 2;
            time_map.erase(server_ack);
        }
        
        if (maxbyte - lastbyteAcked <= MAX_SEQ_NUM_HALF)
        {
            long bytes_left = MAX_SEQ_NUM_HALF - (maxbyte - lastbyteAcked);
            long bytes_read = 0;
            long read_len;
            if (MAX_SEQ_NUM_HALF-(maxbytePtr-file_buf) < (bytes_left))
            {
                unsigned long part1 = MAX_SEQ_NUM_HALF - (maxbytePtr - file_buf);
                unsigned long part2 = bytes_left - part1;
                read_len = read(fd, maxbytePtr, part1);
                bytes_read += read_len;
                read_len = read(fd, file_buf, part2);
                bytes_read += read_len;
            }
            else
            {
                read_len = read(fd, maxbytePtr, bytes_left);
                bytes_read += read_len;
            }
            
            maxbyte += bytes_read;
            if (maxbytePtr + bytes_read > file_buf + MAX_SEQ_NUM_HALF)
                maxbytePtr = maxbytePtr + bytes_read - MAX_SEQ_NUM_HALF;
            else
                maxbytePtr = maxbytePtr + bytes_read;
            
            total_read += bytes_read;
            if (total_read == file_size)
                eof = true;
        }
    }
    
    teardown(sockfd, clientaddr, clientlen, 0, server_seq);
    
}
コード例 #12
0
ファイル: ehci-tegra.c プロジェクト: 119-org/hi3518-osdrv
static int tegra_usb_resume(struct usb_hcd *hcd)
{
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
	struct ehci_regs __iomem *hw = ehci->regs;
	unsigned long val;

	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	tegra_ehci_power_up(hcd);

	if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
		/* Wait for the phy to detect new devices
		 * before we restart the controller */
		msleep(10);
		goto restart;
	}

	/* Force the phy to keep data lines in suspend state */
	tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);

	/* Enable host mode */
	tdi_reset(ehci);

	/* Enable Port Power */
	val = readl(&hw->port_status[0]);
	val |= PORT_POWER;
	writel(val, &hw->port_status[0]);
	udelay(10);

	/* Check if the phy resume from LP0. When the phy resume from LP0
	 * USB register will be reset. */
	if (!readl(&hw->async_next)) {
		/* Program the field PTC based on the saved speed mode */
		val = readl(&hw->port_status[0]);
		val &= ~PORT_TEST(~0);
		if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
			val |= PORT_TEST_FORCE;
		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
			val |= PORT_TEST(6);
		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
			val |= PORT_TEST(7);
		writel(val, &hw->port_status[0]);
		udelay(10);

		/* Disable test mode by setting PTC field to NORMAL_OP */
		val = readl(&hw->port_status[0]);
		val &= ~PORT_TEST(~0);
		writel(val, &hw->port_status[0]);
		udelay(10);
	}

	/* Poll until CCS is enabled */
	if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
						 PORT_CONNECT, 2000)) {
		pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
		goto restart;
	}

	/* Poll until PE is enabled */
	if (handshake(ehci, &hw->port_status[0], PORT_PE,
						 PORT_PE, 2000)) {
		pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
		goto restart;
	}

	/* Clear the PCI status, to avoid an interrupt taken upon resume */
	val = readl(&hw->status);
	val |= STS_PCD;
	writel(val, &hw->status);

	/* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
	val = readl(&hw->port_status[0]);
	if ((val & PORT_POWER) && (val & PORT_PE)) {
		val |= PORT_SUSPEND;
		writel(val, &hw->port_status[0]);

		/* Wait until port suspend completes */
		if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
							 PORT_SUSPEND, 1000)) {
			pr_err("%s: timeout waiting for PORT_SUSPEND\n",
								__func__);
			goto restart;
		}
	}

	tegra_ehci_phy_restore_end(tegra->phy);
	return 0;

restart:
	if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
		tegra_ehci_phy_restore_end(tegra->phy);

	tegra_ehci_restart(hcd);
	return 0;
}
コード例 #13
0
ファイル: ehci-tegra.c プロジェクト: 119-org/hi3518-osdrv
static int tegra_ehci_hub_control(
	struct usb_hcd	*hcd,
	u16		typeReq,
	u16		wValue,
	u16		wIndex,
	char		*buf,
	u16		wLength
)
{
	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	u32 __iomem	*status_reg;
	u32		temp;
	unsigned long	flags;
	int		retval = 0;

	status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];

	spin_lock_irqsave(&ehci->lock, flags);

	/*
	 * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
	 * that are write on clear, by writing back the register read value, so
	 * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
	 */
	if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
		temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
		ehci_writel(ehci, temp & ~PORT_PE, status_reg);
		goto done;
	}

	else if (typeReq == GetPortStatus) {
		temp = ehci_readl(ehci, status_reg);
		if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
			/* Resume completed, re-enable disconnect detection */
			tegra->port_resuming = 0;
			tegra_usb_phy_postresume(tegra->phy);
		}
	}

	else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
		temp = ehci_readl(ehci, status_reg);
		if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
			retval = -EPIPE;
			goto done;
		}

		temp &= ~PORT_WKCONN_E;
		temp |= PORT_WKDISC_E | PORT_WKOC_E;
		ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);

		/*
		 * If a transaction is in progress, there may be a delay in
		 * suspending the port. Poll until the port is suspended.
		 */
		if (handshake(ehci, status_reg, PORT_SUSPEND,
						PORT_SUSPEND, 5000))
			pr_err("%s: timeout waiting for SUSPEND\n", __func__);

		set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
		goto done;
	}

	/* For USB1 port we need to issue Port Reset twice internally */
	if (tegra->phy->instance == 0 &&
	   (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) {
		spin_unlock_irqrestore(&ehci->lock, flags);
		return tegra_ehci_internal_port_reset(ehci, status_reg);
	}

	/*
	 * Tegra host controller will time the resume operation to clear the bit
	 * when the port control state switches to HS or FS Idle. This behavior
	 * is different from EHCI where the host controller driver is required
	 * to set this bit to a zero after the resume duration is timed in the
	 * driver.
	 */
	else if (typeReq == ClearPortFeature &&
					wValue == USB_PORT_FEAT_SUSPEND) {
		temp = ehci_readl(ehci, status_reg);
		if ((temp & PORT_RESET) || !(temp & PORT_PE)) {
			retval = -EPIPE;
			goto done;
		}

		if (!(temp & PORT_SUSPEND))
			goto done;

		/* Disable disconnect detection during port resume */
		tegra_usb_phy_preresume(tegra->phy);

		ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);

		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
		/* start resume signalling */
		ehci_writel(ehci, temp | PORT_RESUME, status_reg);

		spin_unlock_irqrestore(&ehci->lock, flags);
		msleep(20);
		spin_lock_irqsave(&ehci->lock, flags);

		/* Poll until the controller clears RESUME and SUSPEND */
		if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000))
			pr_err("%s: timeout waiting for RESUME\n", __func__);
		if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000))
			pr_err("%s: timeout waiting for SUSPEND\n", __func__);

		ehci->reset_done[wIndex-1] = 0;

		tegra->port_resuming = 1;
		goto done;
	}

	spin_unlock_irqrestore(&ehci->lock, flags);

	/* Handle the hub control events here */
	return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
done:
	spin_unlock_irqrestore(&ehci->lock, flags);
	return retval;
}
コード例 #14
0
network::connection ana_network_manager::create_client_and_connect(std::string host, int port)
{
    ana::net_id new_client_id = ana::invalid_net_id;

    try
    {
        std::stringstream ss;
        ss << port;

        ana_component* new_component = new ana_component( host, ss.str() );
        components_.insert( new_component );

        ana::client* const client = new_component->client();

        new_client_id = client->id();

        ana_connect_handler handler;

        client->set_raw_data_mode();
        client->set_connect_timeout( ana::time::seconds(10) );

        if ( proxy_settings_.enabled )
            client->connect_through_proxy( proxy_settings_.address,
                                           proxy_settings_.port,
                                           &handler,
                                           proxy_settings_.user,
                                           proxy_settings_.password);
        else
            client->connect( &handler );

        client->set_listener_handler( this );
        client->run();

        handler.wait_completion(); // just wait for handler to finish

        if( handler.error() )
        {
            network::disconnect( client->id() );
            throw network::error(_("Could not connect to host"), client->id() );
        }
        else
        {
            //Send handshake
            ana::serializer::bostream bos;

            ana::ana_uint32 handshake( 0 );
            bos << handshake;

            ana_send_handler send_handler;

            client->send( ana::buffer( bos.str()), &send_handler); //, ana::ZERO_COPY );

            send_handler.wait_completion();

            if ( send_handler.error() )
                throw network::error(_("Could not connect to host"), client->id() );
            else
            {
                ana::ana_uint32 my_id;
                ana::serializer::bistream bis;

                client->wait_raw_object(bis, sizeof(ana::ana_uint32) );

                bis >> my_id;
                ana::network_to_host_long( my_id );

                new_component->set_wesnoth_id( my_id );

                client->set_header_first_mode();
                client->run_listener();

                return network::connection( client->id() );
            }
        }
    }
    catch( const std::exception& )
    {
        throw network::error(_("Could not connect to host"), new_client_id );
        return 0;
    }
}
コード例 #15
0
ファイル: UMV_Servidor.c プロジェクト: LucasMilotich/recovery
int deserializarYejecutar(char** package, int sock, int* tipoProceso,
		int* procesoActivo) {
	//int *operacion;
	int operacion;
	int offset = 0;
	int respuestaINT;
	char algo[1];
	int i;
	/*algo[0] = *package[0];
	 operacion = algo[0];*/
	char * bufferRespuesta;
	memcpy(&algo, (*package + offset), sizeof(uint32_t));
	//log_debug(ptrLog, "Ejecutamos la operacion:%d", operacion);
	operacion = algo[0];
	char* respuestaOperacion = malloc(sizeof(int));
	/*memory leak
	 *
	 * VERIFICAR
	 *
	 * deberia hacer un free de respuesOperacion cada vez que entra en cada case
	 *
	 *
	 * */
	//Compruebo que me haya hecho el handshake
	//if (*tipoProceso != KERNEL || *tipoProceso != CPU) {
	//le asigno -1 para que cuando vaya al case, caiga en el default
	//return  -1;
	//}
	switch (operacion) {
	case 1:
		log_info(ptrLog, "En el case (SERVIDOR)");
		log_debug(ptrLog, "Solicitar Bytes");
		log_debug(ptrLog, "Operacion : %u ", *(*package));
		log_debug(ptrLog, "Base : %u ", *(*package + sizeof(uint32_t)));
		log_debug(ptrLog, "Offset : %u ",
				*(*package + sizeof(uint32_t) + sizeof(uint32_t)));
		log_debug(ptrLog, "Tamanio: %u ",
				*(*package + sizeof(uint32_t) + sizeof(uint32_t)
						+ sizeof(uint32_t)));

		t_solicitarBytes *estructuraSolicitarBytes = deserializarSolicitarBytes(
				package);

		log_debug(ptrLog,
				"Antes de ejecutar la fn solicitarBytes - Imprimiendo la estructura");
		log_debug(ptrLog, "Base : %u ", estructuraSolicitarBytes->base);
		log_debug(ptrLog, "Offset : %u ", estructuraSolicitarBytes->offset);
		log_debug(ptrLog, "Tamanio : %u ", estructuraSolicitarBytes->tamanio);

		if (*tipoProceso == KERNEL || *tipoProceso == CPU) {
			//bufferRespuesta=malloc(estructuraSolicitarBytes->tamanio);
			bufferRespuesta = solicitarBytes(estructuraSolicitarBytes,
					procesoActivo);
			if (bufferRespuesta[0] == -1) {
				log_error(ptrLog, "SEGFAULT");
				enviarDatos(sock, &bufferRespuesta,
						estructuraSolicitarBytes->tamanio, 0);
			} else {
				enviarDatos(sock, &bufferRespuesta,
						estructuraSolicitarBytes->tamanio, 0);
				log_debug(ptrLog, "Lo que se obtuvo es: ");
				for (i = 0; i < estructuraSolicitarBytes->tamanio; ++i)
					log_debug(ptrLog, "%x ", bufferRespuesta[i]);
				log_info(ptrLog, "SolicitarBytes en server correcto");
			}
			free(bufferRespuesta);
			free(estructuraSolicitarBytes);
			free(respuestaOperacion);
			return 1;
		}

		else {
			log_error(ptrLog,
					"Se quiere ejecutar una operacion donde no hay una CPU o un Kernel");
			log_error(ptrLog, "Se envia la respuesta fallida");
			bufferRespuesta = malloc(4);
			respuestaINT = -1;
			memcpy(bufferRespuesta, &respuestaINT, sizeof(int));
			enviarDatos(sock, &bufferRespuesta, sizeof(int), 0);
			free(estructuraSolicitarBytes);
			free(bufferRespuesta);
			free(respuestaOperacion);
			return 1;	//VERIFICAR
		}

	case 2:
		log_debug(ptrLog, "En el case (SERVIDOR)");
		log_debug(ptrLog, "Enviar Bytes");
		log_debug(ptrLog, "Operacion: %u", *(*package));
		log_debug(ptrLog, "Base: %u", *(*package + sizeof(uint32_t)));
		log_debug(ptrLog, "Offset: %u",
				*(*package + sizeof(uint32_t) + sizeof(uint32_t)));
		log_debug(ptrLog, "Tamanio: %u",
				*(*package + sizeof(uint32_t) + sizeof(uint32_t)
						+ sizeof(uint32_t)));
		log_debug(ptrLog, "%u",
				*(*package + sizeof(uint32_t) + sizeof(uint32_t)
						+ sizeof(uint32_t) + sizeof(uint32_t)));

		t_enviarBytes *estructuraEnviarBytes = deserializarEnviarBytes(package);
		log_debug(ptrLog,
				"Antes de ejecutar la fn enviarBytes - Imprimiendo la estructura");
		log_debug(ptrLog, "Base: %u ", estructuraEnviarBytes->base);
		log_debug(ptrLog, "Offset: %u ", estructuraEnviarBytes->offset);
		log_debug(ptrLog, "Tamanio: %u ", estructuraEnviarBytes->tamanio);
		log_debug(ptrLog, "Se recibio en el buffer lo siguiente:");
		for (i = 0; i < estructuraEnviarBytes->tamanio; ++i)
			log_debug(ptrLog, "%x ", estructuraEnviarBytes->buffer[i]);
		bufferRespuesta = malloc(sizeof(int));

		if (*tipoProceso == KERNEL || *tipoProceso == CPU) {
			log_info(ptrLog, "Se procede a enviar bytes");
			bufferRespuesta = enviarBytes(estructuraEnviarBytes,
					*procesoActivo);
			if (bufferRespuesta[0] == -1) {
				log_error(ptrLog, "SEGFAULT");
				enviarDatos(sock, &bufferRespuesta, sizeof(int), 0);
			} else {

				enviarDatos(sock, &bufferRespuesta, sizeof(int), 0);
				log_info(ptrLog, "Se envio bytes");
			}
			free(bufferRespuesta);
			free(estructuraEnviarBytes->buffer);
			free(estructuraEnviarBytes);
			free(respuestaOperacion);

			return 1;
		} else {
			log_error(ptrLog,
					"Se quiere ejecutar una operacion donde no hay una CPU o un Kernel");
			log_error(ptrLog, "Se envia la respuesta fallida");
			bufferRespuesta = malloc(4);
			respuestaINT = -1;
			memcpy(bufferRespuesta, &respuestaINT, sizeof(int));
			enviarDatos(sock, &bufferRespuesta, sizeof(int), 0);
			free(estructuraEnviarBytes);
			free(estructuraEnviarBytes->buffer);
			free(bufferRespuesta);
			free(respuestaOperacion);
			return 1;	//VERIFICAR
		}

	case 3:
		log_debug(ptrLog, "En el case (SERVIDOR)");
		log_debug(ptrLog, "Handshake");
		log_debug(ptrLog, "Tipo de cliente: %u",
				*(*package + sizeof(uint32_t)));
		//log_debug(ptrLog, "%u",
		//		*(*package + sizeof(uint32_t) + sizeof(uint32_t)));
		handshake(deserializarHandshake(package), tipoProceso);
		//Ejecutar funcion Handshake
		free(respuestaOperacion);
		return 1;

	case 4:
		log_debug(ptrLog, "En el case (SERVIDOR)");
		log_debug(ptrLog, "Cambio de proceso activo");
		log_debug(ptrLog, "PID: %u", **package + sizeof(uint32_t));
		if (*tipoProceso == KERNEL || *tipoProceso == CPU) {
			log_info(ptrLog, "Se procede a cambiar el PID activo");
			cambiarProcesoActivo(deserializarCambiarProcesoActivo(package),
					procesoActivo);
			free(respuestaOperacion);
			return 1;

		} else {
			log_error(ptrLog,
					"Se quiere ejecutar una operacion donde no hay una CPU o un Kernel");
			free(respuestaOperacion);
			return 1;
		}

	case 5:
		log_debug(ptrLog, "En el case (SERVIDOR)");
		log_debug(ptrLog, "Crear segmento");
		log_debug(ptrLog, "PID %u", *(*package + sizeof(uint32_t)));
		//log_debug(ptrLog, "%u",
		//	*(*package + sizeof(uint32_t) + sizeof(uint32_t)));

		if (*tipoProceso == KERNEL) {
			log_info(ptrLog,
					"Se procede a atender la solicitud de crear segmento del kernel");
			respuestaINT = crearSegmento((deserializarCrearSegmento(package)));
			memcpy(respuestaOperacion, &respuestaINT, sizeof(int));

			//Envio tamaño de la respuesta de la funcion

			enviarDatos(sock, &respuestaOperacion, sizeof(int), 0);
			free(respuestaOperacion);
			return 1;
		} else {

			respuestaINT = -1;
			memcpy(respuestaOperacion, &respuestaINT, sizeof(int));
			enviarDatos(sock, &respuestaOperacion, sizeof(int), 0);
			log_error(ptrLog,
					"Se quiere ejecutar una operacion donde no hay una CPU o un Kernel");
			free(respuestaOperacion);
			return 1;
		}

	case 6:
		log_debug(ptrLog, "En el case (SERVIDOR)");
		log_debug(ptrLog, "Destruir segmento");
		log_debug(ptrLog, "PID %u", *(*package + sizeof(uint32_t)));
		if (*tipoProceso == KERNEL) {
			respuestaINT = destruirSegmento(
					deserializarDestruirSegmento(package));
			memcpy(respuestaOperacion, &respuestaINT, sizeof(int));
			enviarDatos(sock, &respuestaOperacion, sizeof(int), 0);
			free(respuestaOperacion);
			log_info(ptrLog, "Se realizo la destruccion del segmento");
			return 1;

		} else {
			respuestaINT = -1;
			memcpy(respuestaOperacion, &respuestaINT, sizeof(int));
			enviarDatos(sock, &respuestaOperacion, sizeof(int), 0);
			free(respuestaOperacion);
			log_error(ptrLog,
					"Se quiere ejecutar una operacion donde no hay una CPU o un Kernel");
			return 1;
		}
	default:
		log_debug(ptrLog, "En el case (SERVIDOR)");
		log_error(ptrLog, "No llego la opción correcta. OPERACION INCORRECTA.");
		return -1;
	}

}
コード例 #16
0
ファイル: ehci-hcd.c プロジェクト: tomstokes/u-boot
int
ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
		 int length, struct devrequest *req)
{
	uint8_t tmpbuf[4];
	u16 typeReq;
	void *srcptr = NULL;
	int len, srclen;
	uint32_t reg;
	uint32_t *status_reg;
	int port = le16_to_cpu(req->index) & 0xff;
	struct ehci_ctrl *ctrl = dev->controller;

	srclen = 0;

	debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n",
	      req->request, req->request,
	      req->requesttype, req->requesttype,
	      le16_to_cpu(req->value), le16_to_cpu(req->index));

	typeReq = req->request | req->requesttype << 8;

	switch (typeReq) {
	case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
	case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
	case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
		status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1);
		if (!status_reg)
			return -1;
		break;
	default:
		status_reg = NULL;
		break;
	}

	switch (typeReq) {
	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
		switch (le16_to_cpu(req->value) >> 8) {
		case USB_DT_DEVICE:
			debug("USB_DT_DEVICE request\n");
			srcptr = &descriptor.device;
			srclen = descriptor.device.bLength;
			break;
		case USB_DT_CONFIG:
			debug("USB_DT_CONFIG config\n");
			srcptr = &descriptor.config;
			srclen = descriptor.config.bLength +
					descriptor.interface.bLength +
					descriptor.endpoint.bLength;
			break;
		case USB_DT_STRING:
			debug("USB_DT_STRING config\n");
			switch (le16_to_cpu(req->value) & 0xff) {
			case 0:	/* Language */
				srcptr = "\4\3\1\0";
				srclen = 4;
				break;
			case 1:	/* Vendor */
				srcptr = "\16\3u\0-\0b\0o\0o\0t\0";
				srclen = 14;
				break;
			case 2:	/* Product */
				srcptr = "\52\3E\0H\0C\0I\0 "
					 "\0H\0o\0s\0t\0 "
					 "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0";
				srclen = 42;
				break;
			default:
				debug("unknown value DT_STRING %x\n",
					le16_to_cpu(req->value));
				goto unknown;
			}
			break;
		default:
			debug("unknown value %x\n", le16_to_cpu(req->value));
			goto unknown;
		}
		break;
	case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
		switch (le16_to_cpu(req->value) >> 8) {
		case USB_DT_HUB:
			debug("USB_DT_HUB config\n");
			srcptr = &descriptor.hub;
			srclen = descriptor.hub.bLength;
			break;
		default:
			debug("unknown value %x\n", le16_to_cpu(req->value));
			goto unknown;
		}
		break;
	case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
		debug("USB_REQ_SET_ADDRESS\n");
		ctrl->rootdev = le16_to_cpu(req->value);
		break;
	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
		debug("USB_REQ_SET_CONFIGURATION\n");
		/* Nothing to do */
		break;
	case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
		tmpbuf[0] = 1;	/* USB_STATUS_SELFPOWERED */
		tmpbuf[1] = 0;
		srcptr = tmpbuf;
		srclen = 2;
		break;
	case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
		memset(tmpbuf, 0, 4);
		reg = ehci_readl(status_reg);
		if (reg & EHCI_PS_CS)
			tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
		if (reg & EHCI_PS_PE)
			tmpbuf[0] |= USB_PORT_STAT_ENABLE;
		if (reg & EHCI_PS_SUSP)
			tmpbuf[0] |= USB_PORT_STAT_SUSPEND;
		if (reg & EHCI_PS_OCA)
			tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
		if (reg & EHCI_PS_PR)
			tmpbuf[0] |= USB_PORT_STAT_RESET;
		if (reg & EHCI_PS_PP)
			tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;

		if (ehci_is_TDI()) {
			switch (ehci_get_port_speed(ctrl->hcor, reg)) {
			case PORTSC_PSPD_FS:
				break;
			case PORTSC_PSPD_LS:
				tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
				break;
			case PORTSC_PSPD_HS:
			default:
				tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
				break;
			}
		} else {
			tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
		}

		if (reg & EHCI_PS_CSC)
			tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
		if (reg & EHCI_PS_PEC)
			tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
		if (reg & EHCI_PS_OCC)
			tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
		if (ctrl->portreset & (1 << port))
			tmpbuf[2] |= USB_PORT_STAT_C_RESET;

		srcptr = tmpbuf;
		srclen = 4;
		break;
	case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
		reg = ehci_readl(status_reg);
		reg &= ~EHCI_PS_CLEAR;
		switch (le16_to_cpu(req->value)) {
		case USB_PORT_FEAT_ENABLE:
			reg |= EHCI_PS_PE;
			ehci_writel(status_reg, reg);
			break;
		case USB_PORT_FEAT_POWER:
			if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) {
				reg |= EHCI_PS_PP;
				ehci_writel(status_reg, reg);
			}
			break;
		case USB_PORT_FEAT_RESET:
			if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS &&
			    !ehci_is_TDI() &&
			    EHCI_PS_IS_LOWSPEED(reg)) {
				/* Low speed device, give up ownership. */
				debug("port %d low speed --> companion\n",
				      port - 1);
				reg |= EHCI_PS_PO;
				ehci_writel(status_reg, reg);
				break;
			} else {
				int ret;

				reg |= EHCI_PS_PR;
				reg &= ~EHCI_PS_PE;
				ehci_writel(status_reg, reg);
				/*
				 * caller must wait, then call GetPortStatus
				 * usb 2.0 specification say 50 ms resets on
				 * root
				 */
				ehci_powerup_fixup(status_reg, &reg);

				ehci_writel(status_reg, reg & ~EHCI_PS_PR);
				/*
				 * A host controller must terminate the reset
				 * and stabilize the state of the port within
				 * 2 milliseconds
				 */
				ret = handshake(status_reg, EHCI_PS_PR, 0,
						2 * 1000);
				if (!ret)
					ctrl->portreset |= 1 << port;
				else
					printf("port(%d) reset error\n",
					       port - 1);
			}
			break;
		case USB_PORT_FEAT_TEST:
			ehci_shutdown(ctrl);
			reg &= ~(0xf << 16);
			reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16;
			ehci_writel(status_reg, reg);
			break;
		default:
			debug("unknown feature %x\n", le16_to_cpu(req->value));
			goto unknown;
		}
		/* unblock posted writes */
		(void) ehci_readl(&ctrl->hcor->or_usbcmd);
		break;
	case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
		reg = ehci_readl(status_reg);
		reg &= ~EHCI_PS_CLEAR;
		switch (le16_to_cpu(req->value)) {
		case USB_PORT_FEAT_ENABLE:
			reg &= ~EHCI_PS_PE;
			break;
		case USB_PORT_FEAT_C_ENABLE:
			reg |= EHCI_PS_PE;
			break;
		case USB_PORT_FEAT_POWER:
			if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams)))
				reg &= ~EHCI_PS_PP;
			break;
		case USB_PORT_FEAT_C_CONNECTION:
			reg |= EHCI_PS_CSC;
			break;
		case USB_PORT_FEAT_OVER_CURRENT:
			reg |= EHCI_PS_OCC;
			break;
		case USB_PORT_FEAT_C_RESET:
			ctrl->portreset &= ~(1 << port);
			break;
		default:
			debug("unknown feature %x\n", le16_to_cpu(req->value));
			goto unknown;
		}
		ehci_writel(status_reg, reg);
		/* unblock posted write */
		(void) ehci_readl(&ctrl->hcor->or_usbcmd);
		break;
	default:
		debug("Unknown request\n");
		goto unknown;
	}
コード例 #17
0
ファイル: stream.hpp プロジェクト: 0xDEC0DE8/mcsema
 /**
  * This function is used to perform SSL handshaking on the stream. The
  * function call will block until handshaking is complete or an error occurs.
  *
  * @param type The type of handshaking to be performed, i.e. as a client or as
  * a server.
  *
  * @throws boost::system::system_error Thrown on failure.
  */
 void handshake(handshake_type type)
 {
   boost::system::error_code ec;
   handshake(type, ec);
   boost::asio::detail::throw_error(ec, "handshake");
 }
コード例 #18
0
void zmq::stream_engine_t::in_event ()
{
    //  If still handshaking, receive and prcess the greeting message.
    if (unlikely (handshaking))
        if (!handshake ())
            return;

    zmq_assert (decoder);
    bool disconnection = false;

    //  If there's no data to process in the buffer...
    if (!insize) {

        //  Retrieve the buffer and read as much data as possible.
        //  Note that buffer can be arbitrarily large. However, we assume
        //  the underlying TCP layer has fixed buffer size and thus the
        //  number of bytes read will be always limited.
        decoder->get_buffer (&inpos, &insize);
        insize = read (inpos, insize);

        //  Check whether the peer has closed the connection.
        if (insize == (size_t) -1) {
            insize = 0;
            disconnection = true;
        }
    }

    //  Push the data to the decoder.
    size_t processed = decoder->process_buffer (inpos, insize);

    if (unlikely (processed == (size_t) -1)) {
        disconnection = true;
    }
    else {

        //  Stop polling for input if we got stuck.
        if (processed < insize)
            reset_pollin (handle);

        //  Adjust the buffer.
        inpos += processed;
        insize -= processed;
    }

    //  Flush all messages the decoder may have produced.
    session->flush ();

    //  Input error has occurred. If the last decoded
    //  message has already been accepted, we terminate
    //  the engine immediately. Otherwise, we stop
    //  waiting for input events and postpone the termination
    //  until after the session has accepted the message.
    if (disconnection) {
        if (decoder->stalled ()) {
            rm_fd (handle);
            io_enabled = false;
        }
        else
            error ();
    }
}
コード例 #19
0
 /**
  * This function is used to perform SSL handshaking on the stream. The
  * function call will block until handshaking is complete or an error occurs.
  *
  * @param type The type of handshaking to be performed, i.e. as a client or as
  * a server.
  *
  * @throws asio::system_error Thrown on failure.
  */
 void handshake(handshake_type type)
 {
   asio::error_code ec;
   handshake(type, ec);
   asio::detail::throw_error(ec, "handshake");
 }
コード例 #20
0
static int msm_hsic_resume_thread(void *data)
{
	struct msm_hsic_hcd *mehci = data;
	struct usb_hcd *hcd = hsic_to_hcd(mehci);
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
	u32			temp;
	unsigned long		resume_needed = 0;
	int			retry_cnt = 0;
	int			tight_resume = 0;
	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;

	dbg_log_event(NULL, "Resume RH", 0);

	/* keep delay between bus states */
	if (time_before(jiffies, ehci->next_statechange))
		usleep_range(5000, 5000);

	spin_lock_irq(&ehci->lock);
	if (!HCD_HW_ACCESSIBLE(hcd)) {
		spin_unlock_irq(&ehci->lock);
		mehci->resume_status = -ESHUTDOWN;
		complete(&mehci->rt_completion);
		return 0;
	}

	if (unlikely(ehci->debug)) {
		if (!dbgp_reset_prep())
			ehci->debug = NULL;
		else
			dbgp_external_startup();
	}

	/* at least some APM implementations will try to deliver
	 * IRQs right away, so delay them until we're ready.
	 */
	ehci_writel(ehci, 0, &ehci->regs->intr_enable);

	/* re-init operational registers */
	ehci_writel(ehci, 0, &ehci->regs->segment);
	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
	ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);

	/*CMD_RUN will be set after, PORT_RESUME gets cleared*/
	if (ehci->resume_sof_bug)
		ehci->command &= ~CMD_RUN;

	/* restore CMD_RUN, framelist size, and irq threshold */
	ehci_writel(ehci, ehci->command, &ehci->regs->command);

	/* manually resume the ports we suspended during bus_suspend() */
resume_again:
	if (retry_cnt >= RESUME_RETRY_LIMIT) {
		pr_info("retry count(%d) reached max, resume in tight loop\n",
					retry_cnt);
		tight_resume = 1;
	}


	temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
	temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
	if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
		temp |= PORT_RESUME;
		set_bit(0, &resume_needed);
	}
	dbg_log_event(NULL, "FPR: Set", temp);
	ehci_writel(ehci, temp, &ehci->regs->port_status[0]);

	/* HSIC controller has a h/w bug due to which it can try to send SOFs
	 * (start of frames) during port resume resulting in phy lockup. HSIC hw
	 * controller in MSM clears FPR bit after driving the resume signal for
	 * 20ms. Workaround is to stop SOFs before driving resume and then start
	 * sending SOFs immediately. Need to send SOFs within 3ms of resume
	 * completion otherwise peripheral may enter undefined state. As
	 * usleep_range does not gurantee exact sleep time, GPTimer is used to
	 * to time the resume sequence. If driver exceeds allowable time SOFs,
	 * repeat the resume process.
	 */
	if (ehci->resume_sof_bug && resume_needed) {
		if (!tight_resume) {
			mehci->resume_again = 0;
			ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_MS),
					&mehci->timer->gptimer0_ld);
			ehci_writel(ehci, GPT_RESET | GPT_RUN,
					&mehci->timer->gptimer0_ctrl);
			ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
					&ehci->regs->intr_enable);

			ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_SOF_MS),
					&mehci->timer->gptimer1_ld);
			ehci_writel(ehci, GPT_RESET | GPT_RUN,
				&mehci->timer->gptimer1_ctrl);

			spin_unlock_irq(&ehci->lock);
			if (pdata && pdata->swfi_latency)
				pm_qos_update_request(&mehci->pm_qos_req_dma,
					pdata->swfi_latency + 1);
			wait_for_completion(&mehci->gpt0_completion);
			if (pdata && pdata->swfi_latency)
				pm_qos_update_request(&mehci->pm_qos_req_dma,
					PM_QOS_DEFAULT_VALUE);
			spin_lock_irq(&ehci->lock);
		} else {
			dbg_log_event(NULL, "FPR: Tightloop", 0);
			/* do the resume in a tight loop */
			handshake(ehci, &ehci->regs->port_status[0],
				PORT_RESUME, 0, 22 * 1000);
			ehci_writel(ehci, ehci_readl(ehci,
				&ehci->regs->command) | CMD_RUN,
				&ehci->regs->command);
		}

		if (mehci->resume_again) {
			int temp;

			dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
			pr_info("FPR: retry count: %d\n", retry_cnt);
			spin_unlock_irq(&ehci->lock);
			temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
			temp &= ~PORT_RWC_BITS;
			temp |= PORT_SUSPEND;
			ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
			/* Keep the bus idle for 5ms so that peripheral
			 * can detect and initiate suspend
			 */
			usleep_range(5000, 5000);
			dbg_log_event(NULL,
				"FPR: RResume",
				ehci_readl(ehci, &ehci->regs->port_status[0]));
			spin_lock_irq(&ehci->lock);
			mehci->resume_again = 0;
			retry_cnt++;
			goto resume_again;
		}
	}

	dbg_log_event(NULL, "FPR: RT-Done", 0);
	mehci->resume_status = 1;
	spin_unlock_irq(&ehci->lock);

	complete(&mehci->rt_completion);

	return 0;
}
コード例 #21
0
static int
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
                  int length, struct devrequest *req)
{
    struct QH *qh;
    struct qTD *td;
    volatile struct qTD *vtd;
    unsigned long ts;
    uint32_t *tdp;
    uint32_t endpt, token, usbsts;
    uint32_t c, toggle;
    uint32_t cmd;
    int timeout;
    int ret = 0;

    debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
          buffer, length, req);
    if (req != NULL)
        debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n",
              req->request, req->request,
              req->requesttype, req->requesttype,
              le16_to_cpu(req->value), le16_to_cpu(req->value),
              le16_to_cpu(req->index));

    qh = ehci_alloc(sizeof(struct QH), 32);
    if (qh == NULL) {
        debug("unable to allocate QH\n");
        return -1;
    }
    qh->qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
    c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
         usb_pipeendpoint(pipe) == 0) ? 1 : 0;
    endpt = (8 << 28) |
            (c << 27) |
            (usb_maxpacket(dev, pipe) << 16) |
            (0 << 15) |
            (1 << 14) |
            (usb_pipespeed(pipe) << 12) |
            (usb_pipeendpoint(pipe) << 8) |
            (0 << 7) | (usb_pipedevice(pipe) << 0);
    qh->qh_endpt1 = cpu_to_hc32(endpt);
    endpt = (1 << 30) |
            (dev->portnr << 23) |
            (dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
    qh->qh_endpt2 = cpu_to_hc32(endpt);
    qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);

    td = NULL;
    tdp = &qh->qh_overlay.qt_next;

    toggle =
        usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));

    if (req != NULL) {
        td = ehci_alloc(sizeof(struct qTD), 32);
        if (td == NULL) {
            debug("unable to allocate SETUP td\n");
            goto fail;
        }
        td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
        td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
        token = (0 << 31) |
                (sizeof(*req) << 16) |
                (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
        td->qt_token = cpu_to_hc32(token);
        if (ehci_td_buffer(td, req, sizeof(*req)) != 0) {
            debug("unable construct SETUP td\n");
            ehci_free(td, sizeof(*td));
            goto fail;
        }
        *tdp = cpu_to_hc32((uint32_t) td);
        tdp = &td->qt_next;
        toggle = 1;
    }

    if (length > 0 || req == NULL) {
        td = ehci_alloc(sizeof(struct qTD), 32);
        if (td == NULL) {
            debug("unable to allocate DATA td\n");
            goto fail;
        }
        td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
        td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
        token = (toggle << 31) |
                (length << 16) |
                ((req == NULL ? 1 : 0) << 15) |
                (0 << 12) |
                (3 << 10) |
                ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
        td->qt_token = cpu_to_hc32(token);
        if (ehci_td_buffer(td, buffer, length) != 0) {
            debug("unable construct DATA td\n");
            ehci_free(td, sizeof(*td));
            goto fail;
        }
        *tdp = cpu_to_hc32((uint32_t) td);
        tdp = &td->qt_next;
    }

    if (req != NULL) {
        td = ehci_alloc(sizeof(struct qTD), 32);
        if (td == NULL) {
            debug("unable to allocate ACK td\n");
            goto fail;
        }
        td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
        td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
        token = (toggle << 31) |
                (0 << 16) |
                (1 << 15) |
                (0 << 12) |
                (3 << 10) |
                ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0);
        td->qt_token = cpu_to_hc32(token);
        *tdp = cpu_to_hc32((uint32_t) td);
        tdp = &td->qt_next;
    }

    qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH);

    /* Flush dcache */
    ehci_flush_dcache(&qh_list);

    usbsts = ehci_readl(&hcor->or_usbsts);
    ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));

    /* Enable async. schedule. */
    cmd = ehci_readl(&hcor->or_usbcmd);
    cmd |= CMD_ASE;
    ehci_writel(&hcor->or_usbcmd, cmd);

    ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, STD_ASS,
                    100 * 1000);
    if (ret < 0) {
        printf("EHCI fail timeout STD_ASS set\n");
        goto fail;
    }

    /* Wait for TDs to be processed. */
    ts = get_timer(0);
    vtd = td;
    timeout = USB_TIMEOUT_MS(pipe);
    do {
        /* Invalidate dcache */
        ehci_invalidate_dcache(&qh_list);
        token = hc32_to_cpu(vtd->qt_token);
        if (!(token & 0x80))
            break;
        WATCHDOG_RESET();
    } while (get_timer(ts) < timeout);

    /* Check that the TD processing happened */
    if (token & 0x80) {
        printf("EHCI timed out on TD - token=%#x\n", token);
    }

    /* Disable async schedule. */
    cmd = ehci_readl(&hcor->or_usbcmd);
    cmd &= ~CMD_ASE;
    ehci_writel(&hcor->or_usbcmd, cmd);

    ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, 0,
                    100 * 1000);
    if (ret < 0) {
        printf("EHCI fail timeout STD_ASS reset\n");
        goto fail;
    }

    qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);

    token = hc32_to_cpu(qh->qh_overlay.qt_token);
    if (!(token & 0x80)) {
        debug("TOKEN=%#x\n", token);
        switch (token & 0xfc) {
        case 0:
            toggle = token >> 31;
            usb_settoggle(dev, usb_pipeendpoint(pipe),
                          usb_pipeout(pipe), toggle);
            dev->status = 0;
            break;
        case 0x40:
            dev->status = USB_ST_STALLED;
            break;
        case 0xa0:
        case 0x20:
            dev->status = USB_ST_BUF_ERR;
            break;
        case 0x50:
        case 0x10:
            dev->status = USB_ST_BABBLE_DET;
            break;
        default:
            dev->status = USB_ST_CRC_ERR;
            if ((token & 0x40) == 0x40)
                dev->status |= USB_ST_STALLED;
            break;
        }
        dev->act_len = length - ((token >> 16) & 0x7fff);
    } else {
コード例 #22
0
static jdwpTransportError JNICALL
socketTransport_accept(jdwpTransportEnv* env, jlong acceptTimeout, jlong handshakeTimeout) 
{
    int socketLen, err;
    struct sockaddr_in socket;
    jlong startTime = (jlong)0;

    /*
     * Use a default handshake timeout if not specified - this avoids an indefinite
     * hang in cases where something other than a debugger connects to our port.
     */
    if (handshakeTimeout == 0) {
	handshakeTimeout = 2000;
    }
   
    do {
	/*
	 * If there is an accept timeout then we put the socket in non-blocking
	 * mode and poll for a connection.
	 */
        if (acceptTimeout > 0) {
	    int rv;
	    dbgsysConfigureBlocking(serverSocketFD, JNI_FALSE);
            startTime = dbgsysCurrentTimeMillis();
	    rv = dbgsysPoll(serverSocketFD, JNI_TRUE, JNI_FALSE, (long)acceptTimeout);
	    if (rv <= 0) {
	        /* set the last error here as could be overridden by configureBlocking */
	        if (rv == 0) {
	            setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "poll failed");
	        }
		/* restore blocking state */
	        dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);
	        if (rv == 0) {
	            RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "timed out waiting for connection");
	        } else {		
		    return JDWPTRANSPORT_ERROR_IO_ERROR;
		}
	    }
	}   

	/*
	 * Accept the connection
	 */
	memset((void *)&socket,0,sizeof(struct sockaddr_in));
        socketLen = sizeof(socket);
        socketFD = dbgsysAccept(serverSocketFD,
                                (struct sockaddr *)&socket,
                                &socketLen);
        /* set the last error here as could be overridden by configureBlocking */
        if (socketFD < 0) {
	    setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "accept failed");
        }
	/* 
	 * Restore the blocking state - note that the accepted socket may be in 
	 * blocking or non-blocking mode (platform dependent). However as there
	 * is a handshake timeout set then it will go into non-blocking mode
	 * anyway for the handshake.
	 */
        if (acceptTimeout > 0) {
	    dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);
        }
        if (socketFD < 0) {
            return JDWPTRANSPORT_ERROR_IO_ERROR;
        }

	/* handshake with the debugger */
        err = handshake(socketFD, handshakeTimeout);

	/* 
	 * If the handshake fails then close the connection. If there if an accept
	 * timeout then we must adjust the timeout for the next poll.
	 */
        if (err) {
	    fprintf(stderr, "Debugger failed to attach: %s\n", getLastError());
	    dbgsysSocketClose(socketFD);        
	    socketFD = -1;
	    if (acceptTimeout > 0) {
                long endTime = dbgsysCurrentTimeMillis();
		acceptTimeout -= (endTime - startTime);
		if (acceptTimeout <= 0) {
                    setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, 
			"timeout waiting for debugger to connect");
                    return JDWPTRANSPORT_ERROR_IO_ERROR;
		}
	    }
	} 
    } while (socketFD < 0);

    return JDWPTRANSPORT_ERROR_NONE;
}