Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. ;******************************************************************************
  2. ;*                                                                            *
  3. ;* SECDRIVE - Treiber fuer einen 2. HD-Kontroller im PC                       *
  4. ;*                                                                            *
  5. ;* Historie:  12. 8.1993  Grundsteinlegung, Definitionen                      *
  6. ;*            16. 8.1993  Dispatcher                                          *
  7. ;*                        Basislesefunktionen                                 *
  8. ;*            17. 8.1993  Partitionsinformationen zusammenkratzen             *
  9. ;*            18. 8.1993  Laufwerksparameter initialisieren                   *
  10. ;*            19. 8.1993  Zylinder/Sektorregister setzen                      *
  11. ;*                        Partitiossektorbaum durchgehen                      *
  12. ;*            24. 8.1993  BPB aufbauen                                        *
  13. ;*            25. 8.1993  Parameteruebersetzung                               *
  14. ;*                        Einlesen                                            *
  15. ;*                        Sektoren schreiben                                  *
  16. ;*            26. 8.1993  Fehlerbehandlung                                    *
  17. ;*                        Verify                                              *
  18. ;*                        1. Restore-Versuch mit Seek                         *
  19. ;*             7. 9.1993  Versuch Version 1.39 mit Proc's                     *
  20. ;*            28. 9.1993  etwas gekБrzt                                       *
  21. ;*            27.12.1994  leichte Korrekturen im Restore                      *
  22. ;*            28.12.1994  Trennung Low-Level-Routinen begonnen                *
  23. ;*            19. 1.1995  Fehlermeldungen im Klartext                         *
  24. ;*                                                                            *
  25. ;******************************************************************************
  26.  
  27. ;******************************************************************************
  28. ;* globale Definitionen                                                       *
  29. ;******************************************************************************
  30.  
  31. ; A C H T U N G : Mono.SYS muс fБr Debugging geladen sein !!!!
  32.  
  33. debug           equ     0
  34. debug2          equ     0
  35.  
  36.                 include bitfuncs.inc
  37.  
  38.                 cpu     80186           ; WD 1003 fordert min. 80286
  39.  
  40. Diag_NoError    equ     01h             ; Selbstdiagnosecodes: kein Fehler
  41. Diag_ContError  equ     02h             ; Controller-Fehler
  42. Diag_SBufError  equ     03h             ; Sektorpuffer defekt
  43. Diag_ECCError   equ     04h             ; Fehlerkorrektor defekt
  44. Diag_ProcError  equ     05h             ; Steuerprozessor defekt
  45. Diag_Timeout    equ     06h             ; Controller antwortet nicht
  46.  
  47. ParTab          struct
  48. BFlag            db     ?               ; Partitionseintrag: Partition aktiv ?
  49. FHead            db     ?               ; Startkopf
  50. FSecCyl          dw     ?               ; Startzylinder/sektor
  51. Type             db     ?               ; Partitionstyp
  52. LHead            db     ?               ; Endkopf
  53. LSecCyl          dw     ?               ; Endzylinder/sektor
  54. LinSec           dd     ?               ; Anzahl Sektoren
  55. NSecs            dd     ?               ; linearer Startsektor
  56.                 endstruct
  57.  
  58. DErr_WrProtect  equ     00h             ; Treiberfehlercodes: Schreibschutz
  59. DErr_InvUnit    equ     01h             ; unbekannte Geraetenummer
  60. DErr_NotReady   equ     02h             ; Laufwerk nicht bereit
  61. DErr_Unknown    equ     03h             ; Unbekannes Treiberkommando
  62. DErr_CRCError   equ     04h             ; Pruefsummenfehler
  63. DErr_InvBlock   equ     05h             ; ungueltiger Request-Header
  64. DErr_TrkNotFnd  equ     06h             ; Spur nicht gefunden
  65. DErr_InvMedia   equ     07h             ; Unbekanntes Traegerformat
  66. DErr_SecNotFnd  equ     08h             ; Sektor nicht gefunden
  67. DErr_PaperEnd   equ     09h             ; Papierende im Drucker
  68. DErr_WrError    equ     0ah             ; allg. Schreibfehler
  69. DErr_RdError    equ     0bh             ; allg. Schreibfehler
  70. DErr_GenFail    equ     0ch             ; allg. Fehler
  71. DErr_InvChange  equ     0fh             ; unerlaubter Diskettenwechsel
  72.  
  73. DErr_UserTerm   equ     0ffh            ; Fehlercode Abbruch durch Benutzer
  74.  
  75. SecSize         equ     512             ; Sektorgroesse in Bytes
  76. MaxPDrives      equ     2               ; Maximalzahl physikalischer Laufwerke
  77. MaxDrives       equ     10              ; Maximalzahl verwaltbarer Laufwerke
  78. MaxParts        equ     4               ; Maximalzahl Partitionen in einem Sektor
  79. MaxRetry        equ     2               ; max. 2 Lese/Schreibversuche
  80. StackSize       equ     512             ; etwas mehr wg. Rekursion
  81.  
  82. DrPar_Offset    equ     1aeh            ; Offset Parametertabelle im Part.-Sektor
  83. ParTab_Offset   equ     1beh            ; Offset Partitionstabelle "   "     "
  84. ParSecID_Offset equ     1feh            ; Offset Partitionssektorflag (55aa)
  85. BPBOfs          equ     11              ; Offset BPB im Bootsektor
  86.  
  87. INT_DOS         equ     21h             ; DOS-Funktionsaufruf
  88. INT_Mono        equ     60h             ; Haken zum VT100-Treiber
  89. INT_Clock       equ     1ah             ; BIOS-Uhreneinstieg
  90. INT_Keyboard    equ     16h             ; BIOS-Tastatureinstieg
  91.  
  92. DOS_WrString    equ     9               ; DOS-Funktionen
  93. DOS_WrChar      equ     6
  94. DOS_RdString    equ     10
  95. DOS_RdChar      equ     8
  96.  
  97. HD_ID           equ     0f8h            ; Media-ID fuer Festplatten
  98.  
  99. CR              equ     13
  100. LF              equ     10
  101. BEL             equ     7
  102. ESC             equ     27
  103. AUML            equ     84h
  104. OUML            equ     94h
  105. UUML            equ     81h
  106. SZLIG           equ     0e1h
  107.  
  108. ;******************************************************************************
  109. ; Makros                                                                      *
  110. ;******************************************************************************
  111.  
  112. ;jmp             macro adr
  113. ;                !jmp long adr
  114. ;                endm
  115.  
  116. beep            macro
  117.                 push    ax
  118.                 mov     ax,0e07h
  119.                 int     10h
  120.                 pop     ax
  121.                 endm
  122.  
  123. PrMsg           macro   Adr             ; Meldung ausgeben
  124.                 push    dx              ; Register retten
  125.                 lea     dx,[Adr]
  126.                 mov     ah,DOS_WrString
  127.                 int     INT_DOS
  128.                 pop     dx              ; Register zurueck
  129.                 endm
  130.  
  131. PrChar          macro   Zeichen         ; Zeichen ausgeben
  132.                 push    dx              ; Register retten
  133.                 push    ax
  134.                 mov     dl,Zeichen
  135.                 mov     ah,DOS_WrChar
  136.                 int     INT_DOS
  137.                 pop     ax
  138.                 pop     dx              ; Register zurueck
  139.                 endm
  140.  
  141. ;------------------------------------------------------------------------------
  142.  
  143. btst            macro   op,bit          ; ein einzelnes Bit testen
  144.                 test    op,(1<<bit)
  145.                 endm
  146.  
  147. ;------------------------------------------------------------------------------
  148.  
  149. ljnz            macro   adr             ; lange Spruenge
  150.                 jz      Next
  151.                 jmp     adr
  152. Next:
  153.                 endm
  154.  
  155. ljne            macro   adr
  156.                 je      Next
  157.                 jmp     adr
  158. Next:
  159.                 endm
  160.  
  161. ljc             macro   adr
  162.                 jnc     Next
  163.                 jmp     adr
  164. Next:
  165.                 endm
  166.  
  167. lje             macro   adr
  168.                 jne     Next
  169.                 jmp     adr
  170. Next:
  171.                 endm
  172.  
  173. ljz             macro   adr
  174.                 jnz     Next
  175.                 jmp     adr
  176. Next:
  177.                 endm
  178.  
  179. ljb             macro   adr
  180.                 jnb     Next
  181.                 jmp     adr
  182. Next:
  183.                 endm
  184.  
  185. ;------------------------------------------------------------------------------
  186.  
  187. proc            macro   name
  188.                 section name
  189.                 public  name:parent
  190. name            label   $
  191.                 endm
  192.  
  193. globproc        macro   name
  194.                 section name
  195.                 public  name
  196. name            label   $
  197.                 endm
  198.  
  199. endp            macro
  200.                 endsection
  201.                 endm
  202.  
  203. ;------------------------------------------------------------------------------
  204. ; Fehlermakro
  205.  
  206. JmpOnError      macro   Drv,Adr
  207.                 jnc     GoOn            ; kein Fehler, weitermachen
  208.                 mov     ah,Drv
  209.                 call    WrErrorCode     ; Fehler-->ausgeben...
  210.                 jmp     Adr             ; ...Abbruch
  211. GoOn:
  212.                 endm
  213.  
  214. ;******************************************************************************
  215. ;* Treiberkopf                                                                *
  216. ;******************************************************************************
  217.  
  218.  
  219.               assume  cs:code,ds:nothing,ss:nothing,es:nothing
  220.  
  221.                 org     0
  222.  
  223. DriverHead:     dd      -1              ; Zeiger auf Nachfolger
  224.                 dw      0000100000000010b ; Attribut
  225. ;                       ^   ^         ^
  226. ;                       |   |         +- kann 32-Bit-Setornummern verarbeiten
  227. ;                       |   +----------- kennt Close/Open/Removeable
  228. ;                       +--------------- Blocktreiber
  229.                 dw      StrategyProc    ; Zeiger auf Strategieroutine
  230.                 dw      InterruptProc   ; Zeiger auf eigentlichen Treibercode
  231. NrOfVols:       db      0               ; Zahl log. Laufwerke
  232.                 db      "SECDRIV"       ; bei Blocktreibern unbenutzt
  233.  
  234. ;******************************************************************************
  235. ;* residente Daten                                                            *
  236. ;******************************************************************************
  237.  
  238. Rh_Ptr          dd      ?               ; Speicher fuer Request-Header
  239.  
  240. JmpTable        dw      Init            ; Sprungtabelle: Initialisierung
  241.                 dw      MediaCheck      ; Medium gewechselt ?
  242.                 dw      BuildBPB        ; Parameterblock laden
  243.                 dw      IOCTLRead       ; Steuerdaten vom Treiber
  244.                 dw      Read            ; Daten lesen
  245.                 dw      ND_Read         ; Lesen, ohne Pufferstatus zu Дndern
  246.                 dw      InputStatus     ; Daten im Eingabepuffer ?
  247.                 dw      InputFlush      ; Eingabepuffer loeschen
  248.                 dw      Write           ; Daten schreiben
  249.                 dw      Write_Verify    ; Daten mit Prueflesen schreiben
  250.                 dw      OutputStat      ; Ausgabepuffer leer ?
  251.                 dw      OutputFlush     ; Ausgabepuffer loeschen
  252.                 dw      IOCTLWrite      ; Steuerdaten zum Treiber
  253.                 dw      DeviceOpen      ; DOS hat eine Datei darauf geoeffnet
  254.                 dw      DeviceClose     ; DOS hat eine Datei darauf geschlossen
  255.                 dw      Removeable      ; Ist Datentraeger wechselbar ?
  256.                 dw      OutputTillBusy  ; Ausgabe, bis Puffer voll
  257.                 dw      GenIOCTL        ; genormtes IOCTL
  258.                 dw      GetLogical      ; Laufwerkszuordnung lesen
  259.                 dw      SetLogical      ; Laufwerkszuordnung setzen
  260.                 dw      IOCTLQuery      ; Abfrage, ob GenIOCTL unterstuetzt
  261.  
  262. SectorBuffer:   db      SecSize dup (?) ; Sektorpuffer fuer Treiber selber
  263.  
  264.                 db      StackSize dup (?) ; Treiberstack
  265. DriverStack:
  266.  
  267. BPBSize         equ     36
  268. DrTab           struct                  ; Laufwerkstabelle:
  269. StartHead        db     ?               ;  Startkopf
  270. StartCyl         dw     ?               ;  Startzylinder
  271. StartSec         db     ?               ;  Startsektor
  272. LinStart         dd     ?               ;  lin. Startsektor
  273. SecCnt           dd     ?               ;  Gesamtsektorzahl
  274. Drive            db     ?               ;  Laufwerk
  275. BPB              db     BPBSize dup (?) ;  BPB
  276.                 endstruct
  277.  
  278. DrTab           db      DrTab_Len*MaxDrives dup (?)
  279. DrTab_BPBs      dd      2*MaxDrives dup (?)
  280. DrCnt           db      0               ; Anzahl gefundener Laufwerke
  281. DrOfs           db      0               ; erster freier Laufwerksbuchstabe
  282.  
  283. DrPar           struct                  ; Plattenparametersatz:
  284. Cyls             dw     ?               ;  Zylinderzahl
  285. Heads            db     ?               ;  Kopfzahl
  286. RedWr            dw     ?               ;  Startzylinder reduzierter Schreibstrom
  287. PrComp           dw     ?               ;  Startzylinder Praekompensation
  288. ECCLen           db     ?               ;  max. korrigierbarer Fehlerburst (Bits)
  289. CByte            db     ?               ;  Wert fuers Plattensteuerregister
  290. TOut             db     ?               ;  genereller Timeout
  291. FTOut            db     ?               ;  Timeout Formatierung
  292. CTOut            db     ?               ;  Timeout fuer Pruefung
  293. LZone            dw     ?               ;  Landezylinder
  294. NSecs            db     ?               ;  Sektorzahl
  295. Dummy            db     ?               ;  unbenutzt
  296.                 endstruct
  297.  
  298. DrPars          db      DrPar_Len*MaxPDrives dup (0)
  299.  
  300. ;******************************************************************************
  301. ;* Strategieroutine                                                           *
  302. ;******************************************************************************
  303.  
  304. StrategyProc:   mov     word ptr [Rh_Ptr],bx ; Zeiger speichern
  305.                 mov     word ptr [Rh_Ptr+2],es
  306.                 retf
  307.  
  308. ;******************************************************************************
  309. ;* Treiberdispatcher                                                          *
  310. ;******************************************************************************
  311.  
  312. Rh              struct
  313. Size             db     ?               ; gemeinsame Headerteile: Laenge Block
  314. Unit             db     ?               ; angesprochenes Laufwerk
  315. Func             db     ?               ; Treibersubfunktion
  316. Status           dw     ?               ; Ergebnis
  317. Resvd            db     8 dup (?)       ; unbenutzt
  318.                 endstruct
  319.  
  320. InterruptProc:  pusha                   ; alle Register retten
  321.  
  322.                 cli                     ; Stack umschalten
  323.                 mov     si,ss           ; alten zwischenspeichern
  324.                 mov     di,sp
  325.                 mov     ax,cs           ; neuen setzen
  326.                 mov     ss,ax
  327.                 lea     sp,[DriverStack]
  328.                 push    di              ; alten auf neuem (!) speichern
  329.                 push    si
  330.                 sti
  331.  
  332.                 mov     ax,cs           ; DS auf Treibersegment
  333.                 mov     ds,ax
  334.                 assume  ds:code
  335.  
  336.                 les     bx,[Rh_Ptr]     ; Zeiger laden
  337.                 mov     word ptr es:[bx+Rh_Status],0 ; Status loeschen
  338.  
  339.                 mov     al,es:[bx+Rh_Func] ; Subfunktion ausrechnen
  340.                 if      debug
  341.                  call   PrByte
  342.                 endif
  343.                 mov     ah,0
  344.                 add     ax,ax
  345.                 mov     si,ax
  346.                 jmp     JmpTable[si]
  347.  
  348.                 jmp     Init
  349.  
  350. ;******************************************************************************
  351. ;* gemeinsames Ende                                                           *
  352. ;******************************************************************************
  353.  
  354. StateError:     btst    al,1            ; Bit 1: Spur 0 nicht gefunden
  355.                 jz      StateError_N1
  356.                 mov     al,DErr_TrkNotFnd
  357.                 jmp     StateError_End
  358. StateError_N1:  btst    al,2            ; Bit 2: abgebrochenes Kommando
  359.                 jz      StateError_N2
  360.                 btst    ah,5            ; Bit S5: Schreibfehler
  361.                 jz      StateError_N21
  362.                 mov     al,DErr_WrError
  363.                 jmp     StateError_End
  364. StateError_N21: btst    ah,4            ; Bit S4: Positionierung nicht vollstaendig
  365.                 jnz     StateError_N22
  366.                 mov     al,DErr_TrkNotFnd
  367.                 jmp     StateError_End
  368. StateError_N22: btst    ah,6            ; Bit S6: Laufwerk nicht bereit
  369.                 jnz     StateError_N23
  370.                 mov     al,DErr_NotReady
  371.                 jmp     StateError_End
  372. StateError_N23: mov     al,DErr_GenFail ; Notnagel 1
  373.                 jmp     StateError_End
  374. StateError_N2:  test    al,11h          ; Bit 0/4: Sektor nicht gefunden
  375.                 jz      StateError_N3
  376.                 mov     al,DErr_SecNotFnd
  377.                 jmp     StateError_End
  378. StateError_N3:  btst    al,6            ; Bit 6: Pruefsummenfehler
  379.                 jz      StateError_N4
  380.                 mov     al,DErr_CRCError
  381.                 jmp     StateError_End
  382. StateError_N4:  mov     al,DErr_GenFail ; Notnagel 2
  383. StateError_End: les     bx,[Rh_Ptr]     ; Code einspeichern
  384.                 mov     es:[bx+Rh_Status],al
  385.                 jmp     Error
  386.  
  387. Unknown:        les     bx,[Rh_Ptr]
  388.                 mov     byte ptr es:[bx+Rh_Status],DErr_Unknown ; unbek. Funktion
  389.  
  390. Error:          or      byte ptr es:[bx+Rh_Status+1],80h ; Fehler-Flag setzen
  391.                 jmp     Done
  392.  
  393. Busy:           les     bx,[Rh_Ptr]
  394.                 or      byte ptr es:[bx+Rh_Status+1],2  ; Busy-Flag setzen
  395.  
  396. Done:           les     bx,[Rh_Ptr]
  397.                 or      byte ptr es:[bx+Rh_Status+1],1  ; Done-Flag setzen
  398.  
  399.                 if      debug
  400.                  call   NxtLine
  401.                 endif
  402.  
  403.                 cli                     ; Stack zurueckschalten
  404.                 pop     si
  405.                 pop     di              ; alten in SI:DI laden
  406.                 mov     sp,di           ; einschreiben
  407.                 mov     ss,si
  408.                 sti
  409.  
  410.                 popa                    ; Register zurueck
  411.                 retf
  412.  
  413. ;******************************************************************************
  414. ;* Debugginghilfe                                                             *
  415. ;******************************************************************************
  416.  
  417.                 if      debug||debug2
  418.  
  419. HexTab          db      "0123456789ABCDEF"
  420.  
  421. PrByte:         push    es              ; Register retten
  422.                 push    di
  423.                 push    bx
  424.                 push    ax
  425.  
  426.                 lea     bx,[HexTab]
  427.  
  428.  
  429.                 db      0d4h,10h        ; AAM 16
  430.                 push    ax
  431.                 mov     al,ah
  432.                 xlat
  433.                 mov     ah,0eh
  434.                 int     10h
  435.                 pop     ax
  436.                 xlat
  437.                 mov     ah,0eh
  438.                 int     10h
  439.  
  440.                 pop     ax              ; Register zurueck
  441.                 pop     bx
  442.                 pop     di
  443.                 pop     es
  444.                 ret
  445.  
  446. PrWord:         xchg    ah,al           ; Hi-Byte
  447.                 call    PrByte
  448.                 xchg    ah,al
  449.                 call    PrByte
  450.                 ret
  451.  
  452. PrChar:         push    ax
  453.                 mov     ah,0eh
  454.                 int     10h
  455.                 pop     ax
  456.                 ret
  457.  
  458. NxtLine:        push    ax              ; Register retten
  459.                 push    bx
  460.                 push    dx
  461.  
  462.                 mov     ax,0e0dh
  463.                 int     10h
  464.                 mov     ax,0e0ah
  465.                 int     10h
  466.  
  467.                 pop     dx              ; Register zurueck
  468.                 pop     bx
  469.                 pop     ax
  470.  
  471.                 endif
  472.  
  473. ;******************************************************************************
  474. ;* residente Subfunktionen                                                    *
  475. ;******************************************************************************
  476.  
  477. ;******************************************************************************
  478. ;* eine logische Laufwerksnummer ueberpruefen                                 *
  479. ;*              In  :   AL = Laufwerk                                         *
  480. ;*              Out :   C  = 1, falls Fehler                                  *
  481. ;******************************************************************************
  482.  
  483.                 proc    ChkDrive
  484.  
  485.                 cmp     al,[DrCnt]      ; C=1, falls < (d.h. OK)
  486.                 cmc                     ; Deshalb noch einmal drehen
  487.                 jnc     OK              ; C=0, alles in Butter
  488.                 les     bx,[Rh_Ptr]     ; ansonsten Fehlerstatus setzen
  489.                 mov     byte ptr es:[bx+Rh_Status],DErr_InvUnit
  490. OK:             ret
  491.  
  492.                 endp
  493.  
  494. ;******************************************************************************
  495. ;* Adresse der phys. Laufwerkstabelle errechnen                               *
  496. ;*              In  :   AL = Laufwerk                                         *
  497. ;*              Out :   DI = Adresse                                          *
  498. ;******************************************************************************
  499.  
  500.                 proc    GetPTabAdr
  501.  
  502.                 mov     ah,DrPar_Len    ; relative Adresse berechnen
  503.                 mul     ah
  504.                 lea     di,[DrPars]     ; Offset dazu
  505.                 add     di,ax
  506.                 ret
  507.  
  508.                 endp
  509.  
  510. ;******************************************************************************
  511. ;* Adresse eines Partitionsdeskriptors errechnen                              *
  512. ;*              In  :   AL = log. Laufwerk                                    *
  513. ;*              Out :   DI = Adresse                                          *
  514. ;******************************************************************************
  515.  
  516.                 proc    GetTabAdr
  517.  
  518.                 mov     ah,DrTab_Len    ; relative Adresse berechnen
  519.                 mul     ah
  520.                 lea     di,[DrTab]      ; Offset dazu
  521.                 add     di,ax
  522.                 ret
  523.  
  524.                 endp
  525.  
  526. ;******************************************************************************
  527. ;* logische Parameter in physikalische uebersetzen                            *
  528. ;*              In  :   BL = log. Laufwerk                                    *
  529. ;*                      DX:AX = relative Sektornummer                         *
  530. ;*              Out :   AL = phys. Laufwerk                                   *
  531. ;*                      AH = Kopf                                             *
  532. ;*                      BX = Zylinder                                         *
  533. ;*                      CH = Sektor                                           *
  534. ;******************************************************************************
  535.  
  536.                 proc    TranslateParams
  537.  
  538.                 push    di              ; Register retten
  539.  
  540.                 xchg    bx,ax           ; Adresse Parametertabelle holen
  541.                 call    GetTabAdr      
  542.  
  543.                 add     bx,[di+DrTab_LinStart]   ; in absolute Sektornummer
  544.                 adc     dx,[di+DrTab_LinStart+2] ; umrechnen
  545.                 mov     al,[di+DrTab_Drive]      ; phys. Laufwerksnummer holen
  546.                 push    ax              ; bis zum Ende retten
  547.                
  548.                 call    GetPTabAdr      ; von dieser phys. Platte die Tabelle holen
  549.                 mov     ax,bx           ; Sektor# wieder nach DX:AX
  550.                 mov     bl,[di+DrPar_NSecs] ; Sektorzahl auf 16 Bit
  551.                 mov     bh,0            ; aufblasen
  552.                 div     bx
  553.                 mov     ch,dl           ; Modulo-Rest ist Sektornummer auf
  554.                 inc     ch              ; Spur: Vorsicht, Numerierung ab 1 !!!
  555.                 sub     dx,dx           ; wieder auf 32 Bit erweitern
  556.                 mov     bl,[di+DrPar_Heads] ; Kopfnummer herausfummeln
  557.                 div     bx
  558.                 mov     bx,ax           ; Quotient ist Zylinder
  559.                 pop     ax              ; Laufwerk zurueck
  560.                 mov     ah,dl           ; Rest ist Kopf
  561.  
  562.                 pop     di              ; Register zurueck
  563.                 ret
  564.  
  565.                 endp
  566.  
  567. ;******************************************************************************
  568. ;* Einbindung Low-Level-Routinen                                              *
  569. ;******************************************************************************
  570.  
  571. ; definiert werden muessen:
  572.  
  573. ; LowLevelIdent:  Meldung ueber unterstuetzte Hardware ausgeben
  574. ; ContDiag:       Kontroller-Selbsttest durchfuehren
  575. ;                 Ergebniskode in AL
  576. ; Recalibrate:    Laufwerk [AL] auf Zylinder 0 fahren
  577. ;                 Fehlerflag in C, Fehlerkode in AX
  578. ; SetDriveParams: dem Kontroller die Geometrie fuer Laufwerk [AL] einbleuen
  579. ;                 Fehlerflag in C
  580. ; ReadSectors:    von Laufwerk [AL] ab Zylinder [BX], Kopf [AH], Sektor [CH]
  581. ;                 [CL] Sektoren in Puffer ab ES:DI lesen
  582. ;                 Fehlerflag in C, Fehlerkode in AX
  583. ; WriteSectors:   auf Laufwerk [AL] ab Zylinder [BX], Kopf [AH], Sektor [CH]
  584. ;                 [CL] Sektoren von Puffer ab ES:SI schreiben
  585. ;                 Fehlerflag in C, Fehlerkode in AX
  586. ; VeriSectors:    auf Laufwerk [AL] ab Zylinder [BX], Kopf [AH], Sektor [CH]
  587. ;                 [CL] Sektoren verifizieren
  588. ;                 Fehlerflag in C, Fehlerkode in AX
  589. ; FormatUnit:     Laufwerk [AL] mit Interleave [AH] formatieren, Fehlerkode
  590. ;                 in AX
  591. ; FormatTrack:    Zylinder [BX], Kopf [AH] auf Laufwerk [AL] mit Interleave
  592. ;                 [CL] formatieren, Fehlerkode in AX
  593. ; MarkBad:        Zylinder [BX], Kopf [AH] auf Laufwerk [AL] als defekt
  594. ;                 markieren, Fehlerkode in AX
  595.  
  596.                 include "lowlevel.inc"
  597.  
  598. ;******************************************************************************
  599. ;* Bootsektor eines log. Laufwerkes lesen                                     *
  600. ;*              In  :   AL = Laufwerksnummer                                  *
  601. ;*              Out :   C+AX = Fehlerstatus                                   *
  602. ;******************************************************************************
  603.  
  604.                 proc    ReadBootSec
  605.  
  606.                 push    es              ; Register retten
  607.                 push    bx
  608.                 push    cx
  609.                 push    di
  610.  
  611.                 call    GetTabAdr       ; Eintrag in Laufwerkstabelle ermitteln
  612.                 mov     al,[di+DrTab_Drive] ; davon ersten Sektor lesen
  613.                 mov     ah,[di+DrTab_StartHead]
  614.                 mov     bx,[di+DrTab_StartCyl]
  615.                 mov     cl,1
  616.                 mov     ch,[di+DrTab_StartSec]
  617.                 mov     di,cs
  618.                 mov     es,di
  619.                 lea     di,[SectorBuffer]
  620.                 call    ReadSectors
  621.  
  622.                 pop     di              ; Register zurueck
  623.                 pop     cx
  624.                 pop     bx
  625.                 pop     es
  626.                 ret
  627.  
  628.                 endp
  629.  
  630. ;******************************************************************************
  631. ;* Funktion 1: Test, ob Medium gewechselt                                     *
  632. ;******************************************************************************
  633.  
  634.                 proc    MediaCheck
  635.  
  636. Rh_MediaID      equ     Rh_Resvd+8      ; erwartetes Media-ID
  637. Rh_Return       equ     Rh_MediaID+1    ; Ergebnis-Flag
  638. Rh_VolName      equ     Rh_Return+1     ; Adresse alter Laufwerksname
  639.  
  640.                 cmp     byte ptr es:[bx+Rh_MediaID],HD_ID ; gueltige ID ?
  641.                 je      OK
  642.                 mov     byte ptr es:[bx+Rh_Status],DErr_InvMedia ; nein...
  643.                 jmp     Error
  644. OK:             mov     byte ptr es:[bx+Rh_Return],1 ; nie gewechselt
  645.                 jmp     Done
  646.  
  647.                 endp
  648.  
  649. ;******************************************************************************
  650. ;* Funktion 2: BPB aufbauen                                                   *
  651. ;******************************************************************************
  652.  
  653.                 proc    BuildBPB
  654.  
  655. Rh2             struct
  656.                  db     Rh_Len dup (?)
  657. MediaID          db     ?               ; erwartetes Media-ID
  658. FATSector        dd     ?               ; Pufferadresse 1. FAT-Sektor
  659. BPBAddress       dd     ?               ; Adresse neuer BPB
  660.                 endstruct
  661.  
  662.                 mov     al,es:[bx+Rh_Unit]
  663.                 call    ChkDrive        ; Laufwerksnummer gueltig ?
  664.                 ljc     Error           ; nein-->Fehler & Ende
  665.  
  666.                 call    ReadBootSec     ; Bootsektor lesen
  667.                 ljc     StateError      ; bei Fehlern Ende
  668.  
  669.                 les     bx,[Rh_Ptr]        ; Zeiger neu laden
  670.                 mov     al,es:[bx+Rh_Unit] ; Tabellenadresse aufbauen
  671.                 call    GetTabAdr
  672.                 lea     di,[di+DrTab_BPB]  ; DI auf BPB-Speicher
  673.                 mov     es:[bx+Rh2_BPBAddress],di ; BPB-Zeiger abspeichern
  674.                 mov     es:[bx+Rh2_BPBAddress+2],cs
  675.                
  676.                 mov     si,cs              ; BPB umkopieren
  677.                 mov     es,si
  678.                 lea     si,[SectorBuffer+BPBOfs]
  679.                 cld
  680.                 mov     cx,BPBSize
  681.                 rep     movsb
  682.  
  683.                 jmp     Done
  684.  
  685.                 endp
  686.  
  687. ;******************************************************************************
  688.  
  689. IOCTLRead:      jmp     Unknown
  690.  
  691. ;******************************************************************************
  692. ;* Funktion 4: Sektoren lesen                                                 *
  693. ;******************************************************************************
  694.  
  695. Rh4             struct
  696.                  db     Rh_len dup (?)
  697. MediaID          db     ?               ; Media-ID Laufwerk
  698. BufOfs           dw     ?               ; Adresse Datenpuffer
  699. BufSeg           dw     ?
  700. NSecs            dw     ?               ; Anzahl zu lesender Bloecke
  701. FirstSec         dw     ?               ; Startsektor bzw. $FFFF fuer 32-Bit-Nummern
  702. VolID            dd     ?               ; Adresse Laufwerksname
  703. LFirstSec        dw     ?               ; lange Startsektornummer
  704. HFirstSec        dw     ?
  705.                 endstruct
  706.  
  707. Read:           mov     al,es:[bx+Rh_Unit] ; Laufwerksnummer pruefen
  708.                 call    ChkDrive
  709.                 ljc     Error
  710.  
  711.                 mov     ch,al                   ; Laufwerksnummer retten
  712.                 mov     ax,es:[bx+Rh4_FirstSec] ; Sektor holen (BIGDOS beachten)
  713.                 sub     dx,dx
  714.                 cmp     ax,-1
  715.                 jne     Read_SmallSec
  716.                 mov     ax,es:[bx+Rh4_LFirstSec]
  717.                 mov     dx,es:[bx+Rh4_HFirstSec]
  718. Read_SmallSec:  mov     cl,es:[bx+Rh4_NSecs]    ; Sektorzahl laden (muss <=128 sein)
  719.                 les     di,es:[bx+Rh4_BufOfs]   ; Zieladresse laden
  720.                 mov     bl,ch                   ; Laufwerksnummer nach BL
  721.  
  722.                 if      debug
  723.                  push   ax
  724.                  push   cx
  725.                  mov    cx,ax
  726.                  mov    al,' '
  727.                  call   PrChar
  728.                  mov    al,bl           ; Laufwerksnummer
  729.                  call   PrByte
  730.                  mov    al,' '
  731.                  call   PrChar
  732.                  mov    ax,dx           ; Startsektor
  733.                  call   PrWord
  734.                  mov    ax,cx
  735.                  call   PrWord
  736.                  mov    al,' '
  737.                  call   PrChar
  738.                  pop    cx
  739.                  mov    al,cl           ; Sektorzahl
  740.                  call   PrByte
  741.                  mov    al,' '
  742.                  call   PrChar
  743.                  mov    ax,es           ; Startadresse
  744.                  call   PrWord
  745.                  mov    al,':'
  746.                  call   PrChar
  747.                  mov    ax,di
  748.                  call   PrWord
  749.                  pop    ax
  750.                 endif
  751.  
  752.                 call    TranslateParams         ; umrechnen lassen
  753.                 call    ReadSectors             ; der eigentliche Lesevorgang
  754.  
  755.                 ljc     StateError              ; bei Fehlern...
  756.                 jmp     Done                    ; ansonsten o.k.
  757.  
  758. ;******************************************************************************
  759.  
  760. ND_Read:        jmp     Unknown
  761.  
  762. InputStatus:    jmp     Unknown
  763.  
  764. InputFlush:     jmp     Unknown
  765.  
  766. ;******************************************************************************
  767. ;* Funktion 8: Sektoren schreiben                                             *
  768. ;******************************************************************************
  769.  
  770. Rh8             struct
  771.                  db     Rh_len dup (?)
  772. MediaID          db     ?               ; Media-ID Laufwerk
  773. BufOfs           dw     ?               ; Adresse Datenpuffer
  774. BufSeg           dw     ?
  775. NSecs            dw     ?               ; Anzahl zu lesender Bloecke
  776. FirstSec         dw     ?               ; Startsektor bzw. $FFFF fuer 32-Bit-Nummern
  777. VolID            dd     ?               ; Adresse Laufwerksname
  778. LFirstSec        dw     ?               ; lange Startsektornummer
  779. HFirstSec        dw     ?
  780.                 endstruct
  781.  
  782. DoWrite:        if      debug2
  783.                  mov    al,es:[bx+Rh_Unit]
  784.                  call   PrByte
  785.                  mov    al,' '
  786.                  call   PrChar
  787.                  mov    ax,es:[bx+Rh8_FirstSec]
  788.                  call   PrWord
  789.                  mov    al,' '
  790.                  mov    ax,es:[bx+Rh8_HFirstSec]
  791.                  call   PrWord
  792.                  mov    ax,es:[bx+Rh8_LFirstSec]
  793.                  call   PrWord
  794.                  call   NxtLine
  795.                 endif
  796.  
  797.                 mov     al,es:[bx+Rh_Unit]
  798.                 mov     ch,al                   ; Laufwerksnummer retten
  799.                 mov     ax,es:[bx+Rh8_FirstSec] ; Sektor holen (BIGDOS beachten)
  800.                 sub     dx,dx
  801.                 cmp     ax,-1
  802.                 jne     DWrite_SmallSec
  803.                 mov     ax,es:[bx+Rh8_LFirstSec]
  804.                 mov     dx,es:[bx+Rh8_HFirstSec]
  805. DWrite_SmallSec:mov     cl,es:[bx+Rh8_NSecs]    ; Sektorzahl laden (muss <=128 sein)
  806.                 les     si,es:[bx+Rh8_BufOfs]   ; Zieladresse laden
  807.                 mov     bl,ch                   ; Laufwerksnummer nach BL
  808.  
  809.                 if      debug
  810.                  push   ax
  811.                  push   cx
  812.                  mov    cx,ax
  813.                  mov    al,' '
  814.                  call   PrChar
  815.                  mov    al,bl           ; Laufwerksnummer
  816.                  call   PrByte
  817.                  mov    al,' '
  818.                  call   PrChar
  819.                  mov    ax,dx           ; Startsektor
  820.                  call   PrWord
  821.                  mov    ax,cx
  822.                  call   PrWord
  823.                  mov    al,' '
  824.                  call   PrChar
  825.                  pop    cx
  826.                  mov    al,cl           ; Sektorzahl
  827.                  call   PrByte
  828.                  mov    al,' '
  829.                  call   PrChar
  830.                  mov    ax,es           ; Startadresse
  831.                  call   PrWord
  832.                  mov    al,':'
  833.                  call   PrChar
  834.                  mov    ax,si
  835.                  call   PrWord
  836.                  pop    ax
  837.                 endif
  838.  
  839.                 call    TranslateParams         ; umrechnen lassen
  840.                 call    WriteSectors            ; der eigentliche Lesevorgang
  841.  
  842.                 ret
  843.  
  844. Write:          mov     al,es:[bx+Rh_Unit] ; Laufwerksnummer pruefen
  845.                 call    ChkDrive
  846.                 ljc     Error
  847.  
  848.                 call    DoWrite
  849.  
  850.                 ljc     StateError              ; bei Fehlern...
  851.                 jmp     Done                    ; ansonsten o.k.
  852.  
  853.  
  854. ;******************************************************************************
  855. ;* Funktion 9: Sektoren schreiben mit Ueberpruefung                           *
  856. ;******************************************************************************
  857.  
  858. Rh9             struct
  859.                  db     Rh_len dup (?)
  860. MediaID          db     ?               ; Media-ID Laufwerk
  861. BufOfs           dw     ?               ; Adresse Datenpuffer
  862. BufSeg           dw     ?
  863. NSecs            dw     ?               ; Anzahl zu lesender Bloecke
  864. FirstSec         dw     ?               ; Startsektor bzw. $FFFF fuer 32-Bit-Nummern
  865. VolID            dd     ?               ; Adresse Laufwerksname
  866. LFirstSec        dw     ?               ; lange Startsektornummer
  867. HFirstSec        dw     ?
  868.                 endstruct
  869.  
  870. Write_Verify:   mov     al,es:[bx+Rh_Unit] ; Laufwerksnummer pruefen
  871.                 call    ChkDrive
  872.                 ljc     Error
  873.  
  874.                 call    DoWrite         ; schreiben
  875.  
  876.                 ljc     StateError      ; bei Fehlern vorher abbrechen
  877.  
  878.                 les     bx,[Rh_Ptr]     ; Parameter nochmal fuer Verify laden
  879.                 mov     al,es:[bx+Rh_Unit]
  880.                 mov     ch,al
  881.                 mov     ax,es:[bx+Rh9_FirstSec]
  882.                 sub     dx,dx
  883.                 cmp     ax,-1
  884.                 jne     VWrite_SmallSec
  885.                 mov     ax,es:[bx+Rh9_LFirstSec]
  886.                 mov     dx,es:[bx+Rh9_HFirstSec]
  887. VWrite_SmallSec:mov     cl,es:[bx+Rh9_NSecs]
  888.                 mov     bl,ch
  889.  
  890.                 call    TranslateParams ; nochmal umrechen...
  891.                 call    VeriSectors     ; und prueflesen
  892.  
  893.                 jmp     Done            ; alles gut gegangen
  894.  
  895. ;******************************************************************************
  896.  
  897. OutputStat:     jmp     Unknown
  898.  
  899. OutputFlush:    jmp     Unknown
  900.  
  901. IOCTLWrite:     jmp     Unknown
  902.  
  903. ;******************************************************************************
  904. ;* kein Device wechselbar, Oeffnen/Schliessen interessiert nicht              *
  905. ;******************************************************************************
  906.  
  907. DeviceOpen:     jmp     Done
  908.  
  909. DeviceClose:    jmp     Done
  910.  
  911. Removeable:     jmp     Done
  912.  
  913. ;******************************************************************************
  914.  
  915. OutputTillBusy: jmp     Unknown
  916.  
  917. GenIOCTL:       jmp     Unknown
  918.  
  919. GetLogical:     jmp     Unknown
  920.  
  921. SetLogical:     jmp     Unknown
  922.  
  923. IOCTLQuery:     jmp     Unknown
  924.  
  925. ;******************************************************************************
  926. ;* Funktion 0: Initialisierung                                                *
  927. ;******************************************************************************
  928.  
  929.                 include "secparam.inc"
  930.  
  931. Rh0             struct
  932.                  db     Rh_len dup (?)
  933. Units            db     ?               ; Zahl bedienter Laufwerke
  934. EndOfs           dw     ?               ; Endadresse Offset
  935. EndSeg           dw     ?               ; Endadresse Segment
  936. ParamOfs         dw     ?               ; Parameter Offsetadresse
  937. ParamSeg         dw     ?               ; Parameter Segmentadresse
  938. FirstDrive       db     ?               ; erstes freies Laufwerk
  939. MsgFlag          db     ?               ; Flag, ob DOS Fehler ausgeben darf
  940.                 endstruct
  941.  
  942. Init:           PrMsg   HelloMsg        ; Meldung ausgeben
  943.                 call    LowLevelIdent   ; Startmeldung des Low-Level-Treibers
  944.  
  945.                 mov     byte ptr es:[bx+Rh0_Units],0 ; noch keine Laufwerke
  946.  
  947.                 mov     al,es:[bx+Rh0_FirstDrive] ; Startlaufwerk retten
  948.                 mov     [DrOfs],al
  949.  
  950.                 mov     ax,cs           ; ES auf gem. Segment
  951.                 mov     es,ax
  952.  
  953. ; Schritt 1: Controller pruefen
  954.  
  955.                 PrMsg   DiagMsg0
  956.                 call    ContDiag        ; Diagnose ausfuehren
  957.                 sub     al,Diag_NoError
  958.                 cmp     al,6            ; ausserhalb ?
  959.                 jae     Diag_Over
  960.                 add     al,al           ; Meldung ausrechnen
  961.                 mov     ah,0
  962.                 mov     si,ax
  963.                 mov     dx,DiagMsgTable[si]
  964.                 mov     ah,9
  965.                 int     INT_DOS
  966.                 or      si,si           ; fehlerfrei ?
  967.                 ljnz    Init_Err        ; Nein, Fehler
  968.                 jmp     Init_ChkDrives  ; Ja, weiter zum Laufwerkstest
  969.  
  970. Diag_Over:      push    ax
  971.                 PrMsg   UndefDiagMsg    ; undefinierter Fehlercode
  972.                 pop     ax
  973.                 add     al,Diag_NoError ; Meldung rueckkorrigieren
  974.                 db      0d4h,10h        ; AAM 16
  975.                 add     ax,'00'
  976.                 push    ax
  977.                 mov     al,ah
  978.                 mov     ah,14
  979.                 int     10h
  980.                 pop     ax
  981.                 mov     ah,14
  982.                 int     10h
  983.                 PrChar  CR
  984.                 PrChar  LF
  985.                 jmp     Init_Err
  986.  
  987.  
  988. ; Schritt 2: Laufwerke testen
  989.  
  990. ; Menueaufruf?
  991.  
  992. Init_ChkDrives: mov     ax,40h          ; CTRL gedrueckt ?
  993.                 mov     es,ax
  994.                 btst    byte ptr es:[17h],2
  995.                 jz      Init_Menu
  996.                 call    DiskMenu
  997.  
  998. ; Schritt 2a: Laufwerk rekalibrieren
  999.  
  1000. Init_Menu:      mov     al,[MomDrive]
  1001.                 call    Recalibrate
  1002.                 ljc     Init_NextDrive  ; Fehler: Laufwerk ueberspringen
  1003.  
  1004. ; Schritt 2b: Masterpartitionssektor lesen
  1005.  
  1006. ReadMaster:     mov     al,[MomDrive]
  1007.                 mov     ah,0            ; Kopf...
  1008.                 sub     bx,bx           ; ...Zylinder...
  1009.                 mov     cx,0101h        ; ...ein Sektor ab Sektor 1
  1010.                 mov     di,ds
  1011.                 mov     es,di
  1012.                 lea     di,[SectorBuffer] ; in den Sektorpuffer
  1013.                 call    ReadSectors
  1014.                 JmpOnError [MomDrive],Init_NextDrive ; Fehler ?
  1015.  
  1016. ; Schritt 2c: Laufwerksparameter initialisieren
  1017.  
  1018.                 lea     si,[SectorBuffer+DrPar_Offset] ; Quelladresse im Sektor
  1019.                 mov     al,[MomDrive]   ; Zieladresse ausrechnen
  1020.                 call    GetPTabAdr
  1021.                 mov     cx,DrPar_Len
  1022.                 cld
  1023.                 rep     movsb
  1024.  
  1025.                 sub     di,DrPar_Len    ; Laufwerk nicht initialisiert ?
  1026.                 cmp     word ptr[di+DrPar_Cyls],0
  1027.                 je      DoQuery
  1028.                 cmp     byte ptr[di+DrPar_Heads],0
  1029.                 je      DoQuery
  1030.                 cmp     byte ptr[di+DrPar_NSecs],0
  1031.                 jne     NoQuery
  1032. DoQuery:        mov     al,[MomDrive]   ; wenn ja, dann nachfragen
  1033.                 mov     ah,1            ; Rueckschreiben hier erlaubt
  1034.                 call    QueryParams
  1035.                 or      al,al           ; =0-->Laufwerk ignorieren
  1036.                 jz      Init_NextDrive
  1037.                 dec     al              ; =1-->nochmal lesen
  1038.                 jz      ReadMaster      ; ansonsten weitermachen
  1039.  
  1040. NoQuery:        mov     al,[MomDrive]   ; Laufwerksparameter ausgeben...
  1041.                 call    PrintPDrive
  1042.                 mov     al,[MomDrive]   ; ...und dem Controller einbleuen
  1043.                 call    SetDriveParams
  1044.                 JmpOnError [MomDrive],Init_NextDrive
  1045.                 mov     al,[MomDrive]
  1046.                 call    Recalibrate
  1047.                 JmpOnError [MomDrive],Init_NextDrive
  1048.  
  1049. ; Schritt 2d: durch die Partitionssektoren hangeln
  1050.  
  1051.                 mov     al,[MomDrive]   ; Laufwerk : momentanes
  1052.                 cbw                     ; Kopf : 0
  1053.                 push    ax
  1054.                 sub     ax,ax
  1055.                 push    ax              ; Zylinder : 0
  1056.                 inc     ax              ; Sektor : 1
  1057.                 push    ax
  1058.                 dec     ax
  1059.                 push    ax              ; lin. Sektornummer 0
  1060.                 push    ax
  1061.                 call    ScanParts
  1062.  
  1063. Init_NextDrive: inc     [MomDrive]      ; Zaehler weitersetzen
  1064.                 cmp     [MomDrive],MaxPDrives
  1065.                 ljb     Init_ChkDrives
  1066.  
  1067.                 cmp     [DrCnt],0       ; keine Partitionen gefunden ?
  1068.                 jne     Init_PDrives
  1069.                 PrMsg   ErrMsgNoDrives  ; ja: meckern
  1070.                 jmp     Init_Err
  1071.  
  1072. Init_PDrives:   PrMsg   LDriveMsg
  1073.                 mov     [MomDrive],0    ; Parameter der Partitionen ausgeben
  1074.                 lea     bp,[DrTab_BPBs] ; und BPB-Tabelle aufbauen
  1075.                 cld
  1076.  
  1077. Init_PLDrives:  mov     al,[MomDrive]
  1078.                 call    PrintLDrive
  1079.  
  1080.                 mov     al,[MomDrive]   ; Bootsdektor lesen
  1081.                 call    ReadBootSec
  1082.                 lea     si,[SectorBuffer+BPBOfs] ; BPB rauskopieren
  1083.                 mov     al,[MomDrive]
  1084.                 call    GetTabAdr
  1085.                 lea     di,[di+DrTab_BPB]
  1086.                 mov     ax,cs
  1087.                 mov     es,ax
  1088.                 mov     ds:[bp],di      ; Adresse nebenbei ablegen
  1089.                 add     bp,2
  1090.                 mov     cx,BPBSize
  1091.                 rep     movsb
  1092.  
  1093.                 inc     [MomDrive]
  1094.                 mov     al,[MomDrive]
  1095.                 cmp     al,[DrCnt]
  1096.                 jb      Init_PLDrives
  1097.  
  1098.                 PrChar  LF              ; sieht besser aus...
  1099.  
  1100.                 les     bx,[Rh_Ptr]     ; Zeiger auf BPB-Zeiger einschreiben
  1101.                 lea     ax,[DrTab_BPBs]
  1102.                 mov     es:[bx+Rh0_ParamOfs],ax
  1103.                 mov     es:[bx+Rh0_ParamSeg],cs
  1104.                 jmp     Init_OK         ; Initialisierung erfolgeich zu Ende
  1105.  
  1106. Init_Err:       PrMsg   WKeyMsg
  1107.                 xor     ah,ah           ; damit Meldung lesbar bleibt
  1108.                 int     16h
  1109.                 sub     ax,ax           ; Treiber aus Speicher entfernen
  1110.                 jmp     Init_End
  1111.  
  1112. Init_OK:        mov     al,[DrCnt]      ; Laufwerkszahl holen
  1113.                 les     bx,[Rh_Ptr]
  1114.                 mov     es:[bx+Rh0_Units],al ; im Request Header eintragen
  1115.                 mov     [NrOfVols],al   ; im Treiberkopf eintragen
  1116.                 lea     ax,[Init]       ; residenten Teil installieren
  1117.  
  1118. Init_End:       les     bx,[Rh_Ptr]
  1119.                 mov     es:[bx+Rh0_EndOfs],ax ; Endadresse setzen
  1120.                 mov     es:[bx+Rh0_EndSeg],cs
  1121.  
  1122.                 jmp     Done
  1123.  
  1124. ;******************************************************************************
  1125. ;* transiente Unterroutinen                                                   *
  1126. ;******************************************************************************
  1127.  
  1128. ;******************************************************************************
  1129. ;* Partitionsbaum durchgehen                                                  *
  1130. ;*              In  :   dw Kopf/Laufwerk                                      *
  1131. ;*                      dw Zylinder                                           *
  1132. ;*                      dw Sektor                                             *
  1133. ;*                      dd lineare Nummer des Sektors                         *
  1134. ;******************************************************************************
  1135.  
  1136. ScParts_DrHd    equ     12              ; Parameteradressen auf Stack
  1137. ScParts_Cyl     equ     10
  1138. ScParts_Sec     equ     8
  1139. ScParts_LinSec  equ     4
  1140. ScParts_ParTab  equ     0-(MaxParts*ParTab_Len)   ; Kopie Partitionstabelle
  1141. ScParts_LocSize equ     0-ScParts_ParTab          ; belegter Stack
  1142.  
  1143. ScanParts:      enter   ScParts_LocSize,0
  1144.  
  1145. ; Partitionssektor lesen
  1146.  
  1147.                 mov     ax,[bp+ScParts_DrHd]
  1148.                 mov     bx,[bp+ScParts_Cyl]
  1149.                 mov     ch,[bp+ScParts_Sec]
  1150.                 mov     cl,1
  1151.                 mov     di,cs
  1152.                 mov     es,di
  1153.                 lea     di,[SectorBuffer]
  1154.                 call    ReadSectors
  1155.                 JmpOnError [MomDrive],ScanParts_End
  1156.  
  1157. ; Partitionssektorkennung o.k. ?
  1158.  
  1159.                 cmp     word ptr SectorBuffer[ParSecID_Offset],0aa55h
  1160.                 ljne    ScanParts_End
  1161.  
  1162. ; Partitionstabelle auslesen
  1163.  
  1164.                 lea     si,[SectorBuffer+ParTab_Offset] ; Quelladresse
  1165.                 mov     di,ss           ; Zieladresse auf Stack
  1166.                 mov     es,di
  1167.                 lea     di,[bp+ScParts_ParTab]
  1168.                 mov     cx,MaxParts*ParTab_Len  ; Laenge
  1169.                 cld
  1170.                 rep     movsb
  1171.  
  1172. ; Partitionstabelle durchgehen
  1173.  
  1174.                 mov     si,ScParts_ParTab       ; vorne anfangen
  1175.                 mov     cx,MaxParts             ; alle durchgehen
  1176. ScanParts_Scan: push    cx
  1177.  
  1178.                 mov     al,[bp+si+ParTab_Type]  ; Typ der Partition lesen
  1179.                 lea     bx,[AccPartTypes-1]     ; auf Suchtabelle
  1180. ScanParts_LAcc: inc     bx                      ; einen Eintrag weiter
  1181.                 cmp     byte ptr [bx],0         ; Tabellenende ?
  1182.                 je      ScanParts_Next          ; ja-->war nix
  1183.                 cmp     al,[bx]                 ; gefunden ?
  1184.                 jne     ScanParts_LAcc          ;
  1185.  
  1186.                 mov     bx,[bp+si+ParTab_LinSec] ; linearen Startsektor ausrechnen
  1187.                 mov     cx,[bp+si+ParTab_LinSec+2]
  1188.                 add     bx,[bp+ScParts_LinSec]  ; in CX:BX
  1189.                 adc     cx,[bp+ScParts_LinSec+2]
  1190.  
  1191.                 cmp     al,5                    ; extended partition ?
  1192.                 jne     ScanParts_Enter
  1193.  
  1194.                 push    si                      ; ja: Zeiger fuer Rekursion retten
  1195.                 mov     al,[bp+ScParts_DrHd]    ; Laufwerk & Kopf zusammenbauen
  1196.                 mov     ah,[bp+si+ParTab_FHead]
  1197.                 push    ax
  1198.                 mov     ax,[bp+si+ParTab_FSecCyl] ; Zylinder ausfiltern
  1199.                 xchg    ah,al
  1200.                 shr     ah,6
  1201.                 push    ax
  1202.                 mov     al,[bp+si+ParTab_FSecCyl] ; Sektor ausfiltern
  1203.                 and     ax,63
  1204.                 push    ax
  1205.                 push    cx
  1206.                 push    bx
  1207.                 call    ScanParts
  1208.                 pop     si                      ; Zeiger zurueck
  1209.                 jmp     ScanParts_Next
  1210.  
  1211. ScanParts_Enter:mov     al,[DrCnt]              ; Partition in Tabelle eintragen
  1212.                 call    GetTabAdr               ; dazu Adresse neuen Eintrags holen
  1213.                 cld
  1214.                 mov     ax,cs                   ; Ziel im Segment
  1215.                 mov     es,ax
  1216.                 mov     al,[bp+si+ParTab_FHead] ; Kopf kopieren
  1217.                 stosb  
  1218.                 mov     ax,[bp+si+ParTab_FSecCyl] ; Zylinder kopieren
  1219.                 xchg    ah,al
  1220.                 shr     ah,6
  1221.                 stosw
  1222.                 mov     al,[bp+si+ParTab_FSecCyl] ; Sektor kopieren
  1223.                 and     al,63
  1224.                 stosb
  1225.                 mov     ax,bx                   ; linearen Startsektor kopieren
  1226.                 stosw
  1227.                 mov     ax,cx
  1228.                 stosw
  1229.                 mov     ax,[bp+si+ParTab_NSecs] ; Sektorzahl kopieren
  1230.                 stosw
  1231.                 mov     ax,[bp+si+ParTab_NSecs+2]
  1232.                 stosw
  1233.                 mov     al,[bp+ScParts_DrHd]    ; Laufwerksnummer kopieren
  1234.                 stosb
  1235.                 inc     [DrCnt]                 ; ein log. Laufwerk mehr
  1236.  
  1237. ScanParts_Next: add     si,ParTab_Len           ; auf naechste Partition
  1238.                 pop     cx
  1239.                 dec     cx
  1240.                 ljnz    ScanParts_Scan
  1241.  
  1242. ScanParts_End:  leave
  1243.                 ret     10
  1244.  
  1245. ;******************************************************************************
  1246. ;* Daten eines physikalischen Laufwerks ausgeben                              *
  1247. ;*              In  :   AL = Laufwerk                                         *
  1248. ;******************************************************************************
  1249.  
  1250.                 proc    PrintPDrive
  1251.  
  1252.                 push    cx              ; Register retten
  1253.                 push    dx
  1254.                 push    di
  1255.  
  1256.                 cbw                     ; AH loeschen
  1257.                 push    ax              ; Laufwerk ausgeben
  1258.                 PrMsg   PDriveMsg1
  1259.                 pop     ax
  1260.                 push    ax
  1261.                 inc     ax
  1262.                 mov     cl,1
  1263.                 call    WriteDec
  1264.                 PrMsg   PDriveMsg2
  1265.  
  1266.                 pop     ax              ; Adresse Laufwerkstabelle berechnen
  1267.                 call    GetPTabAdr
  1268.  
  1269.                 mov     ax,[di+DrPar_Cyls] ; Zylinder ausgeben
  1270.                 mov     cl,5
  1271.                 call    WriteDec
  1272.                 PrMsg   PDriveMsg3
  1273.  
  1274.                 mov     al,[di+DrPar_Heads] ; Koepfe ausgeben
  1275.                 mov     ah,0
  1276.                 mov     cl,3
  1277.                 call    WriteDec
  1278.                 PrMsg   PDriveMsg4
  1279.  
  1280.                 mov     al,[di+DrPar_NSecs] ; Sektoren ausgeben
  1281.                 mov     ah,0
  1282.                 mov     cl,4
  1283.                 call    WriteDec
  1284.                 PrMsg   PDriveMsg5
  1285.  
  1286.                 mov     al,[di+DrPar_Heads] ; Gesamtsektorzahl berechnen
  1287.                 mul     byte ptr [di+DrPar_NSecs]
  1288.                 mul     word ptr [di+DrPar_Cyls]
  1289.                 call    WriteMBytes
  1290.                 PrMsg   PDriveMsg6
  1291.  
  1292.                 pop     di              ; Register zurueck
  1293.                 pop     dx
  1294.                 pop     cx
  1295.                 ret
  1296.  
  1297.                 endp
  1298.  
  1299. ;******************************************************************************
  1300. ;* Daten eines logischen Laufwerks ausgeben                                   *
  1301. ;*              In  :   AL = Laufwerk                                         *
  1302. ;******************************************************************************
  1303.  
  1304.                 proc    PrintLDrive
  1305.  
  1306.                 push    cx              ; Register retten
  1307.                 push    dx
  1308.                 push    di
  1309.  
  1310.                 mov     dx,ax           ; Laufwerk retten
  1311.                 push    dx
  1312.                 mov     cx,3            ; ausgeben
  1313.                 call    WriteSpc
  1314.                 add     dl,[DrOfs]
  1315.                 add     dl,'A'
  1316.                 mov     ah,DOS_WrChar
  1317.                 int     INT_DOS
  1318.                 PrChar  ':'
  1319.  
  1320.                 pop     ax              ; Tabelle holen
  1321.                 call    GetTabAdr
  1322.  
  1323.                 mov     al,[di+DrTab_Drive] ; Laufwerk ausgeben...
  1324.                 inc     al
  1325.                 cbw
  1326.                 mov     cl,9
  1327.                 call    WriteDec
  1328.  
  1329.                 mov     ax,[di+DrTab_StartCyl] ; ...Zylinder...
  1330.                 mov     cl,10
  1331.                 call    WriteDec
  1332.  
  1333.                 mov     al,[di+DrTab_StartHead] ; ...Kopf...
  1334.                 cbw
  1335.                 mov     cl,7
  1336.                 call    WriteDec
  1337.  
  1338.                 mov     al,[di+DrTab_StartSec] ; ...Sektor...
  1339.                 cbw
  1340.                 mov     cl,8
  1341.                 call    WriteDec
  1342.  
  1343.                 mov     cx,2
  1344.                 call    WriteSpc
  1345.                 mov     ax,[di+DrTab_SecCnt] ; ...Groesse
  1346.                 mov     dx,[di+DrTab_SecCnt+2]
  1347.                 call    WriteMBytes
  1348.  
  1349.                 PrMsg   PDriveMsg6      ; Meldung wiederverwertet...
  1350.  
  1351.                 pop     di              ; Register zurueck
  1352.                 pop     dx
  1353.                 pop     cx
  1354.                 ret
  1355.  
  1356.                 endp
  1357.  
  1358. ;******************************************************************************
  1359. ;* Fehlercode eines Laufwerks ausgeben                                        *
  1360. ;*              In :    AL = Fehlercode                                       *
  1361. ;*                      AH = Laufwerksnummer (0,1...)                         *
  1362. ;******************************************************************************
  1363.  
  1364.                 proc    WrErrorCode
  1365.  
  1366.                 push    bx              ; Register retten
  1367.                 push    cx
  1368.                 push    dx
  1369.  
  1370.                 add     ah,'1'          ; LW-Nummer in ASCII umrechnen...
  1371.                 mov     [DrvErrorMsg2],ah ; ...und einschreiben
  1372.                 mov     ch,al           ; Kode sichern
  1373.                 PrMsg   DrvErrorMsg
  1374.                 mov     cl,7            ; bei Bit 0 anfangen
  1375. ErrLoop:        rol     ch,1            ; fagl. Bit in Carry
  1376.                 jnc     NoErrBit
  1377.                 mov     bl,cl           ; Bit gefunden: Index ausrechnen
  1378.                 mov     bh,0
  1379.                 add     bx,bx
  1380.                 mov     dx,[bx+Pointers]
  1381.                 mov     ah,DOS_WrString
  1382.                 int     INT_DOS
  1383. NoErrBit:       dec     cl              ; naechstes Bit
  1384.                 jnz     ErrLoop
  1385.  
  1386.                 pop     dx              ; Register zurueck
  1387.                 pop     cx
  1388.                 pop     bx
  1389.  
  1390.                 ret
  1391.  
  1392. DrvErrorMsg:    db      "Fehler auf Festplatte "
  1393. DrvErrorMsg2:   db      "0:",CR,LF,'$'
  1394.  
  1395. Pointers        dw      Msg0,Msg1,Msg2,Msg3,Msg4,Msg5,Msg6,Msg7
  1396. Msg0            db      "  Adre",SZLIG,"marke nicht gefunden",CR,LF,'$'
  1397. Msg1            db      "  Spur 0 nicht gefunden",CR,LF,'$'
  1398. Msg2            db      "  Kommandoabbruch",CR,LF,'$'
  1399. Msg3            db      "$"
  1400. Msg4            db      "  Sektor nicht gefunden",CR,LF,'$'
  1401. Msg5            db      "$"
  1402. Msg6            db      "  Datenfehler",CR,LF,'$'
  1403. Msg7            db      "  Sektor als defekt markiert",CR,LF,'$'
  1404.  
  1405.                 endp
  1406.  
  1407. ;******************************************************************************
  1408. ;* Sektorenzahl als MBytes ausgeben                                           *
  1409. ;*              In:     DX:AX = Sektorzahl                                    *
  1410. ;******************************************************************************
  1411.  
  1412.                 proc    WriteMBytes
  1413.  
  1414. SecsPerMByte    equ     (2^20)/SecSize
  1415.  
  1416.                 push    cx              ; Register retten
  1417.                 push    dx
  1418.  
  1419.                 add     ax,SecsPerMByte/20 ; wg. Rundung
  1420.                 adc     dx,0
  1421.  
  1422.                 mov     cx,SecsPerMByte ; durch 2048 teilen = MByte
  1423.                 div     cx
  1424.                 push    dx              ; Nachkommastellen retten
  1425.                 mov     cl,6
  1426.                 call    WriteDec
  1427.  
  1428.                 PrChar  '.'             ; Nachkommastelle
  1429.                 pop     ax              ; holen
  1430.                 cwd
  1431.                 mov     cx,SecsPerMByte/10 ; Sektoren pro 100 KByte
  1432.                 div     cx
  1433.                 mov     cl,1            ; ausgeben
  1434.                 call    WriteDec
  1435.  
  1436.                 pop     dx              ; Register zurueck
  1437.                 pop     cx
  1438.                 ret
  1439.  
  1440.                 endp
  1441.  
  1442. ;******************************************************************************
  1443. ;* transiente Daten                                                           *
  1444. ;******************************************************************************
  1445.  
  1446. HelloMsg:       db      CR,LF,"SekundДrlaufwerkstreiber V0.4",CR,LF,'$'
  1447.  
  1448. ErrMsgNoDrives: db      CR,LF,"Fehler: keine Partitionen gefunden",CR,LF,'$'
  1449.  
  1450. DiagMsg0:       db      CR,LF,"Controller-Selbsttest: ",'$'
  1451. DiagMsg1:       db      "OK",CR,LF,'$'
  1452. DiagMsg2:       db      "Controller fehlerhaft",CR,LF,'$'
  1453. DiagMsg3:       db      "Sektorpuffer defekt",CR,LF,'$'
  1454. DiagMsg4:       db      "Fehlerkorrektur defekt",CR,LF,'$'
  1455. DiagMsg5:       db      "Steuerprozessor defekt",CR,LF,'$'
  1456. DiagMsg6:       db      "Timeout",CR,LF,'$'
  1457. DiagMsgTable    dw      DiagMsg1,DiagMsg2,DiagMsg3,DiagMsg4,DiagMsg5,DiagMsg6
  1458. UndefDiagMsg    db      "Unbekannter Fehlercode #$"
  1459. WKeyMsg:        db      "Weiter mit beliebiger Taste...",CR,LF,'$'
  1460.  
  1461. PDriveMsg1:     db      "Festplatte $"
  1462. PDriveMsg2:     db      " :$"
  1463. PDriveMsg3:     db      " Zylinder,$"
  1464. PDriveMsg4:     db      " K",OUML,"pfe,$"
  1465. PDriveMsg5:     db      " Sektoren,$"
  1466. PDriveMsg6:     db      " MByte",CR,LF,'$'
  1467.  
  1468. LDriveMsg:      db      CR,LF,"vorhandene Partitionen:",CR,LF
  1469.                 db      "Laufwerk  Platte  Zylinder  Kopf"
  1470.                 db      "  Sektor      Kapazit",AUML,"t",CR,LF,'$'
  1471.  
  1472. AccPartTypes    db      1               ; akzeptierte Partitionstypen: DOS 2.x FAT12
  1473.                 db      4               ; DOS 3.x FAT16
  1474.                 db      5               ; DOS 3.3 extended
  1475.                 db      6               ; DOS 3.31 >32 MByte
  1476.                 db      0               ; Tabellenende
  1477.  
  1478. MomDrive        db      0               ; momentan gescanntes Laufwerk
  1479.  
  1480.                 end
  1481.