!spear ! SPEAR: LANCE emulator ! RWT January 1985 ! The purpose of this module is to provide the same low-level ! interface to the CSD142 2MHz Ethernet controller ("SPEAR") ! as is provided by the Am7990 10MHz controller ("LANCE"). ! The level of interface provided is that of access to the ! LANCE (or SPEAR) Control/Status Registers. ! For LANCE emulation of SPEAR to be possible, the access ! has to be procedural: a function to read a CSR, and a ! routine to write to a CSR. %include "lance.inc" %option "-low-nodiag-noline-nocheck" ! LANCE interface @16_fe0000 %half lance address port @16_fe0004 %half lance data port %ownhalf lance register = 9999 %externalintegerfn lance read csr(%half which) %unless lance register = which %start lance address port = which lance register = which %finish %result = lance data port %end %externalroutine lance write csr(%half which,value) %unless lance register = which %start lance address port = which lance register = which %finish lance data port = value %end ! SPEAR INTERFACE %ownhalfarray csr(0:3) = c stop, 0, 0, bswp {The four CSRs %ownrecord(ibf)%name ib {Pointer to Init Block %ownrecord(drf)%name rdr,tdr {Pointers to descriptor rings %ownrecord(df)%name rd,td {Pointers to current descriptors %ownhalf rdn = 0, tdn = 0 {Index (0:127) of current descs %ownhalf r mask = 0, t mask = 0 {Number of descs in ring minus one %owninteger old vector = 0 @16_1070 %integer hardware vector {IPL=4: physical 2M ether device {IPL=3: physical 10M ether device @16_ff5fff %byte spear interrupt {IPL=2: virtual 2M ether device %routinespec write csr0(%integer value) %routinespec install interrupt handler %routinespec remove interrupt handler %externalintegerfn spear read csr(%integer which) %result = csr(which&3) %end %externalroutine spear write csr(%integer which,value) which = which&3 %if which#0 %start %returnif csr(0) & c stop = 0 csr(which) = value %unless csr(0)&c stop#0 %else write csr0(value) %finish %end ! INTERNAL WORKINGS START HERE @16_010f8 %routine ether open(%integer port,remote) @16_03fa8 %byte ether ldte,ether lsap,ether rdte,ether rsap @16_7fffc %byte ether status @16_7fffd %byte ether data @16_7ffff %byte ether control %constbyte %c ether reset = 16_40, ether tbe = 8, ether drf = 4, ether crf = 2, ether rrf = 1, ether rdy = 16_10, ether stx = 16_20, ether dtx = 16_30, ether ack = 16_c0, ether etx = 16_0b, ether transparent = 2 %routine ether twait %cycle; %repeatuntil etherstatusðertbe#0 %end %integerfn ether dread %cycle; %repeatuntil etherstatusðerdrf#0 %result = etherdata %end %integerfn ether cread %cycle; %repeatuntil etherstatusðercrf#0 %result = ethercontrol %end %consthalf %c implicit clear = c err ! c intr, explicit clear = c babl ! c cerr ! c miss ! c merr ! c rint ! c tint ! c idon, explicit copy = c inea, explicit set = c tdmd ! c stop ! c strt ! c init, errors = c babl ! c cerr ! c miss ! c merr, interrupts = c babl ! c miss ! c merr ! c rint ! c tint ! c idon %routinespec csrset(%integer flags) %routine writecsr0(%integer value) csr(0) = csr(0) %c & \(value & explicit clear ! implicit clear ! explicit copy) %c ! value & (explicit set ! explicit copy) %if value & c stop#0 %start {Overrides everything else ether status = ether reset remove interrupt handler csr(0) = c stop ether status = ether crf ! ether drf ether open(ether lsap, ether rdte <<8! ether rsap) %return %finish %if csr(0) & c init # 0 %start ether status = ether reset csr(0) = csr(0) &\ c stop ib == record(csr(2)<<16+csr(1)) rmask = 1<<(ib_rcount>>3)-1 rdr == record(ib_highrad<<16+ib_lowrad) rdn = 0; rd == rdr_desc(rdn) tmask = 1<<(ib_tcount>>3)-1 tdr == record(ib_hightad<<16+ib_lowtad) tdn = 0; td == tdr_desc(tdn) ether status = 0 ether twait ether control = ether transparent ether twait install interrupt handler csr(0) = csr(0) &\ c rxon %unless ib_mode & m drx = 0 csr(0) = csr(0) &\ c txon %unless ib_mode & m dtx = 0 csr(0) = csr(0) ! c idon %finish %if csr(0) & c strt # 0 %start csr(0) = csr(0) ! c rxon %if ib_mode & m drx = 0 csr(0) = csr(0) ! c txon ! c tdmd %if ib_mode & m dtx = 0 %finish %if csr(0) & c tdmd # 0 %start ether status = ether crf ! ether tbe %finish csrset(0) %end %routine remove interrupt handler hardware vector = old vector %unless old vector = 0 old vector = 0 %end %routine install interrupt handler %option "-low-nodiag-noline-nocheck" %label entry point %ownrecord(df)%name nextdesc %ownbyte dump,char %ownhalf quota %routinespec fill buffer(%record(df)%name d) %routinespec empty buffer(%record(df)%name d) %returnunless old vector = 0 old vector = hardware vector *lea entry point,a0 *move.l a4,-4(a0) *move.l a0,hardware vector %return *=0; *=0 {space for own base (A4) entry point: *movem.l d0-d1/d4/a0/a4,-(sp) *lea entry point,a4 *move.l -4(a4),a4 *clr.l d4 *temp d0/d1/d4/a0 %if ether status & ether crf # 0 %start char = ether control dump = ether dread %if char = ether dtx %start ether twait; ether control = ether rdy ether twait; ether data = 0 %elseif char = ether stx %if csr(0) & c rxon = 0 %start fill buffer(nil) %elseif rd_control & r own = 0 fill buffer(nil) csrset(c miss) %else rd_control = rd_control ! r stp %cycle fill buffer(rd) %exitif rd_control & r enp # 0 rdn = (rdn+1)&rmask nextdesc == rdr_desc(rdn) %if nextdesc_control & r own = 0 %start rd_control = (rd_control ! r buff ! r oflo) &\ r own rd == nextdesc %exit %finish rd == nextdesc %repeat rd_control = rd_control &\ r own csrset(c rint) %finish %elseif char = ether rdy ether twait; ether control = ether stx ether twait; ether data = 0 quota = 512+20+14 %cycle empty buffer(td) %exitif td_control & t enp # 0 tdn = (tdn+1)&tmask nextdesc == tdr_desc(tdn) %if nextdesc_control & t own = 0 %start td_plus = d buff ! d uflo td_control = td_control ! t err td == nextdesc %exit %finish td == nextdesc %repeatuntil csr(0) & (c babl ! c inea) = c babl ! c inea ether twait; ether control = ether etx td_control = td_control &\ t own csrset(c tint) %elseif char = ether ack %if td_control & (t own ! t stp) = t own ! t stp %start ether twait; ether control = ether dtx ether twait; ether data = 0 %finish %finish %elseif csr(0) & c tdmd # 0 ether status = ether crf %if td_control & (t own ! t stp) = t own ! t stp %start ether twait; ether control = ether dtx ether twait; ether data = 0 %finish %finish ether status = ether crf *movem.l (sp)+,d0-d1/d4/a0/a4 *rte %routine fill buffer(%record(df)%name d) %half i,j %integer p %if d==nil %start %cycle %if ether status & ether crf # 0 %start i = ether control; %return %finish %if ether status & ether drf # 0 %start i = ether data %finish %repeat %finish i = d_minus; j = 0 p = d_highad<<16+d_lowad %cycle %if ether status & ether crf # 0 %start d_plus = j; d_control = d_control ! t enp i = ether control %return %finish %if ether status & ether drf # 0 %start %if i=0 %start d_plus = j; %return %finish i = i+1; j = j+1; byteinteger(p) = ether data; p = p+1 %finish %repeat %end %routine empty buffer(%record(df)%name d) %half i %integer p i = d_minus p = d_highad<<16+d_lowad %while i#0 %cycle i = i+1; quota = quota+1 %if quota=0 %start csrset(c babl) %returnif csr(0) & c inea # 0 %finish ether twait; ether data = byteinteger(p); p = p+1 %repeat %end %end %routine csrset(%integer flags) *temp d0/d1/d4/a0 {NB called from interrupt handler csr(0) = csr(0) ! flags csr(0) = csr(0) ! c err %if csr(0) & errors # 0 csr(0) = csr(0) ! c intr %if csr(0) & interrupts # 0 %returnunless csr(0) & (c intr ! c inea) = (c intr ! c inea) spear interrupt = 255 %end