.MCALL .MODULE .MODULE NI,VERSION=33,COMMENT=,AUDIT=NO ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL CONDITIONAL ASSEMBLY SUMMARY ;+ ;COND ; NI$CNA (0) DECNA (PRO) hardware ; NI$QNA (0) DEQNA (QBUS) hardware ; NI$UNA (0) DEUNA (UBUS) hardware ; Exactly 1 of the three above must be on ; ; MMG$T std conditional must be 1 ; TIM$IT std conditional (no code effects) ; ERL$G std conditional (no code effects) ;- .SBTTL Class Handler Edit History .ENABL LC ;+ ; ; Original version: ; ; V05 (000) 01-Nov-84 Start of coding for ethernet class support. ; MBG Initial coding completed 3-Dec-84. Now ; testing prior to field test. ; ; V05 (001) 04-Dec-84 Changed order of assembly. This module is ; MBG "included" by the port handler module. Added ; replacement for .RMODULE since that was causing ; problems. ; ; V05 (002) 05-Dec-84 Abort code was not clearing ownership, protocol, ; MBG and address tables if there were no queue elements ; to return to RT. Also, SAV30 return address could ; get corrupted, it is now kept on the stack. ; ; V05 (003) 07-Dec-84 NIIDEQ not setting flag to indicate queue is ; MBG unstable while it is working on it. ; ; V05 (004) 07-Dec-84 Support for slot independence for NC applications. ; CA ; ; V05 (005) 09-Dec-84 Recovering lost comments. ; MBG ; ; V05 (006) 19-Dec-84 Adding definitions for configuration word 2. ; MBG ; ; V05 (007) 21-Jan-85 Change to allocate unit. Will now return the ; MBG station's physical address to a successful ; allocate unit. ; ; V05 (008) 07-Feb-85 Added bit definition for private global region. ; MBG ; ; V05 (009) 12-Feb-85 Added check on transmit frame for minimum and ; MBG maximum word count. Now returns error if too ; small or large. ; ; V05 (010) 25-Feb-85 Adding .MCALL of .BR to avoid phase errors. ; MBG ; ; V05 (011) 04-Mar-85 Transmit and receive frame now have extra word ; MBG following status word and before actual frame. ; ; ; V05 (012) 11-Apr-85 When no ports remain open, NIABRT need only ; MBG call DISABL rather than first calling SETUP as ; SETUP will be called on the next open. (changes ; due to transmit watchdog code) ; ; V05 (013) ??-???-?? New handler macros ; JRW ; ; V05 (014) 09-Nov-85 Change to make ethernet handlers non-fetchable ; MBG due to direct PAR1 usage. ; ; V05 (015) ??-???-?? Change of copyright ; JBM ; ; V05 (016) 03-Dec-85 Added code to handle abort by channel (.ABTIO) ; MBG due to change in RMON ; ; V05 (017) 31-Dec-85 Made queue manipulation more robust, added ; MBG definitions for table sizes, added code to ; handle the case of more multicast addresses ; than a device can use. ; ; V05 (018) 16-Jan-86 Incorrect processing of last Qelement on ; MBG internal receive queue in NIIDEQ. Also changed ; some hard-wired values to symbols. ; ; V05 (019) 06-Feb-86 Added definition for QBUS bit in CONFG2 as ; MBG well as new XMSUBS entry point for extended ; memory deallocation. ; ; V05 (020) 21-Feb-86 Changes due to code review ; MBG ; ; V05 (021) 27-Feb-86 Q$COMP needs to be cleared in abort code so that ; MBG monitor doesn't hang. ; ; V05 (023) 21-Nov-88 V5.5: Temporary support of UB for pass 1 of ; MBG field test. ; ; V05 (025) 05-Dec-88 V05.05: Added support for UMR (UB) in NU ; MBG ; ; V05 (028) 10-May-90 Modified code in NIFIN to remove race by using ; MBG technique for returning qelements using a fake ; device queue. ; ; (029) 26-Sep-90 MBG Added UNLOAD code for all Ethernet handlers so ; they may not be unloaded while active. Added ; call to port handler load and unload routines. ; ; (030) 16-Oct-90 MBG Change previously added code so that handler ; in use is determined by PORTCT word, which ; indicates number of open ports. ; ; (031) 24-Aug-91 MBG Ensure aborted Qelements have hard error set ; in CSW and that no completion routines will ; run for aborted Qelements. Change to algorithm ; for aborting internally queued handlers - Qelements ; are returned one at a time via the fake device ; queue. Fix channel abort code to prevent ; deallocation of channel. ; ; (032) 31-Aug-91 MBG Change back to previous method of aborting ; Qelements. Removed setting of hard error bit ; for aborted Qelements, retained code to clear ; completion word as well as code to prevent ; deallocation of unit/portal on channel abort. ; ; (033) 2-Jan-97 ARB Add special functions: ; spfun 206 - frame queueing ; spfun 207 - physical ethernet address ; spfun 210 - handler status block ; ;- .SBTTL Class Handler Functional Description ;+ ; ; This portion of the ethernet handlers is the CLASS handler, it provides ; a common user interface to the ethernet. The PORT handlers provide the ; hardware control specific to a given interface. ; ; The handler provides the following special functions: ; ; Allocate unit SP.POR = 200 blkn = 1 ; arguments: ; unit number (Q$UNIT) ; station physical address (2nd-4th words of BUFF) ; status: ; 0 Success ; 1 Unknown portal (unit) ; 2 Channel not on ; 3 No resources (portal in use) ; 6 Promiscuous receiver active ; notes: ; Allocates a portal (unit) for exclusive use by a job. Errors ; are returned if the unit is already allocated to another job ; or if another unit has enabled promiscuous mode. Returns ; the station's physical address. ; ; Deallocate unit SP.POR = 200 blkn = 0 ; arguments: ; unit number (Q$UNIT) ; status: ; 0 Success ; 1 Unknown portal (unit) ; 2 Channel not on ; 11 Portal still active ; ; notes: ; Deallocates the unit so that it may be used by another job. ; ; Enable promiscuous mode SP.PM = 201 blkn = 1 ; arguments: ; unit number (Q$UNIT) ; status: ; 0 Success ; 1 Unknown portal (unit) ; 2 Channel not on ; 6 Promiscuous receiver active ; 7 Not implemented ; notes: ; Causes all messages with all protocols to be returned to ; read requests via this unit. Errors returned if the unit has ; not been allocated to a job or if another unit has enabled ; promiscuous mode. ; ; Disable promiscuous mode SP.PM = 201 blkn = 0 ; arguments: ; unit number (Q$UNIT) ; protocol type (2nd word of BUFF) ; status: ; 0 Success ; 1 Unknown portal ; 2 Channel not on ; 6 Promiscuous receiver active ; 10 Protocol type in use ; notes: ; Causes only messages with the address(es) and protocol(s) ; specified for this port to be returned to read requests. ; ; Enable protocol type SP.PT = 202 blkn = 1 ; arguments: ; unit number (Q$UNIT) ; protocol type (2nd word of BUFF) ; status: ; 0 Success ; 1 Unknown portal ; 2 Channel not on ; 3 No resources (portal's protocol table is full) ; 6 Promiscuous receiver active ; 10 Protocol type in use ; notes: ; Adds a protocol to the list of those to be recognized as ; types to be returned to read requests via this unit. ; ; Disable protocol type SP.PT = 202 blkn = 0 ; arguments: ; unit number (Q$UNIT) ; protocol type (2nd word of BUFF) ; status: ; 0 Success ; 1 Unknown portal ; 2 Channel not on ; notes: ; Removes a protocol from the list of those recognized for ; this unit. ; ; Enable multicast address SP.MA = 203 blkn = 1 ; arguments: ; unit number (Q$UNIT) ; address (2nd-4th words of BUFF) ; status: ; 0 Success ; 1 Unknown portal (unit) ; 2 Channel not on ; 3 No Resources (portal's address table is full or ; hardware's address table is full) ; notes: ; Adds an address to the list of those to be recognized as ; destined to be returned to read requests via this unit. ; ; Disable multicast address SP.MA = 203 blkn = 0 ; arguments: ; unit number (Q$UNIT) ; address (2nd-4th words of BUFF) ; status: ; 0 success ; 1 Unknown portal (unit) ; 2 Channel not on ; notes: ; Removes an address from the list of those to be recognized for ; this unit. ; ; Transmit ethernet frame SP.XMT = 204 ; arguments: ; unit number (Q$UNIT) ; ethernet frame (3rd-Q$WCNT words of BUFF) ; status: ; 0 Success ; 1 Unknown portal (unit) ; 2 Channel not on ; 13 Transmit failed ; error subcodes: ; 1 Frame too long ; 2 Excessive collisions ; 3 Carrier check failed ; 4 Short circuit ; 5 Open circuit ; 6 Remote failure to defer ; notes: ; Transmits the ethernet frame passed in BUFF. If the source address ; field of the frame is non-zero, it is used as is. If it is zero, ; the physical address is inserted before transmission. ; ; Receive ethernet frame SP.RCV = 205 ; arguments: ; unit number (Q$UNIT) ; received frame size in bytes (2nd word) ; buffer (3rd-Q$WCNT words of BUFF) ; status: ; 0 Success ; 1 Unknown portal (unit) ; 2 Channel not on ; 4 Truncation ; notes: ; Returns to the buffer the next ethernet frame with the desired ; address and protocol. ; ; +033 ; Enable frame queueing SP.QUE = 206 blkn = 1 ; arguments: ; ; status: ; 0 Success ; notes: ; Enables internal handler queueing of received ethernet ; packets even if no que element requests are pending ; for an enabled protocol. ; ; Disable frame queueing SP.QUE = 206 blkn = 0 ; arguments: ; ; status: ; 0 Success ; 6 address/protocol active ; notes: ; Disables internal handler queueing of received ethernet ; packets. ; ; Get ethernet address SP.ADD = 207 ; arguments: ; ; status: ; 0 Success ; notes: ; Returns the physical station address. ; ; Get ethernet status block SP.STT = 210 ; arguments: ; status block (3rd-Q$WCNT words of BUFF) ; status: ; 0 Success ; notes: ; Returns handler status information. ; ; -033 ;- .SBTTL Class Handler Definitions ; System macros we'll be using .MCALL .DRDEF, .ADDR, .ASSUME .MCALL .INTEN, .BR ; Assembly parameters .IIF NDF NI$CNA NI$CNA = 0 .IIF NE NI$CNA NI$CNA = 1 .IIF NDF NI$QNA NI$QNA = 0 .IIF NE NI$QNA NI$QNA = 1 .IIF NDF NI$UNA NI$UNA = 0 .IIF NE NI$UNA NI$UNA = 1 .Assume MMG$T NE 0 MESSAGE= NI$$NI = .Assume NI$$NI NE 0 MESSAGE= .Assume NI$$NI EQ 1 MESSAGE= ; Device definition NI$PRI =: 5 ;Device priority level .IF NE NI$CNA .DRDEF NI,61,,0,0,0,DMA=NO NI$HND = <^RNC > ;Name to use in place of .RMODULE .ENDC ;NE NI$CNA .IF NE NI$QNA .IIF DF NQ$CSR NI$CSR = NQ$CSR .IIF DF NQ$VEC NI$VEC = NQ$VEC .DRDEF NI,61,,0,174440,120 NI$HND = <^RNQ > ;Name to use in place of .RMODULE .ENDC ;NE NI$QNA .IF NE NI$UNA .IIF DF NU$CSR NI$CSR = NU$CSR .IIF DF NU$VEC NI$VEC = NU$VEC .DRDEF NI,61,,0,174510,120,DMA=YES,PERMUMR=RUMRCT NI$HND = <^RNU > ;Name to use in place of .RMODULE .ENDC ;NE NI$UNA .DRPTR FETCH=*NO*,LOAD=NILOAD,UNLOAD=NIUNLO .DREST CLASS=DVC.NI .DRSPF <200> ;Open/Close portal (unit) .DRSPF <201> ;Enable/Disable promiscuous mode .DRSPF <202> ;Enable/Disable protocol type .DRSPF <203> ;Enable/Disable multicast address .DRSPF <204> ;Transmit ethernet frame .DRSPF <205> ;Receive ethernet frame .DRSPF <206> ;Enabel/Disable frame queueing ;033 .DRSPF <207> ;Get physical ethernet address ;033 .DRSPF <210> ;Get handler status block ;033 ; RT System communications area SYSPTR =: 54 ;Pointer to base of RMON ; RMON fixed offsets QCOMP =: 270 ;Address of COMPLT routine in RMON SPUSR =: 272 ;Special function error word CONFG2 =: 370 ;Configuration word 2 PROS$ = 020000 ;Running on a PRO-300 series machine QBUS$ = 000100 ;Running on a QBUS machine MEMPTR =: 430 ;Fixed offset to memory pointers CORPTX =: 4 ;Offset to extended memory block P1EXT =: 432 ;PAR1 externalization routine XDEALC =: -18. ;JMP to extended memory deallocation routine FINDGR =: -10. ;JMP to find region routine XALLOC =: -6 ;JMP to extended memory allocate routine BLKMOV =: -2 ;BR to block memory move routine $H2UB =: 460 ;Pointer to UB dispatch vector UB.GET =: 0 ;BR to routine for temporary UMR allocation UB.ALL =: 2 ;BR to routine for permanent UMR allocation UB.RLS =: 4 ;BR to routine for permanent UMR deallocation $CNFG3 =: 466 ;Configuraton word 3 CF3.UA =: 000040 ;UB is active $SLOT2 =: 502 ;Value of $SLOT*2 ; Special functions SP.POR =: 200 ;Open/Close portal (unit) SP.PM =: 201 ;Enable/Disable promiscuous mode SP.PT =: 202 ;Enable/Disable protocol type SP.MA =: 203 ;Enable/Disable multicast address SP.XMT =: 204 ;Transmit ethernet frame SP.RCV =: 205 ;Receive ethernet frame SP.QUE =: 206 ;Enabel/Disable frame queueing ;033 SP.ADD =: 207 ;Get physical ethernet address ;033 SP.STT =: 210 ;Get handler status block ;033 ; Special function return codes RC.SUC =: 0 ;Success RC.UNK =: 1 ;Unknown portal (unit) RC.CHN =: 2 ;Channel not on RC.RES =: 3 ;No resources RC.TRU =: 4 ;Truncation RC.NON =: 5 ;None outstanding RC.EXC =: 6 ;Promiscuous receiver active RC.IMP =: 7 ;Not implemented RC.PRO =: 10 ;Protocol type in use RC.ACT =: 11 ;Channel still active RC.INC =: 12 ;Incomplete RC.XMT =: 13 ;Transmit failed SC.WFL =: 1 ;Frame length error SC.WEC =: 2 ;Excessive collisions SC.WCC =: 3 ;Carrier check failed SC.WSC =: 4 ;Short circuit SC.WOC =: 5 ;Open circuit SC.WRF =: 6 ;Remote failure to defer RC.RLN =: 14 ;Receive length error RC.INV =: 15 ;Receive invalid data RC.ABO =: 16 ;Receive aborting SC.RFL =: 1 ;Frame too long SC.RBC =: 2 ;Block check error SC.RFE =: 3 ;Framing error RC.QUE =: 17 ;Ports active ;033 RC.STT =: 20 ;Invalid length ;033 ; Miscellaneous RT definitions JOBMK =: 370 ;Job number mask (Q$UNIT) UNITMK =: 007 ;Unit number mask (Q$UNIT) KTGRAN =: 32. ;KT-11 addressing granularity KISAR1 =: 172342 ;Kernel I-Space PAR1 PSW =: 177776 ;Processor status word .SBTTL Class Handler Data Structure Definitions ; Global region control block (in free area) GR.SIZ =: 0 ;Size in 32 word blocks GR.ADR =: 2 ;Base address in 32-word blocks GR.STA =: 4 ;Status byte GR.PVT = 100000 ;Private region GR.NRF = 000040 ;Don't return memory to free list GR.NAM =: 6 ;Name (2 words rad50) GR.ESZ =: 10. ;GRCB size in bytes ; Unit ownership table entry format UO.JOB =: 0 ;Job/unit mask UO.OFG =: 1 ;Open flag UO.ESZ =: 2 ;UOT entry size ; Unit address table entry format UA.ADD =: 0 ;Ethernet address (6 bytes) UA.ESZ =: 6 ;UAT entry size ; Unit protocol table entry format UP.TYP =: 0 ;Frame protocol (2 bytes) UP.ESZ =: 2 ;UPT entry size ; Ethernet data link layer frame format EF.DST =: 0 ;Destination address ; 6 octets (bytes) EF.SRC =: 6 ;Source address ; 6 octets (bytes) EF.TYP =: 14 ;Frame type (protocol) ; 2 octets (bytes) EF.DAT =: 16 ;Data block ; 46.-1500. octets (bytes) NIMFSZ =: 1514. ;Maximum frame size ; Protocol types P.RTBS = 003140 ;RT Binary shuffle protocol ; customer number (60-06) .SBTTL Psect Ordering .PSECT NIDVR ;Handler code .PSECT NIDAT ;Handler low-memory data .PSECT NIEND ;Handler end .PSECT SETOVR ;Installation/Set code overlays .DREND NI,PSECT=NIEND .SBTTL Handler Entry Point .DRBEG NI ;Implicit .PSECT NIDVR .IF NE BR NIBEG ;Branch around some impure data NICSR: .WORD NI$CSR ;Ethernet controller base address .Assume LE 1000 MESSAGE= NIVEC: .WORD NI$VEC ;Ethernet controller vector address .Assume LE 1000 MESSAGE= .ENDC ;NE NIBEG: ASR (PC)+ ;Once-only initialization? .WORD 1 ; : Once-only flag BCC 10$ ;Nope... MOV @#SYSPTR,R4 ;R4 -> $RMON MOV P1EXT(R4),R4 ;R4 -> PAR1 extern routine entry .ADDR #NINAME,R5 ;R5 -> Our region name CALL FINDGR(R4) ;Ask RT where the extended region is MOV GR.ADR(R1),NIXADR ; and save the response CALL INIT ;Do once-only initialization BCS 10$ ;It failed... MOV SP,NICHFG ;It succeeded, set 'channel on' flag 10$: MOV NICQE,R4 ;R4 -> Current queue element MOVB Q$FUNC(R4),R5 ;R5 = Special function code MOVB Q$UNIT(R4),R3 ;R3 = Job/unit number BIC #^C,R3 ;Strip to unit number .Assume UO.ESZ EQ 2 MESSAGE= ASL R3 ;Calculate offset to entry .ADDR #NIUOT,R3,ADD ; then address of entry (pic) CMPB R5,#SP.ADD ;Get physical address check ;033 BEQ SPFUN ;033 CMPB R5,#SP.STT ;Get handler status check ;033 BEQ SPFUN ;033 CMPB R5,#SP.POR ;Open portal request? BNE 20$ ;Nope, do ownership check .Assume Q$BLKN EQ 0 TST (R4) ;Maybe, is it really? BNE 40$ ;Yes, bypass ownership check 20$: .Assume UO.JOB EQ 0 .Assume UO.OFG EQ 1 TST (R3) ;Nope, is unit allocated? BNE 30$ ;Yes... MOV #RC.UNK,-(SP) ;Code = 'Unknown portal' BR SPERR 30$: .Assume UO.JOB EQ 0 CMPB Q$UNIT(R4),(R3) ;Is unit owned by this job? BEQ 40$ ;Yes, then let them use it MOV #RC.RES,-(SP) ;Code = 'No resources' BR SPERR 40$: TSTB R5 ;Special function requested? BNE SPFUN ;Yes, process it BR NIERR ;Anything else is inappropriate ; at this time .SBTTL SPFUN - Special Function Dispatcher ;+ ; ; SPFUN ; Dispatches to routines which process the SPFUN codes specific ; to this handler. ; ; Entered with ; R3 -> UOT entry for unit ; R4 -> Current queue element ; R5 = Special function ; ; Dispatches with ; R3 -> UOT entry for this unit ; R4 -> Current queue element ; R5 = Unit number ; ;- .ENABL LSB SPFUN: TST NICHFG ;Is channel on and usable? BEQ 30$ ;Nope... CLR -(SP) ;Default to success CALL @$PTWRD ;Place it in the user's buffer SUB #2,Q$BUFF(R4) ;Correct PUTWRD altered address info .ADDR #SPFTAB,R2 ;R2 -> SPFUN dispatch table 10$: TST (R2) ;End of dispatch table? BEQ NIDONE ;Yes, then it's an unknown code... CMPB R5,(R2) ;Is this the SPFUN we want? BEQ 20$ ;Yes... ADD #4,R2 ;Nope, try next entry BR 10$ 20$: MOV 2(R2),R2 ;R2 = Offset to routine ADD PC,R2 ;Add in PC for real address SPFDSP: MOVB Q$UNIT(R4),R5 ;R2 = unit/job mask BIC #^C,R5 ;Strip to unit number JMP @R2 ;Dispatch to the routine 30$: MOV #RC.CHN,-(SP) ;Code = 'Channel not on' ; SPERR ; Returns the error status (on stack) into status word which ; is the first word of BUFF. SPERR: CALL @$PTWRD ;Return the error code NIERR: BIS #HDERR$,@-(R4) ;Flag the error NIDONE: .DRFIN NI ; SPFTAB ; A table of two-word entries consisting of the function number ; and the offset to the routine which processes that function. SPFTAB: .WORD SP.POR, .SPPOR-SPFDSP ;Open/Close portal (unit) .WORD SP.PM, .SPPM-SPFDSP ;Enable/Disable promiscuous mode .WORD SP.PT, .SPPT-SPFDSP ;Enable/Disable protocol type .WORD SP.MA, .SPMA-SPFDSP ;Enable/Disable multicast address .WORD SP.XMT, .SPXMT-SPFDSP ;Transmit ethernet frame .WORD SP.RCV, .SPRCV-SPFDSP ;Receive ethernet frame .WORD SP.QUE, .SPQUE-SPFDSP ;Enabel/Disable frame queueing ;033 .WORD SP.ADD, .SPADD-SPFDSP ;Get physical ethernet address ;033 .WORD SP.STT, .SPSTT-SPFDSP ;Get handler status block ;033 .WORD 0 ;Table fence .DSABL LSB .SBTTL .SPPOR - Open/Close Portal ;+ ; ; .SPPOR ; On open, allocates a portal (unit) for exclusive use by a job. ; All subsequent OPENs to this portal will fail with 'portal in ; use' error code. In addition, the station's physical address ; is returned to the user. ; ; On close, releases a portal (unit) if there are no requests ; pending for that unit. ; ; CALL: ; blkn <> 0, Open portal (unit) ; blkn = 0, Close portal (unit) ; ;- .ENABL LSB .SPPOR: .Assume Q$BLKN EQ 0 TST (R4) ;Open or Close? BEQ SPCLO. ;Close if blkn = 0 SPOPP.: .Assume UO.JOB EQ 0 .Assume UO.OFG EQ 1 TST NIPMFG ;Promiscuous receiver active? BNE 30$ ;Yes... TST (R3) ;Unit already allocated? BNE 20$ ;Yes... .Assume UO.JOB EQ 0 .Assume UO.OFG EQ 1 MOV #-1,(R3) ;Flag unit as allocated .Assume UO.JOB EQ 0 MOVB Q$UNIT(R4),(R3) ; by this job INC PORTCT ;Bump for each open portal BNE 10$ ;Not first time... CALL ENABLE ;First portal open, start interrupts BCS 35$ ;The enable failed somehow... ;+033 ; ; .SPADD ; The station's physical address ; is returned to the user. ; ; CALL: ; ;-033 .SPADD: ;033 10$: MOV NICQE,R4 ;R4 -> Current queue element MOV @#KISAR1,-(SP) ;Save current PAR1 context ; ** don't use SAVPAR ** MOV Q$PAR(R4),@#KISAR1 ;Map to user's buffer MOV Q$BUFF(R4),R0 ;R0 -> User's buffer ADD #2,R0 ;Bump past status word MOV NIPHAD,(R0)+ ;Return the station's MOV NIPHAD+2,(R0)+ ; physical MOV NIPHAD+4,(R0)+ ; address MOV (SP)+,@#KISAR1 ;Restore PAR1 context BR NIDONE 20$: MOV #RC.RES,-(SP) ;Code = 'No resources' BR SPERR 30$: MOV #RC.EXC,-(SP) ;Code = 'Promiscuous receiver active' BR SPERR 35$: CLR NICHFG ;Reset the channel flag MOV #RC.CHN,-(SP) ;Code = 'Channel not on' BR SPERR SPCLO.: MOVB Q$UNIT(R4),R0 ;R0 = Job/unit mask MOV NIOCQE,R1 ;Anything on the transmit queue? BEQ 50$ ;Nope... 40$: CMPB R0,Q$UNIT(R1) ;Yes, who does it belong to? BEQ 100$ ;For unit being closed, report error MOV Q$LINK(R1),R1 ;Is there another element? BNE 40$ ;Yes, check it 50$: MOV NIICQE,R1 ;No more for transmit, check receive BEQ 70$ ;Nothing there... 60$: CMPB R0,Q$UNIT(R1) ;Who does it belong to? BEQ 100$ ;For unit being closed, report error MOV Q$LINK(R1),R1 ;Is there another element? BNE 60$ ;Yes, check it 70$: CLR NIPMFG ;If user got this far with promiscuous ; mode set, he's got every right to do ; this. 80$: .Assume UO.JOB EQ 0 .Assume UO.OFG EQ 1 CLR (R3) ;All done, free unit for use .Assume UP.ESZ EQ UO.ESZ CLR NIUPT-NIUOT(R3) ;Clear the protocol for this unit MOV R5,R3 ;Get unit number MUL #UA.ESZ,R3 ;Calculate offset to appropriate entry .ADDR #NIUAT,R3,ADD ;R3 -> Unit's address entry CLR (R3)+ ;Clear the entry CLR (R3)+ CLR (R3)+ CALL SETUP ;Report change in address filtering ; (Error ignored here since we're ; removing addresses from the table) DEC PORTCT ;One less portal open BPL 90$ ;Still some open... CALL DISABL ;Last one to close, shut down CLR NIQUEF ;Clear frame queueing ;033 90$: CALL TSTQUE ;Check frame queue ;033 BR NIDONE ;033 100$: MOV #RC.ACT,-(SP) ;Code = "Portal active" BR SPERR .DSABL LSB .SBTTL .SPPM - Enable/Disable Promiscuous Mode ;+ ; ; .SPPM ; Exclusive-use implementation of promiscuous mode. Only ; one unit may be open and in promiscuous mode. ; ; On disable, turns request into an ENABLE and drops into ; protocol code. ; ; ** Note ** ; This is an implicit change of the address filtering, so ; the port handler needs to be informed ; ;- .ENABL LSB .SPPM: .Assume Q$BLKN EQ 0 TST (R4) ;Enable or disable? BEQ SPDPM. ;Disable... SPEPM.: TST PORTCT ;Are there any open portals? BGT 10$ ;Other than this one, yes... MOV #-1,NIPMFG ;Flag that port is promiscuous MOVB Q$UNIT(R4),NIPMFG ; and it's this jobs fault CALL SETUP ;Report change in address filtering ; (Error ignored here since we're ; altering PM mode setting, not ; adding an address to the table) JMP NIDONE ;033 10$: MOV #RC.EXC,-(SP) ;Code - 'Non-exclusive' JMP SPERR SPDPM.: CLR NIPMFG ;If user got this far with promiscuous ; mode set, he's got every right to do ; this. CALL SETUP ;Report change in address filtering ; (Error ignored here since we're ; altering PM mode setting, not ; adding an address to the table) .Assume Q$BLKN EQ 0 MOV #1,(R4) ;Turn request into an enable .BR .SPPT ; of the protocol type passed .DSABL LSB .SBTTL .SPPT - Enable/Disable Protocol Type ;+ ; ; .SPPT ; On enable, if the protocol table entry for this unit is ; currently filled, returns 'No resources' code. If not ; filled, the protocol is compared against those defined ; for other portals (units) and if it is already in use, ; returns 'Protocol in use' code. If it is not in use, ; the protocol is placed in the table entry for the current ; unit. ; ; On disable, if the protocol specified is not the one ; in the table entry for this unit, just returns. If it is ; the same, it is cleared. ; ; CALL: ; blkn <> 0, Enable ; blkn = 0, Disable ; ; protocol is contained in 2nd word of user's buffer ; ;- .ENABL LSB .SPPT: .Assume UP.ESZ EQ 2 MESSAGE= ASL R5 ;Calculate address of protocol table .ADDR #NIUPT,R5,ADD ; entry for this unit MOV @#KISAR1,-(SP) ;Save current PAR1 context ; ** don't use SAVPAR ** MOV Q$PAR(R4),@#KISAR1 ;Map to user's buffer MOV Q$BUFF(R4),R0 ;R0 -> User's buffer MOV 2(R0),PROTMP ;Get the protocol MOV (SP)+,@#KISAR1 ;Restore PAR1 context .Assume Q$BLKN EQ 0 TST (R4) ;Enable or Disable? BEQ SPDPT. ;Disable... SPEPT.: TST (R5) ;Is a protocol already enabled? BEQ 10$ ;Nope... MOV #RC.RES,-(SP) ;Code = 'No resources' JMP SPERR 10$: .ADDR #NIUPT,R0 ;R0 -> Protocol table MOV #UP.TSZ,R1 ;R1 = Unit count 20$: CMP PROTMP,(R0)+ ;In use? BEQ 30$ ;Yes... DEC R1 ;Nope, more entries to check? BGT 20$ ;Yes... MOV PROTMP,(R5) ;Enable it for this unit JMP NIDONE 30$: MOV #RC.PRO,-(SP) ;Code = 'Protocol type in use' JMP SPERR SPDPT.: CMP PROTMP,(R5) ;Disable this protocol? BNE 40$ ;Nope, not the one enabled... CLR (R5) ;Yes... 40$: JMP NIDONE .DSABL LSB .SBTTL .SPMA - Enable/Disable Multicast Address ;+ ; ; .SPMA ; On enable, if the address table entry for this unit is currently ; filled, returns 'no resources' code. If not filled, the address ; specified is placed in the table. ; ; On disable, if the address specified is not the one enable for ; this unit, just returns. It it is the same, the entry is cleared. ; ; CALL: ; blkn <> 0, Enable ; blkn = 0, Disable ; ; Address is 3 words long starting with 2nd word of user's buffer. ; ;- ; *** ACTION *** 'All multicast' based on setting of WCNT? .ENABL LSB .SPMA: MUL #UA.ESZ,R5 ;R5 = Unit's address table offset .ADDR #NIUAT,R5,ADD ;R5 -> Unit's address table entry MOV @#KISAR1,-(SP) ;Save current PAR1 context ; ** don't use SAVPAR ** MOV Q$PAR(R4),@#KISAR1 ;Map to user's buffer MOV Q$BUFF(R4),R0 ;R0 -> User's buffer TST (R0)+ ;On to address argument .ADDR #ADDTMP,R1 ;R1 -> Where to save it temporarily MOV (R0)+,(R1)+ ;Copy the user specified address MOV (R0)+,(R1)+ MOV (R0)+,(R1)+ MOV (SP)+,@#KISAR1 ;Restore PAR1 context .Assume Q$BLKN EQ 0 TST (R4) ;Enable or disable? BEQ SPDMA. ;Disable... SPEMA.: MOV (R5)+,-(SP) ;Is an address already set? BIS (R5)+,(SP) BIS (R5)+,(SP)+ BEQ 20$ ;Nope... 15$: MOV #RC.RES,-(SP) ;Code = 'No resources' JMP SPERR 20$: .ADDR #ADDTMP+UA.ESZ,R0 ;R0 -> Beyond last word of address MOV -(R0),-(R5) ;Place specified address in table MOV -(R0),-(R5) MOV -(R0),-(R5) BR 50$ SPDMA.: MOV R5,-(SP) ;Save table entry pointer .ADDR #ADDTMP,R0 ;R0 -> Specified address MOV #3,R1 ;R1 = Count of words to match 30$: CMP (R0)+,(R5)+ ;Match in this word? BNE 40$ ;Nope... DEC R1 ;More to do? BGT 30$ ;Yes... MOV (SP),R5 ;Get back pointer to entry CLR (R5)+ ;Clear the entry CLR (R5)+ CLR (R5)+ 40$: TST (SP)+ ;Unstack the saved pointer 50$: CALL SETUP ;Report change in address filtering ; ** ACTION ** Add support to all handlers for returning this ; information ;;; BCS 15$ ;Device can't handle this many JMP NIDONE .DSABL LSB .SBTTL .SPXMT - Transmit Ethernet Frame ;+ ; ; .SPXMT ; Places a transmit request queue element on the internal ; transmit queue and then calls XMIT in the port handler code. ; ; Note: ; NOQCHG is set to indicate to the transmit interrupt processing ; code that the internal queue is not stable and that it should ; suspend processing of transmit interrupts. ; ; Also note that the MIN and MAX user buffer sizes include the ; status and reserved words preceeding the actual frame. ; ;- MNBFSZ == 32. ;Minimum user buffer size MXBFSZ == 759. ;Maximum user buffer size .SPXMT: CMP Q$WCNT(R4),#MNBFSZ ;Too small to transmit? ; (32. includes status and reserved ; words prior to actual frame) BGE 20$ ;Nope... 10$: MOV #,-(SP) ;Code = 'Transmit failure' ;Subcode = 'Frame length error' JMP SPERR 20$: CMP Q$WCNT(R4),#MXBFSZ ;Too large to transmit? BGT 10$ ;Yes... MOV SP,NOQCHG ;Set 'output queue being modified' JSR R5,ENQ ;Queue the write request NIOCQE: .WORD 0 ; : Output CQE NIOLQE: .WORD 0 ; : Output LQE CLR NOQCHG ;Reset 'output queue being modified' CALLR XMIT ;Start the transmitter .SBTTL .SPRCV - Receive Ethernet Frame ;+ ; ; .SPRCV ; Places a receive request queue element on the internal receive ; queue and then calls RECV in the port handler code. ; ; Note: ; NIQCHG is set to indicate to the receive interrupt processing ; code that the internal queue is not stable and that it should ; suspend processing of receive interrupts. ; ;- .SPRCV: MOV SP,NIQCHG ;Set 'input queue being modified' JSR R5,ENQ ;Queue the receive request NIICQE: .WORD 0 ; : Input CQE NIILQE: .WORD 0 ; : Input LQE CLR NIQCHG ;Reset 'input queue being modified' CALLR RECV ;Start up the receiver .SBTTL .SPQUE - Enable/Disable Receive Frame Queue ;+033 ; ; .SPQUE ; On enable, received frames of enabled protocols are not ; discarded. The queued frame will be read by the next ; read data request for this protocol type. Frames are ; read in the same sequence as received. ; ; On disable, if all protocalls have been disabled then frame ; queueing will be disabled. Otherwise an error is returned. ; ; CALL: ; blkn <> 0, Enable ; blkn = 0, Disable ; ;-033 ;+033 .ENABL LSB .SPQUE: .ASSUME Q$BLKN EQ 0 TST (R4) ;Q$BLKN = 1, Enable queueing BEQ SPDQU. ;Q$BLKN = 0, Disable queueing SPEQU.: MOV #-1,NIQUEF ;Enable internal frame queueing JMP NIDONE SPDQU.: TST PORTCT ;If portct not zero, error BMI 5$ MOV #RC.QUE,-(SP) ;Ports active JMP SPERR 5$: CLR NIQUEF ;Disable internal frame queueing JMP NIDONE TSTQUE: TST NIQUEF ;If internal frame queueing is BEQ 10$ ;Enabled, then check receive frame CALL RECV 10$: RETURN .DSABL LSB ;-033 .SBTTL .SPSTT - Get Handler Status Block ;+033 ; ; .SPSTT ; Read handler status area into user buffer. ; This area contains statistics about receive ; and transmit interrupts and frames. ; ;-033 ;+033 .ENABL LSB .SPSTT: MOV NICQE,R4 MOV Q$WCNT(R4),R2 CMP #NISLEN,R2 ;Valid length ? BHIS 5$ ;Yes - skip MOV #,-(SP) JMP SPERR ;Invalid length 5$: MOV @#KISAR1,-(SP) ;Now access user buffer MOV Q$PAR(R4),@#KISAR1 MOV Q$BUFF(R4),R0 ADD #2,R0 .ADDR #NISBLK,R1 ;Status block address 10$: MOV (R1)+,(R0)+ ;Copy status SOB R2,10$ MOV (SP)+,@#KISAR1 JMP NIDONE .DSABL LSB ;-033 .SBTTL SAV30 - Save Registers R0 to R3 ;+ ; ; SAV30 ; Used to save the contents of general registers 0-3. ; ; ** Coroutine ** ; ;- SAV30: MOV R0,-(SP) ;Save the registers MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV 10(SP),-(SP) ;Top it with the return address CALL @(SP)+ ;Co-routine back to caller MOV (SP)+,R3 ;Restore the registers MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 TST (SP)+ ;Don't return to the caller, RETURN ; but to the callers' caller .SBTTL SAVPAR - Save PAR1 Mapping Context ;+ ; ; SAVPAR ; Used to save/restore the PAR1 mapping context. ; ; ** coroutine ** ; ;- SAVPAR: MOV (SP),-(SP) ;Stack the return address MOV @#KISAR1,2(SP) ;Save current PAR1 contents CALL @(SP)+ ;Coroutine back to caller MOV (SP)+,@#KISAR1 ;Restore original PAR1 context RETURN ; and return to callers' caller .SBTTL FIXPAR - Normalize Address/Par Information in Queue Element ;+ ; ; FIXPAR ; Used to ensure that PAR bias does not fall outside the ; PAR1 range. Also normalizes the PAR value to keep BUFF ; within the range 20000-20077 (required to call MPPHY). ; ; CALL: ; R4 -> Current queue element ; ;- FIXPAR: CMP Q$BUFF(R4),#20000 ;Too low? BGE 10$ ;Nope... ADD #20000,Q$BUFF(R4) ;Yes, adjust into range SUB #200,Q$PAR(R4) ;Adjust PAR bias BR FIXPAR ;And check again 10$: CMP Q$BUFF(R4),#20000+ ;Too high? BLO 20$ ;Nope... SUB #,Q$BUFF(R4) ;Yes, adjust a little INC Q$PAR(R4) ;Bump the PAR bias BR 10$ ;Check it again 20$: RETURN .SBTTL ENQ - Place Queue Element on Internal Queue ;+ ; ; ENQ ; Removes the current queue element from the RT-maintained ; device queue and places it on an internal queue. ; ; CALL: ; R4 -> queue element (at Q.BLKN) ; R5 -> two-word queue ; first word is CQE pointer ; second word is LQE pointer ; ** linkage register is R5 ** ; ;- ENQ: MOV Q$LINK(R4),NICQE ;Remove from RT-maintained queue BNE 5$ ;Not last, LQE still important CLR NILQE ;Was last, LQE should be discarded 5$: CLR Q$LINK(R4) ;Ensure it doesn't link anywhere TST (R5) ;Is our internal queue empty? BNE 10$ ;Nope... MOV R4,(R5)+ ;Yes, so make it the first MOV R4,(R5)+ ; and last element BR 20$ 10$: TST (R5)+ ;Bump to LQE pointer MOV R4,-(SP) ;Save address of new element MOV (R5),R4 ;R4 -> last queue element MOV (SP),Q$LINK(R4) ;Link it to the new element MOV (SP)+,(R5)+ ; making new element the last one 20$: RTS R5 .SBTTL NIIDEQ - Remove Queue Element from Internal Receive Queue ;+ ; ; NIIDEQ ; Remove the specified queue element from the internal receive ; queue. Falls through into NIFIN to return the queue element ; to RT. ; ; CALL: ; R4 -> Qelement (at Q$BLKN) ; ; Notes: ; This is a specialized routine for removing queue elements from ; the internal receive queue because they may be completed in an ; order other than how they are placed in the queue. ; ; Transmit requests are processed in the order in which they are ; received, so removing one from the internal transmit queue and ; returning it to RT is done as follows: ; ; MOV NIOCQE,R4 ;R4 -> queue element just completed ; MOV Q$LINK(R4),NIOCQE ;Link the queue forward ; CALL NIFIN ;Return the element to RT ; ;- NIIDEQ: MOV R0,-(SP) ;We'll need a scratch register MOV SP,NIQCHG ;Set 'input queue being modified' .ADDR #NIICQE-Q$LINK,R0 ;R0 -> Before internal CQE 10$: CMP Q$LINK(R0),R4 ;Is this the element we are removing? BEQ 20$ ;Yes... MOV Q$LINK(R0),R0 ;Nope, on to next element BNE 10$ ;If there is one... HALT ;If we get here, the internal receive BR .-2 ; queue is corrupted 20$: MOV Q$LINK(R4),Q$LINK(R0) ;Remove the element from the queue BNE 30$ ;Qelement removed was not last... MOV R0,NIILQE ;Record new end of queue 30$: CLR Q$LINK(R4) ;Complete removal from queue CLR NIQCHG ;Reset 'input queue being modified' MOV (SP)+,R0 ;Restore scratch register .BR NIFIN ;Return the queue element to RT .SBTTL NIFIN - Internal Queue Element Completion ;+ ; ; NIFIN ; Used to return completed internal queue elements to the ; RT-maintained queue. ; ; CALL: ; R4 -> queue element to return to RT (at Q$BLKN) ; ; ** Note ** ; Fake device queue is used to return Qelements to avoid race ; in previous code. ; ;- NIFIN: MOV R4,NIFCQE ;Queue element we are returning will MOV R4,NIFLQE ; become the first and last element CLR Q$LINK(R4) ;Detach it from the world .ADDR #NIFCQE,R4 ;R4 -> NICQE for passing to COMPLT MOV @#SYSPTR,R5 ;R5 -> $RMON CALL @QCOMP(R5) ;Call the I/O completion routine RETURN .SBTTL NIABRT - Class Handler Abort Code ;+ ; ; NIABRT ; Entered as a result of the abort of a job or an HRESET. It ; removes queue elements from both the transmit and receive ; internal queues and returns them to the device queue and ; informs RT that all I/O requests by the aborting job are ; now complete. ; ; Entered with: ; R4 = Job number {aborting | issuing .ABTIO} ; R5 = 0 if abort by job ; -> Channel Control Block (CCB) if abort by channel (.ABTIO) ; ; ** Note ** ; This causes an implicit change in the address filtering, so ; the port handler must be informed. ; ;- .ENABL LSB NIABRT: CALL SAV30 ;Save a few registers ; First, remove outstanding requests for the job from the internal ; queues and place them on the device queue. MOV SP,NIQCHG ;Set 'input queue being modified' JSR R4,110$ ; while we remove entries from the .WORD NIICQE-120$-Q$LINK ; internal receive queue CLR NIQCHG ;Reset 'input queue being modified' MOV SP,NOQCHG ;Set 'output queue being modified' JSR R4,110$ ; while we remove entries from the .WORD NIOCQE-120$-Q$LINK ; internal transmit queue CLR NOQCHG ;Reset 'output queue being modified' ; Now scan the unit ownership table for units allocated by this ; job, deallocate them and clear the corresponding entries in the ; unit protocol table and unit address table. TST R5 ;Abort by channel? BNE 40$ ;Yes, then don't discard unit .ADDR #NIUOT,R0 ;R0 -> Unit ownership table MOV #UO.TSZ,R1 ;R1 = Units to check 10$: MOV (R0),R2 ;R2 = Job/Unit mask of owner BEQ 30$ ;If zero, there is no owner MOV R2,-(SP) ;Make a copy BIC #^C,(SP) ; which contains the unit number BIC #^C,R2 ;Isolate the job number ASR R2 ; and shift it ASR R2 ; to check against ASR R2 ; aborting job CMPB R2,R4 ;This unit owned by aborting job? BNE 20$ ;Nope... CLR (R0) ;Yes, it doesn't own it anymore .ASSUME UP.ESZ EQ UO.ESZ CLR NIUPT-NIUOT(R0) ;Clear any protocol he had set MOV (SP),R3 ;R3 = Unit index MUL #UA.ESZ,R3 ;R3 = Address table offset .ADDR #NIUAT,R3,ADD ;R3 -> Address table entry CLR (R3)+ CLR (R3)+ CLR (R3)+ 20$: TST (SP)+ ;Discard the unit number 30$: TST (R0)+ ;On to next unit DEC R1 ;More to do? BGT 10$ ;Yep... 40$: ; We now need to correct the count of open (allocated) units and ; possibly the address filtering MOV PORTCT,-(SP) ;Save for later check MOV #-1,PORTCT ;PORTCT initial value .ADDR #NIUOT,R0 ;R0 -> Unit ownership table MOV #UO.TSZ,R1 ;R1 = Count of unit entries 50$: TST (R0)+ ;Is this unit open? BEQ 60$ ;Nope... INC PORTCT ;Yes, count it 60$: DEC R1 ;More to check? BGT 50$ ;Yes... MOV NIPMFG,R0 ;Are we in promiscuous mode? BEQ 70$ ;Nope... BIC #^C,R0 ;Yes, isolate the job number ASR R0 ; and shift it ASR R0 ; to check against ASR R0 ; aborting job CMPB R0,R4 ;Was aborting job promiscuous? BNE 70$ ;Nope... CLR NIPMFG ;Yes, so we're not any more 70$: CMP PORTCT,(SP)+ ;Is it the same port count? BEQ 90$ ;Yes... TST PORTCT ;Are any units still open? BPL 80$ ;Yes... CLR NIPMFG ;Nope, then disable promiscuous CLR NIQUEF ;and frame queueing ;033 CALL DISABL ; and shut down... BR 90$ 80$: CALL SETUP ;Implicit address filtering change ; (Error ignored here since we're ; removing addresses from the table) 90$: TST NICQE ;Returning anything to RT? BNE 100$ ;Yep... RETURN ;Nope, then just return 100$: .DRFIN NI ;Return aborted queue elements to RT ; The following code scans the internal queue for queue elements which ; match the abort criteria (job number for job abort, channel if abort ; by channel). It then dequeues them from the internal queue, returning ; them to the device queue. SP.CCB = 4 ;Stacked CCB pointer SP.JOB = 6 ;Stacked job number 110$: MOV R5,-(SP) ;Save CCB pointer MOV (R4)+,R5 ;Pick up the displacement and MOV R4,-(SP) ; store the return address ADD PC,R5 ;Calculate actual address ; (120$ must follow this) .BR 120$ 120$: MOV R5,-(SP) ;Save the Q header address 130$: MOV Q$LINK(R5),R4 ;Follow link to next qelement BEQ 170$ ;No more elements... TST SP.CCB(SP) ;Abort by channel (.ABTIO) ? BEQ 140$ ;Nope, aborting job... CMP Q$CSW(R4),SP.CCB(SP) ;Yes, this qelement for that channel? BNE 160$ ;Nope... BR 150$ ;Yes, go remove it 140$: MOVB Q$JNUM(R4),R0 ;R0 = Job/unit mask BIC #^C,R0 ;Isolate the job number ASR R0 ; and shift it ASR R0 ; to check against ASR R0 ; the aborting job CMP R0,SP.JOB(SP) ;This qelement for aborting job? BNE 160$ ;Nope... 150$: MOV Q$LINK(R4),Q$LINK(R5) ;Yes, remove it from the link CLR Q$LINK(R4) ;Ensure it doesn't link anywhere CLR Q$COMP(R4) ; and disable any completion for it TST NICQE ;Anything on the device queue? BNE 155$ ;Yes, then link it at the end MOV R4,NICQE ;Nope, make it the first MOV R4,NILQE ; and only on the device queue BR 130$ ;Check for further elements to abort 155$: MOV NILQE,R0 ;R0 -> Qelement at end of device queue MOV R4,Q$LINK(R0) ;Link it to this one, making it MOV R4,NILQE ; the last on the device queue BR 130$ ;Check for further elements to abort ; Here if a qelement is not part of the aborting job 160$: MOV R4,R5 ;Skip the element BR 130$ ;Check for further elements to abort ; Here when done, record the new end of the internal queue 170$: MOV (SP)+,R4 ;R4 -> Internal queue header MOV R5,Q$LINK+2(R4) ;Set new end of internal queue MOV (SP)+,R4 ;Recover the return address MOV (SP)+,R5 ;Restore CCB pointer RTS R4 .DSABL LSB .SBTTL Class Handler Impure Data Area .PSECT NIDAT ;+033 NISBLK: NIIPKT: .BLKW 2 ; Receive interrupt count NIOPKT: .BLKW 2 ; Transmit interrupt count NIRTMO: .BLKW 2 ; Receive timeout count NIXTMO: .BLKW 2 ; Transmit timeout count NIRUN0: .BLKW 16. ; Received packet count by unit NIXUN0: .BLKW 16. ; Transmited packet count by unit NIQUEF: .WORD 0 ; 'Frame queueing enabled' flag ;-033 NIXADR: .BLKW ; Address/32. of extended region NICHFG: .WORD 0 ; : 'Channel on' flag PORTCT: .WORD -1 ; : 'Enable required' flag and ; open portal count NIPMFG: .WORD 0 ; : 'Promiscuous receiver active' flag ; (low byte contains job/unit mask) NIAMFG: .WORD 0 ; : 'All multicast' flag NOQCHG: .WORD 0 ; : 'Output queue being modified' flag NIQCHG: .WORD 0 ; : 'Input queue being modified' flag PROTMP: .BLKW ; Protocol type - temporary ADDTMP: .BLKW 3 ; Address - temporary NIUOT: ; Unit ownership table .REPT 8. .WORD 0 .ENDR UO.TSZ = <.-NIUOT>/UO.ESZ ; Unit ownership table size NIUPT: ; Unit protocol table .REPT 8. .WORD 0 .ENDR UP.TSZ = <.-NIUPT>/UP.ESZ ; Unit protocol table size ; *** Begin critical ordering *** NIPHAD: .BLKB 6 ; Ethernet physical address NIBROD: .WORD 177777,177777,177777 ; Broadcast address NIUAT: ; Unit address table .REPT 8. .WORD 0,0,0 .ENDR UA.TSZ = <.-NIUAT>/UA.ESZ ; Unit address table size ; *** End critical ordering *** ; *** Begin critical ordering *** ; Fake device queue header for returning qelements .WORD 0 ;Handler hold = OFF NIFLQE: .BLKW ;Last Qelement pointer NIFCQE: .BLKW ;Current Qelement pointer ; *** End critical ordering *** .SBTTL LOAD - Ethernet Class Handler Load Code .SBTTL UNLOAD - Ethernet Class Handler Unload Code ;+ ; ; LOAD ; Performs Ethernet class handler load operations, then passes ; control to port handler load code. ; ; UNLOAD ; Performs Ethernet class handler unload operations, verifying ; that the handler is not active and may be removed. If it is ; active, UNLOAD is rejected with an error message. If it is ; not active, control passes to Ethernet port handler unload ; code. ; ; Note: ; This should be the first occurance of the SETOVR .PSECT ; ;- .PSECT SETOVR LODOVR = . ;Base for this overlay .ENABL LSB NILOAD:: CALL LOAD ;Perform port specific task BCC 20$ ;Load was successful... BR 30$ ;Load failed... NIUNLO:: MOV R5,-(SP) ;Save R5 for awhile MOV @R5,R5 ;R5 -> Handler entry point (NILQE) TST (R5) ;Any portals open? BMI 10$ ;Nope, handler is idle .ADDR #NOUNLO,R0 ;R0 -> Error message string ; (KMON reports error) MOV (SP)+,R5 ;Restore R5 BR 30$ 10$: MOV (SP)+,R5 ;Ensure proper R5 for UNLOAD code CALL UNLOAD ;Perform port specific unload task 20$: TST (PC)+ ;Good return, handler is idle 30$: SEC ;Error return, handler is in use RETURN .DSABL LSB NOUNLO: .IF NE NI$CNA .ASCII "?NC-" .ENDC ;NE NI$CNA .IF NE NI$QNA .ASCII "?NQ-" .ENDC ;NE NI$QNA .IF NE NI$UNA .ASCII "?NU-" .ENDC ;NE NI$UNA .ASCIZ "F-Handler may not be unloaded while in use" .EVEN