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

📄 usb_isr.c

📁 一个linux下的usb接口源代码
💻 C
字号:
/*********************************************************************
**	Module Name:		USB_ISR.c									**
**	Author:				ZhangQuan									**
**	Version:			1.0											**
**	CreateDate:			2001-05-18									**
**	Description:		PDISUBD12 Interrupt Service Program			**
**	Remark:															**
**	Revision History:												**
**********************************************************************/
//#include <linux/interrupt.h>
//#include <asm/segment.h>
#include "DataType.h"
#include "MC68VZ328.h"

#define PD12_DEBUG	0
#define DMA_IDLE					0x00
#define DMA_RUNNING					0x01
#define DMA_PENDING					0x02

// Variable Definitions
//UCHAR GenEpBuf[EP1_PACKET_SIZE];

// Functions Declarations
void  usb_initialize(void);
void  usb_isr(int irq, void* dev_id, struct pt_regs * regs);
void  usb_bus_reset(void);
void  ep0_rxdone(void);
void  ep0_txdone(void);
void  ep1_txdone(void);
void  ep1_rxdone(void);
void  main_rxdone(void);
void  main_txdone(void);

// Functions Definitions
void  usb_initialize(void) // Initialization for USB
{
	cli();
	//Following three instructions : Disable the interrupt level 7(Caused by keyboard)
	/*PFDIR |= 0x70;
	PFSEL |= 0x70;
	PFPUEN |= 0x70;
	// PDIUSBD12 Chip Select
	PKDIR |= 0x01;
	PKSEL |= 0x01;
	PKPUEN |= 0x01;
	// PDIUSBD12 Read/Write Control
	PKDIR |= 0x60;
	PKSEL |= 0x60;
	PKPUEN |= 0x60;
	// PDIUSBD12 Other Control
	PKDIR |= 0x10;
	PKSEL |= 0x10;
	PKPUEN |= 0x10;
	// PDIUSBD12 Data
	PCDIR = 0xFF;
	PCSEL = 0xFF;
	PCPDEN = 0xFF;*/
	// PDIUSBD12 Interrupt	//Modified by Mike Chan: PD6/IRQ3
	PDPUEN |= 0x40;
	PDSEL &= (~0x40);
	// Initialize Port Value
	/*PCDATA = 0xFF;
	PKDATA |= 0x01;
	PKDATA |= 0x60;
	PKDATA &= (~0x10);*/
	bEPPflags.bits.set_d12 = 0;
	// Enable PDIUSBD12 Interrupt
	D12_ReadInterruptRegister();
	sti();
}

//extern UCHAR Flagwrite;
//void  usb_isr(int irq, void * dev_id, struct pt_regs* regs)
void usb_isr()
{
	UWORD ists;
	ULONG tmp = IMR;
	IMR = 0x01FFFFFF;
	//cli();
	//if (Flagwrite == 1)
	if (bD12flags.bits.BOT_state == USBFSM4BOT_DATAOVER)
		return;
	if (bEPPflags.bits.in_isr == 1)
		return;
	bEPPflags.bits.in_isr = 1;

	ists = D12_ReadInterruptRegister();
//		printf("in isr=%x\n",ists);

	if(ists != 0x00)
	{
		if(ists & D12_INT_BUS_RESET)
		{
			usb_bus_reset();
		}
		else
		{

			if(ists & D12_INT_SUSPEND_CHANGE) 
			{
				UCHAR ch;
				ch = PKDATA;
			}
			
			if(ists & D12_INT_EP0_IN) 
			{
				ep0_txdone();
			}
			
			if(ists & D12_INT_EP0_OUT) 
			{
				ep0_rxdone();
			}
			
			if(ists & D12_INT_EP1_IN) 
			{
				ep1_txdone();
			}
			if(ists & D12_INT_EP1_OUT) 
			{
				ep1_rxdone();
			}
			
			if(ists & D12_INT_EP2_IN)
			{
			 	main_txdone();
			}
			if(ists & D12_INT_EP2_OUT)
			{
				main_rxdone();
			}
		}
	}
	bEPPflags.bits.in_isr = 0;
	//sti();
	IMR = tmp;
}

void  usb_bus_reset(void)
{
	UWORD i,j;
	cli();
	if(bEPPflags.bits.set_d12 == 0)
	{
		bEPPflags.bits.set_d12 = 1;
			
		D12_SetAddressEnable(0x00,0x01);
		D12_SetEndpointEnable(0x01);
		D12_SetEndpointStatus(4, 0);
		D12_SetEndpointStatus(5, 0);
		// enable normal+sof interrupt
		D12_SetDMA(D12_DMA_EP4_INT_ENABLE | D12_DMA_EP5_INT_ENABLE);
		// Initialize D12 configuration
		D12_SetMode(D12_NO_LAZY_CLOCK | D12_CLOCK_RUNNING | D12_SOFT_CONNECT, D12_CLOCK_12M | D12_SET_TO_ONE);
	}
	bD12flags.bits.BOT_state = USBFSM4BOT_IDLE;//Modified by Mike Chan
	sti();
	return;
}

extern void control_handler(void);

void  ep0_rxdone(void)
{
	UWORD ep_last, i;
	cli();
	ep_last = D12_ReadLastTransactionStatus(0); // Clear interrupt flag
	if(ep_last & D12_SETUPPACKET)
	{
		//OK, it is a setup packet;
		ControlData.wLength = 0;
		ControlData.wCount = 0;		
		ep_last = D12_ReadEndpoint(0, (UCHAR *)(&(ControlData.DeviceRequest)), sizeof(ControlData.DeviceRequest));
		if(ep_last != sizeof(DEVICE_REQUEST))
		{
			//If the package received is wrong, then let Host terminate the transfer.
			D12_SetEndpointStatus(0, 1);
			D12_SetEndpointStatus(1, 1);
			bEPPflags.bits.control_state = USB_IDLE;
			sti();
			return;
		}

		//OK. the data in setup package received is right;
		ControlData.DeviceRequest.wValue = SWAP(ControlData.DeviceRequest.wValue);
		ControlData.DeviceRequest.wIndex = SWAP(ControlData.DeviceRequest.wIndex);
		ControlData.DeviceRequest.wLength = SWAP(ControlData.DeviceRequest.wLength);

		
		// Acknowledge setup here to unlock in/out endp
		//The data are read out, so the endpoint can be reused;
		D12_AcknowledgeEndpoint(0);
		D12_AcknowledgeEndpoint(1);
		ControlData.wLength = ControlData.DeviceRequest.wLength;
		ControlData.wCount = 0;
		if(ControlData.DeviceRequest.bmRequestType & (UCHAR )USB_DATA_TRANSMIT_DEVICE_TO_HOST)
		{
			bEPPflags.bits.control_state = USB_TRANSMIT; // get command//Modified by ChenXiaotian
			control_handler();
		}
		else
		{
			if(ControlData.DeviceRequest.wLength == 0)
			{
				bEPPflags.bits.control_state = USB_IDLE; // set command
				control_handler();
			}
			else
			{
				if(ControlData.DeviceRequest.wLength > MAX_CONTROLDATA_SIZE)
				{
					bEPPflags.bits.control_state = USB_IDLE;
					D12_SetEndpointStatus(0, 1);
					D12_SetEndpointStatus(1, 1);		//Wrong receive
				}
				else
					bEPPflags.bits.control_state = USB_RECEIVE; // set command with OUT token
			} // set command with data
		} // else set command
	} // if setup packet
	else if(bEPPflags.bits.control_state == USB_RECEIVE)
	{
		//Not the setup package, it is the phase which receives the data.
		i =	D12_ReadEndpoint(0, ControlData.dataBuffer + ControlData.wCount, EP0_PACKET_SIZE);
		ControlData.wCount += i;
		if(i != EP0_PACKET_SIZE || ControlData.wCount >= ControlData.wLength)
		{
				bEPPflags.bits.control_state = USB_IDLE;	//Receive over
				control_handler();
		}
	}
	else
	{
		bEPPflags.bits.control_state = USB_IDLE;
	}
	sti();
}

void ep0_txdone(void)
{
	SLONG i;
	cli();
	i = ControlData.wLength - ControlData.wCount;
	
	D12_ReadLastTransactionStatus(1); // Clear interrupt flag
	if(bEPPflags.bits.control_state != USB_TRANSMIT) 
	{
		sti();
		return;
	}
	if( i >= EP0_PACKET_SIZE)
	{
		D12_WriteEndpoint(1, ControlData.pData + ControlData.wCount, EP0_PACKET_SIZE);
		ControlData.wCount += EP0_PACKET_SIZE;
		
		bEPPflags.bits.control_state = USB_TRANSMIT;
	}
	else if(i != 0)
	{
		D12_WriteEndpoint(1, ControlData.pData + ControlData.wCount, i);
		ControlData.wCount += i;

		bEPPflags.bits.control_state = USB_IDLE;
	}
	else if(i == 0)
	{
		D12_WriteEndpoint(1, 0, 0); // Send zero packet at the end ???
		bEPPflags.bits.control_state = USB_IDLE;
	}
	sti();
}

void ep1_txdone(void)
{
	cli();
	D12_ReadLastTransactionStatus(3); // Clear interrupt flag
	sti();
}

void ep1_rxdone(void)
{
	UCHAR len;
	cli();
	D12_ReadLastTransactionStatus(2); // Clear interrupt flag
	len = D12_ReadEndpoint(2, Allbuffer, EP1_PACKET_SIZE);
	if(len != 0) bEPPflags.bits.do_ep1_rxdone = 1;
	sti();
}

void main_rxdone(void)
{
	UCHAR c;
	UCHAR	*cbwpt;
	ULONG i;
	
	c = D12_ReadLastTransactionStatus(4); // Clear interrupt flag 
	if(!(c & D12_TRANSMIT_SUCCESS))
	{
		printk("Fatal Error: Isr_MainRxDone ReadLastTranactionStatus=%x\n",c);
		return ;
	}
	
	//Receive the CBW block;
	switch(bD12flags.bits.BOT_state)
	{
		UCHAR c1;
		case USBFSM4BOT_IDLE:	// The Only state can receive CBW
			c = D12_ReadEndpointStatus(4);
			if(c & (D12_BUFFER0FULL | D12_BUFFER1FULL)) 
			{
				bD12flags.bits.BOT_state = USBFSM4BOT_CBWPROC;
				//TPBulk_CBWHandler();
			}									
			break;
		case USBFSM4BOT_DATAOUT:
			// Normal Path, Data-Out Stage of Command/Data/Status Flow
			c = D12_ReadEndpointStatus(4);
			c1 = c & 0x60;
			i =	D12_ReadMainEndpoint(ControlData.pData + ControlData.wCount);
			ControlData.wCount += i;
			
			if(c1==0x60)
			{
				i =	D12_ReadMainEndpoint(ControlData.pData + ControlData.wCount);
				ControlData.wCount += i;
			}
			if(ControlData.wCount == ControlData.wLength)
			{
				bD12flags.bits.BOT_state = USBFSM4BOT_DATAOVER;
			}
			//The last frame is processed here.			
/*			else if(ControlData.wCount >= ControlData.wLength-64)
			{
			}*/
			break;
		case USBFSM4BOT_DATAOVER:
		case USBFSM4BOT_CBWPROC:
		case USBFSM4BOT_CSW:
			break;
		default:
			// Something wrong here, Stall Bulk-Out and ask host to start recovery routine.
			printk("Fatal error in MainRx !\n");
			D12_SetEndpointStatus(4, 1);
			D12_SetEndpointStatus(5, 1);
			bD12flags.bits.BOT_state = USBFSM4BOT_STALL;
			break;
	}
	//sti();
}

void main_txdone(void)
{
	SLONG i;
	UCHAR c,c1;

	cli();	
	i = ControlData.wLength - ControlData.wCount;
	D12_ReadLastTransactionStatus(5); // Clear interrupt flag
	if(bD12flags.bits.BOT_state == USBFSM4BOT_CSW)
	{						
		c = D12_ReadEndpointStatus(4);
		c1= c & 0x60;
		if( c & (D12_BUFFER0FULL | D12_BUFFER1FULL)) 
		{			
			bD12flags.bits.BOT_state = USBFSM4BOT_CBWPROC;
			//TPBulk_CBWHandler();
		}
		else bD12flags.bits.BOT_state = USBFSM4BOT_IDLE;
		sti();
		
		return;
	}
	if (bD12flags.bits.BOT_state != USBFSM4BOT_DATAIN) return;
	if(i >= EP2_PACKET_SIZE) 
	{
		D12_WriteEndpoint(5, ControlData.pData+ControlData.wCount,EP2_PACKET_SIZE);//Corrected by Mike Chan
		ControlData.wCount += EP2_PACKET_SIZE;
		bD12flags.bits.BOT_state = USBFSM4BOT_DATAIN;
	}
	else if(i != 0) 
	{
		D12_WriteEndpoint(5, ControlData.pData, i);
		ControlData.wCount += i;
		TPBulk_CSWHandler();
	}
	else if (i == 0)
	{
		TPBulk_CSWHandler();
	}
	sti();
}

⌨️ 快捷键说明

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