_bios_disk()

Der Zugriff auf Disketten (und die ersten Festplatten) war bereits mit dem originalen IBM BIOS möglich, denn der INT 13h bot einige Dienste, wie etwas das Lesen und Schreiben einzelner Sektoren.
Das brauchte das BIOS auch selbst, um das OS booten zu können.

Watcom (und andere historische Compiler) stellen für diesen Systemaufruf die C-Funktion _bios_disk() zur Verfügung.


Grundsätzlich funktionieren alle BIOS und DOS Systemaufrufe recht ähnlich. Man schreibt in das A Register (AH, AL oder AX) eine Aufrufnummer, setzt weitere Register auf diverse Parameter und springt zu einem der Interrupts:

  • int 10h für Text- und Grafik
  • int 13h für Disketten und Festplattenzugriffe
  • int 21h für MS-DOS Funktionen
  • und viele mehr

(Hmm … an welchen Unix Klon erinnert uns das jetzt?)

Um das zu vereinfachen, haben die Compiler von damals einige häufig benutzte Assembler Interrupt-Aufrufe in C Funktionen gekapselt.
Watcom stellt auch heute noch in dos.h viele DOS-Aufrufe direkt als
unsigend _dos_*(...); zur Verfügung.

Tatsächlich gibt es auch den Header bios.h, der einige häufig genutzte BIOS Funktionen kapselt:

  • _bios_disk
  • _bios_equiplist
  • _bios_keybrd
  • _bios_memsize
  • _bios_printer
  • _bios_serialcom
  • _bios_timeofday

Disketten auslesen

Wozu sollte man heute Disketten per BIOS-Aufruf auslesen?

Tja, wenn man einen Toshiba T300 hat, der ein 640 KB-Spezialdiskettenformat unterstützt, das kein anderes 5.25 Zoll Laufwerk lesen kann, und wenn man von einer solchen Diskette ein Image ziehen will … dann braucht man das.

Der T300 kann zum Glück auch normale IBM/DOS 360 KB Diskettenformate lesen und schreiben. Doch Booten kann er offenbar nur von seinem Spezialformat.

Meine Idee war daher die Sektoren der Spuren auszulesen und in Dateien auf dem zweiten Laufwerk zu schreiben. So kann man eine “große” Diskette in zwei kleine teilen, die dann ein neuerer PC wieder lesen kann.

Man befüllt also eine struct _ibm_diskinfo_t mit den Laufwerksparametern und ruft
_bios_disk(_DISK_READ, &diskinfo); auf.

 1struct _ibm_diskinfo_t 
 2{
 3  unsigned drive;
 4  unsigned head;
 5  unsigned track;
 6  unsigned sector;
 7  unsigned nsectors;
 8  void* buffer;
 9};

Ein paar Details über den Aufruf musste ich mir von den alten Interrupt-Listen zusammensuchen, die ich zum Glück online finden konnte.

Dass drive mit 0 Laufwerk A und mit 1 dann B meint, ist logisch.
Der Kopf kann mit 0 und 1 die obere untere Seite ansprechen.
track geht von 0 bis einschließlich 79 auf meiner Spezialdiskette.
Und sector, tja der tanzt mit der Nummerierung von 1 bis 8 aus der Reihe.

Doch so konnte ich dann den ersten 512-Bytes Puffer befüllen und freute mich, dass die Daten auch tatsächlich einem FAT12 Format entsprachen. Zumindest einige der Felder konnte ich klar zuordnen und sie stimmten mit den Laufwerksparametern überein.

Leider schlug mein erster Versuch die Sektoren in einer Schleife auszulesen fehl, denn ich erhielt von den Folgesektoren immer leere Puffer zurück.
Vielleicht hat DOS auch etwas dagegen, wenn man im Hintergrund per int 13h das Laufwerk fernsteuert, oder der Aufruf in der Schleife klappt nicht wie erwartet.

Fazit

Zumindest kann ich eines feststellen:

OpenWATCOM erstellt 16-Bit DOS-EXE Programme, die auch auf dem Toshiba T300 lauffähig sind.

Ich war leider zu kurz am Zweitwohnsitz und konnte keine weiteren Tests machen, warum das weitere Auslesen fehlschlug.

Leider ist von vielen BIOS-Varianten bekannt, dass sie Bugs haben und z.B. Registerwerte zerstören. Wann das hier der Fall ist und die _bios_disk Funktion nicht ausreichend abgesichert ist, dann müsste man den Aufruf in Assembler neu schreiben und alles doppelt und dreifach absichern.

Wie dem auch sei … zumindest ein Teilschritt ist erreicht und beim nächsten Mal komme ich hoffentlich wieder ein Stück weiter.

📧 📋 🐘 | 🔔
 

Meine Dokus über:
 
Weitere externe Links zu:
Alle extern verlinkten Webseiten stehen nicht in Zusammenhang mit opengate.at.
Für deren Inhalt wird keine Haftung übernommen.



Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!