Blame | Last modification | View Log | Download | RSS feed
;******************************************************************************;* *;* Includedatei fuer SECMAIN.ASM *;* liefert low-level-Routinen fuer SecMain *;* Version hier fuer WD1002XT-kompatible Kontroller: *;* MFM, RLL (?) *;* *;* Historie: 28.12.1994 *;* 26. 3.1994 Formatierroutinen *;* 8. 4.1994 defekte Spuren markieren *;* *;******************************************************************************section wd1002xt;------------------------------------------------------------------------------; PortadressenPort_Base equ 320h ; primaere BasisadressePort_Data equ Port_Base+0 ; Datenregister (R+W)Port_Status equ Port_Base+1 ; Statusregister (R)Port_Reset equ Port_Base+1 ; Reset ausloesen (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);------------------------------------------------------------------------------; KommandocodesCmd_Diagnose equ 0e4h ; Kommando: Kontroller-SelbsttestCmd_GetStatus equ 003h ; Status letzter Operation lesenCmd_TestReady equ 000h ; Test, ob Laufwerk bereitCmd_Restore equ 001h ; Laufwerk rekalibrierenCmd_SetParams equ 00ch ; Laufwerksparameter setzenCmd_Seek equ 00bh ; Spur anfahrenCmd_Read equ 008h ; Sektoren lesenCmd_Write equ 00ah ; Sektoren schreibenCmd_Verify equ 005h ; Sektoren auf Lesbarkeit pruefenCmd_WriteBuffer equ 00fh ; Sektorpuffer beschreibenCmd_FormatDisk equ 004h ; Laufwerk formatierenCmd_FormatTrack equ 006h ; Spur formatierenCmd_FormatBad equ 007h ; Spur als defekt markieren;------------------------------------------------------------------------------; I/O-BremseIODelay macrojmp $+2endm;------------------------------------------------------------------------------; PufferCmdBufSize equ 6 ; enthaelt Kommandoblock fuer WD1002CmdBuf db CmdBufSize dup (0)StatBufSize equ 4 ; enthaelt Statusinfo vom WD1002StatBuf db StatBufSize dup (0)GeomBufSize equ 8 ; enthaelt Parametertabelle fuer LaufwerkGeomBuf db GeomBufSize dup (0);******************************************************************************;* Kommandopuffer initialisieren *;******************************************************************************proc InitCmdBufpush ax ; Register rettensub ax,ax ; mit Nullen initialisierenmov word ptr[CmdBuf],axmov word ptr[CmdBuf+2],axmov ah,45h ; Retry on, 70us Stepratemov word ptr[CmdBuf+4],axpop ax ; Register zurueckretendp;******************************************************************************;* einen Datenblock an den Kontroller schicken *;* In : ES:SI = Datenblock *;* CX = Anzahl Bytes *;* Out : C=1 bei Protokollfehler *;******************************************************************************proc SendBlockpush ax ; Register rettenpush cxpush dxpush simov dx,Port_Statusjcxz ZeroLoop ; Nullschleife abfangencld ; !!!OutLoop: in al,dx ; Status lesenbtst al,0 ; warten, bis REQ-Bit auf 1jz OutLoopbtst al,1 ; IO-Bit muss 0 seinstcjnz ErrEndmov dl,Lo(Port_Data); ein Byte auf Datenport ausgebensegesoutsbmov dl,Lo(Port_Status) ; zurueck fuer naechsten Durchlaufloop OutLoopZeroLoop: clc ; Ende ohne FehlerErrEnd:pop si ; Register zurueckpop dxpop cxpop axretendp;******************************************************************************;* einen Datenblock vom Kontroller lesen *;* In : ES:DI = Datenblock *;* CX = Anzahl Bytes *;* Out : C=1 bei Protokollfehler *;******************************************************************************proc RecvBlockpush ax ; Register rettenpush cxpush dxpush dimov dx,Port_Statusjcxz ZeroLoop ; Nullschleife abfangencld ; !!!InLoop: in al,dx ; Status lesenbtst al,0 ; warten, bis REQ-Bit auf 1jz InLoopbtst al,1 ; IO-Bit muss 1 seinstcjz ErrEndmov dl,Lo(Port_Data); ein Byte von Datenport einleseninsbmov dl,Lo(Port_Status) ; zurueck fuer naechsten Durchlaufloop InLoopZeroLoop: clc ; Ende ohne FehlerErrEnd:pop di ; Register zurueckpop dxpop cxpop axretendp;******************************************************************************;* Status bilden *;* Out : C+AX = Status *;******************************************************************************proc BuildStatuspush dx ; Register rettenmov dx,Port_Status ; auf Datum wartenLoop: in al,dxbtst al,0 ; bis REQ=1jz Loopbtst al,1 ; und IO=1jz Loopmov dl,Lo(Port_Data); CCB auslesenin al,dxmov ah,al ; retten fuer Fehlerabfrageand al,2 ; Bit 1 ausmaskierenclcljz End ; wenn = 0, kein Fehler und AL=0push cx ; zusaetzliche Register rettenpush sipush dipush escall InitCmdBuf ; ansonsten Kommando absetzen, ummov [CmdBuf],Cmd_GetStatus ; Status zu lesenand ah,20h ; Status fuer korr. Laufwerk abfragenmov [CmdBuf+1],ahmov dx,Port_StatusWaitNBusy: in al,dxbtst al,3jnz WaitNBusymov ax,ds ; NICHT ExecCmd benutzen, da sonstmov es,ax ; Rekursion !lea si,[CmdBuf]mov cx,CmdBufSizemov dl,Lo(Port_Select)out dx,alcall SendBlocklea di,[StatBuf] ; 4 Statusbytes auslesenmov cx,StatBufSizecall RecvBlockmov dl,Lo(Port_Status); CCB nicht vergessen!!Loop2: in al,dxbtst al,0 ; bis REQ=1jz Loop2btst al,1 ; und IO=1jz Loop2mov dl,Lo(Port_Data)in al,dxmov al,[StatBuf] ; Fehlercode = 1.Byte,and al,7fh ; Bit 0..6stc ; Carry signalisiert Fehlerpop es ; zusaetzliche Register zurueckpop dipop sipop cxEnd: mov ah,0 ; MSB ohne Bedeutungpop dx ; Register zurueckretendp;******************************************************************************;* XT- in AT-Fehlerkode umsetzen *;* Eingabe: AL = XT-Fehlerkode *;* Ausgabe: C+AX = AT-Fehlerstatus *;******************************************************************************proc TranslateStatuspush bxpush simov bl,al ; alten Status sichernmov bh,-1lea si,[TransTable]cldTransLoop: lodsw ; einen Eintrag ladencmp al,bh ; Tabellenende?je TransEndcmp al,bl ; Treffer?jne TransLoop ; nein, weitersuchenmov al,ah ; uebersetzten Code ladencmp al,0 ; Code fuer kein Fehler?clcje Ende ; ja, C=0jmp TransErr ; ansonsten C=1TransEnd: mov al,04h ; Aborted Command annehmenTransErr: stc ; Fehlerflag setzenEnde: pop si ; Register zurueckpop bxretTransTable: db 00h,00h ; kein Fehlerdb 02h,02h ; kein Seek Complete-Signaldb 03h,04h ; Write Faultdb 04h,04h ; Laufwerk nicht bereitdb 06h,02h ; Spur 0 nicht gefundendb 08h,02h ; Laufwerk positioniert nochdb 11h,40h ; unkorrigierbarer Datenfehlerdb 12h,01h ; Adreсmarke nicht gefundendb 15h,10h ; Positionierfehlerdb 18h,00h ; korrigierbarer Fehler (ignoriert)db 19h,80h ; Spur als defekt markiertdb -1,-1 ; Tabellenendeendp;******************************************************************************;* ein Kommando ausfБhren *;* In : AL = Kommando *;******************************************************************************proc ExecCmdpush cx ; Register rettenpush axpush dxpush sipush esmov [CmdBuf],al ; Kommandokode in Datenblock einschreibenmov dx,Port_Status ; warten, bis Kontroller freiWaitNBusy: in al,dxbtst al,3jnz WaitNBusymov dx,Port_Select ; Kontroller selektierenout dx,almov ax,ds ; Adresse Kommandoblockmov es,axlea si,[CmdBuf]mov cx,CmdBufSize ; Laenge Kommandoblockcall SendBlock ; Kommandoblock abschickenpop es ; Register zurueckpop sipop dxpop axpop cxretendp;******************************************************************************;* Laufwerk und Sonderwerte in Kommandoblock einprogrammieren *;* In : AL = Laufwerk *;* AH = Kopf *;******************************************************************************proc SetDriveEnvpush ax ; Register rettenshl al,5 ; Laufwerksbit an Stelle 5or al,ahmov [CmdBuf+1],al ; als 2. Byte im Kommandopuffer schreibenpop ax ; Register zurueckretendp;******************************************************************************;* Zylinder- und Sektorparameter an Kontroller ausgeben *;* In : BX = Startzylinder *;* CL = Sektorzahl/Interleave *;* CH = Startsektor *;******************************************************************************proc SetTransParamspush ax ; Register rettenmov [CmdBuf+3],bl ; LSB Startzylindermov al,bh ; MSB Startzylindershl al,6 ; in Bit 6..7 schiebenadd al,ch ; Sektor dazudec al ; !!! Sektoren ab 0mov [CmdBuf+2],almov [CmdBuf+4],cl ; Sektorzahlpop ax ; Register zurueckretendp;******************************************************************************;* BegrБсungsmeldung ausgeben: *;******************************************************************************globproc LowLevelIdentpush ax ; Register rettenPrMsg IdentMsgpop axretIdentMsg db "Low-Level-Routinen f",UUML,"r WD1002S-WX2 und kompatible Controller",CR,LF,'$'endp;******************************************************************************;* Controller-Diagnose: *;* Out : AL = Diagnosecode *;******************************************************************************globproc ContDiagpush cx ; Register rettenpush bxpush dxsub cx,cxmov dx,Port_Status ; auf StatusBWait: in al,dxbtst al,3 ; auf NOT BUSY wartenloopnz BWait ; oder bis 64K Durchlaeufe durchor cx,cx ; Timeout ?jne NTOutmov al,Diag_Timeout ; ja: Fehlercode setzen...jmp End ; ...und FeierabendNTOut: call InitCmdBuf ; Kommando Selbsttest ausfuehrenmov al,Cmd_Diagnosecall ExecCmdcall BuildStatus ; Status holencmp al,5 ; WD1002 definiert nur Code 0..5jb DoTransmov al,7 ; "undefinierter Code"jmp EndDoTrans: lea bx,[TransTbl] ; ansonsten umsetzenxlatEnd: pop dx ; Register zurueckpop bxpop cxretTransTbl: db Diag_NoError ; Code 0: kein Fehlerdb Diag_ContError ; Code 1: WD1010 fehlerhaftdb Diag_ECCError ; Code 2: WD11C00 fehlerhaftdb Diag_SBufError ; Code 3: Sektorpuffer defektdb Diag_ProcError ; Code 4: WD1015 RAM defektdb Diag_ProcError ; Code 5: WD1015 ROM defektendp;******************************************************************************;* Laufwerk rekalibrieren, gleichzeitig Test, ob vorhanden *;* In : AL = Laufwerk *;* Out : C + AX = Status *;******************************************************************************globproc Recalibratepush ax ; Register rettenpush cxcall InitCmdBuf ; testen, ob Laufwerk bereitmov ah,0 ; Kopf dafuer unwichtigcall SetDriveEnvmov dl,al ; Laufwerksnummer retten, gleichzeitigmov dh,0 ; Kopf auf 0 setzenmov al,Cmd_TestReadycall ExecCmdcall BuildStatusjc TotEnde ; C=1 --> Ende mit Fehlercall InitCmdBuf ; sanfte Tour: Spur 0 mit Seek anfahrenmov ax,dxcall SetDriveEnvmov al,0 ; Zylinder lo=0mov [CmdBuf+3],alinc al ; Zylinder Hi=0, Startsektor=1mov [CmdBuf+2],almov al,Cmd_Seekcall ExecCmdcall BuildStatusjnc TotEnde ; kein Fehler, alles in Buttercall InitCmdBuf ; ansonsten echtes Restore versuchenmov ax,dxcall SetDriveEnvmov al,Cmd_Restorecall ExecCmdcall BuildStatuscall TranslateStatusTotEnde: pop dx ; Register zurueckpop axretendp;******************************************************************************;* Dem Kontroller die Laufwerksgeometrie mitteilen *;* In : AL = Laufwerk *;* Out : C = 1-->Fehler *;******************************************************************************globproc SetDriveParamspush cx ; Register rettenpush sipush escall GetPTabAdr ; Adresse Parametertabelle holencall InitCmdBuf ; Kommando anstoсencall SetDriveEnvmov al,Cmd_SetParamscall ExecCmdmov ax,[di+DrPar_Cyls] ; Parametertabelle aufbauenxchg ah,almov word ptr [GeomBuf],axmov al,[di+DrPar_Heads]mov byte ptr[GeomBuf+2],almov ax,[di+DrPar_RedWr]xchg ah,almov word ptr[GeomBuf+3],axmov ax,[di+DrPar_PrComp]xchg ah,almov word ptr[GeomBuf+5],axmov al,[di+DrPar_ECCLen]mov byte ptr[GeomBuf+7],allea si,[GeomBuf] ; Block abschickenmov cx,GeomBufSizemov ax,dsmov es,axcall SendBlockcall BuildStatuscall TranslateStatuspop es ; Register zurueckpop sipop cxretendp;******************************************************************************;* Sektor(en) lesen *;* In : AL = Laufwerk *;* AH = Startkopf *;* BX = Startzylinder *;* CL = Sektorzahl *;* CH = Startsektor *;* ES:DI = Zeiger auf Datenpuffer *;* Out : C+AX = Fehlerstatus *;******************************************************************************globproc ReadSectorspush bx ; Register rettenpush cxpush dxpush dipush escall InitCmdBuf ; Puffer initialisierencall SetDriveEnvcall SetTransParamsmov al,Cmd_Read ; Lesen triggernPrChar '1'call ExecCmdPrChar '2'SecLoop: mov dx,Port_Status ; warten, bis Request-Bit gesetztRLoop: in al,dxbtst al,0jz RLoopbtst al,2 ; Daten oder Status ?jnz ErrEnd ; wenn jetzt Status, ist etwas schief gelaufenpush cx ; ansonsten Sektor auslesenmov cx,SecSizePrChar '3'call RecvBlockPrChar '4'pop cxdec cladd di,SecSizejnz RLoop ; und naechsten Sektor verarbeitenErrEnd: PrChar '5'call BuildStatusPrChar '6'call TranslateStatuspop es ; Register zurueckpop dipop dxpop cxpop bxretendp;******************************************************************************;* Sektor(en) verifizieren *;* In : AL = Laufwerk *;* AH = Startkopf *;* BX = Startzylinder *;* CL = Sektorzahl *;* CH = Startsektor *;* Out : C+AX = Fehlerstatus *;******************************************************************************globproc VeriSectorspush bx ; Register rettenpush cxpush dxcall InitCmdBuf ; Puffer initialisierencall SetDriveEnvcall SetTransParamsmov al,Cmd_Verify ; Verifikation triggerncall ExecCmdcall BuildStatuscall TranslateStatuspop dx ; Register zurueckpop cxpop bxretendp;******************************************************************************;* Sektor(en) schreiben *;* In : AL = Laufwerk *;* AH = Startkopf *;* BX = Startzylinder *;* CL = Sektorzahl *;* CH = Startsektor *;* ES:SI = Zeiger auf Datenpuffer *;* Out : C+AX = Fehlerstatus *;******************************************************************************globproc WriteSectorspush bx ; Register rettenpush cxpush dxpush sipush escall InitCmdBuf ; Puffer initialisierencall SetDriveEnvcall SetTransParamsmov al,Cmd_Write ; Lesen triggerncall ExecCmdSecLoop: mov dx,Port_Status ; warten, bis Request-Bit gesetztWLoop: in al,dxbtst al,0jz WLoopbtst al,2 ; Daten oder Status ?jnz ErrEnd ; wenn jetzt Status, ist etwas schief gelaufenpush cx ; ansonsten Sektor auslesenmov cx,SecSizecall SendBlockpop cxdec cladd si,SecSizejnz WLoop ; und naechsten Sektor verarbeitenErrEnd: call BuildStatuscall TranslateStatuspop es ; Register zurueckpop sipop dxpop cxpop bxretendp;******************************************************************************;* Laufwerk formatieren *;* In : AL = Laufwerk *;* AH = Interleave *;* Out : C+AX = Fehlerstatus *;******************************************************************************globproc FormatUnitpush bx ; Register rettenpush cxpush dxpush sipush dipush esmov bx,ax ; Interleave & Laufwerk rettenmov ax,ds ; vorher noch den Sektorpuffer immov es,ax ; Controller ausnullenlea di,[SectorBuffer]mov cx,SecSize/2sub ax,axrep stoswcall InitCmdBufmov al,Cmd_WriteBuffercall ExecCmdlea si,[SectorBuffer]mov cx,SecSizecall SendBlockcall BuildStatusjc End ; unwahrscheinlich, aber...call InitCmdBuf ; Puffer initialisierenmov al,bl ; Laufwerk wieder zurueckmov ah,0 ; Startkopf ist 0call SetDriveEnvmov [CmdBuf+4],bh ; Interleave einschreibenmov al,Cmd_FormatDisk ; Formatieren triggerncall ExecCmdErrEnd: call BuildStatusEnd: call TranslateStatuspop es ; Register zurueckpop dipop sipop dxpop cxpop bxretendp;******************************************************************************;* Spur formatieren *;* In : AL = Laufwerk *;* AH = Kopf *;* BX = Zylinder *;* CL = Interleave *;* Out : C+AX = Fehlerstatus *;******************************************************************************globproc FormatTrackpush bxpush cxcall InitCmdBuf ; Parameter einschreibencall SetDriveEnvmov ch,1 ; Sektorinformation muss nur gueltig seincall SetTransParamsmov al,Cmd_FormatTrackcall ExecCmdcall BuildStatuspop cxpop bxretendp;******************************************************************************;* Spur als defekt markieren *;* In : AL = Laufwerk *;* AH = Kopf *;* BX = Zylinder *;* Out : C+AX = Fehlerstatus *;******************************************************************************globproc MarkBadpush bxpush cxcall InitCmdBuf ; Parameter einschreibencall SetDriveEnvmov cx,0103h ; Sektorinformation muss nur gueltig seincall SetTransParamsmov al,Cmd_FormatBadcall ExecCmdcall BuildStatuspop cxpop bxretendpendsection