home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Falcon 030 Power 2
/
F030_POWER2.iso
/
ST_STE
/
MAGS
/
TOXIC_14.ARJ
/
toxic_14
/
TOXIC_14.D_2
/
LEONARD
/
LEO_ST.ZIP
/
ST_PC
/
HD_EMUL
/
HARDDISK.S
< prev
next >
Wrap
Text File
|
1995-06-16
|
10KB
|
538 lines
;****************************************************************
;* *
;* HARD-DISK. *
;* Simule un disque dur sur ST grace a un disk dur PC *
;* et une liaison 4 bits paralelle. *
;* *
;* Code and Idea by Leonard/OXYGENE. *
;* *
;****************************************************************
HARD_DRIVE equ ('E'-65)
; Tailles utilisateurs.
;Tailles systems
HEADER_SIZE equ 8
CHAR_BIT equ 8
CRCPOLY equ $EDB88320
; Vecteurs de traitement des secteurs de bas niveau sur ST.
HDV_BPB equ $472
HDV_RW equ $476
HDV_MCH equ $47e
; COMMANDES de l'emulateur de disk au PC.
CMD_HARD_INIT equ 0
CMD_READ_SECTOR equ 1
section text
movea.l sp,a5
lea my_stack,a7
move.l 4(a5),a5
move.l #256,d7
add.l $c(a5),d7
add.l $14(a5),d7
add.l $1c(a5),d7
move.l d7,prg_size
move.l d7,-(sp)
pea (a5)
clr.w -(sp)
move.w #$4a,-(sp)
trap #1
lea 12(sp),sp
lea txt_intro,a0
bsr print
; Passage en superviseur.
clr.l -(sp)
move.w #32,-(sp)
trap #1
addq.l #6,sp
move.l $4c2.w,d0
btst.l #HARD_DRIVE,d0
beq.s init
lea txt_already,a0
bsr print
bsr wait_key
bra gemdos_error
init:
;*************************************************************
; On demande au PC d'initialiser l'emulateur disk.
;*************************************************************
move.w #CMD_HARD_INIT,info_block
moveq #HEADER_SIZE,d0
bsr pc_send_block
beq.s .ok
.pc_error lea txt_pcout,a0
bsr print
bsr wait_key
bra gemdos_error
.ok:
lea ret_value,a0
moveq #HEADER_SIZE,d0
bsr pc_receive_block
bne.s .pc_error
tst.l ret_value
bne.s .pc_error
;****************************************************************
; L'emulateur sur le PC est pret, on peut installer les vecteurs.
;****************************************************************
bsr calc_crctable
bsr built_fast_table
move.l (HDV_BPB).w,bpb_jmp+2
move.l #my_bpb,(HDV_BPB).w
move.l (HDV_RW).w,rw_jmp+2
move.l #my_rw,(HDV_RW).w
move.l (HDV_MCH).w,mch_jmp+2
move.l #my_mch,(HDV_MCH).w
move.l #trap15,($80+15*4).w
move.l $4c2.w,d0
bset.l #HARD_DRIVE,d0
move.l d0,$4c2.w
; On revient au GEM en reservant la place.
bra gemdos_ok
;********************************************************
;* *
;* Get BPB. *
;* *
;********************************************************
bpb_jmp jmp $0
my_bpb:
cmp.w #HARD_DRIVE,4(sp)
bne.s bpb_jmp
;move.l #bpbemul,d0
rts
;********************************************************
;* *
;* Read-Write. *
;* *
;********************************************************
rw_jmp jmp $0
my_rw:
cmp.w #HARD_DRIVE,14(sp)
bne.s rw_jmp
move.w 4(sp),d0
btst #0,d0
beq.s .read
moveq #-36,d0 ; ERROR: Interdit d'ecrire.
rts
.read:
moveq #0,d0
move.w 10(sp),d1 ; Nb de secteurs.
move.w 12(sp),d0 ; Secteur logique.
lsl.l #8,d0
add.l d0,d0 ; *512=offset en octets.
move.w #CMD_READ_SECTOR,info_block
move.l d0,info_block+2
move.w d1,info_block+6
moveq #HEADER_SIZE,d0
bsr pc_send_block ; Envoie la demande de lecture.
beq.s .ok
moveq #-11,d0 ; Erreur de lecture.
rts
.ok:
move.l 6(sp),a0 ; Adresse de lecture
moveq #0,d0
move.w 10(sp),d0 ; nb de secteurs.
lsl.l #8,d0
add.l d0,d0 ; *512=taille block en octets.
bsr pc_receive_block
beq.s .okr
moveq #-11,d0 ; Erreur de lecture.
rts
.okr:
moveq #0,d0
rts
;********************************************************
;* *
;* Media Change. *
;* *
;********************************************************
mch_jmp: jmp $0
my_mch: cmp.w #HARD_DRIVE,4(sp)
bne.s mch_jmp
move.w changed,d0
clr.w changed
rts
;************************************************************************
;**********************************************
; Init le disk dur.
;**********************************************
r_hard_init move.w d0,info_block ; commande.
moveq #HEADER_SIZE,d0
bsr pc_send_block
rts
;**********************************************
; Trap pour passer en sr = $2700
;**********************************************
trap15 move.w #$2700,(sp)
rte
;**********************************************
; SEND BLOCK to PC.
;**********************************************
pc_send_block
; Envoie de d0 octets a partir de info_block au PC.
rts
;****************************************************************
;* *
;* BAS NIVEAU. *
;* PC_RECEIVE_BLOCK *
;* *
;* Recoie D0 bytes a l'adresse A0. *
;* En retour, D0=0 si pas d'erreur. *
;* D0>0 si coupure de liaison *
;* D0=-1 si erreur CRC32. *
;* *
;****************************************************************
pc_receive_block
; Reception de D0 bytes a partir de l'adresse a0.
move.l d0,rec_size
move.l a0,rec_ad
move.w sr,-(sp)
trap #15 ; SR=2700
movea.w #$8800,a6 ; Adresse PSG
; Sauve la config du MFP et PSG
move.b $fffffa05.w,port_dir
move.b #7,(a6)
move.b (a6),psg_7
move.b #$e,(a6)
move.b (a6),psg_e
; Set la config pour recevoir.
move.l #$0700c000,(a6)
move.l #$0e000700,(a6)
bclr.b #0,$fffffa05.w ; Port Centronics en entrée.
move.w d0,d7 ; Taille en octets.
subq.w #1,d7 ; -1 pour DBF.
lea $fffffa01.w,a5
moveq #0,d6 ; Bit busy: 0
; On recoit le block.
.sw1: moveq #-1,d5 ; Time out
.w1: btst d6,(a5)
; bne.s .w1
dbeq d5,.w1
bne .time_out
move.b (a6),d0
lsl.b #4,d0
moveq #$0f,d2
.w2: btst d6,(a5)
; beq.s .w2
dbne d5,.w1
beq .time_out
and.b (a6),d2
or.b d2,d0
move.b d0,(a0)+ ; ecrit l'octet.
dbf d7,.sw1
lea vcrc32,a0
moveq #4-1,d7
; Puis on recoit le CRC32.
.sw2: moveq #-1,d5 ; Time out
.w3: btst d6,(a5)
; bne.s .w3
dbeq d5,.w3
bne .time_out
move.b (a6),d0
lsl.b #4,d0
moveq #$0f,d2
.w4: btst d6,(a5)
; beq.s .w4
dbne d5,.w4
beq .time_out
and.b (a6),d2
or.b d2,d0
move.b d0,(a0)+ ; ecrit l'octet.
dbf d7,.sw2
; On calcul le CRC32
move.l rec_size,d0
move.l rec_ad,a0
bsr calc_crc32
; Et on compare avec le recu.
moveq #-1,d7
cmp.l vcrc32,d0
bne.s .time_out
moveq #0,d7
.time_out:
; On retablit le port.
move.b #7,(a6)
move.b psg_7,2(a6)
move.b #$e,(a6)
move.b psg_e,2(a6)
move.b port_dir,$fffffa05.w
move.w (sp)+,sr ; Retour a l'ancien mode.
moveq #0,d0
move.w d7,d0
tst.w d0
rts
;************************************************************************
calc_crc32
; Input: A0: buffer to check, D0: Size in bytes.
; Output: D0: CRC32
move.l d0,d7
moveq #0,d0 ; CRC
lea crc_table,a1
.loop: moveq #0,d1
move.b (a0)+,d1
eor.b d0,d1
add.w d1,d1
add.w d1,d1
move.l 0(a1,d1.w),d1
lsr.l #CHAR_BIT,d0
eor.l d1,d0
subq.l #1,d7
bne.s .loop
rts
built_fast_table
lea fast_table,a0
moveq #0,d0
.loop: move.w d0,d1
move.w d0,d2
andi.w #$0f00,d1
andi.w #$000f,d2
lsr.w #4,d1
or.w d1,d2
move.b d2,(a0)+
addq.w #1,d0
cmpi.w #$8000,d0
bne.s .loop
rts
calc_crctable
lea crc_table,a0
moveq #0,d0
.loop: move.l d0,d1
rept CHAR_BIT
lsr.l #1,d1
bcc.s *+2+6
eori.l #CRCPOLY,d1
endr
move.l d1,(a0)+
addq.b #1,d0
bne.s .loop
rts
gemdos_error:
clr.w -(sp)
trap #1
gemdos_ok
clr.w -(sp)
move.l prg_size,-(sp)
move.w #$31,-(sp)
trap #1
print: pea (a0)
move.w #9,-(sp)
trap #1
addq.l #6,sp
rts
wait_key:
move.w #7,-(sp)
trap #1
addq.w #2,sp
rts
;***************************************************************************
;***************************************************************************
section data
changed dc.w 2 ; Flag premier changement pour MEDIA-CHG.
txt_intro dc.b 27,'E'
dc.b 'HARD-DISK emulator.',10,13
dc.b '(C)OXYGENE 1995 by Leonard.',10,13
dc.b 0
txt_pcout dc.b 'INIT error: PC not responding',10,13
dc.b 'for initialising hard-disk.',0
txt_already dc.b 'ERROR: Emulated hard disk already',10,13
dc.b 'mounted on drive ',(HARD_DRIVE+'A'),':',0
even
;***************************************************************************
;***************************************************************************
section bss
ds.l 64
my_stack:
prg_size ds.l 1
rec_size ds.l 1
rec_ad ds.l 1
send_size ds.l 1
send_ad ds.l 1
vcrc32 ds.l 1
crc_table ds.l 256
port_dir ds.b 1
psg_7 ds.b 1
psg_e ds.b 1
even
fast_table ds.b $8000 ; Fast-Table de 32Kos
ret_value ds.b HEADER_SIZE
info_block ds.b HEADER_SIZE
ds.b 512
END
; teste de routine qui blinde en lecture avec time out !!!
; try to beat this ha ha ha ha...
move.w d0,d7 ; Nb octets (pas de -1, meme pour DBF)
lea fast_table,a1
moveq #-1,d6 ; Valeur initiale TIME-OUT.
bra.s .w2
; Main loop:
.w1 move.b (a6),d0
dbmi.s d6,.w1 ; dec time out + wait busy
bpl.s .out ; time out ??
move.b 0(a1,d0.w),(a0)+
.w2 move.w (a6),d0
dbpl.s d6,.w2 ; dec time out + wait busy.
dbmi.s d7,.w1 ;
; Sortie:
.out: addq.w #1,d7 ; If d7=-1 alors d7=0, ok.