Add new attachment

Only authorized users are allowed to upload new attachments.

This page (revision-8) was last changed on 27-Dec-2010 16:19 by Carsten Strotmann  

This page was created on 27-Dec-2010 15:50 by Carsten Strotmann

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Difference between version and

At line 267 added 152 lines
!!Teil 4
von Reinhard Wilde
!DIE EINSPRUNGADRESSEN
Nachdem wir Ihnen im letzten Monat die Speicherbelegung der SPEEDY erklärt haben, erfahren Sie jetzt etwas über die Einsprungadressen. Wichtig ist dabei, eines zu wissen: Wir haben am Ende des ROM-Bereiches ab $FF00 eine Einsprungtabelle eingerichtet. Wenn Sie nun eine Funktion innerhalb der SPEEDY ausführen wollen, brauchen Sie nur eine oder mehrere Adressen dieser Sprungtabelle anzuspringen.
Welche Versionen es in Zukunft auch von der SPEEDY geben wird, diese Sprungtabelle wird immer an der gleichen Stelle und in der gleichen Reihenfolge erhalten bleiben. Somit ist gewährleistet, daß alle Programme, die jetzt für die SPEEDY geschrieben werden, auch auf den zukünftigen Versionen laufen, wenn die internen Routinen über diese Tabelle angesprungen werden.
Hier die Beschreibung der einzelnen Jump-Vektoren:
__RESET - $FF00 - DRIVE KALTSTART__
Port A und Port B (6532) werden initialisiert, der komplette RAM-Bereich gelöscht und der Disk-Controller getestet. Sollte ein Fehler beim Testen auftreten, erfolgt ein Sprung nach "SYSER0", wo zweimal "BELL" ausgegeben wird, anschließend folgt ein Sprung nach "RESET2".
__RESET2 - $FF03 - DRIVE WARMSTART__
Die System-Variablen werden neu gesetzt, das Laufwerk in den "SINGLE-DENSITY-MODUS" gebracht, der Schreib-/Lesekopf auf Track 0 justiert und jede Controller-Tätigkeit gestoppt. Zum Rücksetzen des Laufwerkes sollte diese Routine angesprungen werden, da bei "$FF00 - RESET" alle im RAM befindlichen Daten gelöscht werden.
__BEREIT - $FF06 - BEREITSCHAFTSROUTINE__
Zuerst wird der "SLOW"-Schalter abgefragt und das Laufwerk gegebenenfalls in den "SLOW"-Modus geschaltet. Sollten sich noch zu schreibende Sektoren im RAM befinden, wird direkt danach "TSTCO" verzweigt, damit der Motor nicht ausgeschaltet wird, falls die Laufwerksklappe geöffnet wurde. Wurde nicht verzweigt, wird die Laufwerksklappe mit der letzten Stellung verglichen. Sollte die Klappe geöffnet worden sein, werden der Antriebsmotor und der Steppermotor ausgeschaltet und der Controller-Status nach "CONST" kopiert. Ist die Klappe geschlossen worden, wird die DENSITY neu festgestellt, das Laufwerk entsprechend eingestellt und die Sektor-Folge neu eingelesen. In der "TESTCO"-Routine wird die "COMMAND"-Leitung vom Computer abgefragt. Sollte diese "gesetzt" werden, erfolgt ein Sprung nach "RDINF", wo das Kommando vom Computer eingelesen wird. Ist die "COMMAND"-Leitung nicht gesetzt, wird der Motor-Timer heraufgezählt. Sollte dieser den Wert $9800 (16 Bit) erreichen, wird "TSTWR" aufgerufen, um alle Sektoren zu schreiben, die sich noch im RAM befinden.
__MOTON - $FF09 - MOTOR ZWINGEND EINSCHALTEN__
Der Antriebsmotor wird ohne Rücksicht auf die Stellung der Laufwerksklappe eingeschaltet.
__TSTMON - $FF0C - MOTOR EINSCHALTEN, WENN DIE LAUFWERKSKLAPPE GESCHLOSSEN IST__
Erst wird die Laufwerksklappe abgefragt. Ist diese geschlossen, wird der Antriebsmotor eingeschaltet und eine Zeitverzögerung durchgeführt, um den Motor auf Touren kommen zu lassen.
__MOTOFF - $FF0F - MOTOR AUSSCHALTEN__
Der Antriebsmotor wird ausgeschaltet und das entsprechende Bit in "DRSTAT" gesetzt.
__SDELAY - $FF12 - MOTOR TIMER EINSTELLEN__
Diese Routine wird nach einer Kommandoausführung abgearbeitet. Es wird die Zeit vorgegeben, wie lange der Motor nach einer Kommandoausführung noch eingeschaltet bleiben soll.
__SDRDDP - $FF15 - DRIVE DENSITY EINSTELLEN UND ANZEIGEN__
Zuerst wird nach "DENDSP" gesprungen, um die aktuelle DENSITY auf dem Display anzuzeigen. Danach wird, je nach Wert in "FORKEN", der Drive-Status, die Anzahl der Sektoren pro Track und die Anzahl der Bytes pro Sektor gesetzt.
__XWAIT - $FF18 - WARTESCHLEIFE KURZ__
Der Wert im X-Register gibt die Anzahl der Schleifendurchläufe an. 1 Schleifendurchlauf entspricht ca. 100 Taktzyklen (0,1 msek/100 mikrosek).
__X2WAIT - $FF1B - WARTESCHLEIFE LANG__
Der Wert im X-Register gibt die Anzahl der Schleifendurchläufe an. 1 Schleifendurchlauf entspricht ca. 100.000 Taktzyklen (0,1 sek/100 msek).
__TRACK0 - $FF1E - TRACK 0 POSITIONIEREN__
Der Disk-Controller wird gestoppt und der Schreib-/Lesekopf so lange zurückgezogen, bis der Track-0-Sensor anspricht. Danach wird eine Verzögerung zum Ausschwingen der Kopfmechanik durchgeführt.
__TRADJA - $FF21 - TRACK # ANZEIGEN UND SCHREIB-/LESEKOPF POSITIONIEREN__
Zuerst wird die Tracknummer angezeigt und der Controller gestoppt. Ist die Klappe geschlossen, wird der Motor eingeschaltet und die Anzahl der Doppel-Steps errechnet, die durchgeführt werden müssen, um die gewünschte Kopfposition zu erreichen. Sollte der Trackwechsel über 40 Tracks gehen, wird zweimal "BELL" ausgegeben und der Kopf auf Track 0 positioniert.
Nach erfolgreicher Schreib-/Lesekopf-Positionierung wird die Tracknummer in das Track-Register des Controllers kopiert und der Schreib-/Lesekopf-Mechanik Zeit zum Ausschwingen gegeben.
__TRADJ - $FF24 - SCHREIB-/LESEKOPF POSITIONIEREN__
Entspricht der $FF21-Routine, mit dem Unterschied, daß die Tracknummer nur dann angezeigt wird, wenn ein Trackwechsel stattgefunden hat.
__TRVR - $FF27 - 1 STEP VORWÄRTS ODER RÜCKWÄRTS AUSFÜHREN__
Im Y-Register ist die Kennung für Step vorwärts oder rückwärts (plus oder minus). Die Bitposition des Steppermotors wird entsprechend herauf- oder herabgezählt und das neue Bitmuster in Port 5 des Portbausteins geschrieben.
Anmerkung: Für 1 Trackwechsel müssen immer 2 Steps erfolgen. Das heißt aber nicht, daß ohne Bedenken 80 Tracks geschrieben oder gelesen werden können. Die beiden Steps sind verschieden lang und instabil!
__CONRES - $FF2A - DISK CONTROLLER STOPPEN__
Dem Disk-Controller wird der Befehl gegeben, alle laufenden Aktionen zu stoppen. In "WREADY" wird gewartet, bis der Controller den Befehl als "ausgeführt" meldet.
__CONRE2 - $FF2D - CONRES WIRD ZWEIMAL AUSGEFÜHRT__
Beim Einsprung in diese Routine wird die Routine $FF2A - DISK CONTROLLER STOPPEN zweimal ausgeführt.
__WREADY - $FF30 - AUF CONTROLLER "IN USE-FLAG" = 0 WARTEN__
Bei dieser Routine wird darauf gewartet, bis der Controller meldet, daß der letzte Befehl abgeschlossen wurde.
__RD128 - $FF33 - 128 BYTES VOM COMPUTER NACH "EXBUF" HOLEN__
Der Buffer wird auf "EXBUF" (Extended Buffer) und die I/O-Länge auf 128 Bytes gesetzt.
__RD256 - $FF36 - 256 BYTES VOM COMPUTER NACH "EXBUF" HOLEN__
Wie bei der vorhergehenden Routine wird der Buffer auf "EXBUF", aber die I/O-Länge auf 256 Bytes gesetzt.
__RDBTS - $FF39 - ANZAHL DER BYTES IM ACCU IN DEN BUFFER HOLEN (X/Y-REGISTER)__
Im Accu steht die Anzahl der Bytes, im X- und Y-Register die Low- und High-Adresse des Buffers, in dem die Daten vom Computer abgelegt werden sollen. Der Timer wird gesetzt, um zu verhindern, daß der Prozessor hängen bleiben kann. Es wird jeweils ein Byte über einen indirekten Jump-Vektor vom Computer geholt (außer bei HIGH-SPEED) und in dem Buffer abgelegt. Anschließend wird die Checksumme heraufgezählt und geprüft, ob alle Bytes des Datenblocks geholt wurden. Die Checksumme wird verglichen und die I/O-Länge neu gesetzt.
__RDSFOL - $FF3C - NACH VERZÖGERUNG SEKTORFOLGE VOM AKTUELLEN TRACK LESEN__
Eine Verzögerungsschleife am Anfang der Routine verhindert, daß versucht wird, die HEADER schon zu lesen, wenn die Laufwerksklappe noch nicht vollständig geschlossen ist. Danach wird die Zeit gestellt, die der Controller zur Verfügung hat, um alle HEADER zu lesen. Ist ein HEADER eingelesen, wird die Track- und Sektor-Nummer auf Gültigkeit geprüft. Befindet sich die Sektornummer des gelesenen HEADERS bereits in der Sektorliste (doppelter Sektor), wird die Sektorfolge nicht mehr weiter gelesen und das Laufwerk in den Slow-Modus geschaltet. Stimmt die Anzahl der gelesenen Sektor-HEADER nicht mit der vorgegebenen (18 oder 26 Sektoren) überein, wird das Laufwerk ebenfalls in den Slow-Modus geschaltet.
__RDTRA - $FF42 - AKTUELLEN TRACK IN DAS RAM EINLESEN__
Die Track-Slow-Kennung wird gesetzt. Über RDHDSP wird der Kopf positioniert und der nächste HEADER eingelesen. Anschließend wird die Position der Sektor-Nummer des HEADERS in der Sektorliste gesucht. Ab der nächsten Position werden die Sektoren dann in der richtigen Reihenfolge eingelesen. Die Statuswerte der Sektoren werden in die Statusliste eingetragen. Alle Statuswerte außer $08 (CRC-ERROR) und $20 (AM-ERROR) unterbrechen dabei das Einlesen der Sektoren. Nur wenn alle Sektoren des Tracks gelesen wurden, wird die Kennung für Track-Slow zurückgesetzt.
__RDTRAV - $FF45 - WIE RDTRA, JEDOCH MIT VERIFY UND 1 RETRY__
Hier wird zuerst die Track- und Sektornummer errechnet und anschließend $FF42 (RDTRA) aufgerufen. Dann wird die Statusliste auf $08 (CRC-ERROR) und $20 (AM-ERROR) getestet. Ist einer der beiden Statuswerte eingetragen, wird der entsprechende Sektor nochmal gelesen.
Fortsetzung im CSM 5'89.
Da sich viele Beschreibungen auf Zero-Page Adressen beziehen, hier eine Übersicht über die vom SPEEDY-System belegten Adressen:
{{{
DLYT1 = $03 Timer LO für Motor-Timer Routine
DLYT2 = $04 Timer HI für Motor-Timer Routine
LDSW = $05 Letzte SLOW-Schalter Position
WRKEN = $06 Anzahl der zu schreibenden Sektoren im RAM
EXSECT = $07 Sektornummer der Daten im extended Buffer
DUMKEN = $08 SLOW-Status
FORKEN = $09 Aktuelle Density $00=DD, $41=MD, $82=SD
FORKEN2 = $0A Density für Format, wenn durch COM4F gesetzt
LWRTRA = $0B Tracknummer der zu schreibenden Daten im RAM
LTRACK = $0C Tracknummer des zuletzt gelesenen Sektors
TRACK = $0D Aktuelle Tracknummer
SECTOR = $0E Aktuelle Sektornummer
CONST = $0F Controller-Status
DRSTAT = $10 Drive-Status
COMST = $11 Command-Status
RETRY = $12 Anzahl der Retries für Read/Write, normal = 2
RWLEN = $13 I/O Länge
SECLEN = $14 Anzahl der Bytes pro Sektor
USKEN = $15 Kennung für Übertragungsgeschwindigkeit
DLYTIM = $16 Enthält die Zeit, wie lange der Motor nach einem Befehl noch läuft
STPTIM = $17 Verzögerung für Steppermotor
COMPOS = $18 Position des letzten Befehls in der Kommandotabelle
IND = $19 Indirekt-Vektor für Datenbuffer
CHKSUM = $1B Checksum für Datenübertragung
RDDATK = $1C Kennung, ob Daten vom Computer geholt werden müssen
KLAPPE = $1D Letzte Klappen Position
SECANZ1 = $1E Sektoranzahl pro Track, die vorhanden sind
SECANZ = $1F Sektoranzahl pro Track, die vorhanden sein sollen
SECLST = $20 Sektorenliste
STALST = $40 Sektoren-Status-Liste
STPPOS = $60 Bit-Position für Steppermotor
DSPCTR = $61 Display/Drive-Controlbyte
BLOCKS = $62 Anzahl der Datenblocks für Datenübertragung
COUNTL = $64 16-Bit Zähler für Datenübertragung (low-Byte)
COUNTH = $65 16-Bit Zähler für Datenübertragung (high-Byte)
RDIND = $68 Indirekter Vektor für 1 Byte vom Computer empfangen
SDIND = $6A Indirekter Vektor für 1 Byte zum Computer senden
}}}
Die Zeropageadressen $90 bis $CF sind unbenutzt und frei für eigene Programme.
Version Date Modified Size Author Changes ... Change note
8 27-Dec-2010 16:19 68.731 kB Carsten Strotmann to previous
7 27-Dec-2010 16:18 59.163 kB Carsten Strotmann to previous | to last
6 27-Dec-2010 16:08 49.899 kB Carsten Strotmann to previous | to last
5 27-Dec-2010 16:06 49.898 kB Carsten Strotmann to previous | to last
4 27-Dec-2010 16:04 41.963 kB Carsten Strotmann to previous | to last
3 27-Dec-2010 15:59 31.017 kB Carsten Strotmann to previous | to last
2 27-Dec-2010 15:54 20.882 kB Carsten Strotmann to previous | to last
1 27-Dec-2010 15:50 12.223 kB Carsten Strotmann to last
« This page (revision-8) was last changed on 27-Dec-2010 16:19 by Carsten Strotmann