예제 #1
0
파일: flashx.c 프로젝트: Vinhuit/Freescale
_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 */
예제 #2
0
_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 */