/////////////////////////////////////////////////////////////////////////////////// // File : boot_bdv_driver.c // Date : 18/01/2017 // Author : Alain Greiner / Vu Son // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #ifndef SEG_IOC_BASE # error "The SEG_IOC_BASE value should be defined in the 'hard_config.h' file" #endif #ifndef X_IO # error "The X_IO value should be defined in the 'hard_config.h' file" #endif #ifndef Y_IO # error "The Y_IO value should be defined in the 'hard_config.h' file" #endif #ifndef Y_WIDTH # error "The Y_WIDTH value should be defined in the 'hard_config.h' file" #endif /**************************************************************************** * Internal functions. * ****************************************************************************/ /**************************************************************************** * This function returns the value of a BDV register. * * @ reg : BDV register to be read. * * @ returns the value stored in 'reg'. * ****************************************************************************/ static uint32_t boot_bdv_get_register( uint32_t reg ) { cxy_t cxy = (X_IO << Y_WIDTH) + Y_IO; uint32_t * ptr = (uint32_t *)SEG_IOC_BASE + reg; return boot_remote_lw( XPTR( cxy , ptr ) ); } // boot_bdv_get_register() /**************************************************************************** * This function set a new value to a BDV register. * * @ reg : BDV register to be configured. * * @ val : new value to be written. * ****************************************************************************/ static void boot_bdv_set_register( uint32_t reg, uint32_t val ) { cxy_t cxy = (X_IO << Y_WIDTH) + Y_IO; uint32_t * ptr = (uint32_t *)SEG_IOC_BASE + reg; boot_remote_sw( XPTR( cxy , ptr ) , val ); } // boot_bdv_set_register() /**************************************************************************** * Driver API functions. * ****************************************************************************/ /////////////////// int boot_bdv_init( void ) { // Check block size if (boot_bdv_get_register(BDV_BLOCK_SIZE) != 512) { boot_puts("\n[BOOT ERROR] boot_bdv_init(): " "Block size must be 512 bytes\n"); return -1; } // Disable IRQq boot_bdv_set_register(BDV_IRQ_ENABLE, 0); return 0; } // boot_bdv_init() //////////////////////////////////// int boot_bdv_access( uint32_t lba, xptr_t buf_paddr, uint32_t count) { uint32_t error; uint32_t status; // get target buffer cluster and pointer cxy_t buf_cxy = GET_CXY( buf_paddr ); uint32_t buf_ptr = (uint32_t)GET_PTR( buf_paddr ); // Check buffer address alignment if (buf_ptr & 0x3F) { boot_puts("\n[BOOT ERROR] boot_bdv_access(): " "Buffer address is not cache-line-size-aligned\n"); return -1; } // Set BDV device registers boot_bdv_set_register(BDV_BUFFER , buf_ptr ); boot_bdv_set_register(BDV_BUFFER_EXT, buf_cxy ); boot_bdv_set_register(BDV_COUNT , count ); boot_bdv_set_register(BDV_LBA , lba ); #if USE_IOB // software L2/L3 cache coherence if( boot_mmc_inval( buf_paddr, count<<9 ) ) return -1; #endif // Launch data transfer boot_bdv_set_register(BDV_OPERATION, BDV_READ); #if DEBUG_BOOT_IOC boot_printf("\n[BOOT] boot_bdv_access(): Transfer launched at cycle %d\n" " lba = %d / buf = %l / nblocks = %d\n", boot_get_proctime() , lba , buf_paddr , count ); #endif // Wait transfer completion do { status = boot_bdv_get_register(BDV_STATUS); } while ((status != BDV_READ_SUCC ) && (status != BDV_READ_ERR ) && (status != BDV_WRITE_SUCC) && (status != BDV_WRITE_ERR )); #if DEBUG_BOOT_IOC boot_printf("\n[BOOT] boot_bdv_access(): Transfer terminated at cycle %d\n", boot_get_proctime() ); // uint32_t * data = (uint32_t *)(uint32_t)buf_paddr; // uint32_t line; // uint32_t word; // boot_printf("\n"); // for( line = 0 ; line < 16 ; line++ ) // { // for( word = 0 ; word < 8 ; word++ ) // { // boot_printf(" | %x", data[line*8+word] ); // } // boot_printf(" |\n"); // } #endif // Check error error = ((status == BDV_READ_ERR) || (status == BDV_WRITE_ERR)); return error; } // boot_bdv_access()