FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

ISSにIDEコントローラを組込む

xv6のブートプロセスには、idewait()という関数が入っている。IDEコントローラを監視して、BSYではなくなったら、次に進むようになっている。 IDEのコントローラの詳細については、以下を参照した。もちろん、これがMIPSアーキテクチャと異っていることは100も承知だ。だが、とりあえず確実な情報として、x86で動作しているものをそのまま移植したい。

Input/output base address - Wikipedia, the free encyclopedia

ATA PIO Mode - OSDev Wiki

まずは、IDEのセカンダリのIRQアドレスが1f0-1f7であることが分かった。次に、xv6がアクセスしている0x1f7について調査してみる。

Status Byte
In the following table you will find the layout of the so-called Status Byte.
Bit Abbreviation    Function
0   ERR Indicates an error occurred. Send a new command to clear it (or nuke it with a Software Reset).
3   DRQ Set when the drive has PIO data to transfer, or is ready to accept PIO data.
4   SRV Overlapped Mode Service Request.
5   DF  Drive Fault Error (does not set ERR).
6   RDY Bit is clear when drive is spun down, or after an error. Set otherwise.
7   BSY Indicates the drive is preparing to send/receive data (wait for it to clear). In case of 'hang' (it never clears), do a software reset.

なるほど、7ビット目であるBSYが0で、6ビット目であるRDYが1になるまで、idewaitは待つわけか。では、早速IDEコントローラをそのように実装しよう。

github.com

MemResult ModuleIde::LoadData (Addr_t addr, Size_t size, Word_t *data)
{
    switch (addr) {
    case 0xb40001f0:  // Data Port
        fprintf (m_debug_fp, "<IDE: DataPort(0x%08x) Load>\n", addr);
        *data = m_sys_reg[0]; break;
    case 0xb40001f1:  // Features Error Information
        fprintf (m_debug_fp, "<IDE: Feat/ErrInfo(0x%08x) Load>\n", addr);
        *data = m_sys_reg[1]; break;
    case 0xb40001f2:  // Sector Count
        fprintf (m_debug_fp, "<IDE: SectorCount(0x%08x) Load>\n", addr);
        *data = m_sys_reg[2]; break;
    case 0xb40001f3:  // Sector Number LBAlo
        fprintf (m_debug_fp, "<IDE: SecNum:LBAlo(0x%08x) Load>\n", addr);
        *data = m_sys_reg[3]; break;
    case 0xb40001f4:  // Sector Number LBAmid
        fprintf (m_debug_fp, "<IDE: SecNum:LBAmid(0x%08x) Load>\n", addr);
        *data = m_sys_reg[4]; break;
    case 0xb40001f5:  // Sector Number LBAhi
        fprintf (m_debug_fp, "<IDE: SecNum:LBAhi(0x%08x) Load>\n", addr);
        *data = m_sys_reg[5]; break;
    case 0xb40001f6:  // Drive/Head Port
        fprintf (m_debug_fp, "<IDE: Drive/HeadPort(0x%08x) Load>\n", addr);
        *data = m_sys_reg[6]; break;
    case 0xb40001f7:  // CmdPrt/RegStatusPort
        fprintf (m_debug_fp, "<IDE: CommandPort:RegularStatus(0x%08x) Load>\n", addr);
        *data = m_sys_reg[7]; break;
    }

    return MemNoExcept;
}

実装としてはイマイチだが、とりあえずはこれで要件は満たされる。 という訳で、改造したシミュレータを使って再度xv6をブートさせると、、、

swimmer_mips --binfile kernel --out debug.log --debug_func --debug_gvar --init_pc 0x80100000  --max 1000000

xv6...
cpu0: panic: kfree
 80104344 8050d678 65 0 0 0 0 0 0 0v

ありゃー、panicを起こした。。。でも、何となく何ができるのか分かってきたぞ。今度はこれを追い掛ける。