Вопросы по драйверу контроллера AHCI - PullRequest
0 голосов
/ 28 февраля 2020

Привет, я новичок в изучении ОС и пытаюсь выполнить это для написания драйвера AHCI.

Я действительно успешно прочитал данные с контроллера AHCI и вызвал прерывание от MSI.

Но все же у меня есть несколько вопросов для деталей:

  1. Какое прерывание мне следует использовать:

    From "serial-ata-ahci- spe c -rev1-3-1 "сказано, что я должен включить соответствующий бит на Px IE, и если соответствующий бит на PxIS установлен HBA, будет возникать прерывание.

    С операцией чтения я наблюдал PxIS, и единственный бит, который он устанавливает, - это бит 0. Из документации это «Прерывание FIS (DHRS) для устройства на хосте», которое указывает на то, что FIS отправлена ​​с HBA на хост.

    Но как мне установить sh прерывание, когда «данные из HBA копируются в системную память».

  2. Как очистить прерывание :

    При включенном x2API C я использую wrmsr(0x80b, 0UL); для отправки сигнала «обрыв».

    Однако он не очищает соответствующий бит PxIS (бит 0 операции чтения). Так как я должен правильно очистить прерывание.

  3. Для чего используется DATA FIS:

    Как сказано, «используется для передачи данных полезной нагрузки». ». Но из примера я не могу найти, где мне следует чертить эту структуру.

  4. Как обращаться с кэшированной памятью:

    С момента чтения И пишите используйте DMA, это может привести к несовпадению памяти и перехвату. В настоящее время я могу использовать только 2 способа: а) выделить страницу U C; б) использовать инструкцию INVD для неверного кэша.

    Так как я использую пейджинг 2 Мб, я бы предпочел использовать метод б). Но не могу найти ссылки на многоядерные. Если бы INVD испортил sh кеш всех ядер или просто ядро, которое восстанавливало инструкцию.

Большое спасибо всем, кто помог бы мне в этом. Я приложу свой код здесь для справки:

void AHCI_Disk_Init(void)
{
   int i;
   pg_attr ATTR;
    memset(&ATTR, 0, sizeof(pg_attr));
    ATTR.PML4E_Attr.RW    = 1;
    ATTR.PML4E_Attr.P   = 1;
    ATTR.PDPTE_Attr.P   = 1;
    ATTR.PDPTE_Attr.RW   = 1;
    ATTR.PDE_Attr.PS   = 1;
    ATTR.PDE_Attr.P      = 1;
    ATTR.PDE_Attr.RW   = 1;
    //Choose PAT[3]: Uncacheable memory type
    ATTR.PDE_Attr.PCD   = 1;
    ATTR.PDE_Attr.PCD   = 1;

   pagetable_init(PML4E,
      ((unsigned long)AHCI.ABAR - PAGE_OFFSET) & PAGE_2M_MASK,
      ((unsigned long)AHCI.ABAR & PAGE_2M_MASK) + PAGE_OFFSET, 1,
   &ATTR, 0);

   AHCI.ABAR->ghc = AHCI.ABAR->ghc | SATA_GHC_AE;
   AHCI.No_slot = (AHCI.ABAR->cap >> 8) & 0x1f;

   for(i=0;i<32;i++){
      if(AHCI.ABAR->pi & 1<<i){
         if(
            (AHCI.ABAR->ports[i].ssts & 0xf) == 3 &&
            ((AHCI.ABAR->ports[i].ssts >> 8) & 0x0F) == 1 &&
            AHCI.ABAR->ports[i].sig == SATA_SIG_ATA
         ){
            AHCI.ABAR->ports[i].cmd &= ~(HBA_PxCMD_ST | HBA_PxCMD_FRE);
            while(1)
            {
               if (AHCI.ABAR->ports[i].cmd & HBA_PxCMD_FR)
                  continue;
               if (AHCI.ABAR->ports[i].cmd & HBA_PxCMD_CR)
                  continue;
               break;
            }
            AHCI.ABAR->ports[i].clb = kmalloc(sizeof(HBA_CMD_HEADER)*AHCI.No_slot, 0) - PAGE_OFFSET;
            AHCI.ABAR->ports[i].fb  = kmalloc(sizeof(HBA_FIS),0) - PAGE_OFFSET;
            memset((void *)((unsigned long)AHCI.ABAR->ports[i].clb + PAGE_OFFSET), 0, sizeof(HBA_CMD_HEADER)*AHCI.No_slot);
            memset((void *)((unsigned long)AHCI.ABAR->ports[i].fb  + PAGE_OFFSET), 0, sizeof(HBA_FIS));
            AHCI.ABAR->ports[i].cmd |= HBA_PxCMD_FRE;
            AHCI.ABAR->ports[i].cmd |= HBA_PxCMD_ST;
            AHCI.ABAR->ports[i].ie   |= 1;
            color_printk(WHITE, ORANGE, "AHCI.ABAR->ports[%d].is: 0x%08X\n", i, AHCI.ABAR->ports[i].is);
            color_printk(WHITE, ORANGE, "AHCI.ABAR->ports[%d].ie: 0x%08X\n", i, AHCI.ABAR->ports[i].ie);
         }
      }
   }
   AHCI.ABAR->ghc |= SATA_GHC_IE;
   AHCI.MSI._64->MAR.Pre_fix  = 0xFEE;   // Fixed head address
   AHCI.MSI._64->MAR.Dest_ID  = 0;      // Send to APIC ID = 0
   AHCI.MSI._64->MAR.zero     = 0;      
   AHCI.MSI._64->MAR.DM       = 0;      // Pysical destination mode
   AHCI.MSI._64->MAR.RH       = 0;      // Interrupt direcet to processor listed in the Destination ID field
   AHCI.MSI._64->MDR.Del_Mode = 0;    // Fixed mode
   AHCI.MSI._64->MDR.Vector   = 0x2e;   // IDT[0x2E]
   AHCI.MSI._64->MDR.Trg_Mode = 0;      // Edge trigger
   AHCI.MSI._64->MDR.Level      = 0;    // No use for edge triggered interrupt
   AHCI.MSI._64->MDR.zero      = 0;
   AHCI.MSI._64->MCR.MSI_Enable = 1;    // Enable MSI
}
int AHCI_Read_1st_sec(int port)
{
   int i, j, slot = 0;

   unsigned char *buff1 = kmalloc(512, 0);
   memset(buff1, 0, 512);

   AHCI.ABAR->ports[port].is = (unsigned int) - 1;
   slot = AHCI.ABAR->ports[port].sact | AHCI.ABAR->ports[port].ci;
   for(i =0; i<AHCI.No_slot; i++){
      if(!(slot&1)){
         break;
      }
   }
   if(i==AHCI.No_slot){
      color_printk(WHITE,RED,"All slot for port[%d] are busy!\n", port);
   }
   AHCI.ABAR->ports[port].clb[i].cfl    = sizeof(FIS_REG_H2D)/sizeof(int);
   AHCI.ABAR->ports[port].clb[i].w      = 0;
   AHCI.ABAR->ports[port].clb[i].prdtl = 1;
   AHCI.ABAR->ports[port].clb[i].ctba   = kmalloc(sizeof(HBA_CMD_TBL), 0) - PAGE_OFFSET;
   HBA_CMD_TBL * cmdtbl = (HBA_CMD_TBL *)((unsigned long)AHCI.ABAR->ports[port].clb[i].ctba + PAGE_OFFSET);
   memset(cmdtbl, 0, sizeof(HBA_CMD_TBL));

   cmdtbl->prdt_entry[0].dba = ((unsigned long)buff1 - PAGE_OFFSET);
   cmdtbl->prdt_entry[0].dbc = 512 - 1;
   // cmdtbl->prdt_entry[0].i     = 1;

   FIS_REG_H2D *cmdfis = (FIS_REG_H2D*)(&cmdtbl->cfis);
   cmdfis->fis_type = FIS_TYPE_REG_H2D;
   cmdfis->c = 1;   // Command
   cmdfis->command = ATA_CMD_READ_DMA_EX;

   cmdfis->lba0 = 0;
   cmdfis->lba1 = 0;
   cmdfis->lba2 = 0;
   cmdfis->device = 1<<6;   // LBA mode
   cmdfis->lba3 = 0;
   cmdfis->lba4 = 0;
   cmdfis->lba5 = 0;
   cmdfis->countl = 1;
   cmdfis->counth = 0;
   color_printk(WHITE, ORANGE, "AHCI.ABAR->ports[%d].is: 0x%08X\n", port, AHCI.ABAR->ports[port].is);
   while(AHCI.ABAR->ports[port].tfd & (ATA_DEV_BUSY | ATA_DEV_DRQ));
   AHCI.ABAR->ports[port].ci |= 1<<i;
   while(AHCI.ABAR->ports[port].ci & 1<<i);
   color_printk(WHITE, ORANGE, "AHCI.ABAR->ports[%d].is: 0x%08X\n", port, AHCI.ABAR->ports[port].is);
   for(i = 0; i < 512; i++){
      color_printk(BLACK,WHITE,"%02x",buff1[i]);
   }
   color_printk(BLACK,WHITE,"\n",buff1[i]);
   color_printk(WHITE, ORANGE, "AHCI.ABAR->ports[%d].is: 0x%08X\n", port, AHCI.ABAR->ports[port].is);
}
...