! INet process for interim Mouse (Moose), GDMR, Jan... 1988. Based on ! VAX/VMS version. !%option "-NonStandard-Low-NoCheck-NoDiag-NoLine" %option "-NonStandard-Low-NoCheck" ! This file contains some basic definitions and utility routines, together ! with the dispatcher loop at the end, but all the main components are ! linked in from separate files for convenience. Note: (a) there is a clock ! interrupt handler to deal with timestamp calculations and timeouts; (b) ! there is one common semaphore which is waited for by the main dispatch loop; ! (c) most of the subsidiary files are common with the VMS version, except that ! network-ordering is a no-op for 680x0 processors; (d) HMD's compiler is unable ! to cope with real programs using more than a small number of variables. %constinteger buffer pool size = 64 %constinteger ARP lives = 4 %include "INet:Formats.Inc" %include "INet:Utility.Inc" %include "INet:Stats.Inc" %include "INet:Control.Inc" %systemroutinespec phex(%integer what) %systemintegerfnspec free store %externalintegerfnspec global heap get(%integer bytes) %externalroutinespec FS insert(%string(31) what, %integer value) %externalinteger control = 0 %conststring(31) control name = "INET_CONTROL" %externalrecord(semaphore fm) dispatch semaphore = 0 %externalinteger max TCP = 0, max UDP = 0 %externalrecord(TCB table fm)%name TCB table %externalrecord(UDP table fm)%name UDP table %externalrecord(INet statistics fm) stats = 0 ! Queue headers %externalrecord(queue fm) IP inbound queue = 0 %externalrecord(queue fm) ICMP outbound queue = 0 %externalrecord(queue fm) UDP outbound queue = 0 %externalrecord(queue fm) TCP inbound queue = 0 %externalrecord(queue fm) TCP outbound queue = 0 %externalrecord(queue fm) TCP packet delivered queue = 0 %externalrecord(queue fm) buffer lookaside list = 0 ! External module specs come here.... %externalroutinespec start user interfaces(%integername a, b) %externalroutinespec interface user timeouts %externalintegerspec slow ether address %externalroutinespec start slow ether %externalroutinespec slow ether outbound(%record(buffer fm)%name b) %externalroutinespec start ether(%integer station) %externalroutinespec ether outbound(%record(buffer fm)%name b) !%externalroutinespec ARP timer %externalroutinespec define IP addresses(%integer x, fast) %externalroutinespec IP inbound(%record(buffer fm)%name b) %externalroutinespec TCP enable(%integer i) %externalroutinespec TCP inbound(%record(buffer fm)%name b) %externalroutinespec TCP outbound(%record(buffer fm)%name b) %externalroutinespec TCP packet delivered(%record(buffer fm)%name b) %externalroutinespec TCP fast timer %externalroutinespec TCP slow timer %externalroutinespec UDP enable(%integer i) %externalroutinespec UDP outbound(%record(buffer fm)%name b) %externalroutinespec ICMP outbound(%record(buffer fm)%name b) %externalroutinespec start routed %externalroutinespec routed clock ! Clock handler %owninteger slow timer = 0 %owninteger fast timer = 0 %constinteger clock priority = 6 %externalinteger clock ticks = 0 %constinteger slow mask = 127; ! Deciseconds %routine start clock %ownrecord(interrupt handler fm) handler = 0 %label clock handler, no slow setup interrupt handler(handler, addr(clock handler)) add interrupt handler(handler, clock priority) !! printstring("INet module's clock handler inserted"); newline %return clock handler: *move.l clock ticks, D0 { Get current time *addq.l #1, D0 { Bump it *move.l D0, clock ticks { Write it back *and.l #slow mask, D0 { Slow timer expired? *bne no slow { No, -> *move.l #1, slow timer { Tell dispatcher no slow: *move.l #1, fast timer { Tell dispatcher int signal semaphore(dispatch semaphore) return from interrupt *move.l D0, D0; ! HMD-proof it %end ! Main program %begin %record(buffer fm)%name b %integer status, i, k open input(3, ":N"); select input(3) open output(3, ":T"); select output(3) ! Initialise semaphores, queues setup semaphore(dispatch semaphore) setup queue(IP inbound queue) setup queue(TCP inbound queue) setup queue(TCP outbound queue) setup queue(TCP packet delivered queue) setup queue(UDP outbound queue) setup queue(ICMP outbound queue) setup queue(buffer lookaside list) !! printstring("Dispatch semaphore at ") !! phex(addr(dispatch semaphore)); newline !! printstring("Free list at "); phex(addr(buffer lookaside list)) !! newline ! Insert the name of our control word and statistics record FS insert(control name, addr(control)) FS insert(INet statistics record name, addr(stats)) ! Start up the user interface start user interfaces(max TCP, max UDP) %if max TCP = 0 %start printstring("TCP units not configured"); newline %else max TCP = max TCB table %if max TCP > max TCB table TCB table == named heap get(TCB size * max TCP, TCB table name) TCP enable(i) %for i = 1, 1, max TCP %finish %if max UDP = 0 %start printstring("UDP units not configured"); newline %else max UDP = UDP table entries %if max UDP > UDP table entries UDP table == named heap get(UDP entry size * max UDP, UDP table name) UDP enable(i) %for i = 1, 1, max UDP %finish ! Set up buffer pool, etc %for i = 1, 1, buffer pool size %cycle b == record(global heap get(buffer size + 4)) release buffer(b) %repeat !S! peer table == named heap get(peer table size, peer table name) !S! p == new peer info(-1); ! Broadcast record ! Start devices, timers. start clock start routed start slow ether start ether(slow ether address) !L! lights and A(\ clear lights) !L! lights and B(\ clear lights) ! And off we go.... Scan the queues in turn, looking for buffers to ! dequeue. If we find any we call the appropriate service routine, then ! go back up to the top of the loop printstring("INet: "); write(free store, 0) printstring(" free"); newline %cycle b == dequeue buffer(IP inbound queue) %if b ## nil %start IP inbound(b) %continue %finish b == dequeue buffer(TCP inbound queue) %if b ## nil %start TCP inbound(b) %continue %finish b == dequeue buffer(TCP packet delivered queue) %if b ## nil %start TCP packet delivered(b) %continue %finish b == dequeue buffer(TCP outbound queue) %if b ## nil %start TCP outbound(b) %continue %finish %if fast timer # 0 %start fast timer = 0 interface user timeouts TCP fast timer %finish b == dequeue buffer(UDP outbound queue) %if b ## nil %start UDP outbound(b) %continue %finish b == dequeue buffer(ICMP outbound queue) %if b ## nil %start ICMP outbound(b) %continue %finish %if slow timer # 0 %start !! printstring("Slow timer"); newline slow timer = 0 TCP slow timer !ARP timer routed clock %finish semaphore wait(dispatch semaphore) %repeat %end %of %program