; Asm ATALoad.a -o ATALoad.a.o; DumpObj ATALoad.a.o > ATALoad.dmp ; The python script does the rest. ; This is messy and brittle. I got very, very sick of it! MAIN MACHINE MC68030 lea $10(sp),a0 ; re-push the 12 bytes of arguments onto the stack move.l -(a0),-(sp) move.l -(a0),-(sp) move.l -(a0),-(sp) bsr.s OriginalFunc ; ... and call the function add.l #$C,sp ; pop those copied arguments, we don't need them cmp.l #$FFFFDB93,d0 ; ATANoDriverErr -> try our method beq.s NewFunc cmp.l #$FFFFDB92,d0 ; ATANoDDMErr -> try our method beq.s NewFunc rts ; don't try our method OriginalFunc string asis dc.b 'Nsrt' ; placeholder for script to insert the clobbered LINK instruction bra *+2+'ID' ; placeholder for script to jump to remainder of original function var_regs equ -$4FA ataPB equ -$4DA ; to ataPBQType equ -$4D6 ataPBVers equ -$4D4 ataPBReserved2 equ -$4CE ataPBFunctionCode equ -$4C8 ataPBIOSpeed equ -$4C7 ataPBFlags equ -$4C6 ataPBDeviceID equ -$4C2 ataPBTimeOut equ -$4BE ataPBState equ -$4B2 ; common part of PB ends at offset $30 = -$4AA ; this part below is a bit tricky... ataPB34 equ -$4A6 ; 34 ataPB38 equ -$4A2 ; 38 ataPB3C equ -$49E ; 3c ataPB40 equ -$49A ; 40 ; -492...-48A = "task file" ataPBTaskFile_ataTFCount equ -$491 ataPBTaskFile_ataTFSDH equ -$48C ataPBTaskFile_ataTFCommand equ -$48B ; entire PB ends at offset $30 = -$4AA ; max possible PB size ends at $B8 = -$422 var_bstruct_0 equ -$422 var_bstruct_2 equ -$420 var_bstruct_4 equ -$41E var_bstruct_6 equ -$41C var_ddmidx equ -$41A var_drvrcnt equ -$418 var_arg2 equ -$40E var_ddmptr equ -$40C var_buf1 equ -$408 var_buf2 equ -$208 var_flags equ -8 var_4 equ -4 arg_dev equ 8 arg_ddtype equ $C ; a long arg_romdrvr equ $10 NewFunc link a6,#-$4DA movem.l d3-d7/a2-a4,-(sp) ; Wipe the stack frame to be safe lea -$4DA(A6),A0 @lup clr.w (A0)+ cmp.l A0,A6 bne.s @lup ; Check that we are asked for an ATA driver cmp.l #$00000701,arg_ddtype(a6) ; kDriverTypeMacATA bne itr_fail ; Load the actual working driver move.w #$FFFF,$B9E ; temp ROMMapInsert move.l #'DRVR',-(SP) move.w #53,-(SP) ; .ATADisk dc.w $A9A0 movea.l (SP)+,A2 tst.l A2 beq itr_fail movea.l (A2),A2 ; Set pointers to the 512-byte scratch buffer and the param block lea var_buf1(a6),a3 lea ataPB(a6),a4 ; Set bit 31 ("RAM based driver at run time") in the d5 passed to DRVR move.l #0,var_flags(a6) tst.b arg_romdrvr+3(a6) bne.s is_romdrvr ori.b #$80,var_flags(a6) ; set the flag is_romdrvr: ; Get the "IDENTIFY DEVICE" block with CHS information move.l #0, $00(a4) ; ataPBLink move.w #0, $04(a4) ; ataPBQType move.b #2, $06(a4) ; --> ataPBVers move.b #0, $13(a4) ; --> ataPBIOSpeed move.w arg_dev+2(a6),d1 ext.l d1 move.l d1, $18(a4) ; --> ataPBDeviceID move.l #0, $08(a4) ; ? ataPBReserved2 move.l #20000,$1C(a4) ; --> ataPBTimeOut move.b #$13, $12(a4) ; --> ataPBFunctionCode = kATAMgrDriveIdentify move.w #$2000,$14(a4) ; --> ataPBFlags = mATAFlagIORead move.w #0, $28(a4) ; ? ataPBState move.l a3, $38(a4) ; ataPBBuffer sub.l #2,sp move.l a4,-(sp) dc.w $AAF1 ; ATAManager move.w (sp)+,d0 ext.l d0 bne itr_return ; Parse the "IDENTIFY DEVICE" block move.w 2(a3),var_bstruct_0(a6) ; typically 1041 move.w 6(a3),var_bstruct_2(a6) ; typically 0010 move.w $C(a3),var_bstruct_4(a6) ; typically 003f move.w var_bstruct_2(a6),d0 ; can't safely get rid of these for some reason! mulu.w var_bstruct_4(a6),d0 move.w d0,var_bstruct_6(a6) ; Send "Init drive parameters" move.b #$1, $12(a4) ; --> ataPBFunctionCode = IO (not in headers) move.w #0, $14(a4) ; --> ataPBFlags move.w #0, $28(a4) ; ? ataPBState move.b #$91, $48+$7(a4) ; ataPBTaskFile.ataTFCommand = kATAcmdInitDrive move.l arg_dev(a6),d0 ; (leaving bit $40 as zero for CHS) lsr.l #4,d0 and.l #$10,d0 ; master/slave bit or.l #$A0,d0 ; sector size ? 512 move.w var_bstruct_2(a6),d1 sub.w #1,d1 or.w d1,d0 ; head number move.b d0, $48+$6(a4) ; ataPBTaskFile.ataTFSDH move.b var_bstruct_4+1(a6),$48+$1(a4); ataPBTaskFile.ataTFCount sub.l #2,sp move.l a4,-(sp) dc.w $AAF1 ; ATAManager move.w (sp)+,d0 ; Loop over all partitions, ask the driver to pick a bootable one move.w #$2000,ataPBFlags(a6) move.l #$200,ataPB34(a6) move.b #$20,ataPBTaskFile_ataTFCommand(a6) move.l #1,d5 ; Initially check only one partition, increase this number later moveq #0,d6 ; Partition index counter tellDriverAboutPartitionLoop: move.l d6,d0 addq.l #1,d6 cmp.l d0,d5 bcs.s itr_fail move.l a3,ataPB38(a6) move.l #$200,ataPB3C(a6) move.b #1,ataPBTaskFile_ataTFCount(a6) pea var_bstruct_0(a6) move.l d6,-(sp) pea ataPB(a6) bsr paramblk_helper_function subq.l #2,sp pea ataPB(a6) dc.w $AAF1 ;;;;;;;;;;;;;;;;;;;;;;;;; kATAcmdRead again (get next PM entry) move.w (sp)+,d7 lea $C(sp),sp moveq #0,d0 move.w (a3),d0 cmpi.l #'PM',d0 bne.s tellDriverAboutPartitionLoop move.l 4(a3),d5 ; update the *real* number of partitions, so we don't end early move.l var_flags(a6),-(sp) ; var_flags, obviously move.w var_arg2(a6),d0 ext.l d0 move.l d0,-(sp) ; arg_dev+2 extended to a long, pretty much always zero move.l a3,-(sp) ; pointer to this partition map entry move.l a2,-(sp) ; pointer to driver bsr *+2+'BT' ; BOOT function move.l d0,d4 lea $10(sp),sp move.w d4,d7 ; -1 means try a different partition, 0 means succes, otherwise error cmpi.w #$FFFF,d7 beq.s tellDriverAboutPartitionLoop tst.w d7 bne.s itr_fail move.l d4,d0 ; the final pathway for success bra.s itr_return itr_fail: move.l #$FFFFDB93,d0 ; ATANoDriverErr itr_return: movem.l var_regs(a6),d3-d7/a2-a4 unlk a6 rts paramblk_helper_function: link a6,#0 movem.l d6-d7/a3-a4,-(sp) move.l $C(a6),d7 movea.l $10(a6),a3 movea.l $8(a6),a4 move.l $18(a4),d0 lsr.l #8,d0 moveq #1,d6 and.l d0,d6 clr.w $28(a4) moveq #0,d0 move.w 6(a3),d0 move.l d7,d1 divu.l d0,d1 move.w d1,$4C(a4) moveq #0,d0 move.w 4(a3),d0 move.l d7,d1 divu.l d0,d1 moveq #0,d0 move.w 2(a3),d0 tst.l d0 tdivs.l d0,d2:d1 moveq #$F,d0 and.l d2,d0 move.b d0,$4E(a4) move.l d6,d0 lsl.l #4,d0 or.b d0,$4E(a4) ori.b #$A0,$4E(a4) moveq #0,d0 move.w 4(a3),d0 move.l d7,d1 tdivu.l d0,d2:d1 addq.b #1,d2 move.b d2,$4A(a4) movem.l -$10(a6),d6-d7/a3-a4 unlk a6 rts string c mystring dc.b 'log from ATALoad ^n' PrintHex ; A0 is already set to a number... MOVE.L #4, D1 ; r4 arg (1: byte, 2: 2byte, else: 4byte) MOVE.L #97, D0 ; call NKPrintHex DC.W $FE1F LEA mystring,A0 MOVE.L #96, D0 ; call NKXprintf DC.W $FE1F RTS ; stack is safe! END