_mqx_int _io_flashx_flush_buffer ( /* [IN] The device handle */ MQX_FILE_PTR fd_ptr ) { /* Body */ IO_FLASHX_FILE_STRUCT_PTR file_ptr = (IO_FLASHX_FILE_STRUCT_PTR) fd_ptr->DEV_DATA_PTR; _mqx_int error = MQX_OK; /* Check if buffering is enabled */ if (file_ptr->FLAGS & FLASHX_FLASH_BUFFER_ENABLED) { /* Flush sector buffer */ error = _io_flashx_flush_sector_buffer(fd_ptr); } /* No other buffering provided in this driver. */ return error; } /* Endbody */
_mqx_int _io_flashx_ioctl ( /* [IN] the file handle for the device */ MQX_FILE_PTR fd_ptr, /* [IN] the ioctl command */ _mqx_uint cmd, /* [IN/OUT] the ioctl parameters */ pointer param_ptr ) { /* Body */ IO_FLASHX_STRUCT_PTR dev_ptr = (IO_FLASHX_STRUCT_PTR) fd_ptr->DEV_PTR->DRIVER_INIT_PTR; IO_FLASHX_FILE_STRUCT_PTR file_ptr = (IO_FLASHX_FILE_STRUCT_PTR) fd_ptr->DEV_DATA_PTR; _mqx_int result = MQX_OK; _mqx_uint i, j; _mqx_uint sb, ss, offset, fs; char_ptr temp_ptr; pointer _PTR_ pparam_ptr; _mqx_uint_ptr uparam_ptr; _mem_size_ptr mparam_ptr; switch (cmd) { case FLASH_IOCTL_GET_BASE_ADDRESS: mparam_ptr = (_mem_size_ptr)param_ptr; *mparam_ptr = dev_ptr->BASE_ADDR; break; case FLASH_IOCTL_GET_BLOCK_GROUPS: for (i=0; dev_ptr->HW_BLOCK[i].NUM_SECTORS != 0; i++) { /* just count blocks */ } uparam_ptr = (_mqx_uint_ptr)param_ptr; *uparam_ptr = i; break; case IO_IOCTL_GET_NUM_SECTORS: *(uint_32_ptr)param_ptr = fd_ptr->SIZE / MFS_SECTOR_SIZE; break; case FLASH_IOCTL_GET_NUM_SECTORS: _io_flashx_find_correct_sectors(fd_ptr, fd_ptr->SIZE, &sb, &ss, &offset, &fs); uparam_ptr = (_mqx_uint_ptr) param_ptr; *uparam_ptr = fs; break; case FLASH_IOCTL_GET_WIDTH: uparam_ptr = (_mqx_uint_ptr)param_ptr; *uparam_ptr = dev_ptr->WIDTH; break; case IO_IOCTL_DEVICE_IDENTIFY: /* ** This is to let the upper layer know what kind of device this is. ** It's a physical flash device, capable of being erased, read, seeked, ** and written. Flash devices are not interrupt driven, so ** IO_DEV_ATTR_POLL is included. */ uparam_ptr = (_mqx_uint_ptr)param_ptr; uparam_ptr[0] = IO_DEV_TYPE_PHYS_FLASHX; uparam_ptr[1] = IO_DEV_TYPE_LOGICAL_MFS; uparam_ptr[2] = IO_DEV_ATTR_ERASE | IO_DEV_ATTR_POLL | IO_DEV_ATTR_READ | IO_DEV_ATTR_SEEK | IO_DEV_ATTR_WRITE; break; case IO_IOCTL_GET_BLOCK_SIZE: /* returns the fixed size for MFS sector size */ *(uint_32_ptr)param_ptr = MFS_SECTOR_SIZE; break; case FLASH_IOCTL_GET_SECTOR_SIZE: /* ** This returns the size of the sector after a user does an ** fseek to the location he/she wants to know the sector size of. */ _io_flashx_find_correct_sectors(fd_ptr, fd_ptr->LOCATION, &sb, &ss, &offset, &fs); mparam_ptr = (_mem_size_ptr) param_ptr; *mparam_ptr = dev_ptr->HW_BLOCK[sb].SECTOR_SIZE; break; case FLASH_IOCTL_GET_SECTOR_BASE: /* ** This returns the start address of the sector after a user does an ** fseek to the sector he/she wants know the start of. */ _io_flashx_find_correct_sectors(fd_ptr, fd_ptr->LOCATION, &sb, &ss, &offset, &fs); mparam_ptr = (_mem_size_ptr) param_ptr; *mparam_ptr = dev_ptr->BASE_ADDR + dev_ptr->HW_BLOCK[sb].START_ADDR + dev_ptr->HW_BLOCK[sb].SECTOR_SIZE * ss; break; case FLASH_IOCTL_GET_BLOCK_MAP: pparam_ptr = (pointer _PTR_) param_ptr; *pparam_ptr = (pointer) dev_ptr->HW_BLOCK; break; case IO_IOCTL_FLUSH_OUTPUT: case FLASH_IOCTL_FLUSH_BUFFER: _lwsem_wait(&dev_ptr->HW_ACCESS); result = _io_flashx_flush_buffer(fd_ptr); _lwsem_post(&dev_ptr->HW_ACCESS); break; case FLASH_IOCTL_ENABLE_BUFFERING: /* if RAM cache is enabled, enable buffer */ if(file_ptr->FLAGS & FLASHX_SECTOR_CACHE_ENABLED) { file_ptr->FLAGS |= FLASHX_FLASH_BUFFER_ENABLED; result = MQX_OK; } /* else return error */ else result = IO_ERROR; break; case FLASH_IOCTL_DISABLE_BUFFERING: _lwsem_wait(&dev_ptr->HW_ACCESS); result = _io_flashx_flush_buffer(fd_ptr); _lwsem_post(&dev_ptr->HW_ACCESS); if (result != MQX_OK) { break; } /* Endif */ file_ptr->FLAGS &= ~FLASHX_FLASH_BUFFER_ENABLED; break; case FLASH_IOCTL_ENABLE_SECTOR_CACHE: /* Set RAM cache flag */ file_ptr->FLAGS |= FLASHX_SECTOR_CACHE_ENABLED; break; case FLASH_IOCTL_DISABLE_SECTOR_CACHE: /* Disable buffering first */ if(file_ptr->FLAGS & FLASHX_FLASH_BUFFER_ENABLED){ _lwsem_wait(&dev_ptr->HW_ACCESS); result = _io_flashx_flush_sector_buffer(fd_ptr); _lwsem_post(&dev_ptr->HW_ACCESS); if (result != MQX_OK) { break; } /* Endif */ file_ptr->FLAGS &= ~FLASHX_FLASH_BUFFER_ENABLED; } /* clear ram cache flag */ file_ptr->FLAGS &= ~FLASHX_SECTOR_CACHE_ENABLED; break; case FLASH_IOCTL_ERASE_SECTOR: /* ** This erases the sector after a user does an ** fseek to the location of the sector he/she wants to erase. */ if (!dev_ptr->SECTOR_ERASE) { result = IO_ERROR_INVALID_IOCTL_CMD; break; } /* Endif */ _io_flashx_find_correct_sectors(fd_ptr, fd_ptr->LOCATION, &sb, &ss, &offset, &fs); temp_ptr = (char_ptr)(dev_ptr->BASE_ADDR + dev_ptr->HW_BLOCK[sb].START_ADDR + dev_ptr->HW_BLOCK[sb].SECTOR_SIZE * ss); _lwsem_wait(&dev_ptr->HW_ACCESS); if ((*dev_ptr->SECTOR_ERASE)(dev_ptr, temp_ptr, dev_ptr->HW_BLOCK[sb].SECTOR_SIZE)) { file_ptr->ERASE_ARRAY[fs / 8] |= (0x1 << (fs % 8)); if ((sb == file_ptr->CACHE_BLOCK) && (ss == file_ptr->CACHE_SECTOR)) file_ptr->DIRTY_DATA = FALSE; /* invalidate cache */ } else { result = IO_ERROR; /* could not erase sector */ } _lwsem_post(&dev_ptr->HW_ACCESS); break; case FLASH_IOCTL_ERASE_CHIP: /* Though this command erases the whole flash, ** it does not invalidates all the caches ** associated with opened files on this driver. */ if (dev_ptr->CHIP_ERASE) { _lwsem_wait(&dev_ptr->HW_ACCESS); result = (*dev_ptr->CHIP_ERASE)(dev_ptr); for (i = 0; i < file_ptr->ERASE_ARRAY_MAX; i++) { /* The whole chip is cleared, mark sectors as erased */ file_ptr->ERASE_ARRAY[i] = 0xFF; } _lwsem_post(&dev_ptr->HW_ACCESS); break; } else if (!dev_ptr->SECTOR_ERASE) { result = IO_ERROR_INVALID_IOCTL_CMD; break; } else { fs = 0; _lwsem_wait(&dev_ptr->HW_ACCESS); for (i = 0; dev_ptr->HW_BLOCK[i].NUM_SECTORS != 0; i++) { temp_ptr = (char_ptr)(dev_ptr->BASE_ADDR + dev_ptr->HW_BLOCK[i].START_ADDR); for (j = 0; j < dev_ptr->HW_BLOCK[i].NUM_SECTORS; j++) { if ((*dev_ptr->SECTOR_ERASE)(dev_ptr, temp_ptr, dev_ptr->HW_BLOCK[i].SECTOR_SIZE)) { file_ptr->ERASE_ARRAY[fs / 8] |= (0x1 << (fs % 8)); fs++; } else { result = IO_ERROR; /* sector erase was not successfull */ break; } temp_ptr += dev_ptr->HW_BLOCK[i].SECTOR_SIZE; } /* Endfor */ if (result != MQX_OK) break; } /* Endfor */ _lwsem_post(&dev_ptr->HW_ACCESS); }/* Endif */ break; case FLASH_IOCTL_WRITE_PROTECT: if (dev_ptr->WRITE_PROTECT != NULL) { _lwsem_wait(&dev_ptr->HW_ACCESS); result = (*dev_ptr->WRITE_PROTECT)(dev_ptr, *(_mqx_uint_ptr)param_ptr); _lwsem_post(&dev_ptr->HW_ACCESS); } break; default: if(dev_ptr->IOCTL != NULL){ result = (*dev_ptr->IOCTL)(dev_ptr, cmd, param_ptr); } else { result = IO_ERROR_INVALID_IOCTL_CMD; } break; } /* Endswitch */ return result; } /* Endbody */