home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Special 6
/
Sonderheft_6-96.iso
/
pd
/
disktools
/
softrack
/
source
/
install.s
< prev
next >
Wrap
Text File
|
1996-11-03
|
7KB
|
301 lines
; Install.s
; It istalls two routines at the DoIO and SendIO vectors.
; To be Assembled with SAS/C 6.50 Assembler and linked with slink
; to produce SofTrack: 1> asm Install.s
; Written by Kamran Karimi.
INCLUDE "exec/memory.i"
INCLUDE "exec/ports.i"
INCLUDE "exec/io.i"
INCLUDE "devices/trackdisk.i"
INCLUDE "dos/dos.i"
ExecBase equ 4
;EXEC library
PutMsg equ -366
Allocmem equ -198
FreeMem equ -210
Forbid equ -132
Permit equ -138
SetFunction equ -420
; DoIO and SendIO offsets point to the actual jump address, not the 'jmp'
; instruction before them. the jmp for DoIO and SendIO are at offset -456 and -462
; respectvely. As you can see, the 'jmp' opcode has two bytes.
DoIO equ -454
SendIO equ -460
; the main proram will prepare the message port and the routines in this
; file will send information to it
XREF _Port
; these variables are initialized here but used in the main program
XREF _ReservedDoIO
XREF _ReservedSendIO
XREF _SaveDoIO
XREF _SaveSendIO
XREF _SizeOfIO
SECTION inst,CODE
XDEF _Install
_Install:
; subroutines in Amiga can use registers d0, d1, a0 and a1 as scratch.
; all other registers should remain intact, so we save a6, as we will
; over write it here
move.l a6,-(a7)
; initialize message port parameters before they are copied
lea Message,a1
move.b #NT_MESSAGE,LN_TYPE(a1) ;message type
move.w #MN_SIZE+8,MN_LENGTH(a1) ;message length
; save the original vector addresses.
move.l ExecBase,a6
move.l DoIO(a6),_SaveDoIO
move.l SendIO(a6),_SaveSendIO
; the two routines for DoIO and SendIO are identical, so we copy the
; code provided here in two newly allocated places in memory.
; each one will have its own structures and the ability to send messages
; to the main program's port.
;
; NOTE: Amiga does not support run-time relocation of code.
; to be able to move a piece of code after it is loaded in memory,
; all the addressings in it should be PC relative.
move.l ExecBase,a6
move.l _Port,Port
move.l #EndeIO-BeginIO,d0
move.l d0,_SizeOfIO
move.l #MEMF_PUBLIC,d1
jsr Allocmem(a6) ; allocate memory for DoIO
move.l d0,_ReservedDoIO
beq End_Main ; no mem?
move.l _SizeOfIO,d0
move.l #MEMF_PUBLIC,d1
jsr Allocmem(a6) ; another for SendIO
move.l d0,_ReservedSendIO
bne MemAllocated
move.l _ReservedDoIO,a1 ; if failed, free the DoIO memory
move.l _SizeOfIO,d0
jsr FreeMem(a6)
bra End_Main
; memory allocated, now copy the code provided under the BeginIO label
; to these places.
MemAllocated:
; we need the original vector address, so that we can activate it after
; the information have been sent to the main program
move.l DoIO(a6),_SaveIO
move.l #BeginIO,a0 ; source
move.l _ReservedDoIO,a1 ;destination
move.l _SizeOfIO,d0 ; size in bytes
divu #2,d0 ; a word (2 bytes) at a time
subi.l #1,d0 ; 'dbra' stops when the counter in d0 reaches -1!
lop1:
move.w (a0)+,(a1)+ ; do the copy
dbra d0,lop1 ; 'dbra' done?
move.l ExecBase,a1
move.l #DoIO-2,a0
move.l _ReservedDoIO,d0
jsr SetFunction(a6) ; DoIO vector is changed
; the above operations are repeated for SendIO
move.l SendIO(a6),_SaveIO
move.l #BeginIO,a0
move.l _ReservedSendIO,a1
move.l _SizeOfIO,d0
divu #2,d0
subi.l #1,d0
lop2:
move.w (a0)+,(a1)+
dbra d0,lop2
move.l ExecBase,a1
move.l #SendIO-2,a0
move.l _ReservedSendIO,d0
jsr SetFunction(a6)
moveq #RETURN_OK,d0 ; we succeded
bra Payan
End_Main:
move.l #RETURN_FAIL,d0 ; we failed
Payan:
move.l (a7)+,a6
rts
; this is the common routine for getting disk operation information.
; all addresses are relative to program counter, to enable it to be moved
; around in memory
BeginIO:
; save the original register contents. we should give them intact to
; the original DoIO ro SendIO routine.
;
; the address of a ioRequest is in a1. this contains all the information
; about the requested action.
movem.l d0-d4/a0-a4/a6,-(a7)
; first we see if the request is for 'trackdisk.device'
move.l IO_DEVICE(a1),a2 ; pointer to device structure is in a2
move.l LN_NAME(a2),a3
move.l #15,d0
lea TrackName(pc),a4
lop22:
cmpm.b (a3)+,(a4)+
bne Endit ; not for 'trackdisk.device'. just call the original routine
dbra d0,lop22
; prepare the message structure to be filled with information
lea Message(pc),a2
move.l IO_UNIT(a1),a4 ; pointer to a Unit structure is in a4
; this offset ($41) is not documented! (see SofTrack.doc)
; it seems that this code breaks under 2.0 and above! (i.e. the information
; for all drives is shown in the df1 space.
move.b $41(a4),d0
; is it for DF0?
btst #3,d0
bne df1
move.b #0,20(a2)
bra Cont
df1:
btst #4,d0 ;maybe df1?
bne df2
move.b #1,20(a2)
bra Cont
df2:
btst #5,d0 ;or df2 ?
bne df3
move.b #2,20(a2)
bra Cont
df3:
btst #6,d0 ; or df3 ?
bne Endit ; none of them? just call the original routine.
move.b #3,20(a2)
Cont:
move.w IO_COMMAND(a1),d0 ;d0 has command
bclr #TDB_EXTCOM,d0 ; being an extended command is not interesting to us
; now find out the command (read, write, format... )
cmpi.w #CMD_READ,d0
bne NotR
move.b #'R',26(a2)
bra TrackChange
NotR:
cmpi.w #TD_SEEK,d0
bne NotS
move.b #'S',26(a2)
bra TrackChange
NotS:
cmpi.w #TD_RAWREAD,d0
bne NotRawR
move.b #'R',26(a2)
bra TrackChange
NotRawR:
cmpi.w #CMD_WRITE,d0
bne NotW
move.b #'W',26(a2)
bra TrackChange
NotW:
cmpi.w #TD_FORMAT,d0
bne NotF
move.b #'F',26(a2)
bra TrackChange
NotF:
cmpi.w #TD_RAWWRITE,d0
bne Endit
move.b #'W',26(a2)
TrackChange:
moveq #0,d4
move.l #16,d2 ; used for shifts. the result of divu are 16 bit.
move.l 44(a1),d1 ;sector offset
;11264 = 512 (bytes per sector) * 11 (sectors per track) * 2 (sides per disk)
move.l #11264,d3
divu d3,d1 ;track
andi.l #$0000ffff,d1 ; we need only the quotient
; now turn the track number into ASCII, so that it can be displayed
; to the user
divu #100,d1
addi.b #48,d1
cmp.b #'0',d1
bne NZ1
move.b #' ',d1 ; don't show 0
moveq #1,d4
NZ1:
move.b d1,22(a2)
lsr.l d2,d1 ; now the remainder
divu #10,d1
addi.b #48,d1
tst d4
beq NZ2
cmp.b #'0',d1
bne NZ2
move.b #' ',d1
NZ2:
move.b d1,23(a2)
lsr.l d2,d1
addi.b #48,d1
move.b d1,24(a2)
move.l ExecBase,a6
move.l Port(pc),a0
lea Message(pc),a1
jsr PutMsg(a6)
Endit:
; restore the original register contents.
movem.l (a7)+,d0-d4/a0-a4/a6
; push the original routine address on the stack. now an 'rts' will
; transfer control to it.
move.l _SaveIO(pc),-(a7)
rts
_SaveIO: dc.l 0
Message: ds.b 20 ;<- this is the main message structure
dc.w 0 ; <- the unit obeying the command is put here
dc.b "000 ",0 ; <- information to be displayed is put here
; message port address
Port: dc.l 0
TrackName: dc.b "trackdisk.device",0,0
EndeIO:
END