⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usim_drv.c

📁 MTK平台绝密核心代码之 系统驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	{
		case ATR_STATE:			
			dbg_print("ATR_STATE (timeout) should not go over here ");
			// may be optimized by parsing the content instead of using timeout.
			// read the remaining bytes of ATR
			{
				kal_uint32 count;
				
				count = DRV_Reg(SIM_COUNT);
				while(count--)
				{
					usim_dcb.ATR_data[usim_dcb.ATR_index++] = (kal_uint8)DRV_Reg(SIM_DATA);		
				}
            usim_dcb.ev_status = USIM_ATR_REC;	
            USIM_SET_EVENT();
			}			
			break;
		case CLK_STOPPING_STATE:
			dbg_print("CLK_STOPPING_STATE ");
			{
				kal_bool level;

				usim_set_timeout(0);
				usim_dcb.main_state = CLK_STOPPED_STATE;
				if(usim_dcb.clock_stop_type == CLOCK_STOP_HIGH )				
					level = KAL_TRUE;
				else
					level = KAL_FALSE;	
				SIM_Idle(level);				
				SIM_DisAllIntr();
				#if defined(USIM_DEBUG)
				end = get_duration_tick(start);
				dbg_print("clock stoped!! duration = %d", end);
				#endif
			}
			break;
		case CLK_STOPPED_STATE:
			dbg_print("CLK_STOPPED_STATE ");
			{
				usim_dcb.main_state = MAIN_CMD_READY_STATE;
				usim_dcb.ev_status = USIM_NO_ERROR;
				USIM_SET_EVENT();
				dbg_print("clock start!!");
			}
			break;
		default:
			dbg_print("default:");
			DMA_Stop(usim_dcb.dma_port);	
			usim_dcb.ev_status = USIM_BWT_TIMEOUT;
			USIM_SET_EVENT();
	}
	
	dbg_print("\r\n");
}

static void usim_hisr(void)
{
	kal_uint32 int_status;

	int_status = DRV_Reg(SIM_STS);
	usim_dcb.int_status = int_status;	
	PUSH_INT(int_status);
	dbg_print("usim_hisr int:%x\r\n",int_status);

	if(int_status & SIM_STS_RXERR )
	{
		dbg_print("parity error \r\n");
		usim_set_timeout(0);
		usim_dcb.ev_status = USIM_RX_INVALID;
		if(usim_dcb.main_state ==  ACTIVATION_STATE)
		{
			SIM_DisAllIntr();
			USIM_SET_EVENT();
			goto end_of_hisr;
		}
		// wait t1end interrupt
	}
	
	if(int_status& SIM_STS_EDCERR)
	{	
		dbg_print("EDC error \r\n");
		usim_set_timeout(0);
		usim_dcb.ev_status = USIM_RX_INVALID;		
	}
	if(int_status& SIM_STS_TOUT)
	{
		usim_timeout_handler();
		goto end_of_hisr;
	}	
	if(int_status & SIM_STS_T1END)
	{
		usim_t1end_handler();
	}	
	if(int_status & SIM_STS_RX)
	{
		usim_rx_handler(int_status);
	}	
	if(int_status & SIM_STS_SIMOFF)
	{
		usim_dcb.ev_status = USIM_POWER_OFF;
		USIM_SET_EVENT();
		goto end_of_hisr;
	}
	if(int_status & SIM_STS_TXERR || int_status & SIM_STS_OV)
	{
		ASSERT(0);
	}	
	if(int_status & SIM_STS_NATR)
	{
		usim_dcb.ev_status = USIM_NO_ATR;
		USIM_SET_EVENT();
	}
	
end_of_hisr:
	
	IRQClearInt(IRQ_SIM_CODE);
	IRQUnmask(IRQ_SIM_CODE);   
	
}

/*************************************************************************
* FUNCTION
*  usim_rx_handler
*
* DESCRIPTION
*	1. It is called byt usim_hisr
*	2. It is called while RXTIDE interrupt is triggerred
*
* PARAMETERS
	None
	
* RETURNS
	None
	
* GLOBALS AFFECTED
*	usim_dcb
*
*************************************************************************/
static void usim_rx_handler(kal_uint32 int_status)
{
	dbg_print("usim_rx_handler ");
	
	switch(usim_dcb.main_state)
	{
		case ACTIVATION_STATE:
			dbg_print("ACTIVATION_STATE ");		
			{
				kal_uint8 TS,T0,count;

				TS = DRV_Reg(SIM_DATA);
				dbg_print("TS = %x ", TS);
				if(TS == 0x3B || TS == 0x3F)
				{					
					usim_set_timeout(INIT_WWT_T0);
					USIM_ENABLE_TXRX_HANSHAKE();					
					SIM_SetRXRetry(USIM_RETRY);
					SIM_SetTXRetry(USIM_RETRY);    
					count = 0;
					T0 = DRV_Reg(SIM_DATA);
					usim_dcb.hist_index = T0&0xf; // use to contain the length of historical char (temperary)
					USIM_CAL_TD_COUNT(T0, count);
					if((T0 & TDMask) == NULL)
					{
						count += usim_dcb.hist_index;
						if(count >= SIM_TOTAL_FIFO_LEN)
						{
							usim_dcb.abort = KAL_TRUE;	// for temp usage (separate two times)
							count -= 6;					
						}
						usim_dcb.resync = KAL_TRUE; // for temp usage (last time)								
					}
					else
						count++;
					if(count == 0)
					{
						usim_dcb.ev_status = USIM_ATR_REC;
						USIM_SET_EVENT();
					}
					else
					{
						usim_dcb.rx_size = count+1;	// for temp usage (index to TD byte)
						SIM_SetRXTIDE(count); 
						DRV_WriteReg(SIM_IRQEN,USIM_IRQEN_NORMAL);
						usim_dcb.ev_status = USIM_NO_ERROR;
					}
					
					usim_dcb.main_state = ATR_STATE;
					usim_dcb.ATR_index = 0;
					usim_dcb.ATR_data[usim_dcb.ATR_index++] = TS;
					usim_dcb.ATR_data[usim_dcb.ATR_index++] = T0;
				}	
				else
				{
					kal_uint16 reg;
					
					usim_dcb.ev_status = USIM_TS_INVALID;
					SIM_DisAllIntr(); // prevent the following ATR bytes trigger RX interrupt
					reg = DRV_Reg(SIM_STS);		
				}		
				USIM_SET_EVENT();
			}			
			break;
		case ATR_STATE:			
			{	// receive all ATR data without timeout to indicate
				kal_uint32 count;
				kal_uint8 TD;
				
				count = DRV_Reg(SIM_COUNT);					
				dbg_print("ATR_STATE : %d ",count);				
				while(count--)
					usim_dcb.ATR_data[usim_dcb.ATR_index++] = (kal_uint8)DRV_Reg(SIM_DATA);
				if(usim_dcb.abort == KAL_TRUE)
				{
					usim_dcb.abort = KAL_FALSE;
					SIM_SetRXTIDE(6); 
					usim_dcb.resync = KAL_TRUE;
					break;
				}
				if(usim_dcb.resync == KAL_FALSE)
				{
					TD = usim_dcb.ATR_data[usim_dcb.rx_size];
					dbg_print(", TD = %x ,%d", TD,usim_dcb.rx_size);
					count = 0;
					USIM_CAL_TD_COUNT(TD, count);			
					if((TD & TDMask) == NULL)
					{
						count += usim_dcb.hist_index;
						if(count >= SIM_TOTAL_FIFO_LEN)
						{
							// usim_dcb.rx_index = count; // for temp usage (total ATR len)
							usim_dcb.abort = KAL_TRUE;	// for temp usage (separate two times)
							count -= 6;					
						}
						usim_dcb.resync = KAL_TRUE; // for temp usage (last time)								
					}
					else
						count++;				
					usim_dcb.rx_size += (count);	// for temp usage (index to TD byte)
					SIM_SetRXTIDE(count); 					
				}
				else
				{
					usim_set_timeout(0);
					dbg_print("\r\n!! all ATR received \r\n");
					usim_dcb.hist_index = 0;
					usim_dcb.rx_size = 0;					
					usim_dcb.resync = KAL_FALSE;
					usim_dcb.abort = KAL_FALSE;
	            usim_dcb.ev_status = USIM_ATR_REC;
	            USIM_SET_EVENT();					
				}				
			}
			break;
		case PTS_STATE:
			SIM_DisAllIntr();
			usim_dcb.ev_status = USIM_NO_ERROR;
			USIM_SET_EVENT();
			break;			
	}
}

/*************************************************************************
* FUNCTION
*  usim_send_block
*
* DESCRIPTION
*	1. sending a block to UICC, with header in usim_dcb.header_tx
*	2. if len > 0 then using DMA to transfer data from tx buffer to the fifo of sim
		interface.
	3. after a complete block is sent, T1END is generated
	4. after that, three bytes of received block header will come into rx fifo
*
* PARAMETERS
	adrs: tx buffer address
	
* RETURNS
	None
	
* GLOBALS AFFECTED
*	usim_dcb
*
*************************************************************************/
static void usim_send_block(kal_uint8 *adrs )
{
	kal_uint32 len, pcb;
	kal_uint8 *header;
	usim_dcb_struct *dcb = &usim_dcb;

	header = dcb->header_tx;
	dcb->main_state = CMD_TX_STATE;
	USIM_CLR_FIFO();
	// write header into fifo
	len = header[T1_LEN_INDEX];	
	pcb = header[T1_PCB_INDEX];
	dbg_print("usim_send_block [00][%x][%x]\r\n",pcb, len);
	#if defined(USIM_DEBUG)
	{
		kal_uint32 i;
		dbg_print("tx:");
		if(USIM_IS_SBLOCK(pcb)&& len ==1)
		{
			dbg_print(" %x",header[T1_INF_INDEX]);
		}
		else
		{
			for(i=0;i<len;i++)
			{
				dbg_print(" %x",adrs[i]);
			}
		}
		dbg_print("\r\n");
	}
	#endif
	
	DRV_WriteReg(SIM_DATA, header[T1_NAD_INDEX]);
	DRV_WriteReg(SIM_DATA, pcb);
	DRV_WriteReg(SIM_DATA, len);
	DRV_WriteReg(SIM_IMP3, len);
	// transfer by DMA if the count > 12, otherwise by MCU
	SIM_SetTXTIDE(1);
	if(len > 12)
	{
		dcb->dma_menu.addr = (kal_uint32)adrs;
		dcb->dma_input.type = DMA_HWTX;
		dcb->dma_input.count = (kal_uint16)len;
		USIM_TX_START_T1();
		DMA_Config(dcb->dma_port,&dcb->dma_input,KAL_TRUE);
	}
	else if(USIM_IS_SBLOCK(pcb)&& len ==1)
	{
		DRV_WriteReg(SIM_DATA, header[T1_INF_INDEX]);
		USIM_TX_START_T1();
	}
	else
	{
		kal_uint32 i;
		
		for(i=0;i<len;i++)
			DRV_WriteReg(SIM_DATA, adrs[i]);
		USIM_TX_START_T1();
	}
	DRV_WriteReg(SIM_IRQEN, SIM_STS_T1END);
}
/*
1. send S blocks of request or response.
2. if sending request, check if the response is correct.
3. if sending response,
4. EDC will be generated(tx) and removed(rx) by T1 controller

id: PCB of the S block
param: parameter of the S-block

*/
static usim_status_enum usim_send_s_block(usim_s_block_id_enum id, kal_uint8 param)	
{
	kal_uint8 *tx_buf, *rx_buf, len, t;
	kal_bool is_resp;
	kal_uint32 i;
	usim_dcb_struct *dcb = &usim_dcb;

	dbg_print("usim_send_s_block id:%x, param:%d \r\n", id, param);
	tx_buf = dcb->header_tx;
	rx_buf = dcb->header_rx;
	tx_buf[T1_NAD_INDEX] = USIM_NAD_DEFAULT;
	tx_buf[T1_PCB_INDEX] = id;
	is_resp = ((id & PCB_S_RESP) != 0);
	dcb->cmd_state = (is_resp)?(S_BlOCK_RESP_TX):(S_BlOCK_REQ_TX);
	if(id==IFS_REQ || id==WTX_REQ || id==IFS_RESP|| id==WTX_RESP )
	{
		len = 4;
		tx_buf[T1_LEN_INDEX] = 1;
	}
	else
	{
		len = 3;
		tx_buf[T1_LEN_INDEX] = 0;
	}
   tx_buf[T1_INF_INDEX] = param;
   dcb->retry = 0;

   while(dcb->retry++ < 3)
   {
		usim_send_block(&param);
		USIM_WAIT_EVENT();
		if(usim_dcb.ev_status == USIM_NO_ERROR)
		{
			if(!is_resp)
			{
				for(t=0,i=0;i<len;i++)
					t += rx_buf[i]^tx_buf[i];
				if(t != PCB_S_RESP)
					continue;
			}			
			break;
		}
   }
   if(dcb->retry == 4)
   {
   	usim_deactivation();
   }
   #if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
	#endif
	
	return USIM_NO_ERROR;	
	
}

/*************************************************************************
* FUNCTION
*  usim_rx_block_handler
*
* DESCRIPTION
*	1. process the received block including I, R, and S blocks
*	2. prepare the next sending block header in the usim_dcb.header_tx
*
* PARAMETERS
	adrs: address of the data buffer
	
* RETURNS
	KAL_TRUE: a valid block is received
	KAL_FALSE: an invalid block is received
	
* GLOBALS AFFECTED
*	usim_dcb
*
*************************************************************************/
static kal_bool usim_rx_block_handler(kal_uint32 *adrs)
{
	kal_uint8 pcb, len;

	if(usim_dcb.header_rx[T1_NAD_INDEX] != 0)
	{
		dbg_print("(invlid block) invalid NAD\r\n");
		return KAL_FALSE;
	}
	pcb = usim_dcb.header_rx[T1_PCB_INDEX];
	len = usim_dcb.header_rx[T1_LEN_INDEX];
	if(len > usim_dcb.ifsd) // 0 <= len <= IFSC (max 254)
		return KAL_FALSE;
	#if defined(USIM_DEBUG)
	{	
		dbg_print("rx:%x %x %x",usim_dcb.header_rx[0],usim_dcb.header_rx[1],usim_dcb.header_rx[2]);
		if(USIM_IS_SBLOCK( usim_dcb.header_rx[1]))
			dbg_print(" %x \r\n",usim_dcb.rx_buf[3]);
	
	}
	#endif
	// USIM_INV_N(usim_dcb.ns);
	if(USIM_IS_IBLOCK(pcb))
	{	// I-block
		dbg_print("received a I-block\r\n");
		if(pcb & PCB_I_RFU)
		{
			dbg_print("(invlid block) error PCB \r\n");
			return KAL_FALSE;
		}	
		#if defined(USIM_DEBUG)
		{
			kal_uint32 i;
			for(i=0;i<len;i++)
			{
				dbg_print(" %x",usim_dcb.rx_buf[usim_dcb.rx_index+i]);
			}
			dbg_print("\r\n");
		}
		#endif
		if((pcb & PCB_I_SEQ) != usim_dcb.nr)
		{
			dbg_print("(invlid block) receive sequence err\r\n");
			return KAL_FALSE;
		}
		if(usim_dcb.header_rx[T1_LEN_INDEX] > usim_dcb.ifsd)
		{
			dbg_print("(invalid block) receive lenght > IFSD \r\n");
			return KAL_FALSE;
		}		
		if(usim_dcb.header_tx[T1_PCB_INDEX]== RESYNC_REQ)
		{
			// must receive a S RESP not any other block
			dbg_print("(invalid block) must receive a S RESP not any other block \r\n");
			return KAL_FALSE;			
		}
			
		usim_dcb.tx_chain = KAL_FALSE;
		USIM_INV_N(usim_dcb.nr);
		usim_dcb.retry = 0;
		usim_dcb.tx_size -= usim_dcb.header_tx[T1_LEN_INDEX];
		usim_dcb.tx_index += usim_dcb.header_tx[T1_LEN_INDEX]; 		
		usim_dcb.rx_size  -= usim_dcb.header_rx[T1_LEN_INDEX]; 		
		usim_dcb.rx_index += usim_dcb.header_rx[T1_LEN_INDEX];
		if(pcb & PCB_I_M)
		{
			// a chaining I-block received send a R-block
			usim_dcb.rx_chain = KAL_TRUE;
			dbg_print("chaining...\r\n");
			USIM_MAKE_R_BLOCK(PCB_R_STATUS_OK);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -