ঠিক আছে, একটি ছোট বিরতির পর, চলুন আমাদের টিউটোরিয়াল সিরিজটি চালিয়ে যাই। যদি আমরা আগের কোডে ফিরে যাই, তাহলে আমাদের কাছে শূন্য দ্বারা ভাগের জন্য ISR থাকা উচিত। এখন আমাদের বাকি ISR-গুলো পূরণ করতে হবে, যেগুলোর জন্য আমরা আগে একটি বার্তা সেট করেছিলাম (প্রথম ৩২টি)। এখন আমরা ইন্টারাপ্ট প্রোগ্রামিং চালিয়ে যাব; আমরা IRQ তৈরি করব, যা ইন্টারাপ্ট রিকোয়েস্ট নামেও পরিচিত। এই IRQ-গুলো কিবোর্ড, মাউস, প্রিন্টার ইত্যাদির মতো হার্ডওয়্যার ডিভাইস দ্বারা তৈরি হয়। প্রাথমিকভাবে, প্রথম ৮টি IRQ স্বয়ংক্রিয়ভাবে IDT-এর ৮ থেকে ১৫ নম্বর পজিশনে ম্যাপ করা থাকে। যেহেতু আমরা প্রথম ৩২টি এক্সেপশনের জন্য ব্যবহার করেছি, তাই এখন আমাদের সেগুলোকে রিম্যাপ করতে হবে। আমরা ৩২ থেকে ৪৫ পর্যন্ত IRQ-গুলো অ্যাসাইন করব। এটি করার জন্য, আমাদের প্রথমে IRQ-গুলো রিম্যাপ করতে হবে:
void ND::IRQ::Remap(int pic1, int pic2)
{
#define PIC1 0x20
#define PIC2 0xA0
#define ICW1 0x11
#define ICW4 0x01
/* send ICW1 */
ND::Ports::OutputB(PIC1, ICW1);
ND::Ports::OutputB(PIC2, ICW1);
/* send ICW2 */
ND::Ports::OutputB(PIC1 + 1, pic1); /* remap */
ND::Ports::OutputB(PIC2 + 1, pic2); /* pics */
/* send ICW3 */
ND::Ports::OutputB(PIC1 + 1, 4); /* IRQ2 -> connection to slave */
ND::Ports::OutputB(PIC2 + 1, 2);
/* send ICW4 */
ND::Ports::OutputB(PIC1 + 1, ICW4);
ND::Ports::OutputB(PIC2 + 1, ICW4);
/* disable all IRQs */
ND::Ports::OutputB(PIC1 + 1, 0xFF);
}
এখন আমরা আইআরকিউগুলি ইনস্টল করার জন্য একটি ফাংশন তৈরি করি:
void ND::IRQ::Install()
{
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_BLACK);
ND::Screen::PutString("\nInstalling IRQ...");
ND::IRQ::Remap(0x20,0x28);
ND::IDT::SetGate(32,(unsigned)ND::IRQ::IRQ1,0x08,0x8E);
ND::IDT::SetGate(33,(unsigned)ND::IRQ::IRQ2,0x08,0x8E);
ND::IDT::SetGate(34,(unsigned)ND::IRQ::IRQ3,0x08,0x8E);
ND::IDT::SetGate(35,(unsigned)ND::IRQ::IRQ4,0x08,0x8E);
ND::IDT::SetGate(36,(unsigned)ND::IRQ::IRQ5,0x08,0x8E);
ND::IDT::SetGate(37,(unsigned)ND::IRQ::IRQ6,0x08,0x8E);
ND::IDT::SetGate(38,(unsigned)ND::IRQ::IRQ7,0x08,0x8E);
ND::IDT::SetGate(39,(unsigned)ND::IRQ::IRQ8,0x08,0x8E);
ND::IDT::SetGate(40,(unsigned)ND::IRQ::IRQ9,0x08,0x8E);
ND::IDT::SetGate(41,(unsigned)ND::IRQ::IRQ10,0x08,0x8E);
ND::IDT::SetGate(42,(unsigned)ND::IRQ::IRQ11,0x08,0x8E);
ND::IDT::SetGate(43,(unsigned)ND::IRQ::IRQ12,0x08,0x8E);
ND::IDT::SetGate(44,(unsigned)ND::IRQ::IRQ13,0x08,0x8E);
ND::IDT::SetGate(45,(unsigned)ND::IRQ::IRQ14,0x08,0x8E);
ND::IDT::SetGate(46,(unsigned)ND::IRQ::IRQ15,0x08,0x8E);
ND::IDT::SetGate(47,(unsigned)ND::IRQ::IRQ16,0x08,0x8E);
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_GREEN);
ND::Screen::PutString("done");
asm volatile("sti");
}
Asm এর বাক্য STI আমরা আইআরকিউগুলি সক্রিয় করি। আচ্ছা এখন আমরা আইএসআর এর অনুরূপ কিছু নিয়ে চলেছি। একটি বেসিক আইআরকিউ এর কাজগুলি:
void ND::IRQ::IRQ1()
{
asm volatile(
"cli \n"
"pushl 0\n"
"pushl 32\n"
"jmp ND_IRQ_Common"
);
}
একটি সাধারণ অংশ (আইএসআর সমান):
extern "C"
void ND_IRQ_Common()
{
asm volatile(
"pusha \n"
"push %ds\n"
"push %es\n"
"push %fs\n"
"push %gs\n"
"movw $0x10, %ax \n"
"movw %ax, %ds \n"
"movw %ax, %es \n"
"movw %ax, %fs \n"
"movw %ax, %gs \n"
"movl %esp, %eax \n"
"push %eax \n"
"movl $ND_IRQ_Handler, %eax \n"
"call *%eax \n"
"popl %eax \n"
"popl %ds \n"
"popl %es \n"
"popl %fs \n"
"popl %gs \n"
"popa \n"
"addl 8, %esp \n"
"iret \n"
);
}
এবং একটি বেসিক হ্যান্ডলার:
extern "C"
void ND_IRQ_Handler(struct regs* r)
{
void (*handler)(struct regs *r);
if(r->int_no >= 40)
{
ND::Ports::OutputB(0xA0,0x20);
}
ND::Ports::OutputB(0x20,0x20);
}
এটি দিয়ে আমাদের ইতিমধ্যে আইআরকিউ সক্রিয় করা উচিত যদিও তারা এখনও কিছু না করে। পরবর্তী অধ্যায়ে আমরা কীভাবে ঘড়ি বা কীবোর্ডের মতো এই আইআরকিউগুলি থেকে ডেটা প্রাপ্ত করব তা দেখব।
এবং এর সাথে আজকের পোস্টটি শেষ হয়। আপনি এখন দেখতে পাচ্ছেন যে অন্যান্য সমস্যার কারণে আমি নিয়মিত কম লিখি। তবুও আমি আরও সম্পূর্ণ অপারেটিং সিস্টেম না হওয়া পর্যন্ত চালিয়ে যাব