/** * \File : reset_hba.c * \Date : 23/11/2013 * \Author : alain greiner * \Copyright (c) UPMC-LIP6 */ #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// // Global variables /////////////////////////////////////////////////////////////////////////////// // command descriptor (one single command) static hba_cmd_desc_t hba_cmd_desc __cache_aligned__; // command table (one single command) static hba_cmd_table_t hba_cmd_table __cache_aligned__; // IOC/HBA device base address static int* const ioc_address = (int* const)SEG_IOC_BASE; /////////////////////////////////////////////////////////////////////////////// // Extern functions /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // This function register one command in both the command descriptor // and the command data, and updates the HBA_PXCI register. // The all addresses are supposed to be identity mapping (vaddr == paddr). // return 0 if success, -1 if error /////////////////////////////////////////////////////////////////////////////// int reset_hba_read( unsigned int lba, void* buffer, unsigned int count ) { unsigned int pxci; // HBA_PXCI register value unsigned int pxis; // HBA_PXIS register value // check buffer alignment if( (unsigned int)buffer & 0x3F ) { reset_puts("\n[RESET ERROR] in reset_hba_read() "); reset_puts("buffer not aligned on 64 bytes: base = "); reset_putx( (unsigned int)buffer ); reset_puts("\n"); return -1; } // set command data header: lba value hba_cmd_table.header.lba0 = (char)lba; hba_cmd_table.header.lba1 = (char)(lba>>8); hba_cmd_table.header.lba2 = (char)(lba>>16); hba_cmd_table.header.lba3 = (char)(lba>>24); hba_cmd_table.header.lba4 = 0; hba_cmd_table.header.lba5 = 0; // set command data buffer: address and size) hba_cmd_table.buffer.dba = (unsigned int)(buffer); hba_cmd_table.buffer.dbau = 0; hba_cmd_table.buffer.dbc = count*512; // set command descriptor: one single buffer / read access hba_cmd_desc.prdtl[0] = 1; hba_cmd_desc.prdtl[1] = 0; hba_cmd_desc.flag[0] = 0; // read #if USE_IOB // update external memory for command table reset_L2_sync( &hba_cmd_table , 32 ); // update external memory for command descriptor reset_L2_sync( &hba_cmd_desc , 16 ); #endif // start transfer iowrite32( &ioc_address[HBA_PXCI] , 1 ); #if (RESET_HARD_CC == 0) || USE_IOB // inval buffer in L1 cache reset_L1_inval( buffer , count * 512 ); #endif #if USE_IOB // inval buffer in L2 cache reset_L2_inval( buffer , count * 512 ); #endif // poll PXCI until command completed by HBA do { pxci = ioread32( &ioc_address[HBA_PXCI] ); } while( pxci ); // get PXIS register pxis = ioread32( &ioc_address[HBA_PXIS] ); // reset PXIS register iowrite32( &ioc_address[HBA_PXIS] , 0 ); // reset PXCI register : we use only command slot[0] in PXCI iowrite32( &ioc_address[HBA_PXCI] , 0 ); // check error status if ( pxis & 0x40000000 ) { reset_puts("[RESET ERROR] in reset_hba_read() : " " status error returned by HBA\n"); return 1; } return 0; } // end reset_hba_read() /////////////////////////////////////////////////////////////////////////////// // This function initialises both the HBA registers and the // memory structures used by the AHCI peripheral (one single command). /////////////////////////////////////////////////////////////////////////////// int reset_hba_init() { // initialise the command descriptor hba_cmd_desc.ctba = (unsigned int)&hba_cmd_table; hba_cmd_desc.ctbau = 0; #if USE_IOB // update external memory for the commande descriptor reset_L2_sync(&hba_cmd_desc , sizeof( hba_cmd_desc_t ) ); #endif // initialise HBA registers iowrite32(&ioc_address[HBA_PXCLB], (unsigned int)&hba_cmd_desc ); iowrite32(&ioc_address[HBA_PXCLBU], 0 ); iowrite32(&ioc_address[HBA_PXIE], 0 ); iowrite32(&ioc_address[HBA_PXIS], 0 ); iowrite32(&ioc_address[HBA_PXCI], 0 ); iowrite32(&ioc_address[HBA_PXCMD], 1 ); return 0; } // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4