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

📄 icap.c

📁 fpga上的icap端口的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		size_t copy_length = local_buffer_copy_length > user_buffer_copy_length 			? user_buffer_copy_length : local_buffer_copy_length;		if(false) /* disable the next line */		printk("<2>\t\t%s: local = %8.8X, user = %8.8X, actual = %8.8X\n",hwicap_driver_name,			local_buffer_copy_length,user_buffer_copy_length,copy_length);		// transfer the next chunk from the user buffer		copy_from_user(local_buffer_pos,user_buffer_pos,copy_length);		if(false) /* disable the next line */		printk("<2>\t\t%s: copied %8.8X bytes from user buffer position %8.8X-%8.8X\n",			hwicap_driver_name,copy_length,user_buffer_pos-user_buffer_start+(int)*f_pos,			copy_length+user_buffer_pos-user_buffer_start+(int)*f_pos);		// walk through the state machine, deciding what to do with the local buffer data		local_buffer_end = local_buffer_pos + copy_length;		local_buffer_pos = local_buffer_start;		size_t processed_length = run_write_state_machine();		// if an error was detected, be sure to return it		if((int) processed_length < 0) return processed_length;		// copy any residual data to the beginning of the buffer		char* local_buffer_mark = local_buffer_pos;		local_buffer_pos = local_buffer_start;		if(false) /* disable the next line */		printk("<2>\t\t%s: moving %d bytes from local buffer position %8.8X to %8.8X\n",			hwicap_driver_name,local_buffer_end-local_buffer_mark,(unsigned int) local_buffer_mark,			(unsigned int) local_buffer_pos);		while(local_buffer_mark < local_buffer_end) *local_buffer_pos++ = *local_buffer_mark++;		// update the user buffer position		user_buffer_pos += copy_length;		// ensure that we don't flip out and hang up the machine		if(max_iterations++ > 10000) {			printk("<1>\t%s: aborted writing at %d iterations\n",hwicap_driver_name,max_iterations);			return count;		}	}	// update the file pointer	*f_pos += count;	// update the expected file pointer	expected_pos += count;	// and return the number of bytes written	return count;}// run the write state machinessize_t run_write_state_machine(void) {	// declare variables	int exit_loop = false;	int flush = false;	size_t bytes_wanted = 0;	char* ptr = NULL;	// declare static iterators	static char* field_start = NULL;	static char* field_pos = NULL;	static char* field_end = NULL;	static char field_divider = 0;	static int field_index = 0;	static char* field_length[5];	static char** field_bytes[5];	// run through the state machine as long as we still have input data	while(flush || (local_buffer_pos < local_buffer_end && !exit_loop)) {		// determine how many bytes remain		size_t bytes_available = local_buffer_end - local_buffer_pos;		// handle the current state		switch(write_state) {			// this special state is only used to collect field bytes			case FSM_WRITE_STATE_COLLECT:				// determine how many bytes we want				bytes_wanted = field_end - field_pos;				if(bytes_wanted > bytes_available) bytes_wanted = bytes_available;				while(bytes_wanted--) *field_pos++ = *local_buffer_pos++;				if(field_pos == field_end) write_state = next_write_state;				break;			case FSM_WRITE_STATE_START:				// initialize the field arrays				field_index = 0;				field_length[field_index] = (char*) &header.file_magic_length;				field_bytes[field_index] = &header.file_magic_bytes;				field_index++;				field_length[field_index] = (char*) &header.design_name_length;				field_bytes[field_index] = &header.design_name_bytes;				field_index++;				field_length[field_index] = (char*) &header.device_name_length;				field_bytes[field_index] = &header.device_name_bytes;				field_index++;				field_length[field_index] = (char*) &header.date_string_length;				field_bytes[field_index] = &header.date_string_bytes;				field_index++;				field_length[field_index] = (char*) &header.time_string_length;				field_bytes[field_index] = &header.time_string_bytes;				field_index++;				field_divider = 'a';				field_index = 0;				word_count = 0;				total_word_count = 0;				// prepare to collect the magic length				field_start = field_pos = (char*) &header.file_magic_length;				field_end = field_start + 2;				next_write_state = FSM_WRITE_STATE_MAGIC;				write_state = FSM_WRITE_STATE_COLLECT;				break;			case FSM_WRITE_STATE_MAGIC:				// check the magic length				if(header.file_magic_length != 9) return -EINVAL;				//printk("<2>\t\t%s: detected magic length\n",hwicap_driver_name);				// prepare to collect the magic				header.file_magic_bytes = kmalloc(header.file_magic_length,GFP_KERNEL);				if(header.file_magic_bytes == NULL) return -ENOMEM;				field_start = field_pos = header.file_magic_bytes;				field_end = field_start + header.file_magic_length;				next_write_state = FSM_WRITE_STATE_ZERO_ONE;				write_state = FSM_WRITE_STATE_COLLECT;				break;			case FSM_WRITE_STATE_ZERO_ONE:				// check the magic string				ptr = header.file_magic_bytes;				for(int i = 0;i < 4;i++) if(*ptr++ != 0x0f || *ptr++ != 0xf0) return -EINVAL;				if(*ptr != 0) return -EINVAL;				//printk("<2>\t\t%s: detected magic 0FF00FF00FF000\n",hwicap_driver_name);				// prepare to collect the zero-one string				field_start = field_pos = (char*) &header.zero_one;				field_end = field_start + 2;				next_write_state = FSM_WRITE_STATE_A;				write_state = FSM_WRITE_STATE_COLLECT;				break;			case FSM_WRITE_STATE_A:			case FSM_WRITE_STATE_B:			case FSM_WRITE_STATE_C:			case FSM_WRITE_STATE_D:			case FSM_WRITE_STATE_E:				// check the zero-one string				if(write_state == FSM_WRITE_STATE_A) {					if(header.zero_one != 1) return -EINVAL;					//printk("<2>\t\t%s: detected zero-one\n",hwicap_driver_name);				} else {					//printk("<2>\t\t%s: detected field %s\n",					//	hwicap_driver_name,*field_bytes[field_index]);				}				// check the field divider				if(*local_buffer_pos++ != field_divider) return -EINVAL;				field_divider++;				field_index++;				write_state++;				break;			case FSM_WRITE_STATE_DESIGN_LENGTH:			case FSM_WRITE_STATE_DEVICE_LENGTH:			case FSM_WRITE_STATE_DATE_LENGTH:			case FSM_WRITE_STATE_TIME_LENGTH:				// prepare to collect the field length				field_start = field_pos = field_length[field_index];				field_end = field_start + 2;				next_write_state = write_state + 1;				write_state = FSM_WRITE_STATE_COLLECT;				break;			case FSM_WRITE_STATE_DESIGN:			case FSM_WRITE_STATE_DEVICE:			case FSM_WRITE_STATE_DATE:			case FSM_WRITE_STATE_TIME:				// prepare to collect the field bytes				*field_bytes[field_index] = kmalloc(*(Xuint16*) field_length[field_index],GFP_KERNEL);				if(*field_bytes[field_index] == NULL) return -ENOMEM;				field_start = field_pos = *field_bytes[field_index];				field_end = field_start + *(Xuint16*) field_length[field_index];				next_write_state = write_state + 1;				write_state = FSM_WRITE_STATE_COLLECT;				break;			case FSM_WRITE_STATE_LENGTH:				// prepare to collect the length field				field_start = field_pos = (char*) &header.bitstream_length;				field_end = field_start + 4;				next_write_state = FSM_WRITE_STATE_FULL_HEADER;				write_state = FSM_WRITE_STATE_COLLECT;				break;			case FSM_WRITE_STATE_FULL_HEADER:				// provide user feedback				printk("<2>\t%s: %s, %s, %s, %s (%8.8X bytes)\n",hwicap_driver_name,					header.design_name_bytes,header.device_name_bytes,					header.date_string_bytes,header.time_string_bytes,					(int) header.bitstream_length);				write_state = FSM_WRITE_STATE_STREAM;				break;			case FSM_WRITE_STATE_STREAM:				// apply words from the word buffer to the ICAP port				if(word_count) {					if(false) /* disable the next line */					printk("<2>\t\t%s: writing %8.8X words to ICAP from %8.8X\n",						hwicap_driver_name,word_count,(unsigned int) word_buffer);					XStatus status = XHwIcap_SetConfiguration_Fixed(&xhwicap,word_buffer,word_count);					if(status != XST_SUCCESS) {						printk("<2>\t\t%s: XHwIcap_SetConfiguration() returned %d\n",							hwicap_driver_name,(int) status);					}					total_word_count += word_count;				}				if((total_word_count << 2) == header.bitstream_length) {					Xuint32 stat_reg = XHwIcap_GetConfigReg(&xhwicap,XHI_STAT);					printk("<2>\t%s: done writing %8.8X bytes: stat = %8.8X\n",						hwicap_driver_name,(int) header.bitstream_length,(int) stat_reg);					if(stat_reg & 1) printk("<2>\t%s: CRC error\n",hwicap_driver_name);					write_state = FSM_WRITE_STATE_NULL;					flush = false;					break;				}				// prepare to collect the bitstream words				field_start = field_pos = (char*) &word_buffer;				field_end = field_start + sizeof(word_buffer);				if(sizeof(word_buffer) > bytes_available) field_end = field_start + bytes_available;				field_end = (char*) ((int) field_end & ~0x03);				word_count = (field_end - field_start) >> 2;				next_write_state = write_state;				write_state = FSM_WRITE_STATE_COLLECT;				if(false) /* disable the next line */				printk("<2>\t\t%s: collecting %8.8X words from %8.8X to %8.8X\n",					hwicap_driver_name,(field_end - field_start) >> 2,(unsigned int) field_start,					(unsigned int) field_end);				if(bytes_available < 4) exit_loop = true;				break;			case FSM_WRITE_STATE_NULL:				printk("<2>\t%s: ignoring unexptected bytes\n",hwicap_driver_name);				local_buffer_pos = local_buffer_end;				break;		}		// be sure to flush the final words if this is the end of the bitstream		if(local_buffer_pos == local_buffer_end && write_state == FSM_WRITE_STATE_STREAM			&& ((total_word_count + word_count) << 2) == header.bitstream_length)			flush = true;	}	// return the amount of data that we processed	return local_buffer_pos - local_buffer_start;}// remap the base address of the XHwIcap structure to the appropriate virtual addressint XHwIcap_init_remap_baseaddress(XHwIcap *xhwicap) {	// if we have no mapped virtual base address, the device is not initialized	if(!hwicap_virt_ptr) return -ENODEV;	// set the mapped virtual base address and return success	xhwicap->BaseAddress = (Xuint32) hwicap_virt_ptr;	return 0;}// this function corrects and replaces XHwIcap_SetConfiguration provided with EDK#define XHI_BUFFER_START 0XStatus XHwIcap_SetConfiguration_Fixed(XHwIcap *InstancePtr, Xuint32 *Data,                                 Xuint32 Size){    XStatus Status;    Xint32 BufferCount=0;    Xint32 NumWrites=0;    Xboolean Dirty=XFALSE;    Xuint32 I;    /* Loop through all the data */    for (I=0,BufferCount=0;I<Size;I++)    {        /* Copy data to bram */        XHwIcap_StorageBufferWrite(InstancePtr, BufferCount, Data[I]);        Dirty=XTRUE;        if (BufferCount == XHI_MAX_BUFFER_INTS-1)        {            /* Write data to ICAP */            Status = XHwIcap_DeviceWrite(InstancePtr, XHI_BUFFER_START,                                         XHI_MAX_BUFFER_INTS);            if (Status != XST_SUCCESS)            {                return Status;            }            BufferCount=0;            NumWrites++;            Dirty=XFALSE;        } else        {         BufferCount++;        }    }   /* Write unwritten data to ICAP */   if (Dirty==XTRUE)   {      /* Write data to ICAP */      Status = XHwIcap_DeviceWrite(InstancePtr, XHI_BUFFER_START,                                    BufferCount);      return Status;   }   return XST_SUCCESS;};

⌨️ 快捷键说明

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