Advertisement
Guest User

Untitled

a guest
Jul 2nd, 2012
540
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.70 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement