Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Jul 2nd, 2012  |  syntax: None  |  size: 5.70 KB  |  views: 242  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. uint32_t sata_cmd_dma( SataDev *dev, uint8_t cmd, uint32_t start, uint32_t count, uint8_t *buf ) {
  2.         uint8_t                         ncs = 0;                        // Number  of  Command  Slots  (NCS)
  3.         uint32_t                                slot = 0;               // Номер слота в списке команд
  4.         uint32_t                                i;
  5.         HBA_CMD_HEADER          *cmdheader = 0;
  6.         HBA_CMD_TBL                     *cmdtbl = 0;
  7.         FIS_REG_H2D                     *cmdfis = 0;
  8.        
  9.         // Определим, сколько командных слотов есть
  10.         ncs =( ( dev -> abar -> cap ) & 0x00001F00 ) >> 8;      // Выделяем количество ncs
  11.         printf( "ncs = %d\n\r", ncs );
  12.        
  13.         // Найдем свободный хедер
  14.         slot = dev -> abar -> ports[ dev -> portNumber ].sact | dev -> abar -> ports[ dev -> portNumber ].ci;
  15.         for( i = 0; i < ncs; ++i ) {
  16.                 if( ( slot & 1 ) == 0 ) {
  17.                         break;
  18.                 }
  19.                 slot >>= 1;
  20.         }
  21.        
  22.         // Проверим, найден ли свободный слот
  23.         if( i == ncs ) {
  24.                 #ifdef DEBUG
  25.                 printf( "Cannot find free command list entry\n\r" );
  26.                 #endif
  27.                 return DEVICE_IS_BUSY;
  28.         }
  29.         slot = i;
  30.        
  31.         // Слот определили, настраиваем указатели
  32.         // Настроимся на наш слот
  33.         cmdheader = ( HBA_CMD_HEADER* )dev -> abar -> ports[ dev -> portNumber ].clb;
  34.         cmdheader += slot;
  35.        
  36.         // Устанавливаем в нем все необходимые поля
  37.         cmdheader -> cfl = sizeof( FIS_REG_H2D ) / sizeof( uint32_t );          // Размер структуры запроса в двойных словах
  38.         cmdheader -> w = ( cmd == ATA_CMD_WRITE_DMA_EXT ? 1 : 0 );                      // Направление обмена данными 1: H2D, 0: D2H
  39.         cmdheader -> prdtl = ( uint16_t )( ( count - 1 ) >> 4 ) + 1;                    // Формула получения количества записей
  40.        
  41.         // Настраиваем таблицу команд, состоящую из заголовка и записей (0-64535)
  42.         cmdtbl = ( HBA_CMD_TBL* )( cmdheader -> ctba );
  43.         memset( cmdtbl, 0, sizeof( HBA_CMD_TBL ) + ( cmdheader -> prdtl - 1 ) * sizeof( HBA_PRDT_ENTRY ) );
  44.        
  45.         // Устанавливаем команду в структуру H2D
  46.         cmdfis = ( FIS_REG_H2D* )( &cmdtbl -> cfis );
  47.         memset( cmdfis, 0, sizeof( FIS_REG_H2D ) );
  48.         cmdfis -> fis_type = FIS_TYPE_REG_H2D;                                          // Структура Register FIS - host to device
  49.         cmdfis -> cmd_reg = cmd;                                                                                // Устанавливаем команду
  50.         cmdfis -> cmd = 1;                                                                                      // Работаем с командным регистром
  51.        
  52.         // Если это команды с данными, то грузим LBA и буфер
  53.         printf( "cmdheader -> prdtl - 1 = %d\n\r", cmdheader -> prdtl - 1 );
  54.         if( cmd == ATA_CMD_READ_DMA_EXT || cmd == ATA_CMD_WRITE_DMA_EXT ) {
  55.                 // Загружаем данные
  56.                 for( i = 0; i < cmdheader -> prdtl - 1; ++i ) {
  57.                         cmdtbl -> prdt_entry[ i ].dba = ( uint32_t )buf;                        // Устанавливаем указатель на буфер
  58.                         cmdtbl -> prdt_entry[ i ].dbc = 8 * 1024;                               // Размер блока данных
  59.                         cmdtbl -> prdt_entry[ i ].i = 1;                                                        // И включаем прерывания
  60.                         buf += 8 * 1024;                                                                                        // Корректируем указатель на буфер
  61.                         count -= 16;                                                                                            // Корректируем размер оставшихся данных
  62.                 }
  63.                 printf( "Count = %d\n\r", count );
  64.                 // Здесь еще надо обработать последнюю запись
  65.                 cmdtbl -> prdt_entry[ i ].dba = ( uint32_t )buf;                                // Устанавливаем указатель на буфер
  66.                 cmdtbl -> prdt_entry[ i ].dbc = count << 9;                                     // Размер блока данных
  67.                 cmdtbl -> prdt_entry[ i ].i = 1;                                                                // И включаем прерывания
  68.                
  69.                 // Загружаем LBA
  70.                 cmdfis -> lba0 = ( uint8_t )start;                                                      // LBA low
  71.                 cmdfis -> lba1 = ( uint8_t )( start >> 8 );                                     // LBA mid
  72.                 cmdfis -> lba2 = ( uint8_t )( start >> 16 );                                    // LBA high
  73.                 cmdfis -> count_l = count;                                                                      // Количество секторов
  74.                 cmdfis -> device = 1 << 6;                                                                      // Режим адресации - LBA
  75.         }
  76.         if( cmd == ATA_CMD_IDENTIFY ) {
  77.                 cmdtbl -> prdt_entry[ i ].dba = ( uint32_t )buf;                                // Устанавливаем указатель на буфер
  78.                 cmdtbl -> prdt_entry[ i ].dbc = count << 9;                                     // Размер блока данных
  79.                 cmdtbl -> prdt_entry[ i ].i = 1;                                                                // И включаем прерывания
  80.                
  81.                 // Загружаем LBA
  82.                 cmdfis -> count_l = count;                                                                      // Количество секторов
  83.                 cmdfis -> device = 1 << 6;                                                                      // Режим адресации - LBA
  84.         }
  85.        
  86.         // Ну и собственно выполняем команду
  87.         dev -> abar -> ports[ dev -> portNumber ].ci = 1 << slot;                       // Issue command
  88.  
  89.         // Ждем пока на нашем порту произойдет прерывание
  90.         while( 1 ) {
  91.                 if( dev -> abar -> is & ( 1 << dev -> portNumber ) ) {
  92.                         printf( "IS.IPS[ %d ] done\n\r", dev -> portNumber );
  93.                         break;
  94.                 }
  95.         }
  96.  
  97.         // Читаем теперь читаем PxIS
  98.         printf( "(is): " );
  99.         binary( dev -> abar -> ports[ dev -> portNumber ].is, D );
  100.         if( dev -> abar -> ports[ dev -> portNumber ].is != 0x00000001 ) {
  101.                 printf( "Error while doing operation (serr): " );
  102.                 binary( dev -> abar -> ports[ dev -> portNumber ].serr, D );
  103.                 return DEVICE_ERROR;
  104.         }
  105.  
  106.         // Очищаем IS
  107.         dev -> abar -> ports[ dev -> portNumber ].is = 0;
  108.        
  109.         // Очищаем IS.IPS
  110.         dev -> abar -> is &= ( ~( 1 << dev -> portNumber ) );
  111.         printf( "IS.IPS cleared\n\r" );
  112.  
  113.         // Дождемся выполнения команды
  114.         while( 1 ) {
  115.                 // Если бит сброшен, то команда выполнена
  116.                 if( ( dev -> abar -> ports[ dev -> portNumber ].ci & ( 1 << slot ) ) == 0 ) {
  117.                         break;
  118.                 }
  119.         }
  120.         return DONE;
  121. }