xv6のI/O, PIC, IRQ, uart
プロセッサ側とポートを合わせなきゃいけないものと、kernel(ソフト側)で好き勝手に決めればいいものの境界線を探っている。xv6-mipsで定義している
mips.h
static int io_port_base = 0xb4000000;
これはなぜこのアドレスなのかわからない。inb
outb
で uchar *
へキャストしているのが関係ある?
→QEMUのISAバスが Phys 0x1400_0000 に紐付いているから。 0xb400_0000 - 0x1400_0000 = 0xA0000000 (kseg1の先頭)
となる。
uart 0x3F8
COM (hardware interface) - Wikipedia
これは仕様で決まってるっぽい
mips interrupt mask i/O
CPUで、「一体どのハードウェアからinterruptがきたのか」をどうやって判別するのか調べている。ついでにMemory-mapped I/Oの理解もきちんと出来ていないので。「こっからここまではデバイス用I/Oメモリ!」って決めるのは誰?CPUなのかkernelなのか、はたまたデバイスなのか。
https://courses.cs.washington.edu/courses/cse378/07au/lectures/L20-Interrupt.pdf
http://jjc.hydrus.net/cs61c/handouts/interrupts1.pdf
メモリマップドI/Oの入出力ポートとアドレスの割付はハードウェア(address decoder, address code decoderなどと呼ばれる)で決め打ち
このへんを見ると、わかるがI/OメモリマップはCPUの外にあるハードウェア(address decoderという回路)で制御しているっぽい。CPUが出力する物理アドレスを見て、それが特定のアドレス(I/Oにマップされている)の場合、向き先をデバイスに向ける。
CPUに内蔵されているデバイスであれば、ボードが違っても同じアドレスに見えるはずだよね。でも、デバイスを外付けした場合は、ボードの設計によるんだ。この場合は、ボードの仕様書にメモリマップが書かれているはずだよ。
I/Oポートベース(qemuだとPhys0x1400_0000)もハードウェアで好きに設定してよい
(xv6-mipsだと)ベースアドレスからのオフセットで、各周辺デバイスへのメモリマップを行う。COM1を 0x3f8
にしているのもPC/AT互換機のボード設定であり、MIPSおれおれボードで必ずしもこのアドレスに設定する必要はない。(あくまで、address decoderの回路とkernelの設定を一致させればよいだけ)
cpu - Difference between port mapped and memory mapped access? - Super User
The hardware of the system is arranged so that devices on the address bus will only respond to particular addresses which are intended for them, while all other addresses are ignored. This is the job of the address decoding circuitry, and that establishes the memory map of the system.
自作CPUではPICはいらない
パタヘネ本にある通り、ハードウェア側でgeneral exception handler entry point addressを決め打ちする(0x8000_0180
)。例外ベクタは使用しない。PICも必要ない。
DMA (I/O) Controller
I/Oを特に工夫しない通常のデータの流れだと、I/Oデバイスからレジスタファイルへデータ転送(lw
)→レジスタファイルからRAMへデータ転送(sw
) というのが読み出したいbyte分繰り返されることになり、その間CPUは他の仕事をできない。
これを、I/Oデバイス(DMA Controller)⇔RAM間で直接データ転送できるようにするのがDMAである。DMA Controller or I/O Controllerは回路であり、いわゆるマザボ等のハードウェア側で対応しなければ使用できない。
バスとは
単なる概念。Data Busは、ReadData[32], WriteData[32]に分かれていたりする。その集合概念