.NLIST TOC .TITLE NULDRV - NULL ACP DRIVER .SBTTL NULDRV - TITLE PAGE .IDENT /V02.00/ ; ; ************************************************************************ ; * ; THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS ONLY. DIGITAL EQUIPMENT * ; COMPUTER USER'S SOCIETY, DIGITAL EQUIPMENT CORPORATION, MONSANTO, AND * ; THE AUTHOR DISCLAIM ALL WARRANTIES ON THE PROGRAM, INCLUDING WITHOUT * ; LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABLITY AND FITNESS. * ; * ; FULL PERMISSION AND CONSENT IS HEREBY GIVEN TO DECUS AND TO THE DECUS * ; SPECIAL INTEREST GROUPS TO REPRODUCE, DISTRIBUTE, AND PUBLISH AND * ; PERMIT OTHERS TO REPRODUCE IN WHOLE OR IN PART, IN ANY FORM AND * ; WITHOUT RESTRICTION, THIS PROGRAM AND ANY INFORMATION RELATING TO IT. * ; * ; ************************************************************************ ; ; AC: (EXAMPLE ACP) DEVICE DRIVER. THIS DRIVER DOES NOTHING USEFUL. IT ; MEARLY DEMONSTRATES MANY OF THE FEATURES OF ACP PACKET PROCESSING. SEE ; THE ACP MANUAL, CHAPTER 3 AND APPENDIX E FOR MORE DETAILS. ; ; VERSION: V02.00 ; ; AUTHOR: R.W. STAMERJOHN MAPC 03-DEC-79 ; ; MODIFICATION HISTORY: ; ; V01.00 RWS 03-DEC-79 INITIAL VERSION ; ; V02.00 RWS 02-APR-80 UPDATED TO MATCH ACP MANUAL .SBTTL NULDRV - DECLARATIONS .DSABL GBL ; ; MACRO LIBRARY CALLS: ; .MCALL HWDDF$ ;DEFINE HARDWARE SYMBOLICS HWDDF$ .MCALL IOERR$ ;DEFINE I/O ERROR SYMBOLICS IOERR$ .MCALL PKTDF$ ;DEFINE I/O PACKET SYMBOLICS PKTDF$ .MCALL UCBDF$ ;DEFINE UCB SYMBOLICS UCBDF$ ; ; GLOBAL DECLARATIONS: ; .GLOBL $ACTBL ;DRIVER DISPATCH TABLE .GLOBL $ACDAT ;START OF DATA STRUCTURE .GLOBL $ACEND ;END OF DATA STRUCTURE .GLOBL .ACDCB ;START OF DCB .GLOBL .AC0 ;START OF UCB .GLOBL $AC0 ;START OF SCB ; ; GLOBAL REFERENCES: ; .GLOBL $ACHKB ;(IOSUB) ADDRESS CHECK BUFFER (BYTE) .GLOBL $ALOCB ;(CORAL) ALLOCATE SYSTEM BUFFER .GLOBL $EXRQP ;(REQSB) QUEUE PACKET TO ACP .GLOBL $GTPKT ;(IOSUB) GET I/O PACKET ROUTINE .GLOBL $IOALT ;(IOSUB) FINISH PROCESSING PACKET .GLOBL $IOFIN ;(IOSUB) FINISH PROCESSING PACKET .GLOBL $QINSP ;(QUEUE) QUEUE INSERT ROUTINE .GLOBL $RELOC ;(IOSUB) RELOCATE USER ADDRESS ; ; LOCAL (RO) DATA: ; ; DEVICE DISPATCH TABLE ; $ACTBL:: ;REF. LABEL .WORD DRVINI ;DEVICE INITIATOR .WORD DRVCAN ;CANCEL I/O .WORD DRVTMO ;DEVICE TIMEOUT .WORD DRVPWF ;POWER RECOVERY ; ; POLISH CODE DISPATCH VECTOR TABLE ; DRVFNC: .WORD DRVCRE ;(00)-CREATE PROCESS .WORD DRVCLO ;(01)-CLOSE PROCESS .WORD DRVPUT ;(02)-OUTPUT TO PROCESS .WORD DRVGET ;(03)-INPUT FROM PROCESS .WORD DRVCTL ;(04)-PROCESS CONTROL DRVMAX = <.-DRVFNC>/2 ;HIGHEST SUBFUNCTION CODE ; ; CHECK CREATE PROCESS. ; DRVCRE: .WORD CHKDMO ;CHECK IF VOLUME MARKED FOR DISMOUNT .WORD CHKALN ;CHECK IF PROCESS ALREADY ENABLED .WORD NONBUF ;(P1),(P2) NO BUFFER ALLOWED .WORD NONBUF ;(P3),(P4) NO BUFFER ALLOWED .WORD REQPRM ;(P5) ACCESS PARAMETER .WORD NONPRM ;(P6) NO PARAMETER ALLOWED .WORD DRVLCK ;LOCK AND QUEUE TO ACP ; ; CHECK CLOSE PROCESS. ; DRVCLO: .WORD CHKNLN ;CHECK IF PROCESS ENABLED .WORD NONBUF ;(P1),(P2) NO BUFFER ALLOWED .WORD NONBUF ;(P3),(P4) NO BUFFER ALLOWED .WORD NONPRM ;(P5) NO PARAMETER ALLOWED .WORD NONPRM ;(P6) NO PARAMETER ALLOWED .WORD DRVLCK ;LOCK AND QUEUE TO ACP ; ; CHECK PUT PROCESS. ; DRVPUT: .WORD CHKACC,WI$PUT ;CHECK IF PUT ACCESS ALLOWED .WORD MAPBUF ;(P1),(P2) MAP OUTPUT BUFFER .WORD NONBUF ;(P3),(P4) NO BUFFER ALLOWED .WORD NXTSEQ,DRVIOF ;CONTINUE WITH COMMON PROCESSING ; ; CHECK GET PROCESS. ; DRVGET: .WORD CHKACC,WI$GET ;CHECK IF GET ACCESS ALLOWED .WORD NONBUF ;(P1),(P2) NO BUFFER ALLOWED .WORD MAPBUF ;(P3),(P4) MAP INPUT BUFFER ; ; CHECK GET/PUT I/O PARAMETERS ; DRVIOF: .WORD NONPRM ;(P5) NO PARAMETER ALLOWED .WORD NONPRM ;(P6) NO PARAMETER ALLOWED .WORD DRVQUE ;QUEUE TO ACP ; ; CHECK CONTROL PARAMETERS ; DRVCTL: .WORD CHKNLN ;CHECK IF PROCESS ENABLED .WORD NONBUF ;(P1),(P2) NO BUFFER ALLOWED .WORD NONBUF ;(P3),(P4) NO BUFFER ALLOWED .WORD REQPRM ;(P5) ACCESS PARAMETER .WORD NONPRM ;(P6) NO PARAMETER ALLOWED .WORD DRVLCK ;LOCK AND QUEUE TO ACP ; ; LOCAL (RW) DATA: ; PARAM: .BLKW 8. ;PARAMETER BLOCK, USED BY POLISH CODE .SBTTL DRVINI * I/O INITIATOR ; ; DRVINI IS CALLED WHENEVER AN I/O REQUEST IS MADE TO THE NULL ACP ; DEVICE. THE I/O PACKET HAS NOT BEEN QUEUED AND THE FOLLOWING REGISTERS ; ARE SET: ; ; R1 = I/O PACKET ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; DRVINI: MOVB I.FCN+1(R1),R0 ;GET I/O FUNCTION CODE CMPB #IX.ACP/400,R0 ;IS THIS AN ACP FUNCTION? BEQ DRVACP ; IF EQ - YES, GO PROCESS CMPB #IO.CLN/400,R0 ;IS THIS A IO.CLN FUNCTION BEQ DRVSND ; IF EQ - YES, QUEUE TO ACP ; ; QUEUE PACKET TO DEVICE AND GET NEXT PACKET. ; DRVPKT: MOV U.SCB(R5),R0 ;GET DEVICE QUEUE LISTHEAD CALL $QINSP ;QUEUE PACKET TO DEVICE CALL $GTPKT ;GET NEXT PACKET BCS 1000$ ; IF CS - NO PACKET ; ; GOT DATA TRANSFER FUNCTION, JUST RETURN SUCCESS. ; ; N.B. THIS IS WHERE NORMAL DRIVER PROCESS WOULD BEGIN. THIS ; DRIVER SERVICES NO DEVICE, SO ALL DRIVER FUNCTIONS ARE ; SIMPLE SUCCESS RETURNS. ; MOV #IS.SUC,R0 ;SET SUCCESS CODE CALL $IOALT ;RETURN SUCCESS AND EXIT 1000$: RETURN ;RETURN TO CALLER ; ; THE FUNCTION IS A ACP FUNCTION. SETUP FOR POLISH ERROR CHECKING. ; THE FOLLOWING PARAMETERS ARE USED FOR ACP FUNCTIONS. IF PARAMETER ; IS NOT USED FOR A PARTICULAR FUNCTION IS MUST BE ZERO. ; ; P1 - OUTPUT BUFFER ADDRESS ; P2 - OUTPUT BUFFER SIZE ; P3 - INPUT BUFFER ADDRESS ; P4 - INPUT BUFFER SIZE ; P5 - ACCESS PARAMETER ; P6 - ALWAYS ZERO (0) ; DRVACP: MOV R1,R3 ;SETUP FOR $IOFIN CALL BITB #US.MNT,U.STS(R5) ;IS ACP PRESENT (MOUNTED)? BNE DRVDNR ; IF NE - NO, RETURN DEVICE NOT READY MOVB I.FCN(R1),R2 ;GET SUBFUNCTION CODE CMP #DRVMAX,R2 ;IS SUBFUNCTION IN RANGE? BLOS DRVIFC ; IF LOS - NO, RETURN ILLEGAL FUNCTION ADD #I.PRM,R1 ; MOV #PARAM,R4 ;GET TEMPORARY PARAMETER BLOCK ADDRESS ASL R2 ;MAKE CODE INTO WORD INDEX MOV DRVFNC(R2),R2 ;GET POLISH TABLE STARTING ADDRESS ; ; AT THIS POINT, THE I/O PARAMETERS ARE CHECKED FOR CORRECTNESS AND ALL ; ADDRESSES ARE RELOCATED. THIS IS DONE USING POLISH CODE, PRIMARILY FOR ; THE SAKE OF FLEXABLITY. THE REGISTERS ARE SETUP AS FOLLOWS: ; ; R0 = SCRATCH REGISTER ; R1 = I/O PACKET PARAMETER ADDRESS ; R2 = POLISH TABLE ADDRESS ; R3 = I/O PACKET ADDRESS ; R4 = CONSTRUCTED PARAMETER BLOCK ADDRESS ; R5 = UCB ADDRESS ; JMP @(R2)+ ;CALL FIRST POLISH ROUTINE ; ; WHEN THE PACKET IS COMPLETELY CHECKED AND FOUND GOOD, CONTROL RETURNS ; HERE TO FINISH PROCESSING. THE CONSTRUCTED PARAMETER BLOCK IS COPIED ; TO THE I/O PACKET AND THE PACKET QUEUED TO THE DEVICE. ; ; AT THIS POINT, THE PARAMETERS FOR THE PACKET ARE RESTRUCTURED FOR THE ; ACP'S USE. IF THE PARAMETER IS NOT PRESENT, IT WILL BE ZERO. THE I/O ; PACKET PARAMETERS PASSED TO THE ACP ARE AS FOLLOWS: ; ; I.PRM+00 - OUTPUT BUFFER MAPPING BIAS ; I.PRM+02 - OUTPUT BUFFER APR6 DISPLACEMENT ; I.PRM+04 - OUTPUT BUFFER SIZE ; I.PRM+06 - INPUT BUFFER MAPPING BIAS ; I.PRM+10 - INPUT BUFFER APR6 DISPLACEMENT ; I.PRM+12 - INPUT BUFFER SIZE ; I.PRM+14 - ACCESS PARAMETER ; I.PRM+16 - ALWAYS ZERO (0) ; DRVLCK: INC @I.LN2(R3) ;LOCK WINDOW DRVQUE: MOV R3,R1 ;RESTORE I/O PACKET ADDRESS ADD #I.PRM,R3 ;GET ADDRESS OF PARAMETERS MOV #PARAM,R4 ;GET CONSTRUCTED PARAMETER BLOCK MOV #8.,R2 ;GET NUMBER OF PARAMETERS 1000$: MOV (R4)+,(R3)+ ;COPY A PARAMETER SOB R2,1000$ ;LOOP TILL FINISHED ; ; GET ACP TCB ADDRESS AND QUEUE PACKET TO IT. ; DRVSND: INC @U.VCB(R5) ;INCREMENT TRANSACTION COUNT MOV U.ACP(R5),R0 ;GET ACP TCB ADDRESS CALLR $EXRQP ;QUEUE PACKET, SCHEDULE ACP, AND EXIT .SBTTL DRVCAN * CANCEL I/O ; ; DRVCAN IS CALLED BY THE EXECUTIVE WHENEVER AN IO.KIL IS ISSUED OR I/O ; IS BEING RUNDOWN. THE IO.KIL IS A NOP, HOWEVER, AS THE DRIVER WILL NEVER ; HAVE ANY OUTSTANDING INTERRUPT LEVEL I/O. ; ; R0 = ADDRESS OF CURRENT I/O PACKET ; R1 = ADDRESS OF TCB OF TASK TO KILL I/O FOR ; R3 = CONTROLLER INDEX ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; DRVCAN: RETURN ;RETURN TO CALLER ; .SBTTL DRVPWF * POWER FAILURE ; ; DRVPWF IS CALLED WHENEVER THE SYSTEM RECOVERS FROM POWER FAILURE OR THE ; DEVICE DRIVER IS LOADED. THIS ENTRY COULD BE USED TO INITIALIZE DRIVER ; VARIABLES. IN THIS CASE, IT IS A NOP. THE REGISTERS ARE SETUP AS FOLLOWS ; ON CALL. ; ; R3 = CONTROLLER INDEX ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; DRVPWF: RETURN ;RETURN TO CALLER ; .SBTTL DRVTMO * DEVICE TIMEOUT ; ; DRVTMO IS CALLED BY THE EXECUTIVE WHENEVER THE TIMEOUT COUNTER EXPIRES ; FOR THE DEVICE. THIS ENTRY IS A NOP, AS THIS CONDITION SHOULD NOT OCCUR ; FOR THIS DRIVER. THE FOLLOWING REGISTERS ARE SETUP ON CALL: ; ; R0 = I/O STATUS CODE IE.DNR ; R2 = DEVICE CSR ; R3 = CONTROLLER INDEX ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; DRVTMO: RETURN ;RETURN TO CALLER .SBTTL DRVERR * ERROR RETURNS ; ; THE FOLLOWING ENTRIES SETUP THE ERROR RETURN CODE AND EXIT TO $IOFIN. ; EACH ENTRY IS EXPECTED TO BE CALLED WITH R3 = I/O PACKET ADDRESS AND ; R5 = UCB ADDRESS. CALLING $IOFIN IS PROPER HERE BEACUSE THE PACKET WAS ; NEVER QUEUED. ; DRVBAD: MOV #IE.BAD&377,R0 ;SET BAD PARAMETER ERROR BR DRVERR ; DRVDNR: MOV #IE.DNR&377,R0 ;SET DEVICE NOT READY (MOUNTED) ERROR BR DRVERR ; DRVALN: MOV #IE.ALN&377,R0 ;SET FILE ALREADY ACCESS ON LUN ERROR BR DRVERR ; DRVNLN: MOV #IE.NLN&377,R0 ;SET NO FILE ACCESSED ON LUN ERROR BR DRVERR ; DRVPRI: MOV #IE.PRI&377,R0 ;SET PRIVILEGE VIOLATION BR DRVERR ; DRVIFC: MOV #IE.IFC&377,R0 ;SET ILLEGAL FUNCTION CODE ERROR BR DRVERR ; DRVSPC: MOV #IE.SPC&377,R0 ;SET ILLEGAL BUFFER ERROR DRVERR: CLR R1 ;NO SECONDARY PARAMETER CALLR $IOFIN ;RETURN ERROR TO USER AND EXIT .SBTTL DRVCHK * POLISH ROUTINES ; ; CHECK IF VOLUME MARKED FOR DISMOUNT. ; CHKDMO: BITB #US.MDM,U.STS(R5) ;IS VOLUME MARKED FOR DISMOUNT? BNE DRVDNR ; IF NE - YES, RETURN ERROR JMP @(R2)+ ;CONTINUE WITH NEXT CHECK ; ; CHECK IF FILE ALREADY ACCESSED ON LUN. ; CHKALN: TST @I.LN2(R3) ;IS FILE ALREADY ACCESSED? BNE DRVALN ; IF NE - YES, RETURN ERROR JMP @(R2)+ ;CONTINUE WITH NEXT CHECK ; ; CHECK IF NO FILE ACCESSED ON LUN. ; CHKNLN: TST @I.LN2(R3) ;IS A FILE ACCESSED ON LUN? BEQ DRVNLN ; IF EQ - NO, RETURN ERROR JMP @(R2)+ ;CONTINUE WITH NEXT CHECK ; ; CHECK IF NO FILE ACCESSED ON LUN AND ACCESS PRIVILEGES. ; CHKACC: MOV @I.LN2(R3),R0 ;GET WINDOW ADDRESS BEQ DRVNLN ; IF EQ - NOT ACCESSED, RETURN ERROR BIT (R2)+,W$PRIV(R0) ;CHECK IF PROPER PRIVILEGE ENABLED BEQ DRVPRI ; IF EQ - NO, RETURN ERROR JMP @(R2)+ ;CONTINUE WITH NEXT CHECK ; ; CHANGE POLISH PATH. ; NXTSEQ: MOV (R2),R2 ;GET NEW PATH ADDRESS JMP @(R2)+ ;CONTINUE WITH NEW PATH ; ; CHECK FOR REQUIRED ZERO PARAMETER. ; NONPRM: MOV (R1)+,(R4)+ ;COPY PARAMETER BNE DRVBAD ; IF NE - BAD PARAMETER, RETURN ERROR JMP @(R2)+ ;CONTINUE WITH NEXT CHECK ; ; CHECK FOR REQUIRED NONZERO PARAMETER. ; REQPRM: MOV (R1)+,(R4)+ ;COPY PARAMETER BIT #^C,-2(R4) ;ARE ANY ILLEGAL BITS SET BNE DRVBAD ; IF NE - BAD PARAMETER, RETURN ERROR JMP @(R2)+ ;CONTINUE WITH NEXT CHECK ; ; CHECK NO BUFFER SPECIFIED. ; NONBUF: MOV (R1)+,(R4)+ ;IS BUFFER ADDRESS ZERO BNE DRVSPC ; IF NE - BAD BUFFER MOV (R1)+,(R4)+ ;IS BUFFER SIZE ZERO BNE DRVSPC ; IF NE - BAD BUFFER CLR (R4)+ ;CLEAR BUFFER SIZE FIELD JMP @(R2)+ ;CONTINUE WITH NEXT CHECK ; ; CHECK REQUIRED BUFFER AND RELOCATE ; MAPBUF: MOV (R1)+,R0 ;GET PARAMETER BEQ DRVBAD ; IF EQ - BAD PARAMETER, RETURN ERROR MOV R2,-(SP) ;SAVE POLISH INDEX MOV R1,-(SP) ;SAVE I/O PACKET POINTER MOV (R1)+,R1 ;GET BLOCK SIZE BEQ 1100$ ; IF EQ - BAD BUFFER CALL $ACHKB ;CALL ADDRESS CHECKING ROUTINE BCS 1100$ ; IF CS - ERROR CALL $RELOC ;RELOCATE BLOCK ADDRESS MOV R1,(R4)+ ;SAVE RELOCATION BIAS MOV R2,(R4)+ ;SAVE DISPLACEMENT ADDRESS MOV (SP)+,R1 ;RESTORE I/O PACKET POINTER MOV (R1)+,(R4)+ ;SAVE BUFFER SIZE MOV (SP)+,R2 ;RESTORE POLISH INDEX JMP @(R2)+ ;CONTINUE WITH NEXT CHECK 1100$: ADD #4,SP ;CLEAN STACK BR DRVSPC ; BAD BUFFER, RETURN ERROR .SBTTL DRVTBL - DATA STRUCTURE ; ; THE AC: DEVICE DATA STRUCTURE IS UNIQUE (WEIRD) IN SEVERAL WAYS BECAUSE ; IT IS FOR A SOFTWARE DEVICE. THE DRIVER IS MERELY A GATEWAY INTO THE NUL ; ACP. WHEN MOUNTED, THE DEVICE IS MARKED AS FOREIGN. UC.QUE IS SET SO ALL ; FUNCTIONS ARE IMMEDIATELY QUEUED TO THE DRIVER. THE DRIVER THEN PERFORMS ; THE ACP PACKET PROCESSING. ; ; DCB DATA STRUCTURE. ; $ACDAT:: ;REF. LABEL. .ACDCB:: ;REF. LABEL. .WORD 0 ;(D.LNK ) LINK TO NEXT DCB .WORD .AC0 ;(D.UCB ) LINK TO UCB .ASCII /AC/ ;(D.NAM ) DEVICE NAME .BYTE 0,1 ;(D.UNIT) LOWEST, HIGHEST UNIT NUMBER .WORD ACND-ACST ;(D.UCBL) LENGTH OF UCB .WORD 0 ;(D.DSP ) ADDRESS OF DRIVER DISPATCH TABLE .WORD 000206 ;(D.MSK ) LEGAL FUNCTION MASK 0-15 .WORD 000200 ; CNTRL FUNCTION MASK 0-15 .WORD 000000 ; NO-OP FUNCTION MASK 0-15 .WORD 000000 ; ACP FUNCTION MASK 0-15 .WORD 100000 ; LEGAL FUNCTION MASK 16-31 .WORD 100000 ; CNTRL FUNCTION MASK 16-31 .WORD 000000 ; NO-OP FUNCTION MASK 16-31 .WORD 000000 ; ACP FUNCTION MASK 16-31 .IF DF L$$DRV .WORD 0 ;(D.PCB) PCB ADDRESS .ENDC ; ; UCB DATA STRUCTURE (UNIT #0) ; ACST = . .IF DF M$$MUP .WORD 0 ;(U.OWN ) OWNING TERMINAL UCB ADDRESS .ENDC .AC0:: ;REF. LABEL. .WORD .ACDCB ;(U.DCB ) POINTER TO DCB .WORD .-2 ;(U.RED ) REDIRECT UCB POINTER .BYTE UC.QUE ;(U.CTL ) CONTROL FLAGS .BYTE US.MNT ;(U.STS ) STATUS FLAGS .BYTE 0 ;(U.UNIT) UNIT NUMBER .BYTE US.RED ;(U.STS2) STATUS FLAGS .WORD DV.MNT ;(U.CW1 ) DEVICE CHARACTERISTICS .WORD 0 ;(U.CW2 ) DEVICE CHARACTERISTICS .WORD 0 ;(U.CW3 ) DEVICE CHARACTERISTICS .WORD 1000 ;(U.CW4 ) BUFFER SIZE .WORD $AC0 ;(U.SCB ) SCB POINTER .WORD 0 ;(U.ATT ) ATTACH WORD .WORD 0,0 ;(U.BUF ) BUFFER RELOCATION ADDRESS .WORD 0 ;(U.CNT ) BUFFER SIZE (BYTES) .WORD 0 ;(U.ACP ) ACP TCB ADDRESS .WORD 0 ;(U.VCB ) VCB ADDRESS ACND = . ; ; UCB DATA STRUCTURE (UNIT #1) ; ACST = . .IF DF M$$MUP .WORD 0 ;(U.OWN ) OWNING TERMINAL UCB ADDRESS .ENDC .AC1:: ;REF. LABEL. .WORD .ACDCB ;(U.DCB ) POINTER TO DCB .WORD .-2 ;(U.RED ) REDIRECT UCB POINTER .BYTE UC.QUE ;(U.CTL ) CONTROL FLAGS .BYTE US.MNT ;(U.STS ) STATUS FLAGS .BYTE 0 ;(U.UNIT) UNIT NUMBER .BYTE US.RED ;(U.STS2) STATUS FLAGS .WORD DV.MNT ;(U.CW1 ) DEVICE CHARACTERISTICS .WORD 0 ;(U.CW2 ) DEVICE CHARACTERISTICS .WORD 0 ;(U.CW3 ) DEVICE CHARACTERISTICS .WORD 1000 ;(U.CW4 ) BUFFER SIZE .WORD $AC0 ;(U.SCB ) SCB POINTER .WORD 0 ;(U.ATT ) ATTACH WORD .WORD 0,0 ;(U.BUF ) BUFFER RELOCATION ADDRESS .WORD 0 ;(U.CNT ) BUFFER SIZE (BYTES) .WORD 0 ;(U.ACP ) ACP TCB ADDRESS .WORD 0 ;(U.VCB ) VCB ADDRESS ACND = . ; ; SCB DATA STRUCTURE. ; $AC0:: ;REF. LABEL .WORD 0,.-2 ;(S.LHD ) I/O QUEUE LISTHEAD .BYTE 0 ;(S.PRI ) DEVICE PRIORITY .BYTE 0/4 ;(S.VCT ) VECTOR ADDRESS/4 .BYTE 0 ;(S.CTM ) CURRENT TIMEOUT COUNT .BYTE 0 ;(S.ITM ) INITIAL TIMEOUT COUNT .BYTE 0 ;(S.CON ) CONTROLLER NUMBER .BYTE 0 ;(S.STS ) CONTROLLER STATUS .WORD 4 ;(S.CSR ) CSR ADDRESS .WORD 0 ;(S.PKT ) CURRENT PACKET ADDRESS .WORD 0,0,0,0 ;(S.FRK ) FORK CELL .IF DF L$$DRV&M$$MGE .WORD 0 ; ADDITIONAL WORD .ENDC $ACEND:: ;REF. LABEL .END