Autor Thema: A20Gate aktivieren in C  (Gelesen 9055 mal)

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« am: 31. August 2004, 16:20 »
Hallo,
ich habe schon wieder ein Problem.
Ich habe das A20Gate Tut gelesen und versuche nun es in meinem Kernel über
einen funktionsaufruf zu aktivieren.
Die funktion die ich aufrufe sieht folgendermaßen aus:

void A20gate_enable()
{
    unsigned char RetVal;

    //A20-Gate aktivieren
    //A1:
    RetVal = in(0x64);    //Tastatur-Controller Statusbyte lesen
    if (RetVal == 0x2)
    {
        writeln("War 2!");
    }
    else
    {
        writeln(RetVal);
    }
    writeln(0x2);
}
in ist eine andere Funktion, die aber funktioniert:
unsigned char in(unsigned short _port)
{
  // "=a" (result) means: put AL register in variable result when finished
  // "d" (_port) means: load EDX with _port
  unsigned char result;
  __asm__  ("in %%dx, %%al" : "=a" (result) : "d" (_port));
  return result;
}
Nun zu meinem Problem:
eigentlich möchte ich Retval auf 00000010b testen.
Wie kann ich das machen?? Geht das so wie ich es mit dem Hex 0x2 mache?
Irgendwie sagt der mir aber, das ich als rückgabewert allerdings nicht 0x2 habe.
Dann wollte ich sehen was zurück gegeben wird und habe Retval auf Bildschirm ausgeprintet und bekomme den Buchstaben "S".
Was geschieht da? Wie kann ich den Rückgabewert auf 00000010b testen?
Gruß sov21

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #1 am: 31. August 2004, 19:52 »
Bitwise Operations in C sind recht einfach. wenn du wissen willst ob ein Byte  gesetzt ist oder nicht: if(Var&Bitmaske==Bit) also bei dir var&0x02
Das bewirkt ganz einfach dass ein AND auf den Wert angewandt wird, der Rest ist Boolsche Algebra.
Ein ausgegeben S heisst das aus dem Port 53h kam also 01010011h in dem falle wäre bit 2 gesetzt, aber musst erst noch die anderen Bits killen damit das per if festgestellt werden kann
Also bei dir statt:
if (RetVal == 0x2)
müsste
if (RetVal&0x02 == 0x2)
stehen, damit sollte es gehn.

PS: Merk dir das mit Bitwise OP's gut, das wirste im weiteren OS-DEV Process noch oft gebrauchen könn.
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 31. August 2004, 20:38 »
Na logisch mann bin ich doof. hab ich das doch total vergessen.
Ich danke dir vielmals.
Jetzt kann ich endlich weiter machen.
Super :-)
Dann bis zur nächsten dummen Frage von mir.
Gruß sov21

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 31. August 2004, 21:03 »
Mhh hab dennoch das gleiche Prob.
Hab:
RetVal = in(0x64);
RetVal = RetVal&0x02;
writeln(RetVal);

und der gibt schon wieder S aus.
Das dürfte aber nicht sein.
Ist was an meiner Ausgabefunktion falsch??

void writeln(const char *_message)
{
  unsigned short offset;
  unsigned long i;
  unsigned char *vidmem = (unsigned char *)0xB8000;

  // Read cursor position
  out(0x3D4, 14);
  offset = in(0x3D5) << 8;
  out(0x3D4, 15);
  offset |= in(0x3D5);

  // Start at writing at cursor position
  vidmem += offset*2;

  // Continue until we reach null character
  i = 0;
  while (_message != 0) {
    *vidmem = _message[i++];
    vidmem += 2;
  }
Gruß sov21

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #4 am: 01. September 2004, 06:33 »
packs mal in eine Zeile und versuchs so:
putc(in(0x64)&0x02);
putc ist bei mir irgendne Funktion um einen einzelnen Char auszugeben, das kann deine nicht;) deine braucht immer ein abschliessendes 0-Byte
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 01. September 2004, 13:23 »
Also ich habe jetzt folgendes:

while (AnzVersuche == 0)
    {
        if ((in(0x64)&0x02) == 0x02)
        {
            writeln("Gesetzt!");
            AnzVersuche = 1;
        }
        else
        {
            writeln("Nicht gesetzt!");
        }
    }
Der schreibt den ganzen Bildschirm voll mit "Nicht gesetzt!", durch die while.
Aber wenn das flag nicht gesetzt ist und das sich auch nicht ändert, dann kann ich doch auch nicht weiter machen oder??
Gruß sov21

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 01. September 2004, 13:31 »
Ach irgendwie geht bei mir gar nix. Und ich weiß nicht warum.
Ich habe das Gefühl, daß sobald mein Code 2 Kb oder mehr erreicht hat, dann stürzt bochs immer ab und startet neu.

Meine Funktion sieht jetzt so aus:
void A20gate_enable()
{
    //Var deklaration
    unsigned char RetVal;
    int AnzVersuche = 0;

    //A20-Gate aktivieren
    //A1:
    //RetVal = in(0x64);
    //while ((RetVal&0x02) != 0x2)
    //{
    //    RetVal = 0;
    //    RetVal = in(0x64);    //Tastatur-Controller Statusbyte lesen
        //AnzVersuche++;
    //    writeln("In Schleife!");
    //}
    writeln("Teste Mal was");
    writeln("HAllo");
    writeln("Neu hier");

    while (AnzVersuche == 0)
    {
        if ((in(0x64)&0x02) == 0x02)
        {
            writeln("Gesetzt!");
            AnzVersuche = 1;
        }
        else
        {
            writeln("Nicht gesetzt!");
        }
    }
    writeln("Fertig");
   
}

wenn ich die writeln über der schleife weg lasse gehts, und mit ihnen nicht mehr.
Wenn ich sie weg lassen und eine neue Funktion definiere die zu groß wird, dann geht auch nix mehr.
Woran kann das liegen.
Ich verzweifle mit dem blöden code hier noch :-((
Gruß sov21

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #7 am: 01. September 2004, 14:12 »
Klingt irgendwie als ob dein Kernel ganz einfach nicht vollständig in den Speicher geladen wird. Wenn du den Code im Bootloader über Int 13h als Binärdateien ausliest, also wenns nicht FAT o.ä. formatiert ist und so, dann soltlest du mal schaun ob du beim Int genügend Sektoren eingelesen werden, kam bei mir auch schon öfter vor.
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 01. September 2004, 14:31 »
Ich glaube das ist es!
Das ist ein auszug aus dem Bootloader den ich verwende:
reset_drive:
        mov ah, 0               ; RESET-command
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz reset_drive         ; Try again if ah != 0

        mov ax, 0
        mov es, ax
        mov bx, 0x1000          ; Destination address = 0000:1000

        mov ah, 02h             ; READ SECTOR-command
        mov al, 02h             ; Number of sectors to read = 1
        mov ch, 0               ; Cylinder = 0
        mov cl, 02h             ; Sector = 2
        mov dh, 0               ; Head = 0
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz reset_drive         ; Try again if ah != 0

        cli                     ; Disable interrupts, we want to be alone

Nur den verstehe ich nicht wirklich so gut. Bin ja noch anfänger.
Aber ich glaube, der liest doch nur einen Sektor uas oder??
Kannst du mir sagen, wie man das besser machen kann???
Oder vielleicht einfach noch was zu dem ab ; READ SECTOR-command
Zeilen mir erklären?? Ist aber bestimmt zu viel, oder??
Gruß sov21

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 01. September 2004, 16:05 »
Ha, jetzt stürzt nix mehr ab :-)
Hab einfach aus:
mov al, 02h ; Number of sectors to read = 1
das hier gemacht:
mov al, 03h ; Number of sectors to read = 1

somit scheint er mehr sektoren einzulesen und stürzt bei 2kb nicht mehr ab.
Aber das Prob mit dem nicht gesetzten Bit habe ich immer noch :-((
Und wie kann ich denn dynamisch festellen, wieviel Sektoren ich einlesen kann.
Geht das nur, wenn ich es wie bei eurem Fat12 Tut mache, oder gibts da sonst noch ne Möglichkeit??
Und wieviele Sektoren darf ich maximal auf einmal einlesen?
Wie groß ist denn ein Sektor?
Fragen über Fragen :-(
Gruß sov21

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #10 am: 01. September 2004, 20:15 »
Mit dynamischen feststellen braucht du schon irgendne art Dateisystem, oder halt du legst es vorher fest, ich beispielswiese hab nen ähnlichen Bootloader, der lädt 18Sektoren ein, hab im mom 7,5kb verwendet davon^^ da wird dann alles wichtige initialisiert, PM, Paging,Memory Management(noch in ner unvollständigen version), diverse funktionen zu Ausgabe, Tastaturtreiber, nen kleener Festplattentreiber und in geringen Ansätzen ist mein eignes Dateisystem eingebaut (ich nehm kein FAT ext Reiser ntfe o.ä)
ein Sektor ist 512Byte gross, wenn du in al also 3 drin hast lädt er 1,5kb also würde das für 2kb kernel nicht reichen.
Ein maximum gibts beim INT 13h nicht (ausser die maximale anzahl an sektoren auf der disk) würdest du mit ports arbeiten und dma usw, müsstestest du beachten das du über trackgrenzen nicht hinauslesen kannst, ein track hat 18sektoren auf ner normalen disk.
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 01. September 2004, 20:19 »
Danke,
nur wie bekomme ich dieses blöde A20Gate jetzt an, wenn ich nicht mal das erste Flag an habe, bzw nicht ausgelesen wird???

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #12 am: 02. September 2004, 09:20 »
Fehler gefunden:
if ((in(0x64)&0x02) == 0x02)
da testest ob das bit gesetzt und machst weiter wenns so ist. Aber wir wollen das es nicht gesetzt ist! also != draus machen
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 02. September 2004, 17:50 »
oh mann :-) lesen müßte ich können.
Das erklärt natürlich auch warum das flag nie gesetzt war.
Tut mir leid, daß ich dich damit so lang aufgehalten habe.
Dann kann ich ja jetzt doch meinen kernel weiter machen. Ich dachte schon ich könnte ihn einmotten, weil er nicht gut funktioniert.
Also dann vielen Dank nochmal.
Gruß sov21

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 02. September 2004, 18:44 »
So A20Gate erfolgreich aktiviert in C ;-)
Wie ist das eigentlich, könnt ihr den Source für eure Homepage gebrauchen?
Weil wenn bedarf ist würde ich ihn posten.
Muß aber nicht sein, wenn ihr ihn nicht braucht, ist es auch kein Prob.
Vielen Dank noch mal für die schnelle Hilfe Roshl.
Gruß sov21

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #15 am: 03. September 2004, 15:51 »
Ich brauch ihn nicht;) aber wer den haben will kann sich bei dir ja melden, ich find es reicht wenn er in asm da ist, gefällt mir eh besser:)
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

 

Einloggen