Esempio n. 1
0
/*
 * This routine is used to notify the framework the result of
 * an asynchronous request handled by a provider. Valid error
 * codes are the same as the CRYPTO_* errors defined in common.h.
 *
 * This routine can be called from user or interrupt context.
 */
void
crypto_op_notification(crypto_req_handle_t handle, int error)
{
	kcf_call_type_t ctype;

	if (handle == NULL)
		return;

	if ((ctype = GET_REQ_TYPE(handle)) == CRYPTO_SYNCH) {
		kcf_sreq_node_t *sreq = (kcf_sreq_node_t *)handle;

		if (error != CRYPTO_SUCCESS)
			sreq->sn_provider->pd_sched_info.ks_nfails++;
		KCF_PROV_IREFRELE(sreq->sn_provider);
		kcf_sop_done(sreq, error);
	} else {
		kcf_areq_node_t *areq = (kcf_areq_node_t *)handle;

		ASSERT(ctype == CRYPTO_ASYNCH);
		if (error != CRYPTO_SUCCESS)
			areq->an_provider->pd_sched_info.ks_nfails++;
		KCF_PROV_IREFRELE(areq->an_provider);
		kcf_aop_done(areq, error);
	}
}
Esempio n. 2
0
void process_setup_req()
{
	u32_t* p;

	u32_t request_type;

//	DEBUG_OUT('s');

	bRequestError   = NO;
	uCurrentCtrlBlockNum    = 0;
	uNeedDoProcCtrlBlockNum = 0;

	uControlStage = SETUP_STAGE;

	// clear previous buffer
	/*
	writew( readw( UDC_TX0CON ) | TxCLR,  UDC_TX0CON );
	writew( readw( UDC_TX0CON ) & ~TxCLR, UDC_TX0CON );
	writew( readw( UDC_RX0CON ) | RxCLR,  UDC_RX0CON );
	writew( readw( UDC_RX0CON ) & ~RxCLR, UDC_RX0CON );
*/
	// read setup data

	p = (u32_t*)&SetupRequestData;
	*p++ = *(volatile u32_t *)UDC_SETUP1;
	*p   = *(volatile u32_t *)UDC_SETUP2;

	// identify standard request
	request_type = GET_REQ_TYPE(SetupRequestData.bmRequestType);
	if (request_type == REQ_TYPE_STANDARD) {
		if (SetupRequestData.bRequest == GET_DESCRIPTOR ) {
			fn_get_descriptor();
		}
	} else if (request_type == REQ_TYPE_CLASS ) {
		if (SetupRequestData.bRequest == GET_DEVICE_ID) {
			;//printf("process_setup_req() - get device id!\n");
			fn_get_device_id();
		}
	} else if (request_type == REQ_TYPE_VENDOR ) {
		if (SetupRequestData.bRequest == VENDOR_TEST_OUT0 ) {
			;//printf("process_setup_req() - vendor test out!\n");
			fn_vendor_test_out0();
		} else if ( SetupRequestData.bRequest == VENDOR_TEST_IN0 ) {
			;//printf("process_setup_req() - vendor test in!\n");
			fn_vendor_test_in0();
		}
	}

	uControlStage = DATA_STAGE ;
}
Esempio n. 3
0
/*
 * This routine is called by the taskq associated with
 * each hardware provider. We notify the kernel consumer
 * via the callback routine in case of CRYPTO_SUCCESS or
 * a failure.
 *
 * A request can be of type kcf_areq_node_t or of type
 * kcf_sreq_node_t.
 */
static void
process_req_hwp(void *ireq)
{
	int error = 0;
	crypto_ctx_t *ctx;
	kcf_call_type_t ctype;
	kcf_provider_desc_t *pd;
	kcf_areq_node_t *areq = (kcf_areq_node_t *)ireq;
	kcf_sreq_node_t *sreq = (kcf_sreq_node_t *)ireq;

	pd = ((ctype = GET_REQ_TYPE(ireq)) == CRYPTO_SYNCH) ?
	    sreq->sn_provider : areq->an_provider;

	/*
	 * Wait if flow control is in effect for the provider. A
	 * CRYPTO_PROVIDER_READY or CRYPTO_PROVIDER_FAILED
	 * notification will signal us. We also get signaled if
	 * the provider is unregistering.
	 */
	if (pd->pd_state == KCF_PROV_BUSY) {
		mutex_enter(&pd->pd_lock);
		while (pd->pd_state == KCF_PROV_BUSY)
			cv_wait(&pd->pd_resume_cv, &pd->pd_lock);
		mutex_exit(&pd->pd_lock);
	}

	/*
	 * Bump the internal reference count while the request is being
	 * processed. This is how we know when it's safe to unregister
	 * a provider. This step must precede the pd_state check below.
	 */
	KCF_PROV_IREFHOLD(pd);

	/*
	 * Fail the request if the provider has failed. We return a
	 * recoverable error and the notified clients attempt any
	 * recovery. For async clients this is done in kcf_aop_done()
	 * and for sync clients it is done in the k-api routines.
	 */
	if (pd->pd_state >= KCF_PROV_FAILED) {
		error = CRYPTO_DEVICE_ERROR;
		goto bail;
	}

	if (ctype == CRYPTO_SYNCH) {
		mutex_enter(&sreq->sn_lock);
		sreq->sn_state = REQ_INPROGRESS;
		mutex_exit(&sreq->sn_lock);

		ctx = sreq->sn_context ? &sreq->sn_context->kc_glbl_ctx : NULL;
		error = common_submit_request(sreq->sn_provider, ctx,
		    sreq->sn_params, sreq);
	} else {
		kcf_context_t *ictx;
		ASSERT(ctype == CRYPTO_ASYNCH);

		/*
		 * We are in the per-hardware provider thread context and
		 * hence can sleep. Note that the caller would have done
		 * a taskq_dispatch(..., TQ_NOSLEEP) and would have returned.
		 */
		ctx = (ictx = areq->an_context) ? &ictx->kc_glbl_ctx : NULL;

		mutex_enter(&areq->an_lock);
		/*
		 * We need to maintain ordering for multi-part requests.
		 * an_is_my_turn is set to B_TRUE initially for a request
		 * when it is enqueued and there are no other requests
		 * for that context. It is set later from kcf_aop_done() when
		 * the request before us in the chain of requests for the
		 * context completes. We get signaled at that point.
		 */
		if (ictx != NULL) {
			ASSERT(ictx->kc_prov_desc == areq->an_provider);

			while (areq->an_is_my_turn == B_FALSE) {
				cv_wait(&areq->an_turn_cv, &areq->an_lock);
			}
		}
		areq->an_state = REQ_INPROGRESS;
		mutex_exit(&areq->an_lock);

		error = common_submit_request(areq->an_provider, ctx,
		    &areq->an_params, areq);
	}

bail:
	if (error == CRYPTO_QUEUED) {
		/*
		 * The request is queued by the provider and we should
		 * get a crypto_op_notification() from the provider later.
		 * We notify the consumer at that time.
		 */
		return;
	} else {		/* CRYPTO_SUCCESS or other failure */
		KCF_PROV_IREFRELE(pd);
		if (ctype == CRYPTO_SYNCH)
			kcf_sop_done(sreq, error);
		else
			kcf_aop_done(areq, error);
	}
}
Esempio n. 4
0
void process_setup_req()
{
	u32_t* p;

	u32_t request_type;

	UINT	ch;		// channel number
	int i;
//	DEBUG_OUT('s');

	bRequestError   = NO;
	uCurrentCtrlBlockNum    = 0;
	uNeedDoProcCtrlBlockNum = 0;

	uControlStage = SETUP_STAGE;



	if (ResetFlag == 1)
	{
		if ( IS_HIGH_SPEED() ) {
			;//printf(" USB connect with HIGH Speed!\n");
			bIsFullSpeed = 0;
			uBulkBlockSize  = HI_SPEED_BULK_PACKET_SIZE;
			uCurrentCtrlPacketSize  = HI_SPEED_CTRL_PACKET_SIZE;
			uCurrentBulklPacketSize = HI_SPEED_BULK_PACKET_SIZE;
		} else {
			;//printf(" USB connect with FULL Speed!\n");
			bIsFullSpeed = 1;
			uBulkBlockSize  = FULL_SPEED_BULK_PACKET_SIZE;
			uCurrentCtrlPacketSize  = FULL_SPEED_CTRL_PACKET_SIZE;
			uCurrentBulklPacketSize = FULL_SPEED_BULK_PACKET_SIZE;
		}
		uMaxBlockNumber = (BK_BUF_SIZE / uBulkBlockSize);
	
		// change device MaxPacketSize of descriptor
		scusbDscr[7] = uCurrentCtrlPacketSize;		
		ResetFlag = 0;
		for (ch = 0; ch < NUM_OF_USB_CHANNEL; ch++) {
			ChannelSet[ch].uLoopbackCount = 0;
			ChannelSet[ch].uIntrINCount   = 0;

			// start receive from Bulk_OUT pipe
			writew(virt_to_phy( (u32_t)ChannelSet[ch].pBulkOutBuffer), UDC_DMALM_OADDR(ChannelSet[ch].uBulk_OUT));
			writew( ENP_DMA_START, UDC_DMACTRLO(ChannelSet[ch].uBulk_OUT));
		}
		for (i = 0; i < NUM_OF_USB_CHANNEL; i++)
			ChannelSet[i].uCurrentBulkInBlockNum = ChannelSet[i].uCurrentBulkOutBlockNum = ChannelSet[i].uCurrentIntrInBlockNum = 0;		

	}
	// clear previous buffer
	/*
	writew( readw( UDC_TX0CON ) | TxCLR,  UDC_TX0CON );
	writew( readw( UDC_TX0CON ) & ~TxCLR, UDC_TX0CON );
	writew( readw( UDC_RX0CON ) | RxCLR,  UDC_RX0CON );
	writew( readw( UDC_RX0CON ) & ~RxCLR, UDC_RX0CON );
*/
	// read setup data

	p = (u32_t*)&SetupRequestData;
	*p++ = *(volatile u32_t *)UDC_SETUP1;
	*p   = *(volatile u32_t *)UDC_SETUP2;

	// identify standard request
	request_type = GET_REQ_TYPE(SetupRequestData.bmRequestType);
	if (request_type == REQ_TYPE_STANDARD) {
		if (SetupRequestData.bRequest == GET_DESCRIPTOR ) {
			fn_get_descriptor();
		}
	} else if (request_type == REQ_TYPE_CLASS ) {
		if (SetupRequestData.bRequest == GET_DEVICE_ID) {
			;//printf("process_setup_req() - get device id!\n");
			fn_get_device_id();
		}
	} else if (request_type == REQ_TYPE_VENDOR ) {
		if (SetupRequestData.bRequest == VENDOR_TEST_OUT0 ) {
			;//printf("process_setup_req() - vendor test out!\n");
			fn_vendor_test_out0();
		} else if ( SetupRequestData.bRequest == VENDOR_TEST_IN0 ) {
			;//printf("process_setup_req() - vendor test in!\n");
			fn_vendor_test_in0();
		}
	}

	uControlStage = DATA_STAGE ;
}