Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
cpm:write_a_bios:teil_1 [2015/03/03 08:05] – [Der Disk Parameter Block] volkerp | cpm:write_a_bios:teil_1 [2024/12/05 12:54] (aktuell) – [Der Disk Parameter Block] volkerp | ||
---|---|---|---|
Zeile 60: | Zeile 60: | ||
nur die zuerst anzuwählende Disk- und Usernummer in die Speicheradresse | nur die zuerst anzuwählende Disk- und Usernummer in die Speicheradresse | ||
0004h eingetragen zu werden. | 0004h eingetragen zu werden. | ||
+ | |||
+ | |||
+ | * Systemmeldung ausgeben | ||
+ | * IOBYTE Geräte initialisieren | ||
+ | * die verschiedenen Systemparameter, | ||
+ | * Register C auf Null setzen, um Laufwerk A zu wählen | ||
**WBOOT** wird beim Warmstart (z.b. ^C oder JP 0000) aufgerufen. Die BDOS- | **WBOOT** wird beim Warmstart (z.b. ^C oder JP 0000) aufgerufen. Die BDOS- | ||
Zeile 75: | Zeile 81: | ||
Nach dem Neuladen von CCP und BDOS werden die Systemsprünge für JP 0000 und CALL 5 eingerichtet, | Nach dem Neuladen von CCP und BDOS werden die Systemsprünge für JP 0000 und CALL 5 eingerichtet, | ||
das aktuelle Laufwerk wieder selektiert und die Steuerung ans CCP übergeben. | das aktuelle Laufwerk wieder selektiert und die Steuerung ans CCP übergeben. | ||
+ | |||
+ | * Laden von CCP und BDOS | ||
+ | * Initialisieren von JP 0, JP 5 | ||
+ | * IOBYTE 0003h setzen | ||
+ | * CDRIVE 0004h setzen (Highnibble = aktuelle Benutzernummer, | ||
+ | * C = aktuelles Laufwerk. WBOOT sollte CDRIVE auslesen und sicherstellen, | ||
+ | * Sprung nach CCP | ||
+ | |||
< | < | ||
Zeile 221: | Zeile 235: | ||
**SETSEC** bezieht sich auf den im Registerpaar | **SETSEC** bezieht sich auf den im Registerpaar | ||
- | BC übergebenen Sektor. Die so gesetzte Sektornummer ist immer | + | BC übergebenen |
das Ergebnis der SECTRAN-Funktion (s.u.). Auch hier ist ein | das Ergebnis der SECTRAN-Funktion (s.u.). Auch hier ist ein | ||
tatsächlicher Diskzugriff auf diesen Sektor nicht garantiert. | tatsächlicher Diskzugriff auf diesen Sektor nicht garantiert. | ||
+ | |||
+ | Vor direktem Aufruf von SETSEC muss daher immer SECTRAN erfolgen! | ||
**SETDMA**: Alle nachfolgenden Diskzugriffe müssen die DMA-Adresse als | **SETDMA**: Alle nachfolgenden Diskzugriffe müssen die DMA-Adresse als | ||
Zeile 264: | Zeile 280: | ||
übergebene Sektornummer ins Registerpaar HL zu kopieren. | übergebene Sektornummer ins Registerpaar HL zu kopieren. | ||
- | im CP/A wird einfach der übergebene Wert genommen und um 1 erhöht (die Sektoren | + | Die logische Sektornummer in CP/M reicht von 0 bis max. 65535, die physikalischen Sektornummern auf Disketten-Laufwerken beginnen in der Regel mit 1. |
+ | |||
+ | :!: im CP/A wird daher einfach der übergebene Wert genommen und um 1 erhöht (die phys. Sektoren | ||
zählen in CP/A bzw. auf Diskette ab 1). Nutzt man eine allgemeine SECTRAN- | zählen in CP/A bzw. auf Diskette ab 1). Nutzt man eine allgemeine SECTRAN- | ||
- | Routine für alle Laufwerke, muss dies bei den phys. Laufwerkstreibern f. Read und Write beachtet werden. | + | Routine für alle Laufwerke, muss dies bei den phys. Laufwerkstreibern f. Read und Write beachtet werden, insbesondere bei nachladbaren Treibern wie z.B. für eine RAM-Disk. |
< | < | ||
Zeile 298: | Zeile 316: | ||
Laufwerk beziehen. | Laufwerk beziehen. | ||
- | In einem aufwendigen BIOS kann bei SELDSK eine Analyse der Diskette erfolgen, um | + | :!: In einem aufwendigen BIOS kann bei SELDSK eine Analyse der Diskette erfolgen, um |
das konkrete **Diskettenformat automatisch zu ermitteln**. Im CP/A-BIOS gibt es eine Liste von Formaten, die hier getestet werden (z.B. 624k, 780k, 800k). Als Resultat dieser | das konkrete **Diskettenformat automatisch zu ermitteln**. Im CP/A-BIOS gibt es eine Liste von Formaten, die hier getestet werden (z.B. 624k, 780k, 800k). Als Resultat dieser | ||
Analyse wird ein passender DPB ausgewählt (oder dynamisch zusammengestellt) | Analyse wird ein passender DPB ausgewählt (oder dynamisch zusammengestellt) | ||
Zeile 314: | Zeile 332: | ||
Ein DPH umfasst 8 Einträge zu je 16 Bit und hat folgende Struktur: | Ein DPH umfasst 8 Einträge zu je 16 Bit und hat folgende Struktur: | ||
- | <ditaa> | + | <a2s> |
- | | + | |
| XLT | NHDE | CLTK | FSCT | DIRBUF | DPB | CSV | ALV | | | XLT | NHDE | CLTK | FSCT | DIRBUF | DPB | CSV | ALV | | ||
- | | + | |
Byte 0/1 | Byte 0/1 | ||
- | </ditaa> | + | </a2s> |
XLT (s.o.), NHDE, CLTK, FSCT sind mit 0 vorbelegt, DIRBUF ist ein 128 Byte | XLT (s.o.), NHDE, CLTK, FSCT sind mit 0 vorbelegt, DIRBUF ist ein 128 Byte | ||
Zeile 431: | Zeile 449: | ||
Man spricht von physischen Laufwerkstreibern für Read und Write, wenn diese den physischen Transfer eines (physischen) Sektors von/zum Laufwerk übernehmen. Die logischen Laufwerkstreiber übernehmen das Blocking/ | Man spricht von physischen Laufwerkstreibern für Read und Write, wenn diese den physischen Transfer eines (physischen) Sektors von/zum Laufwerk übernehmen. Die logischen Laufwerkstreiber übernehmen das Blocking/ | ||
- | Ganz einfache Routinen: | + | Zur Unterstützung des Blocking/ |
+ | * 0 = normales Schreiben eines Sektors | ||
+ | * 1 = Schreiben eines Directory-Sektors | ||
+ | * 2 = Schreiben des ersten Sektors eines neuen Blocks | ||
+ | |||
+ | Von Digital Research gibt es außerdem die Datei deblock.asm, | ||
+ | |||
+ | |||
+ | Ganz einfache Routinen | ||
< | < | ||
; | ; | ||
Zeile 484: | Zeile 510: | ||
Ein DPB umfasst 15 Bytes in folgender Aufteilung: | Ein DPB umfasst 15 Bytes in folgender Aufteilung: | ||
- | <ditaa> | + | |
- | +----------------------------------------------------------+ | + | <a2s> |
+ | #-----#-----#-----#-----#-----#----#-----#-----#-----#-----# | ||
| SPT | BSH | BLM | EXM | DSM | DRM| AL0 | AL1 | CKS | OFF | | | SPT | BSH | BLM | EXM | DSM | DRM| AL0 | AL1 | CKS | OFF | | ||
- | +----------------------------------------------------------+ | + | #-----#-----#-----#-----#-----#----#-----#-----#-----#-----# |
0/1 | 0/1 | ||
| | ||
- | </ditaa> | + | </a2s> |
Zeile 526: | Zeile 553: | ||
* ... | * ... | ||
| | ||
- | CP/A nutzt die erste Variante. | + | :!: CP/A nutzt die erste Variante. |
- | Unabhängig von der physischen Sektorlänge gibt es im CP/M noch die **Blockgröße**. | + | Unabhängig von der physischen Sektorlänge gibt es im CP/M noch die **Blockgröße** |
Das BDOS teilt jede Diskette in Blöcke (engl. Blocks) auf, um damit den | Das BDOS teilt jede Diskette in Blöcke (engl. Blocks) auf, um damit den | ||
Verwaltungs- und Speicheraufwand für die Belegungstabelle zu verkleinern. | Verwaltungs- und Speicheraufwand für die Belegungstabelle zu verkleinern. | ||
Zeile 568: | Zeile 595: | ||
**BSH** := log2 (block size / 128)\\ | **BSH** := log2 (block size / 128)\\ | ||
**BLM** := (block size / 128) - 1\\ | **BLM** := (block size / 128) - 1\\ | ||
- | **EXM** := (block size / 1024) - 1 bei 8 bit-Blocknummern ( DSM/block size < = 255) bzw.\\ | + | **EXM** := (block size / 1024) - 1 bei 8 bit-Blocknummern ( DSM <= 255) bzw.\\ |
- | **EXM** := (block size / 2048) - 1 bei 16 bit-Blocknummern ( DSM/block size > 255)\\ | + | **EXM** := (block size / 2048) - 1 bei 16 bit-Blocknummern ( DSM > 255)\\ |
- | ^ block size ^ BSH | + | ^ block size ^ |
- | ^ 1 KByte | + | ^ :!: 512 Byte | 2 | 3 | 0 | - | |
- | ^ 2 KByte | + | ^ 1 KByte |
- | ^ 4 KByte | + | ^ 2 KByte |
- | ^ 8 KByte | + | ^ 4 KByte |
- | ^ 16 KByte | 7 | 127 | 15 | 7 | | + | ^ 8 KByte |
+ | ^ 16 KByte | 7 | 127 | 15 | 7 | | ||
+ | |||
+ | :!: 512 Byte funktionieren in CP/A und CP/M 2.2, sind aber nicht dokumentiert. Für eine kleine RAM-Disk reicht es. Die cpmtools kommen damit nicht klar! | ||
Die Anzahl der Directory-Einträge ist frei wählbar. Es werden immer ganze Blöcke vergeben, | Die Anzahl der Directory-Einträge ist frei wählbar. Es werden immer ganze Blöcke vergeben, | ||
Zeile 588: | Zeile 618: | ||
sollte gewahrt bleiben. Es ist wenig sinnvoll, mehr Directory-Einträge als Blöcke zu haben. | sollte gewahrt bleiben. Es ist wenig sinnvoll, mehr Directory-Einträge als Blöcke zu haben. | ||
DSM/ | DSM/ | ||
+ | |||
+ | Es sollte außerdem | ||
+ | |||
+ | für 8-Bit-Blocknummern: | ||
+ | für 16-Bit-Blocknummern: | ||
+ | |||
+ | sein, sonst bekommt man die Diskette gar nicht voll. | ||
Im Beispiel ergibt sich für drei 2K-Blöcke 3 * 2048/32 = maximal mögliche 192 Einträge, | Im Beispiel ergibt sich für drei 2K-Blöcke 3 * 2048/32 = maximal mögliche 192 Einträge, | ||
das Maximum sollte man auch nutzen und DRM auf 191 setzen. | das Maximum sollte man auch nutzen und DRM auf 191 setzen. | ||
- | ^ block size | + | ^ Anz. Dir.Blöcke |
- | ^ ^ 1^ 2^ 3^ 4^ 5^ 6^ 7^ 8^ 9^ 10^ 11^ 12^ 13^ 14^ 15^ 16^ | + | ^ AL0, |
- | ^ 1 KByte| | + | ^ block size |
- | ^ 2 KByte| | + | ^ 1 KByte | |
- | ^ 4 KByte| | + | ^ 2 KByte | |
- | ^ 8 KByte| | + | ^ 4 KByte | 127 | 255 | 383 | 511 | 639 | 767 | 895 | |
- | ^ 16 KByte| | + | ^ 8 KByte | 255 | 511 | 767 | |
+ | ^ 16 KByte | ||
CP/M erkennt Diskettenwechsel, | CP/M erkennt Diskettenwechsel, | ||
Zeile 609: | Zeile 647: | ||
Damit wird nicht auf Diskettenwechsel geprüft. | Damit wird nicht auf Diskettenwechsel geprüft. | ||
- | Im DPH (s.o.) wird für den Prüfsummenvektor Speicherplatz definiert (CHKxx). | + | Im DPH (s.o.) wird für den Prüfsummenvektor Speicherplatz definiert (**CHK**xx). |
Dieser muss CKS Byte groß sein: | Dieser muss CKS Byte groß sein: | ||
CHK00: | CHK00: | ||
- | Der Allocation Vektor (ALV) bildet die Belegungstabelle (besser: | + | Der Allocation Vektor (**ALV**) bildet die Belegungstabelle (besser: |
Belegungsvektor) der Diskette. Für jeden Block der Diskette ist im ALV ein Bit | Belegungsvektor) der Diskette. Für jeden Block der Diskette ist im ALV ein Bit | ||
vorhanden, das entsprechend auf 0 (Block frei) oder 1 (Block belegt) gesetzt | vorhanden, das entsprechend auf 0 (Block frei) oder 1 (Block belegt) gesetzt | ||
wird. Die Zuordnung der Blöcke zu den Bits geschieht in absteigender | wird. Die Zuordnung der Blöcke zu den Bits geschieht in absteigender | ||
Bitnummernfolge (höchstes Bit eines Bytes zuerst) und aufsteigender Bytefolge | Bitnummernfolge (höchstes Bit eines Bytes zuerst) und aufsteigender Bytefolge | ||
- | (erstes Byte des ALV zuerst). Für ALLxx muss man deshalb (DSM+1)/8 Byte bereitstellen: | + | (erstes Byte des ALV zuerst). Für ALLxx muss man deshalb (DSM+7)/8 Byte bereitstellen |
- | ALL00: | + | ALL00: |
Achtung: Bei automatischer Formaterkennung müssen die Speicherplätze CHKxx und | Achtung: Bei automatischer Formaterkennung müssen die Speicherplätze CHKxx und | ||
Zeile 649: | Zeile 687: | ||
DW 0 ;OFS track offset | DW 0 ;OFS track offset | ||
- | CHK00: | ||
ALL00: | ALL00: | ||
+ | CHK00: | ||
</ | </ | ||
- | die Berechnung des DPB und der Größe der Speicherbereiche kann durch ein Makro erfolgen. | + | die Berechnung des DPB und der Größe der Speicherbereiche kann durch die Makro-Bibliothek diskdef.lib |
+ | |||
+ | -> http:// | ||
< | < | ||
Zeile 663: | Zeile 703: | ||
</ | </ | ||
- | Dieses Beispiel erzeugt genau obige Daten für Beispiel 1. | + | Dieses Beispiel erzeugt |
+ | |||
+ | :!: Die originale diskdef.lib funktioniert nur mit dem MAC/ | ||
+ | |||
+ | Der Makroaufruf **DISKDEF** hat die Form: | ||
+ | |||
+ | DISKDEF dn, | ||
+ | |||
+ | wobei | ||
+ | |||
+ | dn ist die logische Plattennummer, | ||
+ | fsc ist die erste physische Sektornummer (0 oder 1). | ||
+ | lsc ist die letzte Sektornummer. | ||
+ | skf ist der optionale Sektor-Skew-Faktor. | ||
+ | bls ist die Blockgröße der Datenzuordnung. | ||
+ | dks ist die Anzahl der Blöcke auf der Platte. | ||
+ | dir ist die Anzahl der Verzeichniseinträge. | ||
+ | cks ist die Anzahl der geprüften Verzeichniseinträge. | ||
+ | ofs ist der Spurversatz zur logischen Spur 00. | ||
+ | [0] ist ein optionales 1.4-Kompatibilitätsflag. | ||
+ | |||
+ | Der Wert dn ist die Laufwerksnummer, | ||
+ | |||
+ | Wenn die Anzahl der Sektoren weniger als 256 beträgt, wird eine Einzelbyte-Tabelle erstellt, ansonsten belegt jedes Übersetzungstabellenelement zwei Bytes. Es wird keine Übersetzungstabelle erstellt, wenn der Parameter skf weggelassen wird oder gleich 0 ist. | ||
+ | |||
+ | Der Parameter bls gibt die Anzahl der Bytes an, die jedem Datenblock zugeordnet sind und nimmt die Werte 1024, 2048, 4096, 8192 oder 16384 an. Im Allgemeinen steigt die Leistung mit größeren Datenblockgrößen, | ||
+ | |||
+ | Der Parameter dks gibt die Gesamtplattengröße in bls-Einheiten an. Das heißt, wenn bls = 2048 und dks = 1000 ist, beträgt die Gesamtplattenkapazität 2.048.000 Byte. Wenn dks größer als 255 ist, muss der Blockgrößenparameter bls größer als 1024 sein. Der Wert von dir ist die Gesamtzahl der Verzeichniseinträge, | ||
+ | |||
+ | Der Parameter cks bestimmt die Anzahl der Verzeichniselemente, | ||
- | Tipp: Die originale diskdef.lib funktioniert nur mit dem MAC/RMAC-Assembler. Für den M80 gibt es eine angepasste Version BUGS fixed 07/07/82 JDW Software. | + | Wie im vorherigen Abschnitt erwähnt, ist der Wert von cks = dir, wenn das Medium leicht geändert werden kann, wie es bei einem Disketten-Subsystem der Fall ist. Wenn die Platte permanent gemountet ist, ist der Wert von cks normalerweise 0, da die Wahrscheinlichkeit eines Plattenwechsels ohne Neustart gering ist. |
+ | Der Wert ofs bestimmt die Anzahl der zu überspringenden Spuren, wenn dieses bestimmte Laufwerk angesprochen wird. Dies kann verwendet werden, um zusätzlichen Betriebssystemspeicherplatz zu reservieren oder mehrere logische Laufwerke auf einem einzelnen physischen Laufwerk mit großer Kapazität zu simulieren. Schließlich ist der Parameter [0] enthalten, wenn Dateikompatibilität mit Versionen von 1.4 erforderlich ist, die für Festplatten mit höherer Dichte modifiziert wurden. Dieser Parameter stellt sicher, dass für jeden Verzeichnisdatensatz nur 16 KB zugewiesen werden, wie dies bei früheren Versionen der Fall war. Normalerweise ist dieser Parameter nicht enthalten. | ||