[comp.sys.amiga] noclick w/source, minus the "last" bug

ISCOVE%UTOROCI.bitnet@ugw.utcs.utoronto.ca (08/22/89)

These updates correct a rather subtle bug that was causing the
program occasionally to fail to silence one of the drives.
Version 3.4 also incorporates changes to the jump tables in
the ram copy of trackdisk (thanks to Werner Guenther for the
suggestion) so that the routines point back into
the ram copy.  The result is that the fix ('fixbug' in the
source) to the raw read/write code will actually take effect.
Version 3.3 differs only in omitting the 'fixjumps' section.
Version 3.4 is to be used with care - there are advantages to
having code controlling disk i/o protected in rom.


begin 644 NoClick3.3
M```#\P`````````!``````````````!.```#Z0```$Y(YS\^+'@`!'P!1_D`0
M``$D2?D```#R3J[_B$'N`98B3$ZN_NPFP"!`9O1'Z__\0>X!I%'._^I.KO^"<
M2?D```$D80``IB!K`$:Q_`#X``!C``"00?D```#R<`!R`$/Y```!!$ZN_D1F*
M``!X)GD```$80_D```$$3J[^/B)K``J2_``8)!%822!1D,)V`#8(5D,@`W(!B
M3J[_.B)`Y$L@0B+84<O__"I`"&T`!P$%.WP,@!HX2?D```$D82XD:P!&E<+;W
MRDZN_X@G30!&3J[_@F$89PY.KO^()TT`1DZN_X)@[DS??/QP`$YU(EPF:0`V3
M(`E.=71R86-K9&ES:RYD979I8V4`````````````````````````````````*
M``````````````````````````````````````````/L````"``````````,#
D````$@```#P```!4````7@```&P```!R````M`````````/R'
``
end
size 396


begin 644 NoClick3.4
M```#\P`````````!``````````````!3```#Z0```%-(YS\^+'@`!'P!1_D`:
M``$V2?D```$$3J[_B$'N`98B3$ZN_NPFP"!`9O1'Z__\0>X!I%'._^I.KO^"!
M2?D```$V80``N"!K`$:Q_`#X``!C``"B0?D```$$<`!R`$/Y```!%DZN_D1FE
M``"*)GD```$J0_D```$63J[^/B)K``J2_``8)!%822!1D,)V`#8(5D,@`W(!8
M3J[_.B)`Y$L@0B+84<O__"8"EH`@0$'H"AQX%9>84<S__"I`"&T`!P$%.WP,I
M@!HX2?D```$V82XD:P!&E<+;RDZN_X@G30!&3J[_@F$89PY.KO^()TT`1DZN,
M_X)@[DS??/QP`$YU(EPF:0`V(`E.=71R86-K9&ES:RYD979I8V4`````````R
M`````````````````````````````````````````````````````````````
M``!.<0```^P````(``````````P````2````/````%0```!>````;````'(`@
+``#&`````````_((#
``
end
size 416


*************************************************************************
*                                                                       *
*                                                                       *
*       Program Name:   NoClick3.4                                      *
*                                                                       *
*       Version Date:   20 August 1989                                  *
*                                                                       *
*       Based on the prototype NoClick program posted by                *
*       Dan Babcock to PLINK in May 1989                                *
*                                                                       *
*       With thanks to Werner Guenther for showing the use of           *
*       FindName to generate the trackdisk task list, and               *
*       pointing out the possibility of changing the code's             *
*       jump table.                                                     *
*                                                                       *
*       Copyright (c) 1989 - Norman Iscove  iscove@utoroci (bitnet)     *
*                                                                       *
*                                                                       *
*       USAGE:  Place in c: directory.  Type 'NoClickxx' from CLI,      *
*       or include in Startup-sequence, preferably after FastMemFirst.  *
*       Safer not to invoke it at a point where disks are concurrently  *
*       active.                                                         *
*                                                                       *
*       FUNCTION:                                                       *
*                                                                       *
*       Intended to eliminate clicking of empty drives installed in     *
*       Amiga 500, 1000 or 2x00 computers, provided the particular      *
*       drive models respond quietly to negative stepping of the        *
*       heads past track 0.  The program checks for and sets            *
*       additional floppy drives if also present.  Aborts harmlessly    *
*       if a second execution is attempted.  Also repairs a known       *
*       bug in the trackdisk.device code involving raw read and         *
*       write calls.                                                    *
*                                                                       *
*       Works by copying the trackdisk.device code from rom into        *
*       ram.  A single byte is modified so that the drive heads         *
*       will be stepped (silently) in a negative rather than            *
*       positive direction during the regular system checks for a       *
*       disk change.  One word is also altered to repair the raw        *
*       read/write bug.  After creating the copy and fixing it, the     *
*       program changes the system vectors in each drive's task         *
*       structure to point to the ram copy.                             *
*                                                                       *
*                                                                       *
*       ENTRY REGISTERS:  none assumed                                  *
*                                                                       *
*       EXIT  REGISTERS:  d2-d7/a2-a6 preserved in entry condition      *
*                         d0 = 0                                        *
*                                                                       *
*       ASSUMPTIONS:                                                    *
*                                                                       *
*       Private structure of the trackdisk.device code in rom is        *
*       not documented.  The offsets of the pointers to start and       *
*       end of the code, and the offsets of the bytes to be altered     *
*       are all determined by inspection of the code in the 1.3 rom.    *
*                                                                       *
*       CAVEAT:                                                         *
*                                                                       *
*       Has been tested and works on a B2000 running KS/WB 1.3 V34.2    *
*       with two internal floppy drives, 2 MB expansion memory (2058)   *
*       and no hard drive.                                              *
*                                                                       *
*************************************************************************




        INCLUDE 'execlib'

*-----------------------------------------------------------------------*
*               Save the incoming registers                             *
*-----------------------------------------------------------------------*
main:   movem.l d2-d7/a2-a6,-(sp)
        movea.l 4,a6            ;a6 = execbase


*-----------------------------------------------------------------------*
*       Make a list of all the trackdisk tasks                          *
*-----------------------------------------------------------------------*
tasklist:
        moveq   #1,d6           ;d6 = counter (search through two lists)
        lea     tasks,a3        ;a3 = pointer to my list of td tasks
        lea     tdname,a4       ;a4 = pointer to "trackdisk.device"
        jsr     _LVODisable(a6) ;disable interrupts & task switching
        lea     406(a6),a0      ;a0 = start of taskready queue
nexttask:
        move.l  a4,a1           ;a1 = pointer to "trackdisk.device"
        jsr     _LVOFindName(a6) ;find the next task with this name
        move.l  d0,(a3)+        ;save task pointer in my list, sets cond.
        movea.l d0,a0           ;a0 = start for next FindName search
        bne.s   nexttask        ;check for next task if not zero
waitqueue:
        lea     -4(a3),a3       ;correct pointer
        lea     420(a6),a0      ;a0 = start of taskwait queue
        dbf     d6,nexttask
        jsr     _LVOEnable(a6)


*-----------------------------------------------------------------------*
*               Abort if already installed                              *
*-----------------------------------------------------------------------*
check:
        lea     tasks,a4        ;1st entry is the one that was ready
        bsr     nextset
        move.l  $46(a3),a0      ;a0 = finalPC, td code that task exits to
        cmp.l   #$f80000,a0     ;exit if already pointing to ram
        bls     exit


*-----------------------------------------------------------------------*
*       Find trackdisk.device in rom, get start, end, size              *
*-----------------------------------------------------------------------*
findcode:

        lea     tdname,a0
        moveq   #0,d0           ;unit df0:
        moveq   #0,d1           ;flags
        lea     iorequest,a1
        jsr     _LVOOpenDevice(a6) ;open the trackdisk.device
        bne     exit
        move.l  iodevice,a3     ;a3 = trackdisk library base address C03AE4
        lea     iorequest,a1
        jsr     _LVOCloseDevice(a6)
        move.l  $0A(a3),a1      ;ln_name(a3) (C03AEE) points to string
                                ; 'trackdisk.device' at FE957E
        sub.w   #$18,a1         ;a1 = FE9566
        move.l  (a1),d2         ;d2 = start of trackdisk routine in rom,
                                ;     FE9564.
        add.w   #4,a1           ;a1 = FE956A
        move.l  (a1),a0         ;a0 = end of trackdisk routine in rom,
                                ;     FEB05C
        suba    d2,a0           ;a0 = signed length of trackdisk routine
        moveq   #0,d3
        move.w  a0,d3           ;d3 = unsigned length (bytes) of td routine
        addq    #3,d3           ;ensure all copied if not multiple of 4


*-----------------------------------------------------------------------*
*              Allocate some ram and copy to it                         *
*-----------------------------------------------------------------------*
copy:
        move.l  d3,d0           ;d0 = number of bytes
        moveq   #1,d1           ;d1 = MEMF_PUBLIC, fastmem if available
        jsr     _LVOAllocMem(a6)
        move.l  d0,a1           ;d0,a1 = location of reserved block in ram
        lsr.w   #2,d3           ;d3 = number of longs to copy
        move.l  d2,a0           ;a0 = start of rom routine

cploop:
        move.l  (a0)+,(a1)+     ;copy rom routine to ram
        dbra    d3,cploop


*-----------------------------------------------------------------------*
*       Fix the copy's jump table so that the code patched by fixbug    *
*        (below) is actually used (thanks to W. Guenther)               *
*-----------------------------------------------------------------------*
fixjumps:
        move.l  d2,d3          ;d3 = start of rom routine
        sub.l   d0,d3          ;- start of ram copy = offset
        movea.l d0,a0          ;a0 = start of ram copy
        lea     $a1c(a0),a0    ;a0 = pointer to copy's jump table
        moveq   #21,d4         ;d4 = 22 functions to patch
fj1:
        sub.l   d3,(a0)+       ;correct the address of each function
        dbf     d4,fj1


*-----------------------------------------------------------------------*
*                   Stop the clicks                                     *
*-----------------------------------------------------------------------*
rmvclick:
        move.l  d0,a5           ;a5 = location of copy
        bchg    #7,$0105(a5)    ;fix the critical byte


*-----------------------------------------------------------------------*
*       Repair trackdisk read/write bug originally at $feaf9c (1.3)     *
*-----------------------------------------------------------------------*
fixbug:
        move.w  #$0C80,$1A38(a5) ;fix to cmp.l #$8000,d0


*-----------------------------------------------------------------------*
*       Fix each task's exit vector to point to ram version             *
*-----------------------------------------------------------------------*
fixptrs:
        lea     tasks,a4        ;a4 = address of task list
        bsr.s   nextset
        move.l  $46(a3),a2      ;a2 = finalPC, td code that task exits to
        sub.l   d2,a2           ;a2 = offset of code from start (d2) in rom
        add.l   a2,a5           ;a5 = corresponding address in ram copy

        jsr     _LVODisable(a6)
        move.l  a5,$46(a3)      ;replace corrected finalPC pointer
        jsr     _LVOEnable(a6)

fixloop:
        bsr.s   nextset
        beq.s   exit
        jsr     _LVODisable(a6)
        move.l  a5,$46(a3)      ;replace corrected finalPC pointer
        jsr     _LVOEnable(a6)
        bra.s   fixloop


*-----------------------------------------------------------------------*
*                       Done                                            *
*-----------------------------------------------------------------------*
exit:
        movem.l (sp)+,d2-d7/a2-a6 ;restore the incoming registers
        moveq   #0,d0             ;tell system no error
        rts




;*** subroutines

*-----------------------------------------------------------------------*
*       Find task's exit pointer to trackdisk code                      *
*                                                                       *
*       Exit registers:  a1 = address of task structure                 *
*                        a3 = tc_SPReg                                  *
*                        d0 = a1                                        *
*                        z flag = 0 if no more tasks                    *
*-----------------------------------------------------------------------*
nextset:
        move.l  (a4)+,a1        ;a1 = address of this task structure
        move.l  $36(a1),a3      ;a3 = tc_SPReg for this task
        move.l  a1,d0           ;test for a1=0
        rts


;*** data


tdname:
        dc.b    'trackdisk.device',0
        EVEN

iorequest:
        dc.b    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
iodevice:
        dc.b    0,0,0,0
iounit:
        dc.b    0,0,0,0,0,0,0,0
        EVEN

tasks:
    ds.l    4   ;room for 4 drives
    dc.l    0   ;end of list marker

        END