1
0
mirror of https://github.com/PDP-10/its.git synced 2026-03-06 11:23:32 +00:00
Files
PDP-10.its/src/mits_s/3com.3
2018-11-25 20:59:17 +01:00

540 lines
12 KiB
Groff
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;;; General info and instructions for the config file:
;;; This uses 3com buffers 10. for receive and 11. for xmit. This
;;; corresponds to addresses [150000-154000) and [154000-160000)
;;; respectively.
;;; Therefore, free memory may not be greater than 150000.
.lif z %defin
.title 3com Ethernet Driver
.sbttl 3com Ethernet Driver: Definitions, Macros and Code
.iif z %defin, .nlist ;don't list definitions and macros if not
;defining them
.if nz %defin ;only define symbols when we are supposed to
defnet 3cm ;declare 3com packet driver
.pkhrd < ;;; for packet transmit (received packet is copied)
..word $3cpdt,0 ;3com packet data
..word $3cpda,3 ;destination address
..word $3cpty,1 ;protocol type
>
.if p1
.sbttl -- Definitions
;;
;;;;;; Status and Control Registers
;;
3c.rcv==0 ;receive control
3c.xmt==2 ;transmit control
;;
;;;;;; receive control register bits
;;
3c%rdn==bit.07 ;[R ] receiver done
3c%rie==bit.06 ;[R/W] receiver interrupt enable
3c%rcl==bit.05 ;[ /W] receiver clear
3c%rsb==bit.04 ;[ /W] set receiver buffer number
3c%rbn==000017 ;[R/W] receiver buffer number
;;
;;;;;; xmit control register bits
;;
3c%jam==bit.15 ;[R ] xmitting packet was jammed
3c%jie==bit.14 ;[R/W] jam interrupt enable
3c%jcl==bit.13 ;[ /W] clear jam and retransmit
3c%clr==bit.08 ;[ W] clear entire board
3c%xdn==bit.07 ;[R ] transmitter done
3c%xie==bit.06 ;[R/W] transmitter interrupt enable
3c%xcl==bit.05 ;[ /W] transmitter clear
3c%xsb==bit.04 ;[ /W] set transmitter buffer number
3c%xbn==000017 ;[R/W] transmitter buffer number
;;
;;;;;; Extra Unibus bits in the receiver register
;;
.if z qbus ;;; if not qbus (i.e. unibus)
3c%ast==bit.14 ;[R/W] Step the address recognition loop
3c%aro==bit.13 ;[R/W] Set when using rom addrss recognition
3c%awc==bit.12 ;[R/W] address recognition memory write clock bit
3c%adr==-1-<17_8> ;[R/W] Various data (BIC mask)
.endc qbus
.endc p1
.sbttl -- Macros
n3com==0 ;no 3com boards yet
.macro 3com vec,csr,ethad0,ethad2,ethad4,chaddr
.iif nz n3com, .error WRONG-O, cons breath, can't define more than one 3com
.iif z n3com, 3cmnet==nnet ;base net object of first 3com board
.if p2
%%==.
.=3c$vec+<2*n3com>
.word vec
.=3c$csr+<2*n3com>
.word csr
.if nz qbus
.=3c$ad0+<2*n3com>
.byte ethad0
.=3c$ad2+<2*n3com>
.byte ethad2
.=3c$ad4+<2*n3com>
.byte ethad4
.endc qbus
.if nz ncpchs
.=3c$cha+<2*n3com>
.word chaddr
.endc
.=%%
.endc
n3com==n3com+1
nnet==nnet+1
.endm
.endc %defin
.iif z %defin, .list ;start listing again
.iif nz %defin, .nlist ;don't list code if only doing definitions
.if z %defin ;only do code if not defining symbols
.sbttl -- Code
.iif z net3cm, .error 3com being included without support in PKTNCP
;;
;;;;;; Tables
;;
3c$vec: .blkw n3com ;table of interrupt vector addresses
3c$csr: .blkw n3com ;table of control/status base addresses
.if nz qbus
3c$ad0: .blkw n3com ;high 16 bits of ethernet address
3c$ad2: .blkw n3com ;middle 16 bits of ethernet address
3c$ad4: .blkw n3com ;low 16 bits of ethernet address
.endc qbus
.if nz ncpchs
3c$cha: .blkw n3com ;CHAOS address of this interface
.endc
.if nz ncpip
3c$in1: .blkw n3com ;high word of internet address
3c$in2: .blkw n3com ;low word of internet address
.endc
;;
;;;;;; Interrupt vector pointers and such
;;
3c$brk:
.rept n3com
.lif z .rpcnt
3c$rbk::
jsr r5,@#3crint
.word netobj+<2*3cmnet>+<2*.rpcnt>
.lif z .rpcnt
3c$xbk::
jsr r5,@#3cxint
.word netobj+<2*3cmnet>+<2*.rpcnt>
.lif z .rpcnt
3c$jbk::
jsr r5,@#3cjint
.word netobj+<2*3cmnet>+<2*.rpcnt>
.endr
l3c$brk==<.-3c$brk>/n3com
3c$vrp: .rept n3com ;vector receive pointers
.word 3c$rbk+<l3c$brk*.rpcnt>
.endr
3c$vxp: .rept n3com ;vector xmit pointers
.word 3c$xbk+<l3c$brk*.rpcnt>
.endr
3c$vjp: .rept n3com ;vector jam pointers
.word 3c$jbk+<l3c$brk*.rpcnt>
.endr
;;
;;;;;; A 3com hardware object
;;
dsect <
.blkb l$nt ;a basic network object
$3ccsr==$ntcsr ;3com CSR in the net CSR
$3crba:: .blkw 1 ;receive buffer address
$3cxba:: .blkw 1 ;xmit buffer address
$3cdmn:: .blkw 1 ;daemon flags
%3crdn==040000 ;receiver is done
%3cxmt==004000 ;xmit in progress
%3cxpk==002000 ;xmit packets on the queue
$3crqu:: .blkb 1 ;receive queue byte operation
$3cxqu:: .blkb 1 ;xmit queue byte operation
>,l$3c
;;
;;;;;; Interrupt routines
;;
.wscalar $3ckik ;;; set when the daemon process needs kicking
3crint: mov @(r5),r5 ;get the hardware object
.if nz qbus ;assumes only one interface
loop < ;exit if ok
cmp 3cqad0,nt.eth+0(r5)
if eq,<
cmp 3cqad2,nt.eth+2(r5)
if eq,<
cmp 3cqad4,nt.eth+4(r5)
exitl eq
> >
else <
cmp 3cqad0,#-1
if eq,<
cmp 3cqad2,#-1
if eq,<
cmp 3cqad4,#-1
exitl eq
> > >
push r4
mov $3ccsr(r5),r4
call 3c$rcl
pop r4
br 10$
>
.endc qbus
bis #%3crdn,$3cdmn(r5) ;tell the daemon the receiver is done
mov $3ccsr(r5),r5 ;get the CSR
bicb #3c%rie,3c.rcv(r5) ;disable interrupts
mov #1,$3ckik ;kick the daemon for rcv
10$: pop r5
rti
3cxint: mov @(r5),r5 ;get the hardware object
bic #%3cxmt,$3cdmn(r5) ;xmitter no longer xmitting
netmet ou
mov $3ccsr(r5),r5
bis #3c%xcl,3c.xmt(r5)
mov #1,$3ckik ;kick the daemon for xmit
pop r5
rti
;;; this code does not do binary exponential backoff
3cjint: mov @(r5),r5 ;get hardware object
netmet ab ;count an abort
mov $3ccsr(r5),r5 ;get the CSR
bis #3c%jcl,3c.xmt(r5) ;retransmit
pop r5
rti
3c$dmn: loop <
clr $3ckik ;about to process everything
push #netobj+<2*3cmnet>
loop <
mov @(sp),r5 ;get hardware object
if ne,<
mov $3ccsr(r5),r4
bit #%3crdn,$3cdmn(r5) ;receiver done?
if ne,<call 3c$rcv> ;receive the packet
call 3c$xmt ;try and xmit
>
add #2,(sp)
cmp (sp),#netobj+<2*3cmnet>+<2*n3com>
rptl lo
>
pop * ;flush pointer
.regs #hng.ne,#$3ckik,#zero
.hang
rptl
>
3c$rcv: bic #%3crdn,$3cdmn(r5)
loop < ;easy way to exit
movb 3c.rcv(r4),r3 ;get the buffer
exitl pl ;nothing there
mov $3crba(r5),r3 ;get receiver buffer address
mov (r3),r1 ;get the offset to end
if mi,< ;checksum error
netmet cr ;indicate crc error
exitl
>
bic #mask11,r1 ;get only the real offset bits
cmp r1,#3777 ;was there a length error?
if eq,< ;length error on the net
netmet bl ;count it
exitl
>
sub #528.+4+<2*<3+3+1>>,r1 ;don't count extra 3com
;space, checksum bytes,
;or ethernet header
mov r1,r0 ;save data size
add #$pktdt,r1 ;add program header
cmp r1,#pksiz. ;is it big enough for anybody?
if lo,<netmet ot
exitl>
cmp r1,#pksiz$ ;too big?
if hi,<netmet ot
exitl>
call pktall ;get a packet
if eq,<netmet ot
exitl>
push r1 ;save pointer
add #$pktdt,r1 ;point to packet data
add #528.+<2*<3+3>>,r3 ;point at type word
inc r0 ;round up...
asr r0 ;...word count
mov (r3)+,r2 ;get type word
loop <
mov (r3)+,(r1)+
sorl r0
>
pop r1
bis #%pkt08,$pktfl(r1) ;declare packet safe for 8 bit
call 3c$rcl
jcall ethrcv ;receive an ethernet packet
>
3c$rcl: movb #3c%rcl,3c.rcv(r4) ;cycle the receiver fifo
movb $3crqu(r5),3c.rcv(r4) ;queue the receive packet
return
3c$xmt: loop < ;easy exit mechanism
bit #%3cxmt,$3cdmn(r5) ;xmit already in progress
exitl ne ;yes, don't do xmit
call ntremq ;get a packet
exitl eq ;nothing there
bis #%3cxmt,$3cdmn(r5) ;xmit now in progress
mov $3cxba(r5),r3 ;get pointer to base of 3com buffer
mov $pktxs(r1),r2 ;get xmit count
mov r2,r0
cmp r0,#60. ;must be at least 60 bytes
if lo,<mov #60.,r0>
neg r0
add #4000,r0 ;offset pointer
mov r0,(r3) ;set it for the hardware
add r0,r3 ;get to beginning of packet
push r1
add #$3cpdt,r1 ;point to packet data
mov (r1)+,(r3)+ ;stuff destination address
mov (r1)+,(r3)+
mov (r1)+,(r3)+
mov nt.eth+0(r5),(r3)+ ;stuff source address
mov nt.eth+2(r5),(r3)+
mov nt.eth+4(r5),(r3)+
mov (r1)+,(r3)+ ;stuff protocol type
sub #2*<3+3+1>,r2 ;count ethernet header words,
asr r2 ;to word count
loop <
mov (r1)+,(r3)+ ;copy
sorl r2
>
pop r1
movb $3cxqu(r5),3c.xmt(r4) ;queue the xmit packet
jcall pktngv ;free packet if not on user list
>
return
;;
;;;;;; Qbus/Unibus finish setup
;;
3c$set: clr $3cdmn(r5) ;no daemon functions
movb #10.+3c%rsb+3c%rie,$3crqu(r5) ;receive queue command
movb #11.+3c%xsb+3c%xie,$3cxqu(r5) ;xmit queue command
mov #<10.*2048.>+100000,$3crba(r5) ;receive buffer address
mov #<11.*2048.>+100000,$3cxba(r5) ;xmit buffer address
;;;--------------------*** initialize all of memory
.if z qbus ;for unibus
lock 7
push r0,@#114,@#116 ;save parity error trap
mov #120$,@#114
mov #pr7,@#116 ;setup the new
mov #100000,r0
mov #160000-100000,r1
loop <
movb (r0),(r0) ;frob the memory
inc r0
sorl r1
exitl
120$: clrb (r0)
rti
>
pop @#116,@#114,r0
unlock
.iff ;for qbus, doesn't need it
.endc
;;;--------------------*** setup for address recognition
.if z qbus ;for unibus
mov #3c%aro,3c.rcv(r4) ;use the ROM
call 200$ ;get a word
mov r1,nt.eth+0(r5) ;keep it
call 200$ ;the second one
mov r1,nt.eth+2(r5)
call 200$ ;the third (and last)
mov r1,nt.eth+4(r5)
loop < ;local subroutines
exitl
200$: push #0
mov #4,r1
loop <
clc
.rept 4
ror (sp)
.endr
mov 3c.rcv(r4),r2
bic #3c%adr,r2
ash #4,r2
bis r2,(sp)
call 220$
sorl r1
>
pop r1
return
220$: mov #3c%aro+3c%ast,r2 ;set to half step
mov #3c%aro,r3 ;clear to finish the step (sigh)
add #3c.rcv,r4
.rept 4 ;gross me out!!
mov r2,(r4)
mov r3,(r4)
.endr
sub #3c.rcv,r4
return
>
.rept 2 ;just to make sure
mov #3c%aro+<7_8>,3c.rcv(r4)
.endr
.iff ;for qbus
mov 3c$ad0(r0),nt.eth+0(r5)
mov 3c$ad2(r0),nt.eth+2(r5)
mov 3c$ad4(r0),nt.eth+4(r5)
3cqad0=100000+<10.*2048.>+528. ;destination address of recv packet
3cqad2=3cqad0+2
3cqad4=3cqad0+4
.endc
;;;--------------------*** arm the board
movb $3crqu(r5),3c.rcv(r4)
mov #3c%jie,3c.xmt(r4)
return
.wscalar $3cnup ;number of alive 3com boards
3cini: clr $3cnup
clr r0
loop <
call 3cinit
add #2,r0
cmp r0,#n3com*2
rptl lo
>
tst $3cnup
if ne,<
.regs #3c$dmn,#40,#100_8 ;start up the daemon
.usrgo
if cs,<bpt>
>
return
3cinit: mov 3c$csr(r0),r4
call nxmcat
3cmnxm
mov #3c%clr,3c.xmt(r4)
inc $3cnup
call nxmclr
mov 3c$vec(r0),r2
mov 3c$vrp(r0),(r2)+ ;receiver interrupt
mov #pr6,(r2)+ ;at priority 6
mov 3c$vjp(r0),(r2)+ ;jam interrupt
mov #pr5,(r2)+ ;at priority 5
mov 3c$vxp(r0),(r2)+ ;xmit complete interrupt
mov #pr4,(r2)+ ;at priority 4
mov #l$3c,r5 ;length of a hardware object
call ntmake ;make it
if eq,<bpt> ;oops
mov r5,netobj+<2*3cmnet>(r0) ;savve device in network table
mov r4,$ntcsr(r5)
call 3c$set ;setup the rest of the registers
mov #3cetgv,nt$eth(r5) ;routine to send ethernet packets to interface
.if nz ncpchs
mov #3cchgv,nt$chs(r5) ;routine to send chaos packets to interface
mov 3c$cha(r0),nt.chs(r5) ;my address on chaos net
mov #12.,$ctrcv(r5) ;3coms a little more expensive than standard
.endc
.if nz ncpip
.endc
mov r0,r4 ;get 3com index into r4
add #<3cmnet*2>,r4 ;now network index
jcall ntmak1 ;finish making the object
3cmnxm: clr netobj+<2*3cmnet>(r0) ;no network object
return
3cetgv: mov r0,$3cpty(r1)
mov r2,$3cpda+0(r1)
mov r3,$3cpda+2(r1)
mov r4,$3cpda+4(r1)
add #<2*<3+3+1>>+1,$pktxs(r1) ;add ethernet header and word rounding
bic #1,$pktxs(r1) ;now even byte count
mov #1,$3ckik ;kick the daemon
jcall ntputq
.if nz ncpchs
;;; call @nt$chs(r5),[r5:=object, r1:=packet, r2:=hardware_destination]
3cchgv: call cpks08 ;make packet safe for 8 bit hardware
push r0,r3,r4
mov #%etchs,r0 ;protocol in r0
call ethtrn
if cs,<call pktngv>
else <call 3cetgv>
pop r4,r3,r0
return
.endc ncpchs
****
$insrt 3com,kludge ;redefine symbols for the 11 simulator
.endc %defin
.iif nz %defin, .list ;start listing as usual
;; local modes:
;; mode:midas
;; auto fill mode:
;; fill column:75
;; comment column:32
;; end: