NetBoot/BootServer/DRVR128.a

431 lines
14 KiB
Plaintext

DrvrBase
dc.w $4C00 ; dCtlEnable dStatEnable dNeedLock
dc.w 0 ; delay
dc.w 0 ; evt mask
dc.w 0 ; menu
dc.w DrvrOpen-DrvrBase
dc.w 0 ; no Prime routine
dc.w DrvrControl-DrvrBase
dc.w DrvrStatus-DrvrBase
dc.w DrvrClose-DrvrBase
dc.b 11, '.BootServer'
; a0=iopb, a1=dce on entry to all of these...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DrvrOpen
; TODO: Move this somewhere that it can respond to AppleTalk going up/down
; Don't care about the caller PB, so use A0 as a scratch register
movem.l A0-A1,-(SP)
; Modify the socket listener code for quick access to driver globals
lea editLeaDCE+2,A0
move.l A1,(A0)
; Open .MPP
; TODO: check globals on old ROMs before trying
lea PB,A0
clr.b $1B(A0) ; IOPermssn = whatever is allowed
lea MPPString,A2 ; IOFileName = .MPP
move.l A2,$12(A0)
dc.w $A000 ; _Open
bne.s openFail
move.w $18(A0),$16(A1) ; save MPP refnum in dctlStorage
; Open a DDP socket: "POpenSkt" via direct call to .MPP
move.w #248,$1A(A0) ; csCode = openSkt
clr.b $1C(A0) ; socket = auto-assign
lea SocketListener,A2
move.l A2,$1E(A0) ; listener
dc.w $A004 ; _Control
bne.s openFail
move.b $1C(A0),$14(A1) ; save socket number in dCtlStorage
; Prepare a Name Table Entry for NBP
; TODO: replace with static Name Table Entry struct below
pea NTE
pea ObjStr
pea TypStr
pea ZonStr
clr.w D0
move.b $1C(A0),D0
move.w D0,-(SP)
bsr NBPSetNTE
; Advertise our socket via NBP: "PRegisterName"
move.w #253,$1A(A0) ; csCode = registerName
move.b #7,$1C(A0) ; interval = ~1sec
move.b #5,$1D(A0) ; count = 5
lea NTE,A2
move.l A2,$1E(A0) ; entityPtr = our NTE
move.b #1,$22(A0) ; verifyFlag = do
dc.w $A004 ; _Control
openFail
move.w $10(A0),D0 ; Just return whatever error we got
movem.l (SP)+,A0-A1
move.w D0,$10(A0)
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DrvrClose
move.w #0,$10(A0) ; ioResult
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DrvrControl
cmp.w #65,$1A(A0)
beq.s accRun
move.w #-17,$10(A0) ; ioResult = controlErr
rts
accRun
move.w #0,$10(A0) ; ioResult = noErr (never need to return an error)
; figure out the packet
lea ReceivedPacket,A2
move.w (A2)+,D0 ; length
cmp.b #1,(A2)
beq ReplyToUserRecordRequest
cmp.b #3,(A2)
beq ReplyToImageRequest
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PushReturnAddress
clr.l -(SP)
clr.l -(SP)
clr.l -(SP)
clr.l -(SP)
clr.w -(SP)
move.l ReturnAddress,D0
move.b #10,1+15(SP)
move.b D0,1+13(SP)
asr.w #4,D0
asr.w #4,D0
move.b D0,1+11(SP)
swap D0
move.w D0,1+7(SP)
move.l 18(SP),-(SP)
rts
ReplyToUserRecordRequest ; A0=iopb A1=dce A2=pkt
bclr.b #5,4(A1) ; clear dNeedTime: done with this packet
move.l SP,A3
move.w #586/2-1,D0 ; Push the whole packet
clrloop clr.w -(SP)
dbra D0,clrloop
move.w #$0201,(SP) ; user record reply v1
move.w 2(A2),2(SP) ; copy osID
move.l 4(A2),4(SP) ; copy userData (timestamp)
move.w #512,8(SP) ; blockSize
move.w #0,10(SP) ; imageID
move.w #0,12(SP) ; result (error code)
move.l #(EndOfPayload-StartOfPayload+511)>>9,14(SP)
move.l SP,A4
; This code should be deduplicated
bsr PushReturnAddress
lea 1(SP),A5 ; the "odd" base of the address struct
move.w #0,-(SP) ; Push the WriteDataStructure
move.l A4,-(SP)
move.w #586,-(SP)
move.l A5,-(SP) ; the first odd address of the WDS
move.w #16,-(SP)
move.l SP,A4
bsr WriteDDP
move.l A3,SP
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The money shot
; Send as many packets as we can in six ticks
; Also be fairly canny with the bitmap
; Internally: D7=ticks D6=whichblock D5=scratch
ReplyToImageRequest ; A0=iopb A1=dce A2=pkt D0=pktlen
moveq #0,D4
move.w D0,D4
subq #8,D4
asl.l #3,D4
cmp.w #(EndOfPayload-StartOfPayload+511)>>9,D4
blo.s dontsubtract
move.l #(EndOfPayload-StartOfPayload+511)>>9,D4
dontsubtract
move.l $16A,D7 ; Ticks
moveq.l #-1,D6 ; Block counter
blockloop addq.l #1,D6
cmp.w D4,D6
bhs endsend
move.w D6,D5
asr.w #3,D5
bclr.b D6,8(A2,D5.W)
beq.s blockloop
; okay, so I am committed to sending this packet
move.l SP,A3
; This code should be deduplicated
bsr PushReturnAddress
lea 1(SP),A5 ; the "odd" base of the address struct
move.w D6,-(SP) ; blocknum (first chunk of packet)
move.w 2(A2),-(SP) ; image ID
move.w #$0401,-(SP) ; image data v1
move.l SP,A4
move.w #0,-(SP) ; Push the WriteDataStructure
lea StartOfPayload,A0
moveq #0,D5
move.w D6,D5
lsl.l #4,D5
lsl.l #5,D5
add.l D5,A0
move.l A0,-(SP)
move.w #512,-(SP)
move.l A4,-(SP)
move.w #6,-(SP)
move.l A5,-(SP) ; the first odd address of the WDS
move.w #16,-(SP)
move.l SP,A4
bsr WriteDDP
move.l A3,SP
; check whether we need to yield time
move.l $16A,D5
sub.l D7,D5
cmp.l #6,D5
bhi.s defersend
bra blockloop
endsend
bclr.b #5,4(A1) ; clear dNeedTime: done with this packet
defersend
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WriteDDP ; pass in the WDS as a4
move.l A0,-(SP)
lea -$32(SP),SP
move.l SP,A0
move.w $16(A1),$18(A0) ; IORefNum = dctlStorage.low
move.w #246,$1A(A0) ; csCode = writeDDP
clr.l $C(A0) ; IOCompletion = NULL
move.b $14(A1),$1C(A0) ; get socket number from dCtlStorage
move.b #1,$1D(A0) ; set checksumFlag
move.l A4,$1E(A0) ; wdsPointer to our WriteDataStructure
dc.w $A004 ; _Control
lea $32(SP),SP
move.l (SP)+,A0
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DrvrStatus
move.w #-18,$10(A0) ; ioResult
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SocketListener
; A0 Reserved for internal use by the .MPP driver. You must preserve this register until after the ReadRest routine has completed execution.
; A1 Reserved for internal use by the .MPP driver. You must preserve this register until after the ReadRest routine has completed execution.
; A2 Pointer to the .MPP driver's local variables. Elliot says: the frame and packet header ("RHA") are at offset 1 from A2 (keeps the 2-byte fields aligned)
; A3 Pointer to the first byte in the RHA past the DDP header bytes (the first byte after the DDP protocol type field).
; A4 Pointer to the ReadPacket routine. The ReadRest routine starts 2 bytes after the start of the ReadPacket routine.
; A5 Free for your use before and until your socket listener calls the ReadRest routine.
; D0 Lower byte is the destination socket number of the packet.
; D1 Word indicating the number of bytes in the DDP packet left to be read (that is, the number of bytes following the DDP header).
; D2 Free for your use.
; D3 Free for your use.
; Parse the packet at accRun time
editLeaDCE lea $12345678,A5 ; live-edited to point to DCE
bset.b #5,4(A5) ; raise dNeedTime in dCtlFlags
; Parse the "return address" from the header
cmp.b #1,1+2(A2) ; test DDP header type
bne.s longhdr
shorthdr moveq.l #0,D2 ; network number = 0
move.w 1+1(A2),D2 ; node number
move.b 1+6(A2),D2 ; socket numder
bra.s doneWithHeader
longhdr move.w 1+9(A2),D2 ; network number
swap D2
move.b 1+12(A2),D2 ; node number
asl.w #4,D2
asl.w #4,D2
move.b 1+14(A2),D2 ; socket number
doneWithHeader
; Save the return address in a standard format
lea ReturnAddress,A5
move.l D2,(A5)
; Save the return address and packet body
lea ReceivedPacket,A3
move.w D1,D3 ; odd that I need to use this register?
move.w D3,(A3)+
jmp 2(A4) ; ReadRest (to A3)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MPPString dc.b 4, ".MPP", 0
ObjStr dc.b 4, "0000", 0
TypStr dc.b 10, "BootServer", 0
ZonStr dc.b 1, "*"
ReturnAddress dc.l 0
ReceivedPacket dcb.b 2+586
; Names table entry for NBP
PB
dcb.b 108
NTE
dcb.b 108
; AddrBlock is Net(w)/Node(b)/Socket(b)
; NTElement RECORD 0
; nteAddress ds AddrBlock ; offset: $0 (0) ; network address of entity
; filler ds.b 1 ; offset: $4 (4)
; entityData ds.b 99 ; offset: $5 (5) ; Object, Type & Zone
; sizeof EQU * ; size: $68 (104)
; ENDR
; NamesTableEntry RECORD 0
; qNext ds.l 1 ; offset: $0 (0) ; ptr to next NTE
; nt ds NTElement ; offset: $4 (4)
; sizeof EQU * ; size: $6C (108)
; ENDR
; PROCEDURE NBPSetNTE( NTEptr:Ptr;NBPObject,NBPType,NBPZone:STRING[32];Socket:INTEGER);
; Builds an Names Table Entry using the parms. Calls NBPSetEntity to fill in the strings.
; This clears the next entry pointer in the NTE. Only LSB 8 bits of Socket are used.
NBPSetNTE
MOVEM.L A0-A3/D0,-(SP)
MOVE.W 24(SP),D0 ;D0=Socket
MOVEM.L 26(SP),A0-A3 ;A0->Zone,A1->Type,A2->Object,A3->NTE
CLR.L (A3)+ ;clear next ptr
MOVE.B D0,3(A3) ;set socket [TupleSkt]
PEA 5(A3) ;set Buffer ptr [TupleName]
PEA (A2) ;Object
PEA (A1) ;Type
PEA (A0) ;Zone
JSR NBPSetEntity ;fill in the strings
MOVEM.L (SP)+,A0-A3/D0
MOVE.L (SP),18(SP)
ADDA.L #18,SP
RTS
; PROCEDURE NBPSetEntity(Buffer:Ptr;NBPObject,NBPType,NBPZone:STRING[32])
; Concatenates the strings Object,Type, & Zone in Buffer
NBPSetEntity
MOVEM.L A0/A1/D0,-(SP)
MOVEQ #28,D0
BSR.S MoveAstring ;move the Object
MOVE.W #24,D0
BSR.S MoveAstring ;move the Type
MOVE.W #20,D0
BSR.S MoveAstring ;move the Zone
MOVEM.L (SP)+,A0/A1/D0
MOVE.L (SP),16(SP)
ADDA.L #16,SP
RTS
MoveAstring
MOVEA.L (SP,D0.W),A0 ;get source string addr
CLR.L D0
MOVE.B (A0),D0 ;setup len and adjust source addr
ADDQ.L #1,D0 ;adj for str len byte
MOVEA.L 32(SP),A1 ;setup dest addr
ADD.L D0,32(SP) ;update dest addr
DC.W $A22E ; _BlockMoveData
RTS
align 9
StartOfPayload
incbin "../payload"
EndOfPayload