summaryrefslogtreecommitdiff
path: root/system/shard-z80-ruc-64180/1.5/src/SCSI.MAC
diff options
context:
space:
mode:
Diffstat (limited to 'system/shard-z80-ruc-64180/1.5/src/SCSI.MAC')
-rw-r--r--system/shard-z80-ruc-64180/1.5/src/SCSI.MAC1478
1 files changed, 1478 insertions, 0 deletions
diff --git a/system/shard-z80-ruc-64180/1.5/src/SCSI.MAC b/system/shard-z80-ruc-64180/1.5/src/SCSI.MAC
new file mode 100644
index 0000000..d77778c
--- /dev/null
+++ b/system/shard-z80-ruc-64180/1.5/src/SCSI.MAC
@@ -0,0 +1,1478 @@
+
+ TITLE SCSI Interface fuer RUC 180 Karte
+
+ INCLUDE HD64180.LIB
+
+ .LIST
+
+;****************************************************************
+;
+; S C S I
+;
+; Elementare Ein- und Ausgaben auf dem SCSI Interface
+;
+; Version 0.7, R. Ellerbrake
+; Version 0.8 vom 31.12.86, M.Staubermann
+;
+; Copyright (C) 1985 by R. Ellerbrake
+;
+; Vers. 0.2: Kommando Transfer per DMA wieder eingebaut
+; Vers. 0.3: Reset Signal implementiert
+; Vers. 0.4: automatische Erkennung 40/80 Spuren Archiv
+;
+;****************************************************************
+
+; Conditional Switches
+
+FALSE EQU 0
+TRUE EQU NOT FALSE
+
+DMA EQU TRUE ;-1 = Daten nur per DMA ausgeben
+EUMEL EQU TRUE ;EUMEL Version
+SEC8 EQU FALSE ;-1 = 8 Sektor Floppy
+TRK40 EQU FALSE ;-1 = Voreinst. 2x40 Spuren
+DEBUG EQU FALSE ; Retries bei DMA/Hardwarefehler
+
+;----------------------------------------------------------------
+
+; Globale Adressen
+
+ GLOBAL SCSIIO, PHYSADR, INITS
+ GLOBAL HDIO, FDIO, INIFLP, INITS1, PARKHD
+;
+;----------------------------------------------------------------
+
+; Externe Adressen
+
+ IF EUMEL
+
+ EXTERNAL WARTE
+
+ ENDIF
+
+;----------------------------------------------------------------
+
+; Port-Adressen
+
+CIOAD EQU 52H ;Z8536 (CIO) Kanal A Daten
+CIOCD EQU 50H ;Z8536 (CIO) Kanal C Daten
+CIOCTL EQU 53H ;Z8536 (CIO) Control Register
+
+SCSIP EQU 80H ;SCSI I/O Port
+
+;................................................................
+
+; Masken und Bits fuer CIO
+
+MBUSY EQU 08H ;BUSY-Signal von SCSI Schnittstelle
+MMSG EQU 10H ;Message-Signal von SCSI Schnittstelle
+MDC EQU 20H ;Data(0)/Command(1) Sig. von SCSI
+MREQ EQU 80H ;REQ-Signal vom SCSI-Controller
+MIO EQU 04H ;I/O Signal von SCSI (0=Tr. Host -> SCSI)
+MSELS EQU 02H ;Select Signal zum SCSI Interface
+
+BSELS EQU 1 ;Bitnummern
+BIO EQU 2
+BBUSY EQU 3
+BMSG EQU 4
+BDC EQU 5
+BREQ EQU 7
+
+BRESS EQU 3 ;Reset-Signal fuer SCSI Controller
+MRESS EQU 78H ;Maske zum Bit setzen (Bit 3)
+
+PCOMA EQU 8 ;Port A Command and Status
+
+;................................................................
+
+; SCSI-Kommandos
+
+TST_RDY EQU 0 ;Drive Ready pruefen
+RECALIBR EQU 1 ;Drive recalibrieren
+REQ_STAT EQU 3 ;Fehlerstatus holen
+FORMAT EQU 4 ;Diskette oder Harddisk formatieren
+CHK_FORM EQU 5 ;Harddisk Format kontrollieren
+FRM_TRKS EQU 6 ;Spuren formatieren
+SREAD EQU 8 ;Sektoren lesen (1 od. mehrere)
+SVREAD EQU 9 ;Read Verify
+SWRITE EQU 10 ;Sektoren schreiben (")
+SEEK EQU 11 ;Auf Block positionieren
+WBUFFER EQU 15 ;Write Controller Buffer
+INITDRV EQU 17 ;Disk Parameter setzen
+RINIT EQU 18 ;Disk Parameter lesen
+FD48TPI EQU 6*32+4 ;Floppy im Doppelstepmodus betreiben
+FD96TPI EQU 6*32+3 ;Floppy im Singlestepmodus betreiben
+
+FDDRIV EQU 0 ;Floppy Laufwerk Nr.
+
+;................................................................
+
+; Werte fuer SCSIIO-Aufruf
+
+DMATRA EQU 4000H ;Datentransfer per DMA
+;DMATRA EQU 0 ;** TEST **
+RDDAT EQU 8000H ;Lesen vom Controller
+
+;................................................................
+
+; DMA-Controller Werte
+
+ENABDMA EQU 90H ;Enable Kanal 1 DMA (keine Interrupts)
+DISDMA EQU 10H ;Disable Kanal 1 DMA (-> DSTAT)
+DE1 EQU 7 ;Bitnummer in DSTAT
+
+CH1MSK EQU 0F4H ;Nicht fuer Kanal 1 wichtige Bits maskieren
+CHGDIR EQU 2 ;Aenderung der Transferrichtung (-> DCNTL)
+
+;................................................................
+
+; Fehlernummern
+
+WPROTE EQU 13H ; Diskette Schreibgeschuetzt
+TSNF EQU 14H ; Target Sector not found
+
+HARD EQU 0F0H ;Kennung Hardware bzw. Kommandofehler
+
+NOCONT EQU 0 ;SCSI-Controller nicht angeschlossen
+TIMOUT EQU 1 ;Timeout Fehler bei SCSI I/O
+ENDERR EQU 2 ;Falsches Kommandoende
+ILLD EQU 3 ;Falsche Datenrichtung
+EARLYE EQU 4 ;vorzeitiges Kommandoende
+ILLCOM EQU 5 ;Fehler bei Kommandoausgabe
+STRERR EQU 6 ;Fehler beim Status lesen
+DMAERR EQU 7 ;Fehler beim DMA Transfer
+UNKNOWN EQU 8 ;undefinierte Fehlerfaelle
+MULCNT EQU 10 ; Reset nach 10 hardwarefehlern
+
+;----------------------------------------------------------------
+
+; Lokale Daten
+
+ DSEG
+
+SCSIST: DEFS 4 ;4 Byte Stati
+CODALN: DEFW 0 ;Datenlaenge
+SEMA: DEFB 0 ;Zugriffs-Semaphor
+TOFLG: DEFB 0 ;Timeoutflag
+
+ IF DEBUG
+RETRCN: DEFB 4 ;Retry Flag
+HERCNT: DEFB 10 ;Hardwarefehlerzaehler
+ ENDIF
+
+ CSEG
+
+;****************************************************************
+;
+; SCSIIO
+;
+; Elementare Ausgabe auf SCSI-Interface
+;
+; Entry: HL = Zeiger auf Datenbereich (falls vorhanden)
+; DE = Zeiger auf Kommandobereich (immer 6 Byte)
+; BC = Groesse des Datenbereichs (0=nicht vorhanden)
+; B Bit 7: 1 = Lesen vom SCSI-Controller
+; 0 = Schreiben auf SCSI-Controller
+; B Bit 6: 1 = Datentransfer per DMA
+; 0 = Datentransfer per Programm
+;
+; Exit: A = Status (0 = ok, <>0 = Fehlercode)
+; alle anderen Register (ausser AF) unveraendert
+;
+SCSIIO:
+ IF DEBUG
+ LD A,3 ;Retries bei Unknown Error
+ ENDIF
+
+NRETSC:
+ IF DEBUG
+ LD (RETRCN),A
+ ENDIF
+
+ PUSH HL
+ PUSH BC
+ PUSH DE
+
+ CALL SCSI2 ;Kommando ausfuehren
+ LD L,A
+ AND 9FH ;Drive Code ausmaskieren
+ JR Z,EOCOM ;Kein Fehler ->
+
+ CP 2 ;SCSI-Fehler ?
+ LD A,L
+ JR NZ,EOCOM ;Nein -> fertig
+
+ POP HL ;Kommandotab.-Adr.
+ PUSH HL
+ LD A,(HL) ;altes Kommando retten
+ PUSH AF
+ LD A,HARD+STRERR ;Fehler beim Status lesen annehmen
+ LD (SCSIST),A
+ LD (HL),REQ_STAT ;Kommando 3: Request Status
+ EX DE,HL
+ LD BC,4+RDDAT ;4 Byte Status Informationen
+ LD HL,SCSIST ;Statusbereich
+ CALL SCSI2
+ POP AF
+ POP HL
+ LD (HL),A ;altes Kommando zurueckschreiben
+ PUSH HL
+ LD A,(SCSIST)
+ RES 7,A
+ AND A ;Meldung: kein Fehler ?
+ JR NZ,EOCOM
+
+; kein Fehler: falsche Meldung da vorher einer aufgetreten war !!
+
+ LD A,HARD+UNKNOWN ;unbekannnter Fehler melden
+
+EOCOM:
+ POP DE
+ POP BC
+ POP HL
+
+ IF DEBUG
+ CP HARD+ENDERR
+ JR C,RETSCSI
+
+ LD A,(RETRCN)
+ DEC A
+ JR NZ,NRETSC ;Retries bei "Unknown Error"
+
+ LD A,HARD+UNKNOWN
+RETSCSI:
+ PUSH HL
+ LD HL,HERCNT ;Hardware Fehler Zaehler
+ CP HARD ;Hardware Fehler ?
+ JR C,NOHER ;Nein ->
+
+ DEC (HL)
+ JR NZ,EOHER ;nicht mehrere Hardwarefehler hintereinander
+
+ LD (HL),MULCNT
+ PUSH AF
+ PUSH DE
+ PUSH BC
+ CALL INITS1 ;Schnittstelle neu initialisieren
+ POP BC
+ POP DE
+ POP AF
+ JR EOHER
+
+NOHER:
+ LD (HL),MULCNT
+
+EOHER:
+ POP HL
+ ENDIF
+
+ AND A
+ RET
+
+;................................................................
+;
+; SCSI2
+;
+; Kommandoausgabe auf dem SCSI-Interface
+;
+; Entry-Parameter wie SCSIIO
+;
+; Exit: A = 0: alles ok
+; A = 2: Fehler ist aufgetreten
+; A >= F0H: Hardware oder Bedienungsfehler
+;
+SCSI2:
+ PUSH BC ;Laenge retten
+
+; Pruefen ob letzter DMA beendet wurde
+
+ IN0 A,(DSTAT) ;DMA beendet ?
+ BIT DE1,A
+ JR Z,DMAOK ;Ja ->
+
+ LD A,DISDMA ;Reset Kanal 1 DMA
+ OUT0 (DSTAT),A
+
+DMAOK:
+ LD BC,CIOAD ;B=0 !
+ JR TENDLP
+
+; "Bus free", Controller selektieren
+
+BUSYOK:
+ IN A,(C)
+ SET BSELS,A ;Select Leitung aktivieren
+ OUT (C),A
+ RES BSELS,A ;und wieder zuruecknehmen
+ OUT (C),A
+
+; "Command Phase"
+
+ XOR A
+
+WAIREQ:
+ PUSH AF ;Auf Kommandoanforderung warten
+ IN A,(C)
+ AND MDC+MREQ+MIO+MMSG
+ CP MDC+MREQ
+ JR Z,RDYCOM ;Ok ->
+
+ POP AF
+ DEC A
+ JR NZ,WAIREQ
+
+; keine Reaktion der Schnittstelle: Versuchen Restbytes einzulesen falls
+; dies nicht der 2. Timeout ist.
+
+ LD A,(TOFLG) ;Timeoutflag gesetzt ?
+ AND A
+ LD A,HARD+TIMOUT ;Timeout Fehler
+ JP NZ,POPRET ;bereits gesetzt ->
+
+ LD (TOFLG),A ;Timeoutflag setzen
+
+; ggf. letztes Kommando abschliessen
+
+TENDLP:
+ IN0 A,(CIOAD) ;"Bus free" ?
+ BIT BBUSY,A
+ JR Z,BUSYOK ;Ja -> neu selektieren
+
+ CALL CHKREQ
+ BIT BIO,A
+ JR NZ,INPU
+
+ XOR A
+ OUT0 (SCSIP),A
+ JR TENDLP
+
+INPU:
+ IN0 A,(SCSIP)
+ JR TENDLP
+
+ILLMOD:
+ LD A,HARD+ILLCOM ;Fehler bei Kommandoausgabe
+ JP POPRET
+
+; Kommando Ausgabe
+
+RDYCOM:
+ POP AF ;Clear Stack
+ LD BC,SCSIP+6*256 ;6 Bytes ausgeben
+ EX DE,HL
+
+CMNON:
+ CALL CHKREQ
+ CP MDC
+ JR NZ,ILLMOD ;keine Kommandoausgabe -> Fehler
+
+ DI
+ OTIM ;Kommando ausgeben
+ EI
+ JR NZ,CMNON ;Nicht fertig ->
+
+; "Data Phase"
+
+ POP HL ;B=0!
+ PUSH HL
+ LD A,H ;Datenlaenge = 0 ?
+ AND 3FH ;Bit 6 und 7 ausblenden
+ OR L
+ JP Z,NODAT ;Ja -> keine Datenphase
+
+ IF NOT DMA
+
+ BIT 6,H ;Datentransfer per DMA ?
+ JR Z,DTAPROG ;Nein -> per Programm
+
+ ENDIF
+
+; CIO Pattern Match Logik aktivieren
+
+ DI
+ LD C,CIOCTL ;CIO Control Register
+ LD A,PCOMA ;Port A Command Register
+ OUT (C),A
+ LD A,20H ;Clear IP & IUS
+ OUT (C),A
+ EI
+
+;* IF DMA AND EUMEL
+
+;* BIT 7,H ;schreiben ?
+;* JR Z,POLWRIT
+
+;* ENDIF
+
+; DMA-Kanal 1 initialisieren (I/O Adresse wird in SCINIT gesetzt)
+
+ CALL DMASTUP ;DMA-Adressen eintragen
+
+;* IF NOT EUMEL
+
+ BIT 7,H ;lesen ?
+ JR Z,ISWRITE ;Nein ->
+
+;* ENDIF
+
+ OR CHGDIR ;Richtung aendern (I/O -> Memory)
+
+ISWRITE:
+ OUT0 (DCNTL),A
+ LD A,ENABDMA ;DMA aktivieren
+ OUT0 (DSTAT),A
+
+; Auf Kommandoende warten
+; Die CIO ist so initialisiert dass der SCSI-Status "Status lesen"
+; einen Pattern Match Zustand erzeugt
+
+WEND2:
+ LD C,CIOCTL ;auf Pattern Match warten
+
+WAIEND:
+
+ IN0 L,(DSTAT) ;DMA Status pruefen
+ DI
+ LD A,PCOMA ;Port A Command Register
+ OUT (C),A
+ IN A,(C) ;CIO Status lesen (Port A Statusregister)
+ BIT 5,A ;Interrupt pending ?
+ JR NZ,DATRDY ;Ja -> Datentransfer beendet
+
+ EI
+ IN0 A,(CIOAD)
+ BIT BBUSY,A ;steht Busy noch an ?
+ JR Z,ILLEND
+
+ BIT DE1,L ;DMA beendet ?
+ JR Z,DMAEND
+
+NOEND:
+ IF EUMEL
+ CALL WARTE ;andere Tasks zulassen
+ ENDIF
+
+ JR WAIEND
+
+; Pruefen ob ein DMA-Fehler aufgetreten ist
+
+DMAEND:
+ IN0 A,(CIOAD)
+
+ BIT BREQ,A ;Anforderung ?
+ JR Z,NOEND ;Nein -> warten
+
+ AND MDC+MIO+MMSG
+ CP MDC+MIO ;Statusanforderung ?
+ JR Z,CMNST ;Ja -> alles in Ordnung
+
+; Fehler beim DMA-Transfer
+
+ LD L,HARD+DMAERR
+ JR WENDLP
+
+DATRDY:
+ IN A,(C) ;Pattern match testen
+ EI
+ BIT 1,A
+ JR Z,ENDKL ;Nein -> DMA hat Status geklaut
+
+CMNST:
+
+ IN0 L,(SCSIP) ;Status holen
+
+; Letztes Statusbyte holen (Kommandoende)
+
+ CALL CHKREQ
+ IN0 H,(SCSIP) ;letzten Status einlesen (Dummy Read)
+ CP MDC+MIO+MMSG ;wirklich letzter Status ?
+ JR Z,ENDOK ;Ja ->
+
+ILLEND:
+ LD L,HARD+ENDERR
+
+ENDOK:
+ LD A,L ;Status in A
+
+POPRET:
+ POP BC
+
+; Interrupt Daisy Chain der CIO freigeben
+
+ DI
+ LD L,PCOMA ;Port A Command
+ OUT0 (CIOCTL),L
+ LD L,20H ;Clear IP & IUS
+ OUT0 (CIOCTL),L
+ EI
+ RET
+
+ENDKL:
+
+; DMA anhalten falls dieser nicht beendet wurde
+
+ LD L,DISDMA ;Reset Kanal 1 DMA
+ OUT0 (DSTAT),L
+ LD L,2 ;Error Status
+
+WENDLP:
+ IN0 A,(CIOAD) ;"Bus free" ?
+ BIT BBUSY,A
+ JR Z,ENDOK ;Ja -> fertig
+
+ CALL CHKREQ
+ BIT BIO,A
+ JR NZ,INPU2
+
+ XOR A
+ OUT0 (SCSIP),A
+ JR WENDLP
+
+INPU2:
+ IN0 A,(SCSIP) ;Dummy Read
+ JR WENDLP
+
+ IF NOT DMA
+
+; Datentransfer bei Schreiben per Programm
+
+POLWRIT:
+ CALL CHKREQ
+ JR NZ,NODAT ;Kein Datentransfer -> Fehler
+
+ BIT BIO,A ;Lesen von SCSI ?
+ JR NZ,DIRERR ;Ja -> falsche Richtung
+
+ LD A,(DE) ;Daten holen
+ OUT0 (SCSIP),A ;und ausgeben
+
+ INC DE ;Datenadresse inkrementieren
+ DEC HL ;Datenlaenge dekrementieren
+ LD A,H ;Fertig ?
+ AND 3FH
+ OR L
+ JR NZ,POLWRIT ;Nein -> naechstes Byte holen
+
+ JP WEND2
+
+; Falsche Datenrichtung (falsches Kommando)
+
+DIRERR:
+ LD A,HARD+ILLD
+ JR POPRET
+
+; Datentransfer per Programm
+
+DTAPROG:
+ CALL CHKREQ
+ JR NZ,NODAT ;Kein Datentransfer -> Fehler
+
+ BIT BIO,A ;Lesen von SCSI ?
+ JR NZ,RDSCSI ;Ja ->
+
+ BIT 7,H ;Schreiben definiert ?
+ JR NZ,DIRERR ;Nein -> falsche Richtung !!
+
+ LD A,(DE) ;Daten holen
+ OUT0 (SCSIP),A ;und ausgeben
+
+ JR CMDIO
+
+RDSCSI:
+ BIT 7,H ;Lesen definiert ?
+ JR NZ,RDSOK ;Ja ->
+
+; Falsche Datenrichtung (falsches Kommando)
+
+DIRERR:
+ LD A,HARD+ILLD
+ JR POPRET
+
+RDSOK:
+ IN0 A,(SCSIP) ;Daten holen
+ LD (DE),A
+
+CMDIO:
+ INC DE ;Datenadresse inkrementieren
+ DEC HL ;Datenlaenge dekrementieren
+ LD A,H ;Fertig ?
+ AND 3FH
+ OR L
+ JR NZ,DTAPROG ;Nein -> naechstes Byte holen
+
+ ENDIF
+
+; Status lesen
+
+NODAT:
+ CALL CHKREQ
+ CP MDC+MIO ;Status Anforderung ?
+ JR NZ,ILLEND ;Nein -> Fehler
+ JR CMNST
+
+;................................................................
+;
+; Pruefen ob Busy und Request anstehen
+;
+; Exit: A = CIO Port A SCSI-Status Leitungen (ohne BUSY und REQ)
+; F = Z: Datentransfer
+;
+CHKREQ:
+ IN0 A,(CIOAD)
+ BIT BBUSY,A ;Busy aktiv ?
+ JR Z,INCOMPL ;Nein -> vorzeitiges Kommandoende
+
+ BIT BREQ,A ;Anforderung ?
+ JR Z,CHKREQ ;Nein -> warten
+
+ AND MDC+MIO+MMSG
+ BIT BDC,A
+ RET
+
+INCOMPL:
+ POP HL ;Skip Return Adresse
+ LD A,HARD+EARLYE ;vorzeitiges Ende
+ JR POPRET
+
+;................................................................
+;
+; DMASTUP
+;
+; Adressen des DMA-Kanals 1 eintragen
+;
+; Entry: DE = log. Adresse
+; DE = 0: auf 6502 Bereich FC00 schalten
+;
+; Exit: A = (DCNTL) Kanal 1
+;
+DMASTUP:
+ DI
+ LD A,D
+ OR E
+ JR NZ,DOCHG
+
+ LD A,6
+ LD D,0FDH ; 6FD00..6FEFF ist SCSI-Puffer
+ JR NOCHG
+
+DOCHG:
+ CALL PHYSADR ;Physikalische Adresse bestimmen (in ADE)
+
+NOCHG:
+ LD C,MAR1L ;Adressen eintragen
+ OUT (C),E ;Speicheradresse eintragen (LSB)
+ INC C
+ OUT (C),D ;mittleres Byte
+ INC C
+ OUT (C),A ;upper Byte
+ LD C,BCR1L
+ OUT (C),L ;Byte Zaehler (LSB)
+ INC C
+ LD A,H
+ AND 3FH
+ OUT (C),A ;MSB
+
+ IN0 A,(DCNTL) ;DMA-Richtung setzen
+ AND CH1MSK ;nur DMA-Kanal 1 Bits veraendern !
+ EI
+ RET
+
+;................................................................
+;
+; P H Y S A D R
+;
+; Umrechnung der logischen in eine physikalische Adresse
+;
+; Entry: DE = logische Adresse im 64K Adressraum
+;
+; Exit: DE = niederwertiger Teil der phys. Adr. im 512K Adr.-raum
+; A = hoechstwertiges Nibble der phys. Adr.
+; alle anderen Register bleiben unveraendert
+;
+PHYSADR:
+ INC D ;Fuer Vergleiche
+ IN0 A,(CBAR) ;Common Bank Area Register
+ PUSH AF
+ AND 0F0H ;Common Area Teil ausmaskieren
+ CP D ;D >= Common Area 1 Anfang ?
+ JR C,COMA1 ;Ja -> (Stack!!)
+
+ POP AF
+ AND 0FH ;Bank Area Teil ausmaskieren
+ RLCA
+ RLCA
+ RLCA
+ RLCA ;und ins MSN schieben
+ CP D ;D >= Bank Area Anfang ?
+ JR C,BAR ;Ja ->
+
+; Common Area 0 (unveraenderte Adresse)
+
+ DEC D ;D wieder korrigieren
+ XOR A
+ RET
+
+; Bank Area
+
+BAR:
+ DEC D
+ IN0 A,(BBR) ;Bank Base Register
+
+CMND:
+ PUSH BC
+ LD B,0
+ SLA A
+ RL B
+ SLA A
+ RL B
+ SLA A
+ RL B
+ SLA A
+ RL B ;B = MSN Phys. Adr., A = mittleres MSB
+
+ ADD A,D ;+ Offset zum Area Anfang
+ LD D,A ;wieder in D (mittleres MSB der phys. Adr.)
+ LD A,B ;A = MSN
+ ADC A,0 ;ggf. 64K-Uebertrag beruecksichtigen
+ POP BC
+ RET
+
+; Common Area 1
+
+COMA1:
+ DEC D ;D wieder korrigieren
+ POP AF ;Clear Stack
+ IN0 A,(CBR)
+ JR CMND
+
+ IF EUMEL
+
+;................................................................
+;
+; C H K A C C
+;
+; Auf Freiwerden des SCSI-Controllers warten
+;
+CHKACC:
+ LD A,(SEMA) ;SCSI-Zugriffssemaphor
+ AND A ;0=frei
+ JR Z,ISFREE ;Ja ->
+ CALL WARTE
+ JR CHKACC
+
+ISFREE:
+ DEC A
+ LD (SEMA),A ;Semaphor sperren
+ RET
+
+ ENDIF
+
+;................................................................
+;
+; I N I T S
+;
+; Initialisierung der SCSI-Schnittstelle
+;
+; CIO und DMA Kanal 1 werden initialisiert
+; Floppy Parameter werden gesetzt
+;
+; Exit: AF', BC, DE und HL werden veraendert
+; AF = Status des Floppy Parameters setzens
+;
+INITS1:
+ IF NOT EUMEL
+ CALL INICIO
+ ENDIF
+
+INITS:
+ IF EUMEL
+ XOR A
+ LD (SEMA),A ;Semaphor initialisieren
+ ENDIF
+
+ LD C,DISDMA
+ OUT0 (DSTAT),C ;Kanal 1 stoppen, beide Kanaele keine
+ ; Interrupts zulassen
+
+; DMA - Kanal 0 intialisieren (Memory <--> Memory Transfer)
+
+ LD C,2 ; Memory <--> Memory im Burst Mode
+ OUT0 (DMODE),C
+
+; DMA - Kanal 1 initialisieren (Memory <--> SCSI I/O - Transfer)
+
+ LD BC,SCSIP ;DMA-Kanal 1 I/O Adresse auf SCSI setzen
+ OUT0 (IAR1L),C
+ OUT0 (IAR1H),B
+
+; Warten bis Harddisk hochgelaufen ist
+
+ IF NOT EUMEL
+WRTHRD:
+ LD DE,TESTRD
+ LD BC,0
+ CALL SCSIIO
+ AND A ;Drive not Ready ?
+ JR NZ,WRTHRD ;Ja -> warten
+
+ ENDIF
+
+; Teil der bei Controller RESET neu initialisert werden muss
+
+SCINIT:
+
+; Floppy Parameter setzen
+
+ LD DE,FLPINI ;Initialize Kommando
+ LD HL,FLPDAT ;Parameter
+ LD BC,PARALNG ;Anzahl der Parameter Bytes
+ CALL SCSIIO
+
+ LD L,A
+ LD A,(FLPTRKS)
+ CP 40 ;40 Tracks ?
+ LD A,L
+ LD BC,0
+ LD DE,SGLSTEP ; Floppy im Doppelstep Modus
+ JR NZ,NODBLS ;Nein -> kein Double Step
+ LD DE,DBLSTEP
+NODBLS:
+ JP SCSIIO
+
+;................................................................
+;
+; I N I C I O
+;
+ IF NOT EUMEL
+INICIO:
+ DI
+
+; CIO initialisieren
+
+ IN0 C,(CIOCTL) ;Dummy Read
+ LD B,INILNG
+ LD HL,INITAB ;CIO Initialisierungstabelle
+
+INILOP:
+ LD C,(HL) ;Wert holen
+ OUT0 (CIOCTL),C ;und ausgeben
+ INC HL
+ DJNZ INILOP
+ RET
+ ENDIF
+
+;................................................................
+;
+; P A R K H D
+;
+; Harddisk in Parkposition fahren
+;
+PARKHD:
+
+ LD BC,0
+ LD DE,PARSEK ; seek (0)
+ CALL SCSIIO
+ LD DE,RECAL ; Recalibrate
+ JP SCSIIO
+
+ IF 0
+ LD HL,INIHDT
+ LD DE,RDINI
+ LD BC,RDDAT+PARALNG
+
+ CALL SCSIIO ;Harddisk Konfiguration lesen
+
+ LD HL,(INIHDT) ;Spuranzahl (H=LSB!)
+ PUSH HL
+ INC H ;um 1 erhoehen
+ JR NZ,INCOK
+
+ INC L
+INCOK:
+ LD (INIHDT),HL
+ LD HL,RDINI
+ LD DE,INIHDT
+ LD (HL),INITDRV ;Init-Schreibkommando eintragen
+ EX DE,HL
+ LD BC,PARALNG
+
+ CALL SCSIIO ;neue, groessere, Konfiguration setzen
+
+ POP HL
+
+ LD D,L
+ LD L,H
+ LD H,D ;Spuranzahl richtig
+ LD A,(INIHDT+2) ;Kopfanzahl
+ LD E,L
+
+HDLOP:
+ DEC A
+ JR Z,HDAOK
+
+ ADD HL,DE
+ JR HDLOP
+
+HDAOK:
+ XOR A
+ ADC HL,HL
+ RLCA
+ ADC HL,HL ;*4
+ RLCA
+ ADC HL,HL ;*8
+ RLCA
+ ADC HL,HL ;*16
+ RLCA
+ ADC HL,HL ;*32
+ RLCA
+
+; max. Blocknr. in AHL
+
+ DEC HL ;-1: 1.Block hinter formatiertem Bereich
+
+ LD (BKNR),A
+ LD A,L
+ LD L,H
+ LD H,A
+
+ LD (BKNR+1),HL ;Blocknr. eintragen
+ LD BC,0 ;keine Daten
+ LD DE,PARSEK
+
+ JP SCSIIO ;Drive parken
+
+ ENDIF
+
+;................................................................
+;
+; H D I O
+;
+; Lesen / Schreiben eines Blocks (512 Byte) auf der Harddisk
+;
+; Entry: A = Kommandocode (0 = Lesen, 1 = Schreiben)
+; HL = Hauptspeicheradresse
+; BC = Pointer auf Drive und Offset (256 Byte Bloecke)
+; DE = (512 Byte-) Blocknummer (ohne Offset)
+;
+; BC + 2 -> Low (Block Offset)
+; BC + 1 -> Middle (Block Offset)
+; BC + 0 -> High (BLock Offset) + Drive * 32
+;
+; Exit: A = Status (0=ok, sonst SCSIIO-Fehlercode)
+; BC, DE, HL, AF' = veraendert
+;
+FDIO:
+HDIO:
+ PUSH AF
+ XOR A
+ LD (TOFLG),A ;Timeoutflag ruecksetzen
+
+ IF EUMEL
+
+ CALL CHKACC ;Pruefen ob SCSI-Controller bereits belegt ist
+
+ ENDIF
+
+ LD A,(BC)
+ BIT 6,A ;Floppy Drive ?
+ JP NZ,FDIO1 ;Ja ->
+
+ POP AF
+
+ CP 2
+ JR C,COMOK1
+
+ LD A,20H ;illegal Command Code
+ RET
+
+COMOK1:
+ PUSH HL
+ PUSH BC
+ CALL CMSCOM ;Kommandonr. umrechnen
+ LD (HDIOTB),A ;Kommando eintragen
+ POP BC
+ LD HL,(CODALN) ;Datenlaenge
+ PUSH HL
+ LD HL,HDIOTB+3 ;Harddisk Read Command
+
+ SLA E ;Blocknummer * 2 (256 Byte Bloecke)
+ RL D
+
+CMFDIO:
+ INC BC
+ INC BC
+ LD A,(BC) ;Low Offset
+ ADD A,E ;+ Low Block No.
+ LD (HL),A ;eintragen
+ DEC HL
+ DEC BC
+ LD A,(BC) ;Middle Offset
+ ADC A,D ;+ Block No.
+ LD (HL),A
+ DEC HL
+ DEC BC
+ LD A,(BC)
+ LD (HL),A ;Drive + High Blocknr.
+ DEC HL
+ EX DE,HL ;DE = Read Command Adresse
+ POP BC ;Datenlaenge
+ POP HL ;Hauptspeicheradresse
+ CALL SCSIIO
+
+ IF EUMEL
+
+ PUSH AF
+ XOR A
+ LD (SEMA),A ;Semaphor freigeben
+ POP AF
+
+ ENDIF
+
+ RET
+
+;................................................................
+;
+; I N I F L P
+;
+; Blockanzahl der Floppy ermitteln (nur BC, A und HL veraendern !!)
+;
+; Eingang:A = Anzahl Spuren, Voreinstellung (40 oder 80)
+; Exit: BC = Blockanzahl der Floppy (in 512 Byte Bloecken)
+; A = 0 = ok, <> 0 = SCSI-Fehlercode
+;
+INIFLP:
+ PUSH AF ; Anzahl Spuren Voreinstellung (40, 80)
+
+ IF EUMEL
+ CALL CHKACC ;keine Doppelzugriffe !!
+ ENDIF
+
+ XOR A
+ LD (TOFLG),A ;Timeoutflag ruecksetzen
+ POP AF
+
+ PUSH HL
+ PUSH DE
+
+ LD (FLPTRKS),A ;Spuren eintragen
+ CALL SCINIT ;Floppy Parameter setzen
+
+ LD A,2 ;Retry-Anzahl
+RETR1:
+ PUSH AF
+
+ LD DE,SEK18 ; Auf Block 18 (Track 2)
+ LD BC,RDDAT+512
+ LD HL,0
+ LD A,1
+ CALL NRETSC ;Read ohne Retries
+
+ AND 7FH
+ LD C,A
+ JR Z,OKA ; Format ok
+
+ CP TSNF ; Target Sector not found ?
+ CALL Z,TOB ; anderes Format (B) versuchen
+
+ POP AF ; Anderer Floppy Fehler, Retries
+ DEC A
+ JR NZ,RETR1
+
+ XOR A
+ LD (SEMA),A
+
+ LD A,C ; permanenter Fehler
+
+ LD BC,0
+ POP DE
+ POP HL
+ RET
+
+; auf B Spuren umschalten
+
+TOB:
+ LD A,(FLPTRKS)
+ XOR 01111000B ; aus 40 wird 80, aus 80 wird 40
+ LD (FLPTRKS),A
+ CALL SCINIT ;Floppy Parameter setzen
+ LD C,TSNF
+ RET
+
+OKA:
+ POP AF
+ POP DE
+ POP HL
+
+ LD BC,(FLPTRKS)
+
+ IF SEC8
+ LD B,8
+ ELSE
+ LD B,9
+ ENDIF
+
+ MLT BC
+ SLA C ;*2: 2 Seiten
+ RL B
+ XOR A
+
+ IF EUMEL
+ LD (SEMA),A ;Sempahor wieder freigeben
+ ENDIF
+
+ RET
+
+;................................................................
+;
+; F D I O
+;
+; Lesen oder Schreiben eines Blocks (512 Byte) auf der Floppy Disk
+;
+; Entry: A = Kommandocode (0=Lesen, 1=Schreiben, 2=Formatieren)
+; HL = Hauptspeicheradresse
+; BC = Pointer auf Drive und Offset (512 Byte Bloecke)
+; DE = (512 Byte-) Blocknummer (ohne Offset)
+;
+; BC + 2 -> Low (Block Offset)
+; BC + 1 -> Middle (Block Offset)
+; BC + 0 -> High (BLock Offset) + Drive * 32
+;
+; Exit: A = Status (0=ok, sonst SCSIIO-Fehlercode)
+; BC, DE, HL, AF' = veraendert
+;
+FDIO1:
+ POP AF
+ CP 3
+ JR C,COMOK
+
+ LD A,20H ;illegal Command Code
+ RET
+
+COMOK:
+ PUSH HL
+ PUSH BC
+ CP 2
+
+ CALL Z,SW80 ;Beim Formatieren immer 2x80 Spuren
+
+ CALL CMSCOM ;Kommando und Datenlaenge best.
+ LD (FDIOTB),A ;Kommandocode eintragen
+
+ LD A,C
+ LD (FDIOTB+4),A ;Block Count / Skew Faktor eintragen
+
+; DE enthaelt Blocknummer x aus EUMEL-Sicht.
+; Block x meint die 512 Bytes ab 512*x auf Floppy.
+;
+; Aus Blocknummer: Spur, Sector, Seite berechnen
+;
+; EUMEL behandelt, im Gegensatz zum SCSI-Controller,
+; zunaechst die Oberseite der Floppy und erst dann die Unterseite.
+
+ LD H,D
+ LD L,E
+ XOR A
+
+ IF SEC8
+ LD DE,8
+ ELSE
+ LD DE,9 ;Anzahl der Sektoren pro Spur
+ ENDIF
+
+DIVLOP:
+ AND A
+ SBC HL,DE
+ JR C,DIVDON
+ INC A
+ JR DIVLOP
+
+DIVDON:
+ ADD HL,DE
+
+; A = Spurnummer; HL = sector/seite
+
+ LD BC,(FLPTRKS) ;Spuren pro Seite (B undefiniert !)
+ CP C ;Rueckseite ?
+ JR C,NOBACK ;Nein -> alles ok
+
+; Rueckseite: Spurnummer := Spurnummer - Spuranzahl
+; Sektornummer := Sektornummer + Sektoranzahl (9)
+
+ SUB C ;tatsaechliche Spurnummer
+ ADD HL,DE ;HL = sector (cylinder)
+
+; SCSI Blocknummer aus Spur und Sektor ausrechnen
+
+NOBACK:
+ LD D,A
+
+ IF SEC8
+ LD E,16
+ ELSE
+ LD E,18
+ ENDIF
+
+ MLT DE ;DE = Spur * 18
+ ADD HL,DE ;HL = Spur * 18 + Sektor (cylinder)
+ EX DE,HL
+
+; SCSI Blocknummer in DE
+
+ POP BC ;Offsetadresse wiederherstellen
+
+ LD HL,(CODALN)
+ PUSH HL
+ LD HL,FDIOTB+3 ;Floppy Read Command
+ JP CMFDIO
+
+SW80:
+ PUSH AF
+ PUSH BC
+ PUSH DE
+ PUSH HL
+
+ LD A,80 ; 80 Tracks
+ LD (FLPTRKS),A
+ CALL SCINIT
+
+ POP HL
+ POP DE
+ POP BC
+ POP AF
+ RET
+
+;................................................................
+;
+; C M S C O M
+;
+; Entry: A = Funktionsnr.
+;
+; Exit: A = SCSI-Kommandonr.
+; C = Block Count / Skew Faktor
+; HL = veraendert
+; B = veraendert
+; (CODALN) = Datenlaenge
+;
+CMSCOM:
+ LD BC,LGTAB ;Datenlaenge ermitteln
+ LD L,A
+ LD H,0
+ ADD HL,HL ;16 Bit Werte
+ ADD HL,BC
+ LD C,(HL)
+ INC HL
+ LD B,(HL)
+ LD (CODALN),BC
+
+ LD HL,COMTB ;Kommandonr. umrechnen
+ ADD A,L
+ LD L,A
+ LD A,H
+ ADC A,0
+ LD H,A
+ LD A,(HL) ;SCSI-Kommando holen
+
+ LD BC,BCSKTB-COMTB
+ ADD HL,BC
+ LD C,(HL) ;Block Count ./. Skew Faktor holen
+
+ RET
+
+;****************************************************************
+;
+; SCSI-Kommandotabellen
+;
+; Achtung: Die Schreib- und Lesetabellen werden vom Programm
+; geaendert (muessen im RAM stehen)
+;
+COMTB:
+ DEFB SREAD ;Lesekommando
+ DEFB SWRITE ;Schreibkommando
+ DEFB FORMAT ;Formatierkommando
+
+LGTAB:
+ DEFW 512+DMATRA+RDDAT ;Datenlaenge Lesen
+ DEFW 512+DMATRA ;Datenlaenge schreiben
+ DEFW 0 ;Datenlaenge formatieren
+
+BCSKTB:
+ DEFB 1 ;1 Block lesen (nur Floppy)
+ DEFB 1 ;1 Block schreiben (")
+ DEFB 4 ;Skew 4 (nur Floppy)
+
+;................................................................
+;
+ IF NOT EUMEL
+TESTRD:
+ DEFB 0,0,0,0,0,0 ;Test Ready (Harddisk)
+ ENDIF
+
+
+FDIOTB: ;Lesen / Schreiben auf Floppy Disk
+ DEFB SREAD ;Lesekommando (wird ueberschrieben)
+ DEFB FDDRIV*32+40H ;Floppy Drive (wird ueberschrieben)
+ DEFB 0, 0 ;Block Middle und Low (")
+ DEFB 1 ;Block Count / Interleave (Format)
+ DEFB 80H ;keine Retries
+
+
+HDIOTB: ;Lesen / Schreiben auf Harddisk
+ DEFB SREAD ;Lesekommando (wird ueberschrieben)
+ DEFB 0 ;Harddisk Drive (wird ueberschrieben)
+ DEFB 0, 0 ;Block Middle und Low (")
+ DEFB 2 ;Block Count
+ DEFB 0H ;Retries
+
+ IF 0
+RDINI:
+ DEFB RINIT ;Harddisk Konfiguration lesen
+ DEFB 0 ;Harddisk Drive
+ DEFB 0,0,0,0
+INIHDT:
+ DEFB 0,0,0,0,0
+ DEFB 0,0,0,0,0
+ ENDIF
+
+
+RECAL:
+ DEFB RECALIBR ;Drive recalibrieren
+ DEFB 0 ; Harddisk
+ DEFB 0,0,0,80H ; keine Retries
+
+
+PARSEK:
+ DEFB SEEK
+ DEFB 0 ;Harddisk
+ DEFB 0,0,0
+ DEFB 80H ;keine Retries
+
+
+FLPINI: ;Setze Floppy Parameter
+ DEFB INITDRV ;Initialize Kommando
+ DEFB FDDRIV*32+40H ;Floppy Drive
+ DEFB 0, 0, 0, 0 ;nicht benutzt
+FLPDAT: ;Floppy Disk Parameter zu INIFLP
+ DEFB 0
+FLPTRKS:
+ IF TRK40
+ DEFB 40 ;Spuranzahl
+ ELSE
+ DEFB 80
+ ENDIF
+
+ DEFB 2 ;2 Koepfe (doppelseitig)
+ DEFB 1*16+3 ;4 ms Steprate, MFM
+ DEFB 3 ;512 Byte/Sektor
+ DEFB 15 ;Head Unload Time (240ms)
+ DEFB 10 ;Motor Start Time (0.1 s)
+ DEFB 23 ;Head Load Time (46 ms)
+ DEFB 3 ;Motor off time (3 s)
+ IF SEC8
+ DEFB 0 ;8 Sektoren/Spur
+ ELSE
+ DEFB 1 ;9 Sektoren/Spur
+ ENDIF
+
+PARALNG EQU $-FLPDAT
+
+
+DBLSTEP:
+ DEFB FD48TPI ;Doppel Step aktivieren
+ DEFB FDDRIV*32+40H ;Floppy Drive
+ DEFB 0, 0, 0, 0 ;nicht benutzt
+
+
+SGLSTEP:
+ DEFB FD96TPI ;auf Single Step zurueckschalten
+ DEFB FDDRIV*32+40H
+ DEFB 0, 0, 0, 0 ;nicht benutzt
+
+
+SEK18:
+ DEFB SREAD ;auf Block positionieren
+ DEFB FDDRIV*32+40H ;Floppy Drive
+ DEFB 0,18,1,80H ;Track 2, ein Block, keine Retries
+
+
+;...........................................................................
+;
+; CIO Initialisierungs Tabelle
+;
+
+ IF NOT EUMEL
+
+INITAB:
+;* DEFB 0,1 ;Set Reset Bit
+ DEFB 0,0 ;Reset Reset Bit
+ DEFB 1,0 ;Master configuration control
+
+; SCSI-Interface-Leitungen
+
+ DEFB 20H,00000010B ;Port A Mode Reg.
+ DEFB 22H,01000010B ;Port A Data Path Polarity Reg.
+ DEFB 23H,10111101B ;Port A Data Direction Reg.
+ DEFB 24H,0 ;Port A Special I/O Control
+ DEFB 25H,10101100B ;Port A Pattern Polarity
+ DEFB 26H,0 ;Port A Pattern Transition
+ DEFB 27H,10101100B ;Port A Pattern Mask
+ DEFB 0DH,0 ;Port A Data
+ DEFB 02H,18H ;Port A Interrupt Vector (** TEST **)
+ DEFB PCOMA,11100000B ;Port A Command: Clear IE
+ DEFB PCOMA,00100000B ;Port A Command: Clear IUS & IP
+
+; General Purpose Port (Centronics, SCSI, 6502-IRQ-Maske)
+
+ DEFB 06H,00000001B ;Port C Data Direction Reg.
+ DEFB 05H,00001000B ;Port C Data Path Polarity Reg.
+ DEFB 07H,0 ;Port C Special I/O Control
+ DEFB 0FH,4 ;Port C Data Register
+
+; Centronics Interface
+
+ DEFB 28H,10010000B ;Port B Mode
+ DEFB 29H,01000000B ;Port B Handshake: Strobed
+ DEFB 09H,00100000B ;Port B Command: Clear IUS & IP
+ DEFB 2AH,0 ;Port B Data Path Polarity
+ DEFB 2CH,0 ;Port B Special I/O Control
+ DEFB 03H,30H ;Port B Interrupt Vektor
+
+; Deskew Timer
+
+ IF 0
+ DEFB 1EH,00000010B ;Counter 3 Mode Specification
+ DEFB 0CH,00100000B ;Counter 3 Command and Status
+ DEFB 1AH,0 ;Counter 3 Time Constant MSB
+ DEFB 1BH,7 ;Counter 3 Time Constant LSB (2,268 us)
+ DEFB 0CH,11100100B ;Counter 3 Gate Enable
+ ENDIF
+
+; Timer
+
+ DEFB 1CH,10000000B ;Counter/Timer 1 Mode Spec. Reg.
+ DEFB 1DH,10000000B ;Counter/Timer 2 Mode Spec. Reg.
+ DEFB 0AH,00100000B ;Counter/Timer 1 Command: Clear IP & IUS
+ DEFB 0BH,00100000B ;Counter/Timer 2 Command: Clear IP & IUS
+ DEFB 16H,HIGH 38400 ;Time Constant 1 MSB
+ DEFB 17H,LOW 38400 ;Time Constant 1 LSB
+ DEFB 18H,0 ;Time Constant 2 MSB, mit Timer 1 zus. 50ms
+ DEFB 19H,4 ;Time Constant 2 LSB
+ DEFB 04H,18H ;Interrupt Vector Counters
+
+; CIO-Interrupts freigeben
+
+ DEFB 01H,11110111B ;Master Config. Register
+ DEFB 00H,10000010B ;Master Interrupt Enable
+
+ DEFB 09H,11000000B ;Port B Command: Set IE
+
+ DEFB 0BH,11000110B ;Counter/Timer 2 Command: Set IE
+ DEFB 0AH,11100110B ;Counter/Timer 1 Command: Clear IE
+
+INILNG EQU $-INITAB
+ ENDIF
+
+
+;****************************************************************
+
+ END
+ \ No newline at end of file