Page 1 of 1

Thoroughly confusing problem after remapping PIC (solved)

Posted: Sun Oct 05, 2008 6:22 pm
by WillOfTheEye
After I remap the PIC, the keyboard interrupt won't work until I read from the keyboard buffer on port 0x60... Even odder, this problem only appeared when I added in code to allow processes to wait for a message - to do this I moved my context switching code out of the timer interrupt (something I'd been meaning to do for a while - was this a mistake?). Odder still, my PIC remapping happens far before my scheduling code starts!

Here's my kmain:

Code: Select all

void _kmain( void* mbd, unsigned int magic )
{
  global_mbd_addr = mbd;
  global_magic = magic;
  // write your kernel here
  kvideoinit();
  koutstr("Video OK!\n",BLACK, DEFCOL);
  koutstr("Initialising...\n",BLACK, DEFCOL);
  koutstr("Setting up IDT...\n",BLACK, DEFCOL);
  kidt_setup();
  if((unsigned int)global_mbd_addr < 4096*1024) //if the mbd is in kernel memory
    {
      //translate the address
      global_mbd = (struct mbd*)(KERNEL_MEMSTART + (unsigned char*)global_mbd_addr);
    }
  else
    {
      //if not, at some point we'll allocate a page to refer to it with
      //but for now, we'll just give an error
      kerror("Error: MBD not in kernel memory!\n");
      while(1);
    }
  koutstr("Initialising keyboard...\n",BLACK, DEFCOL);
  kkeyinit();
  koutstr("Setting up kernel process...\n",BLACK, DEFCOL);
  //set up the kernel process
  systemprocess.page0 = KERNEL_MEMSTART>>12;
  systemprocess.pages = 1024;
  systemprocess.type = 0;
  systemprocess.firstfree = (struct blockheader*)&_end;
  systemprocess.firstfree->size = 4096*1024 - ((unsigned int)(&_end)-KERNEL_MEMSTART);
  systemprocess.firstfree->next = 0;
  systemprocess.firstfree->prev = 0;
  systemprocess.firstfree->type = 0;
  asm volatile("mov %%cr3, %0":"=a"(systemprocess.cr3));
  systemprocess.nextproc = &systemprocess;
  systemprocess.priority = 50;
  systemprocess.count = systemprocess.priority;
  systemprocess.waiting = 0;
  systemprocess.next_msg = 0;
  systemprocess.msg_queue_end = 0;
  prevproc = currentproc = &systemprocess; //lets processes exit properly (without a previous process, there's a dead pointer passed about in the process linked list)
  koutstr("Remapping PIC...\n",BLACK, DEFCOL);
  kpicinit(0x20, 0x28);
  inb(0x60); //(why does this need to be here?)
  koutstr("Initialising memory management...\n",BLACK, DEFCOL);
  kmeminit();
  koutstr("Starting floppy daemon...\n",BLACK, DEFCOL);
  kthread(&kfloppydaemon); //turns off floppy motor after a period of inaction
  asm volatile("sti");
  koutstr("Initialising terminal I/O...\n",BLACK, DEFCOL);
  kioinit();
  koutstr("Initialising timer...\n",BLACK, DEFCOL);
  ktimerinit();
  koutstr("Calibrating floppy drives...\n",BLACK, DEFCOL);
  kfloppyinit();
  ksleep(100);
  kclearscreen();
  koutstr("Welcome to Freya!\nOperating system of the gods!\n",BLACK, DEFCOL);
  if(global_mbd->flags&(1<<11)) koutstr("Received video info!\n",BLACK,DEFCOL);
  else koutstr("No video info!\n",BLACK,DEFCOL);
  //bit of code here to test my floppy code
  unsigned char *bootsect = kmalloc(512, 0);
  kmainfloppyreadsinglesect(0, bootsect);
  koutstr("Read boot sector.\n", BLACK, DEFCOL);
  if(bootsect[510] == 0x55) koutstr("First floppy boot signature found.\n", BLACK, DEFCOL);
  if(bootsect[511] == 0xAA) koutstr("Second floppy boot signature found.\n", BLACK, DEFCOL);
  while(1) //loop forever - otherwise the computer will turn off
    {
    }
}
And here's the PIC code... but as these worked fine before I really don't know what's wrong with them.

Code: Select all

#define PIC1		0x20		/* IO base address for master PIC */
#define PIC2		0xA0		/* IO base address for slave PIC */
#define PIC1_COMMAND	PIC1
#define PIC1_DATA	(PIC1+1)
#define PIC2_COMMAND	PIC2
#define PIC2_DATA	(PIC2+1)

#define PIC_EOI		0x20		/* End-of-interrupt command code */

#define ICW1_ICW4	0x01		/* ICW4 (not) needed */
#define ICW1_SINGLE	0x02		/* Single (cascade) mode */
#define ICW1_INTERVAL4	0x04		/* Call address interval 4 (8) */
#define ICW1_LEVEL	0x08		/* Level triggered (edge) mode */
#define ICW1_INIT	0x10		/* Initialization - required! */

#define ICW4_8086	0x01		/* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO	0x02		/* Auto (normal) EOI */
#define ICW4_BUF_SLAVE	0x08		/* Buffered mode/slave */
#define ICW4_BUF_MASTER	0x0C		/* Buffered mode/master */
#define ICW4_SFNM	0x10		/* Special fully nested (not) */

#define PIC1_MASK       0xBC
#define PIC2_MASK       0xFF
... snip ...
void kpicinit(unsigned char offset1, unsigned char offset2)
{
  outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);  // starts the initialization sequence
  io_wait();
  outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
  io_wait();
  outb(PIC1_DATA, offset1);                 // define the PIC vectors
  io_wait();
  outb(PIC2_DATA, offset2);
  io_wait();
  outb(PIC1_DATA, 4);                       // continue initialization sequence
  io_wait();
  outb(PIC2_DATA, 2);
  io_wait();
  
  outb(PIC1_DATA, ICW4_8086);
  io_wait();
  outb(PIC2_DATA, ICW4_8086);
  io_wait();
  
  outb(PIC1_DATA, PIC1_MASK);   // set the masks
  outb(PIC2_DATA, PIC2_MASK);
}
And finally, the context switching code:

Code: Select all

contextswitch: ;;performs a context switch
    ;; first store the register values
    pushad
    ;; now store the old stack pointers and load the new ones
    mov eax, [currentproc]
    mov ebx, [eax+32] ; ebx is now the next process
    mov [eax+20], esp
    mov [eax+16], ebp
    mov esp, [ebx+20]
    mov ebp, [ebx+16]
    ;; store the stack pointer in the TSS
    mov edi, TSS
    mov [edi+4], esp
    ;; store eax as the previous process
    mov [prevproc], eax
    ;; reset the next process's counter and set it as the current process
    mov eax, [ebx+36]
    mov [ebx+40], eax
    mov [currentproc], ebx
    ;; load the correct page directory
    mov eax, [ebx+24]
    mov cr3, eax
    ;; finally, set the data segment registers to the correct values
    mov eax, [ebx+8]
    or eax, eax
    jz .kernelcode
    mov ax, 0x28
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    popad
    ret
.kernelcode:
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    popad
    ret
Unfortunately, this seems to be the type of bug that likes to hide somewhere, so it may be somewhere completely different...

Re: Thoroughly confusing problem after remapping PIC

Posted: Sun Oct 05, 2008 7:55 pm
by cr2
First clean up your code. Its *very* difficult to read. :wink:

Re: Thoroughly confusing problem after remapping PIC

Posted: Mon Oct 06, 2008 3:37 am
by WillOfTheEye
Yeah, it's messy... I've actually solved my problem, though (initialising keyboard before PIC = bad apparently). Thanks anyway. Think I probably will clean up the code now.