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_2 [2012/03/08 15:49] – Page name changed from cpm:write_a_bios:dbp to cpm:write_a_bios:teil_2 volkerp | cpm:write_a_bios:teil_2 [2025/04/19 15:36] (aktuell) – volkerp | ||
|---|---|---|---|
| Zeile 2: | Zeile 2: | ||
| weiter geht es mit dem **DPB** | weiter geht es mit dem **DPB** | ||
| + | |||
| + | Das BIOS erhält die Information, | ||
| + | * SETDSK (Laufwerk, 0..15), | ||
| + | * SETTRK (Track, Spur 0...x, berechnet aus Blocknummer + Systempuren), | ||
| + | * SECTRAN (Transformation der aktuellen log. Record-Nummer 0..BSM, Sektorversatz, | ||
| + | * und SETSEC (Sector, transformierte Record-Nummer). | ||
| + | |||
| + | Das BDOS ruft diese genannten BIOS-Funktionen immer vor Aufruf von READ oder WRITE in dieser Reihenfolge auf. Ein BIOS speichert daher die Werte für Laufwerk, Spur, Sektor zwischen und greift bei Lese- und Schreiboperationen darauf zu. Pro Format/ | ||
| + | |||
| + | Das folgende Beispiel stammt aus einer [[cpm: | ||
| + | Bei CP/A erfolgt die Sektorzählung ab 1, deshalb steht in sectran ein inc hl. | ||
| + | Die Zählung ab 1 muss bei den direkten Zugriffen (Adressberechnung, | ||
| + | |||
| + | < | ||
| + | ; | ||
| + | ; Uebersetzung Sektornummer in CP/A | ||
| + | ; | ||
| + | sectran: | ||
| + | ld l, c | ||
| + | inc hl ; | ||
| + | ret | ||
| + | </ | ||
| ===== Beispiel 2 ===== | ===== Beispiel 2 ===== | ||
| Wir wollen ein RAM-Floppy ansteuern. | Wir wollen ein RAM-Floppy ansteuern. | ||
| - | Die RAM-Floppy (NANOS) hat folgende Eigenschaften: | + | Die [[: |
| * 256 K Gesamtkapazität | * 256 K Gesamtkapazität | ||
| Zeile 15: | Zeile 37: | ||
| - Ausgabe A17..A16 auf Port " | - Ausgabe A17..A16 auf Port " | ||
| - Ausgabe A15..A8 auf Port " | - Ausgabe A15..A8 auf Port " | ||
| - | - Einblenden in den Hauptspeicher (auf Adresse " | + | - Einblenden |
| - Zugriff auf " | - Zugriff auf " | ||
| - | Für die Nutzung im CP/M soll außerdem eine Kopie von CCP+BDOS (5 KByte) auf der RAM-Disk gehalten werden, sinnvollerweise in Systemspuren. | + | Für die Nutzung im CP/M soll außerdem eine Kopie von CCP+BDOS (5 KByte) auf der |
| + | RAM-Disk gehalten werden, sinnvollerweise in Systemspuren. | ||
| - | Eine RAM-Floppy hat keine physischen Spuren, deshalb kann man die Aufteilung in virtuelle Spuren und Sektoren nach eigenen Ideen vornehmen. | + | Eine RAM-Floppy hat keine physischen Spuren, deshalb kann man die Aufteilung in |
| + | virtuelle Spuren und Sektoren nach eigenen Ideen vornehmen. | ||
| + | |||
| + | Die Ansteuerung als Übersicht: | ||
| + | |||
| + | < | ||
| + | : | ||
| + | :17 16 15 14 13 12 11 10 9 8: 7 6 5 4 3 2 1 0 : | ||
| + | : : | ||
| + | +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ | ||
| + | | | ||
| + | |B0 B1 b0 b1 x x x x | | ||
| + | +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ | ||
| + | : : : : : : | ||
| + | Variante 1 | ||
| + | : 9 8 7 6 5 4 3 2 1 0: : 0: : | ||
| + | : | ||
| + | | ||
| + | |||
| + | Variante 2 | ||
| + | : 6 5 4 3 2 1 0: 3 2 1 0: : | ||
| + | : | ||
| + | |||
| + | </ | ||
| ==== Variante 1 ==== | ==== Variante 1 ==== | ||
| - | Die Fenstergröße von 256 Byte bietet es an, die Spurgröße als 256 Byte zu wählen. Hi-Byte und Lo-Byte der Tracknummer sind dann direkt " | + | Die Fenstergröße von 256 Byte bietet es an, die Spurgröße als 256 Byte zu |
| + | wählen. Hi-Byte und Lo-Byte der Tracknummer sind dann direkt " | ||
| + | Das macht die Ansteuerung besonders einfach. | ||
| also: | also: | ||
| 1 Track = 256 Byte (Fenstergröße)\\ | 1 Track = 256 Byte (Fenstergröße)\\ | ||
| - | d.h. 2 Records/ | + | d.h. 2 Records/ |
| wir brauchen damit 1600h/256 = 22 Tracks f. Systemspur\\ | wir brauchen damit 1600h/256 = 22 Tracks f. Systemspur\\ | ||
| - | insg. 1024 tracks -> DSM = 1023-22\\ | + | insg. 1024 tracks -> DSM = 1024-22 = 1012\\ |
| - | wir wählen die kleinstmögliche Blockgröße 2k (1k gehen nicht wg. EXM, da wir mehr als 256 Spuren haben)\\ | + | wir wählen die kleinstmögliche Blockgröße 2k (1k gehen nicht wg. EXM, da DSM > 255)\\ |
| und z.B. 128 Dir-Einträge (d.h. 2 Dir-Blöcke)\\ | und z.B. 128 Dir-Einträge (d.h. 2 Dir-Blöcke)\\ | ||
| Zeile 39: | Zeile 87: | ||
| < | < | ||
| ;DISKDEF 0, | ;DISKDEF 0, | ||
| - | dpb00: | + | dpb00: |
| - | db 4 ; | + | db 4 ;BSF block shift factor |
| - | db 15 ; | + | db 15 ;BLM block mask |
| - | db 0 ;extnt mask | + | db 0 ;EXM null mask |
| - | dw 1011 ; | + | dw 1011 ;DSM disk size-1 |
| - | dw 127 ; | + | dw 127 ;DRM directory max |
| - | db C0h ;alloc0 | + | db C0h ;AL0 alloc 0 |
| - | db 0 ;alloc1 | + | db 0 ;Al1 alloc 1 |
| - | dw 0 ; | + | dw 0 ;CKS check size |
| - | dw 22 ; | + | dw 22 ;OFS track offset |
| ; | ; | ||
| - | alv00: | + | alv00: |
| - | csv00: | + | csv00: |
| </ | </ | ||
| - | Die BIOS-Routinen zum Blocklesen und -schreiben verweisen auf folgende Routinen: | + | Die BIOS-Routinen zum Blocklesen und -schreiben verweisen auf folgende Routinen. |
| + | Wegen der Spurgröße von 256 Byte = 2 Records muss ein Blocking/ | ||
| + | erfolgen. Glücklicherweise ist das bei einer RAM-Disk nicht weiter schwierig | ||
| + | umzusetzen, da innerhalb des Zugriffsfensters nur der angesprochene Bereich von | ||
| + | 128 Byte gelesen bzw. verändert wird. | ||
| < | < | ||
| Zeile 76: | Zeile 128: | ||
| LD HL, | LD HL, | ||
| OUT (LDAH), | OUT (LDAH), | ||
| - | OUT (LDBB), | + | ld a,h |
| + | rrca | ||
| + | rrca | ||
| + | OUT (LDBB), | ||
| LD HL, WINDOW ; das ist eine xx00h-Adr. | LD HL, WINDOW ; das ist eine xx00h-Adr. | ||
| LD a, (SECTOR) ; 1 oder 2 (in CP/A wg. SECTRAN) | LD a, (SECTOR) ; 1 oder 2 (in CP/A wg. SECTRAN) | ||
| CP 2 | CP 2 | ||
| jr nz, ADRE0a | jr nz, ADRE0a | ||
| - | LD H,80h | + | LD L,80h |
| ADREa: | ADREa: | ||
| LD BC,128 | LD BC,128 | ||
| RET | RET | ||
| + | |||
| + | |||
| </ | </ | ||
| ==== Variante 2 ==== | ==== Variante 2 ==== | ||
| - | Um eine kleinere Blockgröße nutzen zu können, muss die Anzahl der Spuren | + | (System EPOS, EPOSRF2.MAC) |
| - | Da geht z.B. mit einer Spurgröße | + | |
| + | Um eine kleinere Blockgröße nutzen zu können, muss die Anzahl der Spuren | ||
| + | Da geht z.B. mit einer Blockgröße | ||
| 1 Track = 2048 Byte\\ | 1 Track = 2048 Byte\\ | ||
| - | d.h. 16 Records/ | + | d.h. 16 Records/ |
| - | wir brauchen | + | wir brauchen 1600h/2048 = 3 Tracks f. Systemspur OFF, Epos 1 Systemspur\\ |
| - | insg. 256 Tracks-> DSM = 255-3\\ | + | wie wählen kleinste Blockgröße BLS 1k, 8 bit-Blocknummern ( DSM < 256)\\ |
| - | kleinste Blockgröße 1k\\ | + | insg. 256 Tracks-> DSM = (256-3*2)/1-1 = 249, (epos 253)\\ |
| und z.B. 64 Dir-Einträge (d.h. 2 Dir-Blöcke) | und z.B. 64 Dir-Einträge (d.h. 2 Dir-Blöcke) | ||
| - | Diese Aufteilung ist wg. der kleineren Blockgröße günstiger, wenn viele kleine Dateien auf | + | DSM = (DISKSIZE-OFF*SPURSIZE)/ |
| - | der RAM-Disk gehalten werden sollen. Auch wird weniger Platz für den Allocation Vektor ALVxx benötigt. Aber die Umrechnung logischer Track-Sektor -> Adr. f. RAM-Disk ist aufwendiger! | + | |
| + | Diese Aufteilung ist aufgrund | ||
| + | der RAM-Disk gehalten werden sollen. Auch wird weniger Platz für den Allocation Vektor ALVxx benötigt. Aber die Umrechnung logischer Track und Sektor -> Adr. f. RAM-Disk ist aufwendiger! | ||
| < | < | ||
| - | ;DISKDEF 1, | + | dpbm: dw 16 ;spt |
| - | dpb01: dw 16 ;sec per track | + | db 3 ;bsh |
| - | db 3 ;block shift | + | db 7 ;blm |
| - | db 7 ;block mask | + | db 0 ;exm |
| - | db 0 ;extnt mask | + | dw 253 ;dsm |
| - | dw 251 ;disk size-1 | + | dw 63 ;dpm |
| - | dw 63 ;directory max | + | db 0c0h ;al0 |
| - | db C0H ;alloc0 | + | db 00 ;al1 |
| - | db 0 ;alloc1 | + | dw 0 ;cks |
| - | dw 0 ;check size | + | dw 1 ;off |
| - | dw 3 ;offset | + | db 80h ; |
| - | alv01: ds 0020h | + | ds 12,0 |
| - | csv01: ds 0000h | + | ; |
| + | allm: ds 33 ; | ||
| + | ; | ||
| + | rfrwoper: | ||
| + | ld hl, | ||
| + | add hl, | ||
| + | add hl, | ||
| + | add hl, | ||
| + | ld a, | ||
| + | and 1fh | ||
| + | srl a ; sec >> 1 | ||
| + | push af | ||
| + | add a,l | ||
| + | di | ||
| + | out (ioa+5), | ||
| + | out (ioa+7), | ||
| + | out (ioa), | ||
| + | ld a, | ||
| + | and h ; | ||
| + | rrca | ||
| + | rrca : | ||
| + | out (ioa+2), | ||
| + | ; | ||
| + | pop af ; | ||
| + | ld hl, | ||
| + | jr nc, | ||
| + | ld hl, | ||
| + | rf01: | ||
| + | ld a,b | ||
| + | or a ; | ||
| + | jr z, | ||
| + | ex de,hl | ||
| + | rf02: | ||
| + | ldir | ||
| + | ; | ||
| + | xor a | ||
| + | out (ioa+4), | ||
| + | ei | ||
| + | ret | ||
| </ | </ | ||
| - | Read und Write sind wie oben implementiert, | + | ===== Beispiel 3 ===== |
| + | |||
| + | Ein Floppy-Laufwerk: 800K, 2 Seiten, 1K phys. Sektorgröße, | ||
| + | |||
| + | log. Sektoren pro Spur 1..40\\ | ||
| + | Blockgröße BLS = 2048\\ | ||
| + | Diskgröße = 800K/BLS = 400\\ | ||
| + | 192 Directory-Einträge\\ | ||
| + | keine Systemspuren | ||
| < | < | ||
| - | ADRE: | + | ;DISKDEF 0,1,40,,2048,400,192, |
| - | OUT (READEN), A | + | dpba: |
| - | ; | + | db 4 ;BSF block shift factor |
| - | ;Adr. Fenster = (track*16+sector)/ | + | db 15 ;BLM block mask |
| - | LD HL,(TRACK) | + | db 0 ;EXM null mask |
| - | ADD HL,HL | + | dw 399 ;DSM disk size-1 |
| - | ADD HL,HL | + | dw 191 ;DRM directory max |
| - | ADD HL,HL | + | db 0E0H ;AL0 alloc 0 |
| - | ADD HL,HL ; HL = Track * 10h (SPT) | + | db 0 ;Al1 alloc 1 |
| - | LD DE, | + | dw 48 ;CKS check size |
| - | DEC DE ; wg. CP/A | + | dw 0 ;OFS track offset |
| - | ADD HL,DE ; HL := HL + Sector | + | alva: |
| - | XOR A ; A = 0, Cy = 0 | + | csva: |
| - | RR H | + | |
| - | RR L ; HL := HL/2 ( da 2 Sektoren/ | + | |
| - | RR A ; L Lo-Bit in A Hi-Bit ( A = 0 oder 80h) | + | |
| - | OUT (LDAH), L ; hi-adr. | + | |
| - | OUT (LDBB), H ; Bank | + | |
| - | LD H, Hi(WINDOW) | + | |
| - | LD L,A | + | |
| - | LD DE, | + | |
| - | LD BC,128 | + | |
| - | RET | + | |
| </ | </ | ||
| - | Die Ansteuerung | + | CP/M zählt die logischen Recordnummern pro Spur von 0..39. SECTRAN übersetzt |
| + | diese Recordnummern in 1..40 (CP/ | ||
| + | Recordnummer mit SETSEC ans BIOS. | ||
| + | |||
| + | CP/M ermittelt anhand DSM, ob 16Bit- oder 8-Bit-Blocknummern genutzt werden: DSM > 255 -> 16Bit-Blocknummern. | ||
| + | |||
| + | Die max. Spurnummer berechnet sich als DSM*BLS/ | ||
| + | CP/M arbeitet aber intern nicht mit einer maximalen Spurnummer, sondern testet auf Überschreiten von DSM. | ||
| + | |||
| + | Der DPB wird vom CP/M wie folgt angezeigt: | ||
| < | < | ||
| - | | + | A>stat dsk: |
| - | :17 16 15 14 13 12 11 10 9 8: | + | A: Drive Characteristics |
| - | : : | + | 6400: 128 Byte Record Capacity |
| - | +--+--+--+-+--+--+--+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ | + | 800: Kilobyte Drive Capacity |
| - | | + | 192: 32 Byte Directory Entries |
| - | +--+--+--+-+--+--+--+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ | + | |
| - | : | + | |
| - | : 9 8 7 6 5 4 3 2 1 | + | 16: Records/ Block |
| - | Variante 1 : | + | 40: Sectors/ Track |
| - | SECTOR | + | |
| + | </ | ||
| + | POWER gibt ein paar mehr Informationen aus: | ||
| - | : : : | + | < |
| - | : 7 6 5 4 | + | |
| - | Variante 2 | + | A=disk |
| + | disk capacity: | ||
| + | tracks: 160 0 system | ||
| + | sectors/ | ||
| + | sectors/ | ||
| + | dir entries: | ||
| + | sectors/ | ||
| + | kbytes/ | ||
| </ | </ | ||
| + | Bislang wurde noch nicht darauf eingegangen, | ||
| + | hat. Die Adressierung von Diskettenseite/ | ||
| + | Blocking/ | ||
| + | |||
| + | TODO | ||