Home
80's & Games
Javanoïd | Pang
PooPooDream
AmiGames
 
Galleries
Marilyn | Ban
 
Amiga Oldies
modules | Goodies
 
Humour
Gallery | Goodies
 
Bibliothèque
Sci-Fi | Fantasy
Thriller Polar
Divers | Doc
 
Links
GuestBook
Wanted



 

 




..= Hardware Trackloader =..
original french version by Loïc Far

 Amiga Tutos
--------------------
Hardware Trackloader
--------------------

from an article "Les Disques Chouettes" by Loïc Far in Amiga News Tech issues #24-25-27-30 (jul/aug/sept/nov 1990). (cover disks)
source (original) of the hardware trackloader with multidrive test and cia timer delay
cover disk #25

see some trackloader sources (Interphase/Toki custom, standard Trackloader, raw sector loaders)

base before any other non-dos formats (protected or not)

the Complex Interface Adapter CIA assists the DMA disk starting motor, moving I/O heads, choosing the active side and while providing to the system the state of drive.

the DMA disk take charge of Read/Write :
synchronizes the reading with a control word - SyncWord (standard $4489) - to guarantee the alignment of the datas in memory.
the standard coding of the datas is MFM (IBM, Atari...) or GCR
Mfm Uncoding is done by the 68000 (possible with the blitter, but why?!)

CIA-A : $bfe001 - 4 bits used - Input

Bit
Nom
Fonction
5
RDY
Disk Ready. set to 0 when motor on and disk ready
4
TRACK0
Track Zero Detect. set to 0 when I/O head on track 0
3
WPRO
Write Protected. set to 0 if write protected disk
2
CHNG
Disk Change. set to 0 when changing disk. set to 1
when disk is inserted and an impulse step transmitted

CIA-B : $bfd100 - 8 bits used - control - Output

Bit
Nom
Fonction
7
MTR
Disk Motor Control. It doesn't have immediate action but is received by the drive when selected by SELx. To start/stop drive, it's initially necessary to set MTR then select the drive.
6
SEL3
select drive DF3
5
SEL2
select drive DF2
4
SEL1
select drive DF1
3
SEL0
select drive DF0. always.
2
SIDE
select face. it must be maintained during 100 microseconds for writing, and during at least 1,3 millisecond between a writing and change of side. 0 : higher side, 1 : lower side
1
DIR
select direction. 0 : towards center. before the step impulse. 2 mc68000 instructions are necessary. better is worth a timer more compatible : CIA Timer, than dbra loop.
0
STEP
send an impulse for moving head. fast: inactive-active-inactive. move of a track to another in 3 millisec max.
during a change of direction, 18 millisec. between 2 step impulses.

example:

include "hardware/cia.i"
lea $bfd000,a5 CIA-B
lea $bfe001,a4 CIA-A

bsr MotorOn
bsr SeekTrack0
bsr MotorOff
rts

MotorOn:
bset #CIAB_DSKSEL0,ciaprb(a5) ; df0: off
bclr #CIAB_DSKMOTOR,ciaprb(a5) ; 0: motor on
bclr #CIAB_DSKSEL0,ciaprb(a5) ; df0: on
rts

MotorOff:
bset #CIAB_DSKSEL0,ciaprb(a5) ; df0: off
bset #CIAB_DSKMOTOR,ciaprb(a5) ; 1: motor off
bclr #CIAB_DSKSEL0,ciaprb(a5) ; df0: on
rts

SeekTrack0:
bset #CIAB_DSKDIREC,ciaprb(a5) ; dir=1
.seek btst #CIAB_DSKTRACK0,ciapra(a4)
beq.s .Ok
bsr Step
bsr Delay
bra.s .seek
.ok rts

Step: bclr #CIAB_DSKSTEP,ciaprb(a5)
nop
nop
nop
bset #CIAB_DSKSTEP,ciaprb(a5)
rts

Delay: // software delay !!
move.w #3000,d7
dbra d7,*

TestDrive:
btst #CIAB_DSKRDY,ciapra(a4)
bne.s TestDrive
rts

---------
Timer CIA
---------
;--- delay Timer A CIA-B
move.w #$2000,$dff09a ; INTENA bit 13 - stop interrupt CIA-B

move.l #$bfe001,a0 ; CIA-B
move.b $e00(a0),d0 ; register CRA
andi.b #$c0,d0 ; mask unused bits
ori.b #8,d0 ; mode on-shot
move.b d0,$e00(a0) ; init timer A, mode one-shot
move.b #$28,$400(a0) ; 3ms=2128 PAL
move.b #$21,$500(a0) ; 2148 NTSC
wait:
btst.b #0,$d00(a0) ; test register ICR
beq.s wait ; wait

...

bset.b #0,$e00(a0) ; reset the timer
bra.s wait ; loop

------------
format MFM
------------

this format makes possible to avoid any error of synchro during read/write, by inserting one bit of synchro (parity) between each bit of data. Initially coding the odd bits then the even bits, in 2 consecutive buffers

; d0 = nb long word to uncode -1
; a0 = odd bits
; a1 = even bits
; a2 = uncode buffer
Decode:
move.l (a0)+,d1
move.l (a1)+,d2
andi.l #$55555555,d1
andi.l #$55555555,d2
lsl.l #1,d1 ;*2
or.l d2,d1
move.l d1,(a2)+
dbra d0,Decode
rts

MFM sector header :
2 bytes @ $00 ($AAAA MFM)
2 bytes @ $A1 ($4489 MFM)
1 long word : sector description (8 bytes MFM)
16 bytes : AmigaDOS reserved (32 bytes MFM)
1 long word : header checksum (8 bytes MFM)
1 long word : data checksum (8 bytes MFM)
512 bytes datas (1024 bytes MFM)

the first 2 bytes to 0 ($aaaa in mfm) : beginning of the sector
the two following bytes are used to indicate to the DMA when it must start to write/read
the data read in memory this value is a particular word in MFM,
placed in front of each sector : it corresponds to the value $A1 coded without bit 7.
It's sure that this value will never be found in the data of the sector.
It's possible for protection to use another value that $4489.
The sector description : 4 bytes : $FF (amiga format), # track, # sector, sector numbers
remaining to be read before reaching the end of track.
the DMA disc reading full track since a random position, thus know the position of the sector in the track.
the 2 checksums allow of check for each sector which the reading proceeded well (or exclusive EOR of each long word)

-----------
MFM Tracks
-----------
a track contains 11 sectors made up of a various datas field of 32 bytes
followed by a data field of 512 bytes.
the track is preceded by a GAP of approximately 700 bytes (vari according to the position of the track)
it makes it possible to prevent at writing that the last datas don't crush the first (a track is circular)

700+(2*(11*(32+512))) = 12668 bytes MFM by track

SECTOR:

offset
val
?
0
$aaaa
first word
2
$aaaa
second word
4
$4489
first synchro word
6
$4489
second synchro word
8
xxxxx
ID sector odd bits
12
xxxxx
ID sector even bits
16
xxxxx
AmigaDOS datas odd bits
32
xxxxx
AmigaDOS datas even bits
48
xxxxx
checksum header (odd bits)
52
xxxxx
checksum header (even bits)
56
xxxxx
checksum datas (odd bits)
60
xxxxx
checksum datas (even bits)
64
xxxxx
datas odd bits
576
xxxxx
datas even bits

Uncode steps:
1- ID sector
2- checksum header
3- checksum datas
4- datas
+ check 2 checksums (see MFMUncode routine)

-----------
Test Drives
-----------
(from ANT #30 by François 'Altaïr' Braün)
source
cover disk #30
detect multiple drive (df0-1-2-3)
based on RKM

1- MTR off
2- SELxB off
3- SELxB on
4- MTR on
5- SELxB off
loop:
6- SELxB on
7- SELxB off
8- lire et sauver l'etat de DSKRDY
9- SELxB on
10- loop (6-9) x16

routine:
put 4 ID of each drive in buffer

TestDrive:
lea Buffer(pc),a0
bsr TestDisk
rts
Buffer: dc.w 0,0,0,0

TestDisk:
movem.l d0-d7/a1,-(sp)
addq.l #8,a0 ; end of buffer 3 to 0

lea $bfd100,a1 ; CIA-B
moveq #2,d0 ; 3 drives DF3 - DF2 - DF1)
test:
move.b d0,d1
addq.b #4,d1 ; bit DSKSELx (4 à 6)

bclr #7,(a1) ; DSKMOTOR low
bclr d1,(a1) ; DSKSELx low
bset d1,(a1) ; DSKSELx high
bset #7,(a1) ; DSKMOTOR high
bclr d1,(a1) ; DSKSELx low

moveq #0,d2 ; ID
moveq #15,d3 ; 16 tests (1 word)
.loop:
lsl.l #1,d2
bset d1,(a1) ; DSKSELx high
bclr d1,(a1) ; DSKSELx low
btst #5,$f01(a1) ; CIA-A $bfe001 DSKRDY
bne.s .next
bset #0,d2
.next:
bset d1,(a1) ; DSKSELx high
dbra d3,.loop

move.w d2,-(a0)
dbra d0,test

move.w d0,-(a0) ; DF0 always present
movem.l (sp)+,d0-d3/a1
rts

------------------------------------------
Second Part : DMA disk : Read/Write datas
------------------------------------------

The data transmitted via DMA disk, having been encoded or mfm gcr or another for writing

Initialization steps :
- set data buffer : register DSKPT ($dff020-22)
- init register DSKLEN (write) ($dff020) :
bit 15 DMAEN
bit 14 Write
bit 0-13 Lenght

1. DSKEN de DMACON set to 1 (always when DMAEN=1)
2. secure: activate 2x DMAEN
- desactivate DMAEN : DSKLEN=0
- set address buffer in DSKPT
- init DSKLEN : LEN-WRITE-DMAEN, 2x
- wait DMA disk ending
- secure: DSKLEN=0

An interrupt is generated after reading / writing the last word

state: DSKBYTR $dff01a (read)

If you do not want to read an entire track, you can start the DMA access to a fixed position. Written on the word of data where the disk controller must start within DSKSYNC

DSKSYNC : $dff07e (write)
Data word that the transfer should begin.
When the controller reads the data, he compares it with the word data DSKSYNC.
When both match, he began transferring
- wait sync word at the beginning of a data block
- start Interruption when OK

type of encoding data in ADKCON $dff09e (write) - ADKCONR $dff010 (read)
ADKCON:
15. set/clr
13-14. Precomp 0, 2 (140 nanosec), 4 (280 nanosec), 6 (560 nanosec)
12. Memprec : 0= GCR 1=MFM
10. wordsync: 0=MFM 1=GCR
9. Msbsync : 1 = synchro msb
8. fast : 1 = 2 microsec (MFM) - 0 = 4 microsec (GCR)

Writting Datas
-----------
Code the datas in MFM :
(soon)
and replace the Read routine with :
...
Write:
move.w #$7f00,$9e(a6)
move.w #$8100,$9e(a6)
bsr DiskReady
move.l #MFMBuffer,$20(a6)
move.w #$D978,$24(a6)
move.w #$D978,$24(a6)
move.w #2,$9c(a6)
.wait
btst #1,$1f(a6)
beq.s .wait
move.w #$4000,$24(a6)
...