📄 icap.c
字号:
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 + -