aboutsummaryrefslogtreecommitdiffstats
path: root/tests/t_secdrive/wd1002xt.inc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/t_secdrive/wd1002xt.inc')
-rw-r--r--tests/t_secdrive/wd1002xt.inc773
1 files changed, 773 insertions, 0 deletions
diff --git a/tests/t_secdrive/wd1002xt.inc b/tests/t_secdrive/wd1002xt.inc
new file mode 100644
index 0000000..7dd1268
--- /dev/null
+++ b/tests/t_secdrive/wd1002xt.inc
@@ -0,0 +1,773 @@
+;******************************************************************************
+;* *
+;* Includedatei fr SECMAIN.ASM *
+;* liefert low-level-Routinen fr SecMain *
+;* Version hier fr WD1002XT-kompatible Kontroller: *
+;* MFM, RLL (?) *
+;* *
+;* Historie: 28.12.1994 *
+;* 26. 3.1994 Formatierroutinen *
+;* 8. 4.1994 defekte Spuren markieren *
+;* *
+;******************************************************************************
+
+ section wd1002xt
+
+;------------------------------------------------------------------------------
+; Portadressen
+
+Port_Base equ 320h ; prim„re Basisadresse
+Port_Data equ Port_Base+0 ; Datenregister (R+W)
+Port_Status equ Port_Base+1 ; Statusregister (R)
+Port_Reset equ Port_Base+1 ; Reset ausl”sen (W)
+Port_Config equ Port_Base+2 ; Jumper auslesen (R)
+Port_Select equ Port_Base+2 ; Kontroller selektieren (W)
+Port_IRQDRQ equ Port_Base+3 ; IRQ/DRQ-Leitungen freigeben (W)
+
+;------------------------------------------------------------------------------
+; Kommandocodes
+
+Cmd_Diagnose equ 0e4h ; Kommando: Kontroller-Selbsttest
+Cmd_GetStatus equ 003h ; Status letzter Operation lesen
+Cmd_TestReady equ 000h ; Test, ob Laufwerk bereit
+Cmd_Restore equ 001h ; Laufwerk rekalibrieren
+Cmd_SetParams equ 00ch ; Laufwerksparameter setzen
+Cmd_Seek equ 00bh ; Spur anfahren
+Cmd_Read equ 008h ; Sektoren lesen
+Cmd_Write equ 00ah ; Sektoren schreiben
+Cmd_Verify equ 005h ; Sektoren auf Lesbarkeit prfen
+Cmd_WriteBuffer equ 00fh ; Sektorpuffer beschreiben
+Cmd_FormatDisk equ 004h ; Laufwerk formatieren
+Cmd_FormatTrack equ 006h ; Spur formatieren
+Cmd_FormatBad equ 007h ; Spur als defekt markieren
+
+;------------------------------------------------------------------------------
+; I/O-Bremse
+
+IODelay macro
+ jmp $+2
+ endm
+
+;------------------------------------------------------------------------------
+; Puffer
+
+CmdBufSize equ 6 ; enth„lt Kommandoblock fr WD1002
+CmdBuf db CmdBufSize dup (0)
+
+StatBufSize equ 4 ; enth„lt Statusinfo vom WD1002
+StatBuf db StatBufSize dup (0)
+
+GeomBufSize equ 8 ; enth„lt Parametertabelle fr Laufwerk
+GeomBuf db GeomBufSize dup (0)
+
+;******************************************************************************
+;* Kommandopuffer initialisieren *
+;******************************************************************************
+
+ proc InitCmdBuf
+
+ push ax ; Register retten
+
+ sub ax,ax ; mit Nullen initialisieren
+ mov word ptr[CmdBuf],ax
+ mov word ptr[CmdBuf+2],ax
+ mov ah,45h ; Retry on, 70us Steprate
+ mov word ptr[CmdBuf+4],ax
+
+ pop ax ; Register zurck
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* einen Datenblock an den Kontroller schicken *
+;* In : ES:SI = Datenblock *
+;* CX = Anzahl Bytes *
+;* Out : C=1 bei Protokollfehler *
+;******************************************************************************
+
+ proc SendBlock
+
+ push ax ; Register retten
+ push cx
+ push dx
+ push si
+
+ mov dx,Port_Status
+ jcxz ZeroLoop ; Nullschleife abfangen
+ cld ; !!!
+OutLoop: in al,dx ; Status lesen
+ btst al,0 ; warten, bis REQ-Bit auf 1
+ jz OutLoop
+ btst al,1 ; IO-Bit muá 0 sein
+ stc
+ jnz ErrEnd
+ mov dl,Lo(Port_Data); ein Byte auf Datenport ausgeben
+ seges
+ outsb
+ mov dl,Lo(Port_Status) ; zurck fr n„chsten Durchlauf
+ loop OutLoop
+ZeroLoop: clc ; Ende ohne Fehler
+ErrEnd:
+ pop si ; Register zurck
+ pop dx
+ pop cx
+ pop ax
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* einen Datenblock vom Kontroller lesen *
+;* In : ES:DI = Datenblock *
+;* CX = Anzahl Bytes *
+;* Out : C=1 bei Protokollfehler *
+;******************************************************************************
+
+ proc RecvBlock
+
+ push ax ; Register retten
+ push cx
+ push dx
+ push di
+
+ mov dx,Port_Status
+ jcxz ZeroLoop ; Nullschleife abfangen
+ cld ; !!!
+InLoop: in al,dx ; Status lesen
+ btst al,0 ; warten, bis REQ-Bit auf 1
+ jz InLoop
+ btst al,1 ; IO-Bit muá 1 sein
+ stc
+ jz ErrEnd
+ mov dl,Lo(Port_Data); ein Byte von Datenport einlesen
+ insb
+ mov dl,Lo(Port_Status) ; zurck fr n„chsten Durchlauf
+ loop InLoop
+ZeroLoop: clc ; Ende ohne Fehler
+ErrEnd:
+ pop di ; Register zurck
+ pop dx
+ pop cx
+ pop ax
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Status bilden *
+;* Out : C+AX = Status *
+;******************************************************************************
+
+ proc BuildStatus
+
+ push dx ; Register retten
+
+ mov dx,Port_Status ; auf Datum warten
+Loop: in al,dx
+ btst al,0 ; bis REQ=1
+ jz Loop
+ btst al,1 ; und IO=1
+ jz Loop
+ mov dl,Lo(Port_Data); CCB auslesen
+ in al,dx
+ mov ah,al ; retten fr Fehlerabfrage
+ and al,2 ; Bit 1 ausmaskieren
+ clc
+ ljz End ; wenn = 0, kein Fehler und AL=0
+
+ push cx ; zus„tzliche Register retten
+ push si
+ push di
+ push es
+
+ call InitCmdBuf ; ansonsten Kommando absetzen, um
+ mov [CmdBuf],Cmd_GetStatus ; Status zu lesen
+ and ah,20h ; Status fr korr. Laufwerk abfragen
+ mov [CmdBuf+1],ah
+ mov dx,Port_Status
+WaitNBusy: in al,dx
+ btst al,3
+ jnz WaitNBusy
+ mov ax,ds ; NICHT ExecCmd benutzen, da sonst
+ mov es,ax ; Rekursion !
+ lea si,[CmdBuf]
+ mov cx,CmdBufSize
+ mov dl,Lo(Port_Select)
+ out dx,al
+ call SendBlock
+ lea di,[StatBuf] ; 4 Statusbytes auslesen
+ mov cx,StatBufSize
+ call RecvBlock
+ mov dl,Lo(Port_Status); CCB nicht vergessen!!
+Loop2: in al,dx
+ btst al,0 ; bis REQ=1
+ jz Loop2
+ btst al,1 ; und IO=1
+ jz Loop2
+ mov dl,Lo(Port_Data)
+ in al,dx
+ mov al,[StatBuf] ; Fehlercode = 1.Byte,
+ and al,7fh ; Bit 0..6
+ stc ; Carry signalisiert Fehler
+ pop es ; zus„tzliche Register zurck
+ pop di
+ pop si
+ pop cx
+
+End: mov ah,0 ; MSB ohne Bedeutung
+ pop dx ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* XT- in AT-Fehlerkode umsetzen *
+;* Eingabe: AL = XT-Fehlerkode *
+;* Ausgabe: C+AX = AT-Fehlerstatus *
+;******************************************************************************
+
+ proc TranslateStatus
+
+ push bx
+ push si
+
+ mov bl,al ; alten Status sichern
+ mov bh,-1
+ lea si,[TransTable]
+ cld
+TransLoop: lodsw ; einen Eintrag laden
+ cmp al,bh ; Tabellenende?
+ je TransEnd
+ cmp al,bl ; Treffer?
+ jne TransLoop ; nein, weitersuchen
+ mov al,ah ; bersetzten Code laden
+ cmp al,0 ; Code fr kein Fehler?
+ clc
+ je Ende ; ja, C=0
+ jmp TransErr ; ansonsten C=1
+TransEnd: mov al,04h ; Aborted Command annehmen
+TransErr: stc ; Fehlerflag setzen
+
+Ende: pop si ; Register zurck
+ pop bx
+
+ ret
+
+TransTable: db 00h,00h ; kein Fehler
+ db 02h,02h ; kein Seek Complete-Signal
+ db 03h,04h ; Write Fault
+ db 04h,04h ; Laufwerk nicht bereit
+ db 06h,02h ; Spur 0 nicht gefunden
+ db 08h,02h ; Laufwerk positioniert noch
+ db 11h,40h ; unkorrigierbarer Datenfehler
+ db 12h,01h ; Adreámarke nicht gefunden
+ db 15h,10h ; Positionierfehler
+ db 18h,00h ; korrigierbarer Fehler (ignoriert)
+ db 19h,80h ; Spur als defekt markiert
+ db -1,-1 ; Tabellenende
+
+ endp
+
+;******************************************************************************
+;* ein Kommando ausfhren *
+;* In : AL = Kommando *
+;******************************************************************************
+
+ proc ExecCmd
+
+ push cx ; Register retten
+ push ax
+ push dx
+ push si
+ push es
+
+ mov [CmdBuf],al ; Kommandokode in Datenblock einschreiben
+ mov dx,Port_Status ; warten, bis Kontroller frei
+WaitNBusy: in al,dx
+ btst al,3
+ jnz WaitNBusy
+ mov dx,Port_Select ; Kontroller selektieren
+ out dx,al
+ mov ax,ds ; Adresse Kommandoblock
+ mov es,ax
+ lea si,[CmdBuf]
+ mov cx,CmdBufSize ; L„nge Kommandoblock
+ call SendBlock ; Kommandoblock abschicken
+
+ pop es ; Register zurck
+ pop si
+ pop dx
+ pop ax
+ pop cx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Laufwerk und Sonderwerte in Kommandoblock einprogrammieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;******************************************************************************
+
+ proc SetDriveEnv
+
+ push ax ; Register retten
+
+
+ shl al,5 ; Laufwerksbit an Stelle 5
+ or al,ah
+ mov [CmdBuf+1],al ; als 2. Byte im Kommandopuffer schreiben
+
+ pop ax ; Register zurck
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Zylinder- und Sektorparameter an Kontroller ausgeben *
+;* In : BX = Startzylinder *
+;* CL = Sektorzahl/Interleave *
+;* CH = Startsektor *
+;******************************************************************************
+
+ proc SetTransParams
+
+ push ax ; Register retten
+
+ mov [CmdBuf+3],bl ; LSB Startzylinder
+ mov al,bh ; MSB Startzylinder
+ shl al,6 ; in Bit 6..7 schieben
+ add al,ch ; Sektor dazu
+ dec al ; !!! Sektoren ab 0
+ mov [CmdBuf+2],al
+ mov [CmdBuf+4],cl ; Sektorzahl
+
+ pop ax ; Register zurck
+ ret
+
+ endp
+
+;******************************************************************************
+;* Begráungsmeldung ausgeben: *
+;******************************************************************************
+
+ globproc LowLevelIdent
+
+ push ax ; Register retten
+
+ PrMsg IdentMsg
+
+ pop ax
+
+ ret
+
+IdentMsg db "Low-Level-Routinen fr WD1002S-WX2 und kompatible Controller",CR,LF,'$'
+
+ endp
+
+;******************************************************************************
+;* Controller-Diagnose: *
+;* Out : AL = Diagnosecode *
+;******************************************************************************
+
+ globproc ContDiag
+
+ push cx ; Register retten
+ push bx
+ push dx
+
+ sub cx,cx
+ mov dx,Port_Status ; auf Status
+BWait: in al,dx
+ btst al,3 ; auf NOT BUSY warten
+ loopnz BWait ; oder bis 64K Durchl„ufe durch
+ or cx,cx ; Timeout ?
+ jne NTOut
+ mov al,Diag_Timeout ; ja: Fehlercode setzen...
+ jmp End ; ...und Feierabend
+
+NTOut: call InitCmdBuf ; Kommando Selbsttest ausfhren
+ mov al,Cmd_Diagnose
+ call ExecCmd
+ call BuildStatus ; Status holen
+
+ cmp al,5 ; WD1002 definiert nur Code 0..5
+ jb DoTrans
+ mov al,7 ; "undefinierter Code"
+ jmp End
+DoTrans: lea bx,[TransTbl] ; ansonsten umsetzen
+ xlat
+
+End: pop dx ; Register zurck
+ pop bx
+ pop cx
+ ret
+
+TransTbl: db Diag_NoError ; Code 0: kein Fehler
+ db Diag_ContError ; Code 1: WD1010 fehlerhaft
+ db Diag_ECCError ; Code 2: WD11C00 fehlerhaft
+ db Diag_SBufError ; Code 3: Sektorpuffer defekt
+ db Diag_ProcError ; Code 4: WD1015 RAM defekt
+ db Diag_ProcError ; Code 5: WD1015 ROM defekt
+
+
+ endp
+
+;******************************************************************************
+;* Laufwerk rekalibrieren, gleichzeitig Test, ob vorhanden *
+;* In : AL = Laufwerk *
+;* Out : C + AX = Status *
+;******************************************************************************
+
+
+ globproc Recalibrate
+
+ push ax ; Register retten
+ push cx
+
+ call InitCmdBuf ; testen, ob Laufwerk bereit
+ mov ah,0 ; Kopf dafr unwichtig
+ call SetDriveEnv
+ mov dl,al ; Laufwerksnummer retten, gleichzeitig
+ mov dh,0 ; Kopf auf 0 setzen
+ mov al,Cmd_TestReady
+ call ExecCmd
+ call BuildStatus
+ jc TotEnde ; C=1 --> Ende mit Fehler
+
+ call InitCmdBuf ; sanfte Tour: Spur 0 mit Seek anfahren
+ mov ax,dx
+ call SetDriveEnv
+ mov al,0 ; Zylinder lo=0
+ mov [CmdBuf+3],al
+ inc al ; Zylinder Hi=0, Startsektor=1
+ mov [CmdBuf+2],al
+ mov al,Cmd_Seek
+ call ExecCmd
+ call BuildStatus
+ jnc TotEnde ; kein Fehler, alles in Butter
+
+ call InitCmdBuf ; ansonsten echtes Restore versuchen
+ mov ax,dx
+ call SetDriveEnv
+ mov al,Cmd_Restore
+ call ExecCmd
+ call BuildStatus
+ call TranslateStatus
+
+TotEnde: pop dx ; Register zurck
+ pop ax
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Dem Kontroller die Laufwerksgeometrie mitteilen *
+;* In : AL = Laufwerk *
+;* Out : C = 1-->Fehler *
+;******************************************************************************
+
+ globproc SetDriveParams
+
+ push cx ; Register retten
+ push si
+ push es
+
+ call GetPTabAdr ; Adresse Parametertabelle holen
+ call InitCmdBuf ; Kommando anstoáen
+ call SetDriveEnv
+ mov al,Cmd_SetParams
+ call ExecCmd
+
+
+ mov ax,[di+DrPar_Cyls] ; Parametertabelle aufbauen
+ xchg ah,al
+ mov word ptr [GeomBuf],ax
+ mov al,[di+DrPar_Heads]
+ mov byte ptr[GeomBuf+2],al
+ mov ax,[di+DrPar_RedWr]
+ xchg ah,al
+ mov word ptr[GeomBuf+3],ax
+ mov ax,[di+DrPar_PrComp]
+ xchg ah,al
+ mov word ptr[GeomBuf+5],ax
+ mov al,[di+DrPar_ECCLen]
+ mov byte ptr[GeomBuf+7],al
+ lea si,[GeomBuf] ; Block abschicken
+ mov cx,GeomBufSize
+ mov ax,ds
+ mov es,ax
+ call SendBlock
+ call BuildStatus
+ call TranslateStatus
+
+ pop es ; Register zurck
+ pop si
+ pop cx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Sektor(en) lesen *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* ES:DI = Zeiger auf Datenpuffer *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc ReadSectors
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push di
+ push es
+
+ call InitCmdBuf ; Puffer initialisieren
+ call SetDriveEnv
+ call SetTransParams
+ mov al,Cmd_Read ; Lesen triggern
+ PrChar '1'
+ call ExecCmd
+ PrChar '2'
+
+SecLoop: mov dx,Port_Status ; warten, bis Request-Bit gesetzt
+RLoop: in al,dx
+ btst al,0
+ jz RLoop
+ btst al,2 ; Daten oder Status ?
+ jnz ErrEnd ; wenn jetzt Status, ist etwas schief gelaufen
+ push cx ; ansonsten Sektor auslesen
+ mov cx,SecSize
+ PrChar '3'
+ call RecvBlock
+ PrChar '4'
+ pop cx
+ dec cl
+ add di,SecSize
+ jnz RLoop ; und n„chsten Sektor verarbeiten
+
+ErrEnd: PrChar '5'
+ call BuildStatus
+ PrChar '6'
+ call TranslateStatus
+
+ pop es ; Register zurck
+ pop di
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Sektor(en) verifizieren *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc VeriSectors
+
+ push bx ; Register retten
+ push cx
+ push dx
+
+ call InitCmdBuf ; Puffer initialisieren
+ call SetDriveEnv
+ call SetTransParams
+ mov al,Cmd_Verify ; Verifikation triggern
+ call ExecCmd
+
+ call BuildStatus
+ call TranslateStatus
+
+ pop dx ; Register zurck
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Sektor(en) schreiben *
+;* In : AL = Laufwerk *
+;* AH = Startkopf *
+;* BX = Startzylinder *
+;* CL = Sektorzahl *
+;* CH = Startsektor *
+;* ES:SI = Zeiger auf Datenpuffer *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc WriteSectors
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+ push es
+
+
+ call InitCmdBuf ; Puffer initialisieren
+ call SetDriveEnv
+ call SetTransParams
+ mov al,Cmd_Write ; Lesen triggern
+ call ExecCmd
+
+SecLoop: mov dx,Port_Status ; warten, bis Request-Bit gesetzt
+WLoop: in al,dx
+ btst al,0
+ jz WLoop
+ btst al,2 ; Daten oder Status ?
+ jnz ErrEnd ; wenn jetzt Status, ist etwas schief gelaufen
+ push cx ; ansonsten Sektor auslesen
+ mov cx,SecSize
+ call SendBlock
+ pop cx
+ dec cl
+ add si,SecSize
+ jnz WLoop ; und n„chsten Sektor verarbeiten
+
+ErrEnd: call BuildStatus
+ call TranslateStatus
+
+ pop es ; Register zurck
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Laufwerk formatieren *
+;* In : AL = Laufwerk *
+;* AH = Interleave *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc FormatUnit
+
+ push bx ; Register retten
+ push cx
+ push dx
+ push si
+ push di
+ push es
+
+ mov bx,ax ; Interleave & Laufwerk retten
+
+ mov ax,ds ; vorher noch den Sektorpuffer im
+ mov es,ax ; Controller ausnullen
+ lea di,[SectorBuffer]
+ mov cx,SecSize/2
+ sub ax,ax
+ rep stosw
+ call InitCmdBuf
+ mov al,Cmd_WriteBuffer
+ call ExecCmd
+ lea si,[SectorBuffer]
+ mov cx,SecSize
+ call SendBlock
+ call BuildStatus
+ jc End ; unwahrscheinlich, aber...
+
+ call InitCmdBuf ; Puffer initialisieren
+ mov al,bl ; Laufwerk wieder zurck
+ mov ah,0 ; Startkopf ist 0
+ call SetDriveEnv
+ mov [CmdBuf+4],bh ; Interleave einschreiben
+ mov al,Cmd_FormatDisk ; Formatieren triggern
+ call ExecCmd
+
+ErrEnd: call BuildStatus
+End: call TranslateStatus
+
+ pop es ; Register zurck
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ret
+
+ endp
+
+;******************************************************************************
+;* Spur formatieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;* BX = Zylinder *
+;* CL = Interleave *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc FormatTrack
+
+ push bx
+ push cx
+
+ call InitCmdBuf ; Parameter einschreiben
+ call SetDriveEnv
+ mov ch,1 ; Sektorinformation muá nur gltig sein
+ call SetTransParams
+ mov al,Cmd_FormatTrack
+ call ExecCmd
+ call BuildStatus
+
+ pop cx
+ pop bx
+ ret
+
+ endp
+
+;******************************************************************************
+;* Spur als defekt markieren *
+;* In : AL = Laufwerk *
+;* AH = Kopf *
+;* BX = Zylinder *
+;* Out : C+AX = Fehlerstatus *
+;******************************************************************************
+
+ globproc MarkBad
+
+ push bx
+ push cx
+
+ call InitCmdBuf ; Parameter einschreiben
+ call SetDriveEnv
+ mov cx,0103h ; Sektorinformation muá nur gltig sein
+ call SetTransParams
+ mov al,Cmd_FormatBad
+ call ExecCmd
+ call BuildStatus
+
+ pop cx
+ pop bx
+ ret
+
+ endp
+
+ endsection