Autor Thema: keyboard eingabe, pic  (Gelesen 4996 mal)

middle_endian

  • Beiträge: 25
    • Profil anzeigen
Gespeichert
« am: 25. July 2007, 15:25 »
hi,
ich versuch mich gerade an einem tastaturtreiber. dazu hab ich die irqs des master/slave-pics auf die interrupts 20h-27h und 28h-2fh gemappt. soweit ich das richtig verstanden hab, wird bei einer tastatureingabe der irq1 aufgerufen (wobei danach auf port 0x60 der scancode abgelesen werden kann). dem irq1 ist bei mir die isr 21h zugeordnet. allerdings wird diese isr  nicht aufgerufen, wenn ich eine taste drücke.
jetzt frag ich mich, obs an der remapping routine liegt, oder an was anderem. hier der code den ich zum remappen verwende:

;; PIC ports
%define PIC_MASTER_CMD 20h
%define PIC_MASTER_DATA 21h
%define PIC_SLAVE_CMD 0a0h
%define PIC_SLAVE_DATA 0a1h

;; -----------------------------------------------
;; remapping PICs IRQs to not-reserved interrupts
;; -----------------------------------------------
remap_pic:
      ;; ICW1
      mov al, 10001b          ; bit1=1: forth ICW, bit2=0: pic cascading
      out PIC_MASTER_CMD, al
      out PIC_SLAVE_CMD, al

      ;; now starting to send the 3 inizialisation words on the data port
      ;;    ICW2: its vector offset
      ;;    ICW3: tell it how it is wired to master/slaves
      ;;    ICW4: gives additionnal infos about the environment

      ;; ICW2
      mov al, 20h
      out PIC_MASTER_DATA, al       ; map master irqs to int 20h-27h
      mov al, 28h
      out PIC_SLAVE_DATA, al        ; map slave ircq to 28h-2fh

      ;; ICW3
      mov al, 4                     ; 4 == bit3=1 -> irq2@master wired with slave ...
      out PIC_MASTER_DATA, al
      shr al, 2                     ; number of master irq necessary -> also irq2
      out PIC_SLAVE_DATA, al

      ;; ICW4
      ;; before isr finishes, the pic needs to be notified,
      ;; so he knows when to restart work
      mov al, 1
      out PIC_MASTER_DATA, al
      out PIC_SLAVE_DATA, al

      ;; end of interrupt(eoi) signal to both pics
      mov al, 20h
      out PIC_MASTER_CMD, al
      out PIC_SLAVE_CMD, al
      ret

wenn ich den irq1 per software-interrupt aufrufe, wird die entsprechende isr auch ausgeführt, was mich vermuten lässt, dass es nichts mit einer möglicherweise falschen initialisierung der idt zu tun.

meine allgemeine ablaufreihenfolge sieht so aus:

;; interrupts disabled
;; ...

pmode:
      ;; ...

      ;; init idt
      ;; ...

      call remap_pic
      call enable_irqs
      sti

      ;; kernel main
      ;; ...

kann mir jemand sagen, was da schief läuft?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 25. July 2007, 15:36 »
Lass mal das Senden des EOIs in remap_pic weg. Das hat es bei mir nicht gebraucht.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

middle_endian

  • Beiträge: 25
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 25. July 2007, 15:54 »
ändert leider auch nix :(
hab auch versucht kurz delays hinter die out instruktionen zu setzen. bringt auch nix.

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #3 am: 25. July 2007, 16:02 »
Wie bluecode schon sagte, der EOI muss raus der Rest ist richtig. Aber zeigt der IRQ0 bei dir auf einen Handler? Denn dieser wird automatisch aufgerufen. Du solltest allen nicht benutzten IRQs einen Handler angeben, der min. einen EOI (bei master nur an 20h und bei Slave an 20h und A0h) sendet.

bitmaster
In the Future everyone will need OS-64!!!

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 25. July 2007, 17:34 »
Du kannst auch alle IRQs ausser dem Tastatur-IRQ demaskieren etwa so: mov al, 11111101b
out 0x21, al

Gruss
Nooooooooooos

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #5 am: 25. July 2007, 21:05 »
Stimmt, dir kommt wahrscheinlich ein IRQ0 ohne EOI in die Quere und dann ist der PIC beleidigt und hört einfach auf zu tun was man gerne hätte. 8-)
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #6 am: 25. July 2007, 23:57 »
@bluecode: Ja ja ja, mache dich ruhig über mich lustig. Das ist mir egal. Außerdem hat der FC Bayern gerade gegen den VFB gewonnen. Juhuuuuuuuuuuuuuuuuuuuu

bitmaster
In the Future everyone will need OS-64!!!

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #7 am: 26. July 2007, 07:06 »
wtf? :-o Das war jetzt ehrlich nicht meine Intention. Ich hab ehrlich gesagt das mit dem IRQ0 in deinem Post überlesen und dachte das fügste jetzt noch hinzu...
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

middle_endian

  • Beiträge: 25
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 26. July 2007, 07:25 »
ok, hab jetzt den eoi code am ende der ersten beiden irq-handler(0 und 1) eingefügt. in meinen interrupt routinen geb ich wie gesagt aus, welcher interrupt gerade aufgerufen wurde.
jetzt bekomm ich natürlich ständig die irq0-meldung(timer) ausgegeben. das initialisieren der idt mit den handlern scheint also zu funktionieren. wenn ich allerdings eine taste drück, passiert mit irq1 immer noch nichts. erst nach 9-maligem drücken bekomm ich von bochs die meldung

[kbd ] internal keyboard buffer full. ignoring scancode(xy)
aber warum wird der handler nicht aufgerufen?

EDIT: habs hingekriegt. es war ein einfacher logischer fehler. danke für die hilfe :)
« Letzte Änderung: 26. July 2007, 09:06 von middle_endian »

middle_endian

  • Beiträge: 25
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 30. July 2007, 10:41 »
hi,
da ich keinen neuen thread deswegen aufmachen wollte, stell ich die frage gleich hier. es geht um das prinzipielle design des keyboard treibers.
herzstück des treibers ist bei mir die handle_keystroke routine, die beim auftreten des irq1 aufgerufen wird. diese routine schreibt das übertragene zeichen in einen eigens angelegten puffer-bereich. die "user-level" routinen des treibers arbeiten nur noch mit diesem tastatur puffer.
getch sieht bei mir so aus:

;; ---------------------------------------------
;; read one character from the keyboard(buffer)
;; ---------------------------------------------
;; return value:
;; al = keyboard input character
;; temp. register = ebx
getch:
               ;; initialization stuff
               ;; ...

               ;; wait until data is available
.wait:
mov al, [key_buf_pos]
cmp [key_buf_beg], al ; wait for keyboard data
jne .ready
jmp .wait
.ready:

                ;; read data from keyboard buffer
                ;; ...
ret

funktionieren tut das ganze, nur stört mich diese schleife ein wenig, die kontinuierlich die cpu belastet und checkt, ob im puffer daten zur verfügung stehn. prinzipiell wäre das (im moment) kein problem, da die cpu zum zeitpunkt des abarbeitens von getch sowieso nichts anderes zu tun hat. auch im multi-process betrieb seh ich kein problem, da die getch routine in einem eigenen prozess aufgerufen wird, und dieser eben neben anderen prozessen vor sich herläuft.
trotzdem meine frage: gibts eine elegantere (effizientere) variante? mir fällt mit den zur verfügung stehenden mitteln nichts ein(mein kernel besitzt im moment lediglich funktionen zur textausgabe und eben den tastaturtreiber).

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #10 am: 30. July 2007, 11:27 »
Dann solltest du dir so langsam gedanken über gescheite IPC machen. zB könntest du bei message passing deinem scheduler sagen, er soll den thread erst wieder aufwecken, wenn der Thread eine message vom Typ MSG_KEYSTROKE (oder was auch immer) bekommt. Der Tastaturtreiber verschickt dann bei Tastendruck so eine Nachricht. Wenn du als IPC RPC wählst, dann kannst du eine funktion namens keystroke_callback implementieren, die der keyboard treiber dann indirekt aufruft. Natürlich sollte man da auch dem Scheduler sagen können, dass ein Thread grad nichts tun möchte und erst beim nächsten RPC aufgeweckt werden soll.
btw. was du machst nennt man busy-waiting und es ist ein PITA, wenn es mal mehr als einen Thread gibt. :wink:
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

middle_endian

  • Beiträge: 25
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 30. July 2007, 13:20 »
ok ja, das macht sinn. aber im jetzigen zustand meines kernels lässt sich wenig am design der routine ändern bzw sollte diese vorgehensweise doch sogar die "vernünftigste" sein!?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #12 am: 30. July 2007, 13:55 »
Wenn das alles im Kernel ist, dann kannst du auch einfach deine Shell im keyboard isr aufrufen und dort den Tastendruck verarbeiten:

size_t index = 0;
char buf[512];
void shell_callback(char c)
{
  if (c == '\n')
  {
     // execute the command
     if (strcmp(buf, "ls"))
        show_file_listing();
     
     index = 0;
  }
  else
  {
     // append to the buffer
     buf[index++] = c;
  }
  // Null-terminate
  buf[index] = '\0';
}
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

 

Einloggen