Autor Thema: Diskette: int 13h im PM  (Gelesen 19624 mal)

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« am: 11. December 2005, 12:54 »
Hi,

also ich habe mein OS jetzt im PM mit Multitasking laufen. Jetzt möchte ich einen Diskettentreiber schreiben. Also z.B. um Sektore zu lesen, zu schreiben. Das habe ich im RM mit dem int 13h gemacht. Wie mache ich das im PM? Welche Ports benötige ich. Kennt ihr ein gutes Tutorial oder so dazu?

Danke!!!
In the Future everyone will need OS-64!!!

C#ris

  • Beiträge: 47
    • Profil anzeigen
    • http://www.xerxys.org
Gespeichert
« Antwort #1 am: 11. December 2005, 17:06 »
Hi!

Das Ding heißt Intel 82078 Floppy Controller. Ich hab mal angefangen einen Treiber für zu schreiben.


; Driver for Intel 82078 Floppy Controller
; (C)Copyright 2004 by NucleusKL Team & Authors
; Authors: Christian Lins
; Published under GPL - General Public License
; Last change: 17.02.2004

;; Primary
Port0SRB db 3F1h ; R/W Status Register B
Port0DOR db 3F2h ; R/W Digital Output Register
Port0TDR db 3F3h ; R/W Tape Drive Register
Port0MSR db 3F4h ; R Main Status Register
Port0DSR db 3F4h ; W Data Rate Select Register
Port0FIFO db 3F5h ; R/W Data (FIFO)
Port0DIR db 3F7h ; R Digital Input Register
Port0CCR db 3F7h ; W Configuration Control Register

;; Secondary
Port1SRB db 371h ; R/W Status Register B
Port1DOR db 372h ; R/W Digital Output Register
Port1TDR db 373h ; R/W Tape Drive Register
Port1MSR db 374h ; R Main Status Register
Port1DSR db 374h ; W Data Rate Select Register
Port1FIFO db 375h ; R/W Data (FIFO)
Port1DIR db 377h ; R Digital Input Register
Port1CCR db 377h ; W Configuration Control Register

ActiveDrive dw 0000h ; Nummer des aktiven Laufwerks

;; Initialisiert den FC82078
_fc82078_init:
; Paramter ActiveDrive 0, 1, 2, 3
pop ax ;ActiveDrive

call _fc82078_read_msr

; Bit 2 im DOR für Reset setzen
mov dx, Port0DOR
mov al, 00000100b
out dx, al

call _fc82078_read_msr
ret


;; Aktiviert den Motor des aktiven Laufwerks
_fc82078_motor_on:
mov dx, Port0DOR
mov al, 00010000b
out dx, al ; TODO: Drive 0 gewählt, ActiveDrive sollte gewählt werden

call _fc82078_read_msr
push 0
ret


;; Deaktiviert den Motor des aktiven Laufwerks
_fc82078_motor_off:
mov dx, Port0DOR
mov al, 0x0
out dx, al ; TODO: Drive 0 gewählt, ActiveDrive sollte gewählt werden

call _fc82078_read_msr
push 0
ret


;; Wählt die Übertragungsgeschwindigkeit
_fc82078_datarate:
push ax
mov dx, Port0DSR
mov al, 00000010b
out dx, al ; TODO: 250 kbps gewählt, andere Geschwindigkeiten sollten möglich sein
push 0
ret


;; Liest das Status Register und speichert es in al
_fc82078_read_msr:
xor al, al
mov dx, Port0MSR
in al, dx
;mov MSR, al
ret


;; Liest 16 Bytes aus dem FIFO (ohne DMA)
_fc82078_read_fifo:
mov dx, Port0FIFO
__readfifo_loop:
in al, dx ; Liest ein Byte
mov ah, al
in al, dx ; Liest noch ein Byte
push ax ; Speichert das Word auf dem Stack
call _fc82078_read_msr
cmp al, 80h ; Vergleicht ob das Lesen nun zu Ende ist
jne __readfifo_loop

push 0
ret


;; Schreibt 16 Bytes in das FIFO Register (ohne DMA)
_fc82078_write_fifo:
mov dx, Port0FIFO
__writefifo_loop:
pop ax
xchg al, ah
out dx, al
xchg al, ah
out dx, al
call _fc82078_read_msr
cmp al, 80h
jne __writefifo_loop

push 0
ret


;; Schreibt einen Befehl



Zumindest das Anschalten und Ausschalten sollte funktionieren. Vielleicht hilft dir das.

C#ris

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« Antwort #2 am: 11. December 2005, 17:31 »
Hallo, ich hab mal ein Modul in ASM geschrieben, mit dem man auch lesen und schreiben auf Disketten kann (funktionierte auch). Ist zwar etwas lang, aber ich wollt es dir nicht per Mail schicken, falls eventuell noch jemand Anderes Interesse daran hat...
Also, hier der Code (sind eigentlich 2 Dateien), interessant dürften die Funktionen FDD_WRITE_BLOCK und FDD_READ_BLOCK bzw stdfdc_read_block und stdfdc_write_block sein:

;***************************************************************************
;*** FDD                                                                 ***
;***************************************************************************
; Enth„lt Funktionen f?r den Zugriff auf das Floppylaufwerk.

; Maximale L„nge einer Path-Angabe (inclusive 0):
#define MAX_PATH_LEN 100

; Struktur mit allen Daten ?ber das FDD:
#struct_start FDD_DATA_STRUCT
  installed db 0 ; Merker, ob ein FDD installiert ist.
  user dw 0 ; TSS des aktuellen Nutzers (0 wenn keiner).
  floppy_sectors_per_fat dw 0 ; Anzahl der Sektoren pro FAT.
  floppy_root_entrys dw 0 ; Maximale Anzahl an Eintr„gen im Root.
  floppy_root_startblock dw 0 ; Startblock des Root.
  floppy_fat_startblock dw 0 ; Startblock der 1. FAT.
  buffer_blocks dw #dup(0,8) ; Nummern der Blocks in den einzelnen Buffern (bei -1 unbenutzt).
  next_buffer dw 0 ; Nummer des n„chsten Bufferers zum ?berschreiben.
#struct_end
FDD_DATA_STRUCT fdd_data

;----------------------------------------------------------------------------
; FDD_INIT
;----------------------------------------------------------------------------
; Initialisiert das Floppylaufwerk.
; (cl<- = 0 - Fehler, 1 - OK)
@fdd_init(){
; Pr?fen, ob ?berhaupt ein FDD installiert ist:
        cmp     byte ptr [hw_fdc],0
        jz      .not_installed
        cmp     byte ptr [hw_floppys],0
        jz      .not_installed

        mov     byte ptr [fdd_data_installed],1

; Den FDC zur?cksetzen (auch ohne eingelegte Disk):
        push    bx
        call    fdc_reset
        pop     bx
; Alle Daten ?ber die Floppy zur?cksetzen (auch ohne eingelegte Disk):
        call    fdd_init_floppy_disk_changed

; Alle Buffer l”schen:
        push    cx
        push    edi
        mov     cx,8
        mov     edi,fdd_data_buffer_blocks
.reset_buffer_loop:
        mov     word ptr [edi],-1
        add     edi,2
        loop    .reset_buffer_loop
        pop     edi
        mov     cx,[stdfdc_dma_buffer_base]
        mov     [stdfdc_dma_buffer],cx
        mov     word ptr [fdd_data_next_buffer],0
        pop     cx

        mov     cl,1
        ret

.not_installed:
        mov     byte ptr [fdd_data_installed],0
        @add_error(dword num ERROR_FDD_NOT_INSATLLED)
       
.error:
        mov     cl,0
        ret
}

;----------------------------------------------------------------------------
; FDD_INIT_FLOPPY
;----------------------------------------------------------------------------
; Initialisiert alle Werte nach dem Wechsel einer Diskette.
; (cl<- = 0 - Fehler, 1 - OK)
fdd_init_floppy:
        @fdd_login()
        or      cl,cl
        jz      fdd_init_floppy_in_use
; Testen, ob die Diskette gewechselt wurde:
        call    check_diskchange
        or      cl,cl
        jnz     fdd_init_floppy_disk_changed
; Die Diskette wurde nicht gewechselt, neuladen der Daten daher unn”tig.
        mov     cl,1
        @fdd_logout()
        ret

fdd_init_floppy_disk_changed:
        push    ax
        push    bx
        push    dx
        push    gs
        push    edi
        mov     ax,[_des_global_]
        mov     gs,ax

; Alle Buffer l”schen:
        push    cx
        mov     cx,8
        mov     edi,fdd_data_buffer_blocks
.reset_buffer_loop:
        mov     word ptr [edi],-1
        add     edi,2
        loop    .reset_buffer_loop
        mov     cx,[stdfdc_dma_buffer_base]
        mov     [stdfdc_dma_buffer],cx
        pop     cx

; Den Bootsektor laden (in den ersten Buffer):
        @stdfdc_read_block(word num 0)
        or      cl,cl
        jz      fdd_init_floppy_error

        xor     edi,edi
        mov     di,[stdfdc_dma_buffer]
        ; Rooteintr„ge:
        gs:
        mov     ax,[edi+11]
        mov     [fdd_data_floppy_root_entrys],ax
        ; Sektoren/FAT:
        gs:
        mov     ax,[edi+16]
        mov     [fdd_data_floppy_sectors_per_fat],ax
        ; Root-Startblock (FATs*Size of FAT)+hidden sectors+reserved sectors:
        xor     bx,bx

        gs:
        mov     bl,[edi+10] ; Anzahl der FATs.
        mul     bx
        gs:
        add     ax,[edi+0E]
        gs:
        add     ax,[edi+1C]
        mov     [fdd_data_floppy_root_startblock],ax
        ; FAT-Startblock:
        gs:
        mov     ax,[edi+0E]
        mov     [fdd_data_floppy_fat_startblock],ax

        ; Block Nummer 0 nun im 1. Buffer:
        mov     word ptr [fdd_data_buffer_blocks],0
        add     word ptr [stdfdc_dma_buffer],200
        mov     word ptr [fdd_data_next_buffer],1

        pop     edi
        pop     gs
        pop     dx
        pop     bx
        pop     ax
        mov     cl,1
        @fdd_logout()
        ret

fdd_init_floppy_error:
        pop     edi
        pop     gs
        pop     dx
        pop     bx
        pop     ax
        xor     cl,cl
        @fdd_logout()
        ret

fdd_init_floppy_in_use:

        @add_error(dword num ERROR_FDD_IN_USE)
        xor     cl,cl
        ret

;----------------------------------------------------------------------------
; FDD_LOGIN
;----------------------------------------------------------------------------
; Pr?ft, ob die Floppy gerade von jemand anderen benutzt wird. Wenn nicht,
; dann wird das aktuelle TSS eingetragen.
; (cl<- = 0 - Fehler, 1 - OK)
fdd_login_count: dd 0 ; Z„hler, wie oft der Benutzer sich einloggt.
@fdd_login(){
        push    cx
        str     cx
        ; Schon eingeloggt:
        cmp     [fdd_data_user],cx
        jz      .is_logged_in
        cli     ; Keine Interrupts, damit jetzt kein Taskwechesl kommt.
        ; Nein, ist das FDD frei:
        cmp     word ptr [fdd_data_user],0
        jnz     .error
        mov     [fdd_data_user],cx
        sti
        mov     dword ptr [fdd_login_count],0
        pop     cx
        mov     cl,1
        ret
.is_logged_in:
        inc     dword ptr [fdd_login_count]
        pop     cx
        mov     cl,1
        ret
.error:
        sti
        pop     cx
        xor     cl,cl
        ret
}

;----------------------------------------------------------------------------
; FDD_LOGOUT
;----------------------------------------------------------------------------
; Gibt die Floppy wieder frei, wenn man der rechtm„áige Benutzer war.
@fdd_logout(){
        push    cx
        str     cx
        cmp     [fdd_data_user],cx
        jz      .logout
        pop     cx
        ret
.logout:
        cmp     dword ptr [fdd_login_count],0
        jz      .now_logout
        dec     dword ptr [fdd_login_count]
        pop     cx
        ret

.now_logout:
        mov     word ptr [fdd_data_user],0
        pop     cx
        ret
}

;----------------------------------------------------------------------------
; FDD_READ_BLOCK
;----------------------------------------------------------------------------
; Liest den gew?nschten Block von der Disktette und kopiert ihn nach dest.
; (cl<- = 0 - Fehler, 1 - OK)
@fdd_read_block(word block,word dest_seg,dword dest_off){
~word is_block_in_buffer ; Gibt an, ob der Block tats„chlich geladen wurde.

        @fdd_login()
        or      cl,cl
        jz      .in_use

        call    fdd_init_floppy
        or      cl,cl
        jnz     .next
        @fdd_logout()
        ret
.next:

        mov     byte ptr [.is_block_in_buffer],1
        ; Testen, ob der Block im Buffer steht:
        push    ax
        mov     ax,[.block]
        call    fdd_find_block_buffer
        pop     ax
        or      cl,cl
        jnz     .no_load

        mov     byte ptr [.is_block_in_buffer],0

        ; Den Block lesen:
        @stdfdc_read_block(word word ptr [.block])

        or      cl,cl
        jz      .error
.no_load:
        @fdd_logout() ; Das FDD wird nun nicht mehr ben”tigt.

; Nun den Block nach dest kopieren:
        push    es
        push    ax
        push    edi

        mov     ax,[.dest_seg]
        mov     es,ax
        mov     edi,[.dest_off]

        push    ecx
        push    esi
        push    ds
        xor     esi,esi
        mov     si,[stdfdc_dma_buffer]
        mov     ecx,80 ; (4 Bytes auf einmal)
        mov     ax,[_des_global_]
        mov     ds,ax

        rep ; Achtung benutzt hier ecx!
        movsd ; ds:esi -> es:edi

        pop     ds

        cmp     byte ptr [.is_block_in_buffer],1
        jz      .no_buffer_overrun

        ; Den erfolgreich gelesenen Block in den Buffer eintragen:
        xor     edi,edi
        mov     di,[fdd_data_next_buffer]
        shl     di,1 ; *= 2
        add     edi,fdd_data_buffer_blocks
        mov     ax,[.block]
        mov     [edi],ax
        ; Next Buffer um 1 erh”hen:
        inc     word ptr [fdd_data_next_buffer]
        cmp     word ptr [fdd_data_next_buffer],8
        jnz     .no_buffer_overrun
        mov     word ptr [fdd_data_next_buffer],0

.no_buffer_overrun:

        pop     esi
        pop     ecx
        pop     edi
        pop     ax
        pop     es

        mov     cl,1
        ret

.error:

        @fdd_logout()
        xor     cl,cl
        ret

.in_use:
        @add_error(dword num ERROR_FDD_IN_USE)
        xor     cl,cl
        ret
}

;----------------------------------------------------------------------------
; FDD_WRITE_BLOCK
;----------------------------------------------------------------------------
; Schreibt 512 Bytes von scr in den gew?nschten Block.
; (cl<- = 0 - Fehler, 1 - OK)
@fdd_write_block(word block,word scr_seg,dword scr_off){
        @fdd_login()
        or      cl,cl
        jz      .in_use

        call    fdd_init_floppy
        or      cl,cl
        jnz     .next
        @fdd_logout()
        ret
.next:

; Die 512 Byte von scr in den dma-Buffer kopieren:
        push    ds
        push    es
        push    ax
        push    edi
        push    ecx
        push    esi
        xor     edi,edi

        ; Den richtigen Buffer einstellen:
        mov     di,[fdd_data_next_buffer]
        shl     di,9
        add     di,[stdfdc_dma_buffer_base]
        mov     [stdfdc_dma_buffer],di
       
        mov     di,[stdfdc_dma_buffer]
        mov     ecx,80 ; (4 Bytes auf einmal)
        mov     ax,[_des_global_]
        mov     es,ax

        mov     esi,[.scr_off]
        mov     ax,[.scr_seg]
        mov     ds,ax

        rep ; Achtung benutzt hier ecx!
        movsd ; ds:esi -> es:edi

        ; Den Block schreiben:
        @stdfdc_write_block(word word ptr [.block])
        or      cl,cl
        jz      .error
        @fdd_logout() ; Das FDD wird nun nicht mehr ben”tigt.

        ; Den erfolgreich geschriebenen Block in den Buffer eintragen:
        xor     edi,edi
        mov     di,[fdd_data_next_buffer]
        shl     di,1 ; *= 2
        add     edi,fdd_data_buffer_blocks
        mov     ax,[.block]
        mov     [edi],ax
        ; Next Buffer um 1 erh”hen:
        inc     word ptr [fdd_data_next_buffer]
        cmp     word ptr [fdd_data_next_buffer],8
        jnz     .no_buffer_overrun
        mov     word ptr [fdd_data_next_buffer],0
.no_buffer_overrun:

        pop     esi
        pop     ecx
        pop     edi
        pop     ax
        pop     es
        pop     ds

        mov     cl,1
        ret

.error:
        @fdd_logout()
        pop     esi
        pop     ecx
        pop     edi
        pop     ax
        pop     es
        pop     ds

        xor     cl,cl
        ret

.in_use:
        @add_error(dword num ERROR_FDD_IN_USE)
        xor     cl,cl
        ret
}

;----------------------------------------------------------------------------
; FDD_FIND_BLOCK_BUFFER
;----------------------------------------------------------------------------
; Testet, ob der Block in ax schon im Buffer steht, wenn ja wird in cl 1
; zur?ckgegeben, und stdfdc_dma_buffer wird auf den entsprechenden Buffer
; gelegt, ansonsten wird in cl 0 zur?ckgegeben und stdfdc_dma_buffer wird
; auf den n„chsten Buffer zum šberschreiben gelegt.
; (->ax = Block Nr,
;  cl<- = 0 - nicht im Buffer)
fdd_find_block_buffer:
        push    cx
        push    edi
        mov     cx,8
        mov     edi,fdd_data_buffer_blocks
fdd_find_block_buffer_loop:
        cmp     [edi],ax
        jz      fdd_find_block_buffer_found
        add     edi,2
        loop    fdd_find_block_buffer_loop

        mov     di,[fdd_data_next_buffer]
        shl     di,9
        add     di,[stdfdc_dma_buffer_base]
        mov     [stdfdc_dma_buffer],di

        pop     edi
        pop     cx
        xor     cl,cl
        ret

fdd_find_block_buffer_found:

        sub     edi,fdd_data_buffer_blocks
        shl     di,8 ; *= 256
        add     di,[stdfdc_dma_buffer_base]
        mov     [stdfdc_dma_buffer],di

        pop     edi
        pop     cx
        mov     cl,1
        ret

;***************************************************************************
;*** STDFDC                                                              ***
;***************************************************************************
; Enth„lt Funktionen zum Steuern des FDC.
; ALLE FUNKTIONEN NUR ZUM INTERNEN GEBRAUCH!

; *** Drive Geometry ***
#define DG144_HEADS    2 ; heads per drive (1.44M)
#define DG144_TRACKS  50 ; number of tracks (1.44M) (80d)
#define DG144_SPT     12 ; sectors per track (1.44M) (18d)
#define DG144_GAP3FMT 54 ; gap3 while formatting (1.44M)
#define DG144_GAP3RW  1B ; gap3 while reading/writing (1.44M)

; *** I/O ports ***
#define FDC_DOR    3F2 ; Digital Output Register.
#define FDC_DRS    3F4 ; Data Rate Select Register (output).
#define FDC_MSR    3F4 ; Main Status Register (input).
#define FDC_DATA   3F5 ; Data Register.
#define FDC_DIR    3F7 ; Digital Input Register (input).
#define FDC_CCR    3F7 ; Configuration Control Register (output)

; *** Commands ***
#define CMD_SENSEI  08 ; sense interrupt status.
#define CMD_SPECIFY 03 ; specify drive timings.
#define CMD_SEEK    0F ; seek track.
#define CMD_RECAL   07 ; recalibrate.
#define CMD_VERSION 10 ; FDC version.
#define CMD_WRITE  0C5 ; write data (+ MT,MFM)
#define CMD_READ   0E6 ; read data (+ MT,MFM,SK)
#define CMD_FORMAT 04D ; format track (+ MFM)

; Adresse des DMA-Buffers (nur 16 Bit):
stdfdc_dma_buffer: dw 0
stdfdc_dma_buffer_base: dw 0
; Wenn der Counter 0 erreicht wird der Motor ausgeschaltet und der Counter
; wird auf -1 (FFFF) gesetzt (der Timerinterrupt z„hlt den Counter runter).
motor_kill_counter: dw 0

; *** Aktuelle drive geometry ***
drvgeom_heads:   db      00 ; heads
drvgeom_tracks:  db      00 ; tracks
drvgeom_spt:     db      00 ; sectors per track

; *** DATEN ***
irq_0E_done:   db 00 ; Gibt an, ob der IRQ 0E aufgerufen wurde.
motor_running: db 01 ; Motorstatus.
disk_changed:  db 00 ; Gibt an, ob die Diskette gewechselt wurde.
status:        db 00,00,00,00,00,00,00 ; Command-Result Bytes.
sr0:           db 00 ; Status Register 0.
fdc_track:     db 0FF ; Track, ?ber dem der Lesekopf gerade ist.

;----------------------------------------------------------------------------
; FDC_RESET
;----------------------------------------------------------------------------
; Den FDC zur?cksetzen.
; (bl<- = success)
fdc_reset:
        pusha
; IRQ/DMA aus:
        xor     ax,ax
        mov     dx,FDC_DOR
        out     dx,al

; Motor sofort aus:
        call    motoroff_now

; Datenrate einstellen (500K/s):
        mov     dx,FDC_DRS
        out     dx,al

; Interrupts wieder aktivieren:
        mov     ax,0C
        mov     dx,FDC_DOR
        out     dx,al

; Der Reset erzeugt einen Interrupt. Diesen handeln:
        mov     bl,1
        call    waitfdc
        cmp     bl,0
        jz      reset_error

; Die Drive-Timings einstellen (aus dem BIOS entnommen):
        mov     bl,CMD_SPECIFY
        call    sendbyte
        mov     bl,0DF ; SRT = 3ms, HUT = 240ms
        call    sendbyte
        mov     bl,02 ; HLT = 16ms, ND = 0
        call    sendbyte

; Den "disk change" Status l”schen:
        mov     bl,1
        call    seek
        cmp     bl,0
        jz      reset_error
       
        call    recalibrate
        cmp     bl,0
        jz      reset_error

        mov     byte ptr [disk_changed],0
        popa
        mov     bl,1
        ret
reset_error:
        call    motoroff
        popa
        mov     bl,0
        ret

;----------------------------------------------------------------------------
; WAITFDC
;----------------------------------------------------------------------------
; (->bl = sense interrupt status / bl<- = Status)
; Wartet auf einen Interrupt vom FDC.
waitfdc:
        pusha
        mov     di,bx
        and     di,0FF

; Warten bis der Interrupt vom FDC kommt:

        sti
        push    eax
        push    ebx
        mov     ebx,[timer_tick]
waitfdc_loop:
        cmp     byte ptr [irq_0E_done],0
        jnz     waitfdc_weiter

        ; Auf Timeout pr?fen (max 500ms):
        @calc_ticks(dword ebx)
        cmp     eax,50xD
        jb      waitfdc_loop
        ; Timeout:
        pop     ebx
        pop     eax
        cli
        popa
        mov     bl,0
        ret

waitfdc_weiter:
        pop     ebx
        pop     eax
        cli

; Command-Result Bytes einlesen (7 Bytes):
        xor     bx,bx
waitfdc_loop2:
        mov     dx,FDC_MSR
        in      al,dx
        and     al,10
        cmp     al,0
        jz      waitfdc_weiter2
        cmp     bx,7
        jae     waitfdc_weiter2

        push    bx
        call    getbyte
        mov     al,bl
        pop     bx
        mov     byte ptr [bx+status],al

        inc bx
        jmp     waitfdc_loop2
waitfdc_weiter2:

        cmp     di,0
        jz      waitfdc_no_sensei

; Das Sense-Interrupt-Status Kommando senden:
        mov     bl,CMD_SENSEI
        call    sendbyte
        call    getbyte
        mov     byte ptr [sr0],bl
        call    getbyte
        mov     byte ptr [fdc_track],bl
waitfdc_no_sensei:

        mov     byte ptr [irq_0E_done],0

; Testen ob es einen Diskchange gab:
        mov     dx,FDC_DIR
        in      al,dx
        and     al,80
        cmp     al,0
        jz      waitfdc_weiter3
        mov     byte ptr [disk_changed],1

        popa
        mov     bl,0
        ret
waitfdc_weiter3:

        popa
        mov     bl,1
        ret

;----------------------------------------------------------------------------
; SENDBYTE
;----------------------------------------------------------------------------
; (->bl = Byte to send)
; Sendet das Byte in bl an den FDC.
sendbyte:
        push    cx
        push    dx
        push    ax
        mov     cx,80
        mov     dx,FDC_MSR
sendbyte_loop:
        in      al,dx
        and     al,0C0
        cmp     al,80
        jnz     sendbyte_weiter
        mov     dx,FDC_DATA
        mov     al,bl
        out     dx,al
        pop     ax
        pop     dx
        pop     cx
        ret
sendbyte_weiter:
        in      al,80 ; delay
        loop    sendbyte_loop
        pop     ax
        pop     dx
        pop     cx
        ret

;----------------------------------------------------------------------------
; GETBYTE
;----------------------------------------------------------------------------
; (bl<- = received Byte ( FF = Timeout ))
; Empf„ngt in bl ein Byte vom FDC.
getbyte:
        push    cx
        push    dx
        push    ax
        mov     cx,80
        mov     dx,FDC_MSR
getbyte_loop:
        in      al,dx
        and     al,0D0
        cmp     al,0D0
        jnz     getbyte_weiter
        mov     dx,FDC_DATA
        in      al,dx
        mov     bl,al
        pop     ax
        pop     dx
        pop     cx
        ret
getbyte_weiter:
        in      al,80 ; delay
        loop    getbyte_loop
        pop     ax
        pop     dx
        pop     cx
        mov     bl,0FF ; Timeout
        ret

;----------------------------------------------------------------------------
; RECALIBRATE
;----------------------------------------------------------------------------
; Den FDC rekalibrieren
; (bl<- = success)
recalibrate:
; Motor an:
        call    motoron
   
; Das Kommando zum Rekalibrieren sende:
        mov     bl,CMD_RECAL
        call    sendbyte
        mov     bl,0
        call    sendbyte

; Warten bis das Kommando ausgef?hrt wurde:
        mov     bl,1
        call    waitfdc ; Die R?ckgabe von waitfdc bleibt erhalten.
   
; Motor aus:
        call    motoroff
        ret

;----------------------------------------------------------------------------
; MOTORON
;----------------------------------------------------------------------------
; Den Motor anschalten:
motoron:
; L„uft der Motor schon:
        cmp     byte ptr [motor_running],0
        jz      motoron_weiter
        ret
motoron_weiter:
        push    ax
        push    dx
        push    bx

; Den Motor starten:
        mov     dx,FDC_DOR
        mov     al,1C
        out     dx,al

; Den Kill-Counter nicht weiter runterz„hlen:
        mov     word ptr [motor_kill_counter],0FFFF

; Warten damit der Motor anlaufen kann:
        @wait(dword num 50xD) ; 1/2 Sekunde.

        mov     byte ptr [motor_running],1
        pop     bx
        pop     dx
        pop     ax
        ret

;----------------------------------------------------------------------------
; MOTOROFF
;----------------------------------------------------------------------------
; Den Motor stoppen:
motoroff:
; Steht der Motor schon:
        cmp    byte ptr [motor_running],0
        jz     motoroff_ende

; ca. 3 Sekunden warten und dann den Motor aus:
        mov     word ptr [motor_kill_counter],300xD

motoroff_ende:
         ret

;----------------------------------------------------------------------------
; MOTOROFF_NOW
;----------------------------------------------------------------------------
; Den Motor SOFORT stoppen:
motoroff_now:
        push    ax
        push    dx
        mov     ax,0C
        mov     dx,FDC_DOR
        out     dx,al
        mov     byte ptr [motor_running],0
        pop     dx
        pop     ax
        ret

;----------------------------------------------------------------------------
; SEEK
;----------------------------------------------------------------------------
; (->bl = track / bl<- = success)
; Den Lesekopf zum Track bl bewegen.
seek:
        cmp     byte ptr [fdc_track],bl
        jnz     seek_weiter
        mov     bl,1 ; Der Kopf ist schon da.
        ret
seek_weiter:
        push    di
        mov     di,bx

; Den Motor starten:
        call    motoron

; Das Seek Kommando senden:
        mov     bl,CMD_SEEK
        call    sendbyte
        mov     bl,0
        call    sendbyte
        mov     bx,di
        call    sendbyte

; Warten bis das Seek Kommando ausgef?hrt ist:
        mov     bl,1
        call    waitfdc
        cmp     bl,0
        jnz     seek_weiter2
        pop     di
        mov     bl,0 ; Timeout!
        ret
seek_weiter2:

; Den Kopf etwas Zeit geben:

        @wait(dword num 50xD) ; 1/2 Sekunde warten.
; Motor aus:
        call    motoroff
   
; Testen ob der Kopf auch angekommen ist:
        cmp     byte ptr [sr0],20
        jnz     seek_error
        mov     bx,di
        cmp     byte ptr [fdc_track],bl
        jnz     seek_error
        pop     di
        mov     bl,1
        ret
seek_error:
        pop     di
        mov     bl,0
        ret

;----------------------------------------------------------------------------
; BLOCK2HTS
;----------------------------------------------------------------------------
; (->bx = Block
;  bx<- = Head
;  cx<- = Track
;  dx<- = Sektor)
; Konvertiert die Eingabe von Blocks in head, track und sector.
block2hts:
; head = (block % (geometry.spt * geometry.heads)) / (geometry.spt);
; track = block / (geometry.spt * geometry.heads);
; sector = block % geometry.spt + 1;
        push    ax
        push    bp
        pushw   0 ; head (bp+4)
        pushw   0 ; track (bp+2)
        pushw   0 ; sector (bp)
        mov     bp,sp

        mov     ah,0
        mov     al,[drvgeom_heads]
        mov     ch,0
        mov     cl,[drvgeom_spt]
        mul     cx
        mov     cx,ax
; *** ax = (geometry.spt * geometry.heads) ***
        mov     ax,bx
        xor     dx,dx
        div     cx
; *** ax = blocks / spt*heads dx = blocks % spt*heads ***
        mov     [bp+2],ax
        mov     ax,dx
        mov     ch,0
        mov     cl,[drvgeom_spt]
        xor     dx,dx
        div     cx
        mov     [bp+4],ax
; *** Errechnen des Sektors ***
        mov     ax,bx
        div     cl
        add     dx,1
        mov     [bp],dx

        pop     dx
        pop     cx
        pop     bx
        pop     bp
        pop     ax      
        ret

;----------------------------------------------------------------------------
; FDC_RW
;----------------------------------------------------------------------------
; (->bx = block nr
;  ->cl = 1-read 0-write
;  bl<- = 1 success)
; Liest oder Schreibt den Block Nr bx.
fdc_rw:
        pusha
        pushw   0 ; read/write (bp+6)
        pushw   0 ; head (bp+4)
        pushw   0 ; track (bp+2)
        pushw   0 ; sector (bp)
        mov     bp,sp
        mov     [bp+6],cl
; Die logische Adresse in eine physikalische Adresse umwandeln:
        call    block2hts
        mov     [bp],dx
        mov     [bp+2],cx
        mov     [bp+4],bx
; Motor an:
        call    motoron

        mov     di,3 ; Max 3 Male probieren.
fdc_rw_loop:
; Testen, ob die Diskette gewechselt wurde:
        mov     dx,FDC_DIR
        in      al,dx
        and     al,80
        cmp     al,0
        jz      fdc_rw_no_diskchange
; Fehlgeschlagen, da die Diskette gewechselt wurde:
        mov     byte ptr [disk_changed],1
        mov     bl,1
        call    seek ; Disk Changed Staus ausschalten.
        call    recalibrate
        call    motoroff
        add     bp,8
        mov     sp,bp
        popa
        mov     bl,0
        @add_error(dword num ERROR_FD_CHANED_WHILE_RW)
        ret
fdc_rw_no_diskchange:

; Den Kopf zum richtigen Track bewegen:
        mov     bl,[bp+2]
        call    seek
        cmp     bl,1
        jz      fdc_rw_seek_success
; Seek fehlgeschlagen:
        call    motoroff
        add     bp,8
        mov     sp,bp
        popa
        mov     bl,0
        @add_error(dword num ERROR_FD_SEEK_FAILED)
        ret
fdc_rw_seek_success:

; Datenrate (500K/s) einstellen:
        mov     dx,FDC_CCR
        mov     bl,0
        out     dx,al

; Feststellen, was gemacht werden soll:
        cmp     byte ptr [bp+6],1
        jnz     fdc_rw_send_command_write

; Lesen:
        mov     bl,0 ; read
        mov     cx,200 ; 512 Bytes
        call    dma_xfer

        mov     bl,CMD_READ
        call    sendbyte        
        jmp     fdc_rw_send_command_next        
fdc_rw_send_command_write:

; Schreiben:
        mov     bl,1 ; write
        mov     cx,200 ; 512 Bytes
        call    dma_xfer

        mov     bl,CMD_WRITE
        call    sendbyte
fdc_rw_send_command_next:

; Alle Informationen ?ber die Position des Blocks ?bertragen:
        mov     bl,[bp+4] ; head
        shl     bl,2
        call    sendbyte
        mov     bl,[bp+2] ; track
        call    sendbyte
        mov     bl,[bp+4] ; head
        call    sendbyte
        mov     bl,[bp] ; sector
        call    sendbyte
        mov     bl,2 ; 512 Bytes/Sector
        call    sendbyte
        mov     bl,[drvgeom_spt]
        call    sendbyte
        mov     bl,DG144_GAP3RW ; gap 3 size for 1.44M read/write
        call    sendbyte
        mov     bl,0FF ; DTL = unused
        call    sendbyte

; Warten bis das Kommando ausgef?hrt wurde:
; (read/write braucht keinen sense interrupt status)
        mov     bl,0
        call    waitfdc
        cmp     bl,0
        jnz     fdc_rw_no_timeout

        add     bp,8
        mov     sp,bp
        popa
        mov     bl,0 ; Timeout !
        @add_error(dword num ERROR_FD_TIMEOUT_WHILE_RW)
        ret
fdc_rw_no_timeout:

        mov     al,[status]
        and     al,0C0
        cmp     al,0
        jz      fdc_rw_worked

; Es hatt nicht funktioniert, nochmal:
        call    recalibrate
        dec     di
        cmp     di,0
        jnz     fdc_rw_loop
; *** ERROR ***
        call    motoroff

        add     bp,8
        mov     sp,bp
        popa
        mov     bl,0
        @add_error(dword num ERROR_FD_RW_FAILED)
        ret
fdc_rw_worked:

; *** SUCCESS ***
        call    motoroff

        add     bp,8
        mov     sp,bp
        popa
        mov     bl,1
        ret

;----------------------------------------------------------------------------
; LOG_DISK
;----------------------------------------------------------------------------
; (bl<- = 1 = 1.44 Disk / 0 not supported)
; Feststellen um was f?r einen Diskettentyp es sich handelt.
log_disk:
        push    cx
        call    fdc_reset
        cmp     bl,0
        jz      log_disk_no_144

; Davon ausgehen, das es eine 1.44mb Diskette ist und Block 17 auf dem 1.
; Track lesen:
        mov     byte ptr [drvgeom_heads],DG144_HEADS
        mov     byte ptr [drvgeom_tracks],DG144_TRACKS
        mov     byte ptr [drvgeom_spt],DG144_SPT

        mov     bx,11 ; Block 17.
        mov     cl,1 ; Lesen.
        call    fdc_rw
        cmp     bl,0
        jz      log_disk_no_144
        pop     cx

        mov     bl,1
        ret
log_disk_no_144:
        pop     cx

        mov     bl,0
        @add_error(dword num ERROR_FD_TYP_NOT_SUPPORTED)
        ret

;----------------------------------------------------------------------------
; DMA_XFER
;----------------------------------------------------------------------------
; (->bl = 1-read / 0-write
;  ->cx = length)
; Aktiviert den DMA.
dma_xfer:
        pusha

        mov     al,14 ; DMA1 deaktivieren
        out     08,al

        cmp     bl,0
        jnz     dma_xfer_read
; *** Modus: Einzeltransfer, Adressinkrementierung, Schreiben, Kanal 2 ***
        mov     al,56
        out     0B,al
        jmp     dma_xfer_weiter
dma_xfer_read:
; *** Modus: Einzeltransfer, Adressinkrementierung, Lesen, Kanal 2 ***
        mov     al,5A
        out     0B,al
dma_xfer_weiter:

        mov     ax,[stdfdc_dma_buffer]
        mov     bx,[stdfdc_dma_buffer]
        shr     bx,4
        shr     bh,04
        out     0C,al ; Flip-Flop zur?ckstellen

        out     04,al ; Niederwertige Adresse ausgeben
        mov     al,ah
        out     04,al ; H”herwertige Adresse ausgeben
        mov     al,bh
        out     81,al ; Segment ausgeben

        out     0C,al ; Flip-Flop zur?cksetellen

; *** Length -1 ***
        dec     cx
        mov     al,cl ; Low-Byte
        out     05,al
        mov     al,ch ; High-Byte
        out     05,al

        mov     al,02 ; Kanal 2 freigeben
        out     0A,al
        mov     al,10 ; DMA 1 aktivieren
        out     08,al

        popa
        ret

;***************************************************************************
;*** FUNKTIONEN                                                          ***
;***************************************************************************

;----------------------------------------------------------------------------
; STDFDC_IRQ_HANDLER
;----------------------------------------------------------------------------
; Wird vom FDC-IRQ ausgel”st.
stdfdc_irq_handler:
        cli
        push    ax
        push    ds

        cs:
        mov     ax,[_des_kernel_data_]
        mov     ds,ax
        mov     byte ptr [irq_0E_done],1

        push es
        mov ax,[_des_vram_]
        mov es,ax
        es:
        mov byte ptr [(160xD*4)],'H'
        es:
        inc byte ptr [(160xD*4+2)]
        pop es

        ; Dem Controller mitteilen, dass der IRQ bearbeitet wurde:
        mov     al,20
        out     20,al
        pop     ds
        pop     ax
        sti
        iret

;----------------------------------------------------------------------------
; STDFDC_READ_BLOCK
;----------------------------------------------------------------------------
; Liest einen Block (512 Byte) in den aktuellen DMA Buffer ein..
; Gibt in cl 1 zur?ck wenn es funktioniert hat, sonst 0.
@stdfdc_read_block(word block){
        push    ax
        push    bx
        push    dx
        cli     ; Bei FDC Funktionen besser keine Interrupts.

; Testen, ob die Diskette gewechselt wurde:
        call    check_diskchange
        or      cl,cl
        jnz     .log_disk ; Diskette wurde gewechselt.

; Ggf die Diskette testen:
        cmp     byte ptr [drvgeom_tracks],0
        jnz     .no_log_disk
.log_disk:
        call    log_disk
        cmp     bl,0
        jz      .error
.no_log_disk:

; Den Block lesen:
        mov     bx,[.block] ; Block nr.
        mov     cl,1 ; read
        call    fdc_rw
        cmp     bl,0
        jz      .error

        sti
        pop     dx
        pop     bx
        pop     ax
        mov     cl,1
        ret

.error:
        sti
        pop     dx
        pop     bx
        pop     ax
        mov     cl,0
        ret
}

;----------------------------------------------------------------------------
; STDFDC_WRITE_BLOCK
;----------------------------------------------------------------------------
; Schreibt 512 Bytes aus dem aktuellen DMA Buffer auf den angegebenen Block.
; Gibt in cl 1 zur?ck wenn es funktioniert hat, sonst 0.
@stdfdc_write_block(word block){
        push    ax
        push    bx
        push    dx
        cli     ; Bei FDC Funktionen besser keine Interrupts.

; Testen, ob die Diskette gewechselt wurde:
        call    check_diskchange
        or      cl,cl
        jnz     .log_disk ; Diskette wurde gewechselt.

; Ggf die Diskette testen:
        cmp     byte ptr [drvgeom_tracks],0
        jnz     .no_log_disk
.log_disk:
        call    log_disk
        cmp     bl,0
        jz      .error
.no_log_disk:

; Den Block schreiben:
        mov     bx,[.block] ; Block nr.
        mov     cl,0 ; write
        call    fdc_rw
        cmp     bl,0
        jz      .error

        sti
        pop     dx
        pop     bx
        pop     ax
        mov     cl,1
        ret

.error:
        sti
        pop     dx
        pop     bx
        pop     ax
        mov     cl,0
        ret
}

;----------------------------------------------------------------------------
; CHECK_DISKCHANGE
;----------------------------------------------------------------------------
; ->cl = Gibt eine 1 zur?ck, wenn die Diskette gewechselt wurde.
check_diskchange:
        push    dx
        push    ax

; Kommando senden, damit das DIR die Informationen ?ber den Diskchange hat:
        call    motoron
        call    motoroff

        mov     dx,FDC_DIR
        in      al,dx
        and     al,80
        mov     cl,al

        pop     ax
        pop     dx
        ret


Nicht wundern über die seltsame Syntax, hab ich für meinen eigenen Assembler, den MMASM geschrieben (man arbeitet doch am liebsten mit den eigenen Werkzeugen, nich  :wink: ).
Bei Bedarf hab ich sowas ähnliches auch noch in C.

MM

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 11. December 2005, 17:49 »
Wenn der C Code auch in der Lage ist, zu lesen und zu schreiben wär er ganz interessant :D

Mihail121

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 11. December 2005, 18:59 »
Grüß dich, lies dir das hier mal an:

http://www.xaff.org/GI/floppy.html
_p.wur$t

Der Sensemann owz ya

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« Antwort #5 am: 11. December 2005, 19:02 »
Meine Version des C Codes finde ich irgendwie grad nicht, aber dafür hab ich hier nen Link zu nem netten Democode, mit dem man sogar Disketten formatieren kann (aus dem FreeDOS32):
http://www.koders.com/c/fidCACDE05FE2F07441CF52B2104E08993FF8E8D8B5.aspx

Mir ist das zwar etwas zu unübersichtlich, aber eventuell hilft es weiter.
Ich hatte meinen Code übrigends nach der folgenden FDC Referenz geschrieben:
http://www.isdaman.com/alsos/hardware/fdc/floppy.htm

Eventuell finde ich meinen C Code ja nochmal wieder...
MM

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #6 am: 17. December 2005, 17:10 »
Vielen dank für eure Informationen. Also der IRQ6 und die Ports 3F0h-3F7h und 370h-377h benötige ich um mit der Diskette zu komonizieren. Aber ich habe das leider nicht so ganz verstanden. Was muss der Code des IRQ6 denn machen? Und wie lese/schreibe ich Sektoren. Beispiel:
Ich möchte den Sektor 3 der Diskette im ersten Diskettenlaufwerk in den Arbeitsspeicher an Adresse 20000h schreiben. Wie würde der Code dafür aussehen? Gibt es dazu eigentlich auch deutsche Seiten? So wie ich das sehe, werden also max. 4 Diskettenlaufwerke unterstützt. Wann benötige ich den ersten Kontroller (3F0-3F7) und wann den zweiten (370-377)?

Danke!!!

PS:
Zitat von: Mihail121
Grüß dich, lies dir das hier mal an:

http://www.xaff.org/GI/floppy.html
Der Link funktioniert nicht.
In the Future everyone will need OS-64!!!

Osbios

  • Beiträge: 247
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 17. December 2005, 19:47 »
Zitat von: bitmaster
Wann benötige ich den ersten Kontroller (3F0-3F7) und wann den zweiten (370-377)?

Naja, den ersten Kontroller benutzt du fürs erste Floppy und den zweiten Kontroller fürs zweite Floppy.  :|
db 0x55AA

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #8 am: 17. December 2005, 20:07 »
Zitat von: Osbios
Zitat von: bitmaster
Wann benötige ich den ersten Kontroller (3F0-3F7) und wann den zweiten (370-377)?

Naja, den ersten Kontroller benutzt du fürs erste Floppy und den zweiten Kontroller fürs zweite Floppy.  :|
Und fürs dritte und Vierte Floppy?
In the Future everyone will need OS-64!!!

Osbios

  • Beiträge: 247
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 17. December 2005, 20:47 »
Nein, vergiss was ich gesagt habe. :/
Die max. 4 Floppys steuert man ja alle über die selben Register an.

Zitat
The base port address used for the controller is dependant on whether the controller is configured as the primary or secondary controller


Mehr kann ich dir dazu leider nicht sagen als das was in den Docs steht.

[edit]Das ist so wie: Die größe des Speichers hängt von der eingebauten Menge des Speicher ab.[/edit]
db 0x55AA

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #10 am: 18. December 2005, 12:03 »
Ich hab meins jetzt auch zum Laufen gebracht. Fehler war, dass ich nicht lange genug gewartet hab, bis das Teil fertig hatte. ;)
An dieser Stelle möchte ich nocheinmal ein herzliches Dankeschön an die Entwickler von Intel für diesen grandiosen Anti-Logik-Test richten. Sie haben ihr Ziel erreicht und es geschaft, einen Baustein zu entwickeln, der eine Unlogik enthält, wie sie noch nie gesehen wurde.
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

Osbios

  • Beiträge: 247
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 18. December 2005, 13:50 »
@[MM]: Ich habe mir mal deinen Code angeschaut. Schon in denn ersten Zeilen gibt es eine Variable/Pointerkonstante (hw_fdc) die nirgends deklariert wurde!?

Fehlt da eventuell noch was?
db 0x55AA

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« Antwort #12 am: 18. December 2005, 21:27 »
hw_fdd und hw_floppys sind Variablen aus der Hardwareerkennung, in hw_fdd steht glaub ich die Versionsnummer des FDD-Controllers und in hw_floppys die Anzahl der Floppys.
Wie das initialisiert wurde dürfte für dieses Thema unerheblich sein.

MM

Osbios

  • Beiträge: 247
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 18. December 2005, 22:30 »
Ich denke die Hardwareerkennung der Floppy ist hier schon relevant.
Ok, meistens ist nur eine einziges 3 1/2 Floppy am PC angeschlossen aber ein OS sollte doch auch mit allen anderen Fällen zurechtkommen.
Und wenn ein OS sich beim Booten aufhängt nur weil dem Floppytreiber kein formgerechtes Standardgerät vor die Nase gesetzt wurde...   :?

Währe also nett wenn Du eventuell auch deinen Hrdwareerkennungscode für die Floppy postest.  :D
db 0x55AA

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« Antwort #14 am: 18. December 2005, 23:43 »
Gna, immer diese Extrawünsche...
Aber gut, hier der Code mit dem bei diesem Projekt der Floppy-Controller gesucht wurde:
detect_basic_hw_string: db "detecting basic hardware: ",0A,0D,0
create_temp_pmode_env: db "creating temporary pmode environment... ",0
start_pmode: db "starting protected mode... ",0

hw_start:
hw_cpu_id_string: dd 0,0,0 ; Prozessor ID-String (o0 l13).
db 0
hw_cpu_version: dd 0 ; Informationen ?ber die Version (o13 l4).
hw_cpu_features: dd 0 ; Informationen ?ber die Features (o17 l4).
hw_cpu_speed: dd 0 ; ungef„hre MHz Zahl (o21 l4).
hw_memory: dd 0 ; KB an Speicher (o25 l4).
hw_fdc: db 0 ; 0=none / 1=extended fdc (o29 l1).
hw_floppys: db 0 ; Anzahl der Floppylaufwerke (o30 l1).
; Path des Bootscripts (o31 l72).
bootscript_path: db ".......................................................................",0

#define HW_SIZE 103xD

; *** PREPARE_KERNEL ***
prepare_kernel:
; Hardware suchen:
        mov     si,detect_basic_hw_string
        call    print_string

        call    detect_processor
        call    detect_memory
        call    detect_fdc
        call    detect_floppys

; Den Temp-Pmode vorbereiten:
        mov     si,create_temp_pmode_env
        call    print_string
        jmp     temp_pm

; *** DETECT_FDC ***
#define FDC_DATA   3F5 ; Data Register.
#define FDC_MSR    3F4 ; Main Status Register (input).
#define CMD_VERSION 10 ; FDC version.
detect_fdc_string: db " floppy disk controller: ",0
detect_fdc_ec_found: db "extended controller",0A,0D,0
detect_fdc_no_ec_found: db "none",0A,0D,0
detect_fdc:
        mov     bl,COLOR_WHITE
        mov     si,detect_fdc_string
        call    print_string_color

; Testet, welche FDC-Version installiert ist:
        mov     bl,CMD_VERSION
        call    sendbyte_fdc
        call    getbyte_fdc
        cmp     bl,90
        jnz     detect_fdc_no_ec

        mov     si,detect_fdc_ec_found
        call    print_string
        mov     byte ptr [hw_fdc],1
        ret
detect_fdc_no_ec:
        mov     si,detect_fdc_no_ec_found
        call    print_string
        mov     byte ptr [hw_fdc],0
        ret

; *** SENDBYTE_FDC ***
; (->bl = Byte to send)
; Sendet das Byte in bl an den FDC.
sendbyte_fdc:
        push    cx
        push    dx
        push    ax
        mov     cx,80
        mov     dx,FDC_MSR
sendbyte_fdc_loop:
        in      al,dx
        and     al,0C0
        cmp     al,80
        jnz     sendbyte_fdc_weiter
        mov     dx,FDC_DATA
        mov     al,bl
        out     dx,al
        pop     ax
        pop     dx
        pop     cx
        ret
sendbyte_fdc_weiter:
        in      al,80 ; delay
        loop    sendbyte_fdc_loop
        pop     ax
        pop     dx
        pop     cx
        ret

; *** GETBYTE_FDC ***
; (bl<- = received Byte ( FF = Timeout ))
; Empf„ngt in bl ein Byte vom FDC.
getbyte_fdc:
        push    cx
        push    dx
        push    ax
        mov     cx,80
        mov     dx,FDC_MSR
getbyte_fdc_loop:
        in      al,dx
        and     al,0D0
        cmp     al,0D0
        jnz     getbyte_fdc_weiter
        mov     dx,FDC_DATA
        in      al,dx
        mov     bl,al
        pop     ax
        pop     dx
        pop     cx
        ret
getbyte_fdc_weiter:
        in      al,80 ; delay
        loop    getbyte_fdc_loop
        pop     ax
        pop     dx
        pop     cx
        mov     bl,0FF ; Timeout
        ret

; *** DETECT_PROCESSOR ***
detect_processor_string: db " processor: ",0
detect_processor_speed_string1: db " ~",0
detect_processor_speed_string2: db "MHz",0A,0D,0
detect_processor:
        mov     si,detect_processor_string
        mov     bl,COLOR_WHITE
        call    print_string_color
       
; Den ID-String holen (12 Bytes in ebx,edx,ecx):
        xor     eax,eax
        cpuid
        mov     [hw_cpu_id_string],bl
        shr     ebx,8
        mov     [(hw_cpu_id_string+1)],bl
        shr     ebx,8
        mov     [(hw_cpu_id_string+2)],bl
        shr     ebx,8
        mov     [(hw_cpu_id_string+3)],bl
        shr     ebx,8
        mov     [(hw_cpu_id_string+4)],dl
        shr     edx,8
        mov     [(hw_cpu_id_string+5)],dl
        shr     edx,8
        mov     [(hw_cpu_id_string+6)],dl
        shr     edx,8
        mov     [(hw_cpu_id_string+7)],dl
        shr     edx,8
        mov     [(hw_cpu_id_string+8)],cl
        shr     ecx,8
        mov     [(hw_cpu_id_string+9)],cl
        shr     ecx,8
        mov     [(hw_cpu_id_string+0A)],cl
        shr     ecx,8
        mov     [(hw_cpu_id_string+0B)],cl

        mov     si,hw_cpu_id_string
        call    print_string

; Erweiterte Informationen holen:
        xor     eax,eax
        inc     ax
        cpuid
        mov     [hw_cpu_version],eax
        mov     [hw_cpu_features],edx

; CPU Geschwindigkeit ermitteln:

        call    detect_cpu_speed
        mov     si,detect_processor_speed_string1
        call    print_string
        mov     eax,[hw_cpu_speed]
        mov     ebx,10xD
        call    print_number
        mov     si,detect_processor_speed_string2
        call    print_string
        ret

detect_cpu_speed_lo: dd 0
detect_cpu_speed_hi: dd 0
detect_cpu_speed_delay: dd 0
detect_cpu_speed:
; Aktuelle Cycle Zahl holen:
        db 0F,31 ; RDTSC
        mov     [detect_cpu_speed_lo],eax
        mov     [detect_cpu_speed_hi],edx

; Delay von ca. 500ms:
        xor     ax,ax
        int     1A
        shl     ecx,16xD
        mov     cx,dx
        mov     [detect_cpu_speed_delay],ecx
        add     dword ptr [detect_cpu_speed_delay],9

        detect_cpu_speed_delay_loop:
        int     1A
        shl     ecx,16xD
        mov     cx,dx

        cmp     [detect_cpu_speed_delay],ecx
        jg      detect_cpu_speed_delay_loop

; Jetzt aktuelle Cycle Zahl holen und die alte davon abziehen:
        db 0F,31 ; RDTSC
        sub     eax,[detect_cpu_speed_lo]
        sbb     edx,[detect_cpu_speed_hi]

; Einen kleinen Korrekturwert hinzuf?gen:
        add     eax,600000
        adc     edx,0
       
; Nun ausrechnen wie viele Cycle der Rechner in 1000 Sekunden macht (MHz):
        mov     ecx,7A120
        div     ecx
        mov     [hw_cpu_speed],eax
        ret

; *** DETECT_MEMORY ***
detect_memory_string1: db " memory: ",0
detect_memory_string2: db "kb",0A,0D,0
detect_memory:
        mov     si,detect_memory_string1
        mov     bl,COLOR_WHITE
        call    print_string_color

; Dieser Interrupt gibt die Menge an Erweiterungsspeicher in kb zur?ck:
        mov     eax,0E801
        int     15

; Es kann sein, dass „ltere BIOS-Versionen diese Funktion noch nicht haben:
        jc      detect_memory_noE801

        and     eax,0FFFF ; 16-Bit mem unter 16mb in 1kb Bl”cken.
        and     ebx,0FFFF ; 16-bit mem ?ber 16mb in 64kb Bl”cken.
        shl     ebx, 6 ; Auf 1kb Bl”cke bringen.
        add     eax,ebx
        mov     [hw_memory],eax
        jmp     detect_memory_ende

detect_memory_noE801:
; Die SpeichergrӇe aus dem CMOS lesen:
        mov     al,17
        out     70,al
        in      al,71
        mov     [hw_memory],al
        mov     al,18
        out     70,al
        in      al,71
        mov     [(hw_memory+1)],al

detect_memory_ende:
; Den gesammten Speicher nicht nur den Erweiterten (also +1mb):
        add     dword ptr [hw_memory],1024xD
        mov     eax,[hw_memory]
        mov     ebx,10xD
        call    print_number
        mov     si,detect_memory_string2
        call    print_string
        ret

; *** DETECT_FLOPPYS ***
detect_floppys_string: db " floppy disks: ",0
detect_floppys:

        mov     si,detect_floppys_string
        mov     bl,COLOR_WHITE
        call    print_string_color

; Floppy 1 testen:
        push    es
        mov     ax,800
        xor     dx,dx
        int     13
        pop     es
        jc      detect_floppys_done ; Error.
        cmp     cx,0
        je      detect_floppys_done ; Nicht installiert.

        inc     byte ptr [hw_floppys]

; Floppy 2 testen:
        push    es
        mov     ax,800
        mov     dx,1
        int     13
        pop     es
        jc      detect_floppys_done ; Error.
        cmp     cx,0
        je      detect_floppys_done ; Nicht installiert.

        inc     byte ptr [hw_floppys]
detect_floppys_done:
        xor     eax,eax
        mov     al,[hw_floppys]
        mov     ebx,10xD
        call    print_number
        mov     si,new_line
        call    print_string
        ret


detect_fdc wird prüfen, ob eine Floppy da ist und detect_floppys prüft, ob 1 oder 2 Laufwerke installiert sind (glaub ich). Die anderen Funktionen sind für so Zeug wie Prozessorerkennung usw...

MM

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #15 am: 19. December 2005, 12:14 »
Wäre gut wenn jemand ein Tutorial dazu schreiben würde. ;)
In the Future everyone will need OS-64!!!

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #16 am: 21. December 2005, 23:42 »
Ich habe oft gelesen, dass man DMA nicht benutzen sollte. Ich verstehe aber nicht warum. Hat das einen Nachteil? Geht das überhaupt ohne? Und dann hätte ich noch eine Frage. Was muss im IRQ6 passieren? Also was muss der IRQ6 machen wenn er aufgerufen wird?

Danke!!!
In the Future everyone will need OS-64!!!

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #17 am: 22. December 2005, 11:47 »
Zitat von: T0ast3r
Nun den, IRQ & DMA haben einen Nachteil:
Du kannst nur die ersten 16 MB (physikalisch) addressieren, zudem ist es viel zu aufwendig.
Vor allem ist die implementierung ziemlich schwierig...
DMA kann zu dem nicht 32 Bit arbeiten, nur die Register 0-5 oder so...
verstehe ich nicht  :(
In the Future everyone will need OS-64!!!

Osbios

  • Beiträge: 247
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 22. December 2005, 12:45 »
Auch wenn man mit dem DMA für floppy nur im unteren Speicherbereich arbeiten kann würde ich diese Methode vorziehen, denn PIO mit dem FDC ist ein CPU fresser und nichts im Vergleich zu dem was benötigt wird um ein par KB von A nach B zu kopieren.
db 0x55AA

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #19 am: 22. December 2005, 13:04 »
Also mal konkret bitte. Welcher vorteile hat DMA und welche Nachteile hat DMA. Und was muss der Code des IRQ6 machen?

Danke!!!
In the Future everyone will need OS-64!!!

 

Einloggen