|
|
DataMuseum.dkPresents historical artifacts from the history of: Bogika Butler |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Bogika Butler Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 52096 (0xcb80)
Types: TextFile
Names: »UDC.SA«
└─⟦2322e079b⟧ Bits:30009789/_.ft.Ibm2.50006594.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »UDC.SA«
└─⟦311ba069f⟧ Bits:30009789/_.ft.Ibm2.50006625.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »UDC.SA«
└─⟦49237ce80⟧ Bits:30009789/_.ft.Ibm2.50006627.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »UDC.SA«
æ*****************************************************************
Copyright 1984 by
NCR Corporation
Dayton, Ohio U.S.A.
All Rights Reserved
******************************************************************
EOS Software produced by:
NCR Systems Engineering - Copenhagen
Copenhagen
DENMARK
*****************************************************************å
æ UUUU UUUU DDDDDDDDDD CCCCCCC
UUUU UUUU DDDDDDDDDDDD CCCCCCCCCCC
UUUU UUUU DDDD DDDD CCCCC CCCC
UUUU UUUU DDDD DDDD CCCC
UUUUU UUUUU DDDD DDDD CCCCC CCCC
UUUUUUUUUUU DDDDDDDDDDDD CCCCCCCCCCC
UUUUUUU DDDDDDDDDD CCCCCCC
U D C
I P C
M O D U L E
(DRIVER MODULE FOR MOTOROLA'S UDC CONTROLLER)
EOS Operating System
The UDC Ipc Module drives Motorola's Universal Disk Controller Module
through the Intelligent Peripheral Controller interface.
The module adheres to the EOS architectural standard for i/o-families.
The UDC object manages a number of driver objects. A driver object is an
access object which the UDC object creates on call to the Assign-entry.
The driver object is the 'access-path' to one of the devices (flexible
or hard disk) which are operated by the UDC controller. The controller
operates up to eight devices numbered 0 through 7.
The driver object (or Disk object) has Read- and Write-entries, and the
user may wait for a break-condition on the object.
In this version only one of possibly several Disk objects opened to the
same device may have the exclusive i/o-reservation.
Copyright NCR Corporation 1983
Written: April-May 1983
By: Peter Mikkelsen, SE-Copenhagen.
Change history:
===============
83-11-09/mik Bug in ReadSeq and ReadRandom if area to be read in middle of
segment.
83-12-05/ear re-translation with changed iosys.id
å
æ$Eå
æ
OVERVIEW OF THE MODULE'S TEXT: PAGE
==============================
Export description
Import description
Constants and types
Global routines:
å
OBJECT PROGRAM Udc;
const version='udc driver vers. 01.02 83-12-05';
æ$L-å
æOBS! old univfam and knelfam are included because old
dummy version of RefEqual is used in this program å
æ Updated to use SameEntity å
æ$F=FAMILY.UNIV.IDå
æ$F=FAMILY.KNEL.IDå
æ$F=FAMILY.ALLOC.IDå
æ$F=FAMILY.SCHED.IDå
æ$F=FAMILY.OBJDIR.IDå
const OrgSys=4001;
æ$F=PASINCLU.MIKTYPES.SAå
æ$F=FAMILY.IOSYS.IDå
æ$L+å
æ$Eå
æ***** E X P O R T D E S C R I P T I O N *****å
æ***********************************************å
(* removed 83-06-02
OBJECT Ipc;
CONST
minDevno=0; maxDevno=7;
TYPE
devnos=minDevno..maxDevno;
IoType=integer;
ENTRY Assign
(OUT driver: ref æLAO or DAOå;
IN iomode: IoType;
IN devName: fullId);
æ Creates a Line or Disc access object which acts a driver for the
specified device. The access object attempts to reserve the use
of the device as specified by 'iomode'å
PRIVATE Close ætermination procå
(IN driver: ref;
env: ref ækernel suppliedå);
æ Cancels the reservations held by the driver å
ENTRY ScanFiles
(OUT scanOwner: ref æScanå);
æ Not implemented in this demo-version å
ENTRY RenameFile; ærejectå
ENTRY CreateLink; ærejectå
ENTRY DeleteLink; ærejectå
ENTRY InitIpcSys
(IN vector,level: integer;
IN chanAddr: address);
æ Initializes the Ipc object with controller specific info å
ENTRY CreateFile
(IN devName: fullId;
IN devno: integer
æIN hwConfig, swConfig: integerå);
æ Ties a name to the device given by 'devno'. The configuration
parameters are used to configurate MCCM devices each time it
is Assign'ed (with ReadWrite) å
ENTRY DeleteFile
(IN devName: fullId);
æ Deletes a device description. Drivers open to the device are
abortedå
æ$Eå
OBJECT Disk; ære-entrantå
æ This object acts as an access-path to a disk.
Although several disk objects to the same device may exist, only
one of them is active at a time (the other objects reject all
calls), namely the one with the (exclusive) r-, w-, or rw-Reserv
iomode.
Concurrency rules: (demo-version)
All i/o calls are processed First-Come-First-Served. A process may
wait independently for break on the driver object with i/o-
reservation.
Break condition:
When a break condition occurs, all processes waiting in the driver
object are returned with a break status (except the WaitBreak
process which is returned with ok-status). Subsequent i/o
calls will be rejected with break status until WaitReady is
called and has returned.
Speed up of calls:
I/o calls: Normally not possible to speed up (at least not if the
i/o-operation has been sent to the ipc).
WaitBreak: May be speeded up without affecting any other calls.
å
TYPE
bufSpace=ARRAY Æ1..addrMaxÅ OF byte;
bufRef=^^ ÆÅ bufSpace;
BaseMode=integer;
CONST
FromStart=0; FromCurrent=1; FromEnd=2;
ENTRY ReadSeq
(IN segment: bufRef;
OUT byteCount: integer);
ENTRY WriteSeq
(IN segment: bufRef;
OUT byteCount: integer);
ENTRY ReadRandom
(IN segment: bufRef;
OUT byteCount: integer;
IN pos: integer;
OUT posUsed: integer
æhold: HoldModeå);
ENTRY WriteRandom
(IN segment: bufRef;
OUT byteCount: integer;
IN pos: integer;
OUT posUsed: integer);
ENTRY Seek
(IN base: BaseMode;
IN offset: integer;
OUT pos: integer);
ENTRY SetMode; æ not demo å
ENTRY GetFileInf
æ(OUT fsId: ref;
OUT localId: integer;
OUT class: devClass;
OUT descr: lineDescription); not demo å;
ENTRY SetRights; æ reject å
ENTRY CheckRights; æ not demo å
ENTRY MoveRights; æ not demo å æ necessary????? å
ENTRY NewLink; æ reject å
ENTRY AllocSize; æ reject å
ENTRY DataSize; æ reject å
ENTRY WaitBreak;
æ Waits for a break condition in the driver object. The called
driver object must have an i/o-reservation. At most one process may
wait in the entry independently of any concurrent i/o-calls
to the object å
ENTRY WaitReady;
æ Clears the break condition status of the device. Dummy if there
is no break condition on the device. The entry requires that
the object called holds an i/o-reservation å
END æDiskå;
CONST IoFamily=4;
CONST NoRights=0; ReadRight=1; WriteRight=2; ReadWrite=3;
æ***** ERROR CONSTANTS *****å
CONST
FileNotFound =3;
FileNameExists =4;
RightsOccupied =6;
PosOutsideRange =7;
PhysIoError =8;
AttentionPending =10;
ænon-standard error constantså
alreadyNamed=100; æCreate: devno is already namedå
alreadyWaiting=101; æWaitBreak: one process already waiting for breakå
END æIpcå;
******end remove 83-06-02 *)
CONST
ænon-standard error constantså
alreadyNamed=100; æCreate: devno is already namedå
alreadyWaiting=101; æWaitBreak: one process already waiting for breakå
minDevno=0; maxDevno=7;
TYPE
devnos=minDevno..maxDevno;
æ$Eå
æ***** C O N S T A N T S A N D T Y P E S *****å
æ*************************************************å
CONST
æ characters å
nul=0;
stx=2;
etx=3;
cr=13;
æ module constants å
maxIdLength=48; æ # significant characters of a fullId in this module å
kernelStack=100; æsupervisor stack on interrupt å
æ Ipc constants å
æpacket sizeså
rwSize=21;
haltSize=7;
æchannel commandså
readCom=16#10;
writeCom=16#20;
haltCom=16#50;
ædevice commandså
ipcFormatted=16#01;
ipcImage=16#02;
æstatus classeså
completion=16#70;
abortClass=16#71;
solicited=16#72;
unsolicited=16#80;
æstatus valueså
noErrors= 0; æcompletionå
notReady= 3; æcompletionå
invalidDiskAddr=6; æcompletionå
æ$Eå
æ***** Ipc Command and Status Packets *****å
TYPE
outHead=RECORD æ common header of command packets å
stx: byte;
packetId: byte;
size: byte;
devno: byte;
chanCom: byte;
devCom: byte; æ6 byteså
END;
inHead=RECORD æ common header of status packets å
stx: byte;
packetId: byte;
size: byte;
devno: byte;
chanCom: byte;
statusClass:byte;
status: word; æ8 byteså
END;
okind=(rwMess,verifyMess,haltMess,configMess);
outMess=RECORD
dummy: byte; æalignå
CASE kind: okind OF
rwMess: æ read/write å
(h0: outHead;
blocks0: word;
blkSize0: word;
DMAaddress: integer;
filler: word;
options: integer; æ or sector # å
etx0: byte);
verifyMess:
(h1: outHead; æ verify CRC, Format track etc. å
blocks1: word;
blkSize1: word;
sectorNo1: integer;
etx1: byte);
haltMess:
(h2: outHead; æ clear fault, format disk, halt, ready å
etx2: byte);
configMess:
(h3: outHead; æ configure å
hwConfig: integer;
swConfig: integer;
etx3: byte);
END;
iKind=(okAnsw,notReAnsw,crcAnsw,udcStAnsw,mccmStAnsw);
inMess=RECORD æ status packet å
dummy: byte; æalignå
CASE kind: iKind OF
okAnsw:
(h0: inHead; æ UDC: no error (i/o) å
blocks: word; æ MCCM: no error, parity, break å
blockSize: word;
DMAaddress: address;
filler: word;
etx0: byte);
notReAnsw:
(h1: inHead; æ device not ready etc. å
etx1: byte);
crcAnsw:
(h2: inHead; æ UDC CRC-error å
blockNo: integer;
etx2: byte);
udcStAnsw:
(h3: inHead; æ UDC device status (unsolicited) å
noLogBlock: integer;
etx3: byte);
mccmStAnsw:
(h4: inHead; æ MCCM device status (solicited and å
devStat: integer;
hwConfig: integer;
swConfig: integer;
etx4: byte);
END;
requestState=(ipcNotStarted,ipcStarted,ipcAnswered);
ipcRequest=RECORD
æ output message = command packet å
o: outMess;
i: inMess;
state: requestState;
END;
æ$Eå
æ***** Ipc object *****å
TYPE
maxFullId=ARRAY Æ1..maxIdLengthÅ OF char;
countRec=RECORD
transfers, æ# i/o-transfers started in the driver å
repeats, æ# reated i/o-transferså
q1, æ# req's received when one other request occupies driverå
q2, æ# req's received when two other requests occupies driverå
q3: integer; æ# req's received when three other requests occupies driverå
END;
ipcData=RECORD
break: ARRAY ÆdevnosÅ OF boolean; æ break conditions å
ipcReserved: integer; æ # processes waiting in ipc object å
ackFifo: ARRAY ÆdevnosÅ OF devnos; æ fifo of requests waiting å
ackFifoFirst, æ for the use of the ipc- å
ackFifoLast: devnos; æ channel. å
chanAddr: address; æabsolute address of channel registerså
requests: ARRAY ÆdevnosÅ OF ipcRequest;
vector, æ interrupt vector å
level: byte; æ interrupt level å
dir: ARRAY ÆdevnosÅ OF RECORD æ directory å
name: maxFullId;
nameLength: 0..maxIdLength;
hwConfig,
swConfig: integer
END;
count: ARRAY ÆdevnosÅ OF countRec;
END;
drivLocRef=^^drivLocals;
ipcLocRef=^^ipcLocals;
ipcLocals=RECORD æ local pointers in Ipc object å
code: ^^;
ownLocaldata: ^^ipcData; æcreated by Stubå
localdata: ^^ipcData; æcopy of ownLocaldata to become residentå
currDriver: ARRAY ÆdevnosÅ OF drivLocRef; æenvelope ptr's to drivers
with i/o-reservationå
stubRef: ^^ObjDir; æinserted by the Stubå
iSchedRef: ^^Scheduler; æinserted by the Stubå
schedRef: ^^Scheduler; æinserted by the Stubå
allocRef: ^^Allocate; æinserted by the Stubå
egoEnv: ipcLocRef; æinserted by the Stubå
interruptPtr: ^^; ækernel's interrupt pointerå
ipcGate: gateRef;
dirGate: gateRef; æprotects the 'dir'-datastructure, the 'drivers'
manager set, and the reservation status per deviceå
drivers: ARRAY ÆdevnosÅ OF drivLocRef; æmanager set of driver obj'så
ownSet: ^^; æowner set for ipcGate, complete cond's, and breakCond
cond'så
END;
æ$Eå
æ***** Driver object types *****å
drivData=RECORD æ local data in Driver object å
devno: devnos;
reserv: IoType;
mode: RECORD
timeout: integer;
options: integer
æretries, verify etc?å
END;
devReserved: integer;
waitBreak: boolean;
waitEmpty: boolean;
count: countRec;
currPos: integer; ænext byte to be transferredå
discSize: integer;
cylSize: integer;
blockSize: integer;
END;
drivLocals=RECORD
code: ^^;
localdata: ^^drivData;
ipc: ipcLocRef; æto managerå
complete: condRef;
breakCond: condRef;
schedQ: condRef; æFCFS queueå
empty: condRef; æsignalled when no processes wait for i/o in objå
ownSet: ^^; æowner set for 'complete' and 'breakCond'å
normalGate: ^^Gate; æsynchronizes buffering associated with i/oå
END;
æ$Eå
æ***** E X T E R N A L P R O C E D U R E S *****å
æ*************************************************å
PROCEDURE startIpc
(vector: byte;
devno: devnos);
FORWARD;
PROCEDURE intudc;
FORWARD;
function byteaddr(univ var x: byte): integer; forward;
æ$Eå
æ***** G L O B A L P R O C E D U R E S *****å
æ*********************************************å
æ----- AckFifo Routines -----å
æ The following routines operate on the AckFifo datastructure. The
AckFifo is a FIFO-type queue for ipcRequests waiting for access to
the channel.
putAckFifo: insert request at the end of the fifo queue
getAckFifo: get next request in queue
removeAckFifo: remove a specific request from the queue.
The number of requests waiting in the AckFifo queue is indicated by
'ipcReserved' (namely one less than this figure).
The AckFifo datastructure is dimensioned so that overflow never
occurs (there is room for one request per device).
å
PROCEDURE putAckFifo
(devno: devnos;
VAR c: ipcData);
BEGIN
c.ackFifoLast:=(c.ackFifoLast+1) MOD (maxDevno+1);
c.ackFifoÆc.ackFifoLastÅ:=devno;
END æ***putAckFifo***å;
(* implemented in interrupt procedure
FUNCTION getAckFifo
(VAR c: ipcData)
: devnos;
BEGIN
getAckFifo:=c.ackFifoÆc.ackFifoFirstÅ;
c.ackFifoFirst:=(c.ackFifoFirst+1) MOD (maxDevno+1);
END æ***getAckFifo***å;
*)
(* removed 83-04-25
PROCEDURE removeAckFifo
(devno: devnos;
VAR c: ipcData);
VAR i: devnos;
BEGIN
æassert: c.ipcReserved>0å
i:=c.ackFifoFirst;
WHILE c.ackFifoÆiÅ<>devno AND i<>c.ackFifoLast DO
i:=(i+1) MOD (maxDevno+1);
END;
IF c.ackFifoÆiÅ<>devno THEN exception(systemError);
WHILE i<>c.ackFifoLast DO BEGIN
c.ackFifoÆiÅ:=c.ackFifoÆ(i+1) MOD (maxDevno+1)Å;
i:=(i+1) MOD (maxDevno+1);
END;
c.ackFifoLast:=(c.ackFifoLast+maxDevno) MOD (maxDevno+1);
æi.e. decrease ackFifoLastå
END æ***removeAckFifo***å;
end 83-04-25 *)
æ$Eå
PROCEDURE sendReq
(VAR complete: condRef;
VAR req: ipcRequest;
devno: devnos;
VAR c: ipcData);
VAR ignore: ResultType;
BEGIN
c.requestsÆdevnoÅ:=req;
c.requestsÆdevnoÅ.state:=ipcNotStarted;
c.ipcReserved:=c.ipcReserved+1;
IF c.ipcReserved>1 THEN putAckFifo(devno,c)
ELSE startIpc(c.vector,devno);
ignore:=complete.Wait;
req.i:=c.requestsÆdevnoÅ.i; æreturn answerå
END æ***sendReq***å;
æ$Eå
æ***** D I S K O B J E C T I M P L E M E N T A T I O N *****å
æ***************************************************************å
PROGRAM diskImplement OBJECT Fao WITH drivLocals;
æ***** LOCAL ROUTINES *****å
FUNCTION objStatus
(VAR d: drivData;
VAR c: ipcData;
reserv: IoType)
: resultType;
BEGIN
IF NOT ((reserv=NoRights) OR
(d.reserv=ReadWrite) OR
(d.reserv=reserv)) THEN
objStatus:=genRes(-EntryIllegal,Universal,0)
ELSE IF c.breakÆd.devnoÅ THEN
objStatus:=genRes(-BreakPending,IoFamily,0);
END æ***objStatus***å;
æ$Eå
æ----- doIo -----å
æ Function doIo is the central routine controlling the synchronization and
sceduling of i/o requests from the driver object. Although it is textually
placed here in the driver object, it logically belongs to both the driver
and ipc objects å
FUNCTION doIo
(VAR buf: ref;
base: integer; æbase of data in bufå
VAR req: ipcRequest;
reserv: IoType;
VAR d: drivData)
: resultType;
VAR
i: integer;
use: IoType;
res: ResultType;
BEGIN
res.main:=ok;
req.o.kind:=rwMess; æread/write kindå
IN
CASE reserv OF
ReadRight: use:=WriteRight;
WriteRight: use:=ReadRight;
OTHERWISE use:=reserv;
END;
check(ipc^^.ipcGate.Resident(buf; use));
WITH c=ipc^^.localdata^^ DO BEGIN
check(ipc^^.ipcGate.Lock);
IN ægate lockedå
check(objStatus(d,c,reserv));
d.devReserved:=d.devReserved+1;
d.count.transfers:=d.count.transfers+1;
IN æd.devReserved increasedå
IF d.devReserved>1 THEN BEGIN
æprintVar('.....doIo scheduling queue..... devReserved= ',d.devReserved);å
æupdate countRecå
WITH d.count DO BEGIN
IF d.devReserved=2 THEN q1:=q1+1
ELSE IF d.devReserved=3 THEN q2:=q2+1
ELSE q3:=q3+1;
END;
æ check(Propagate(propReject)); kernel-error å
check(schedQ.Wait); æmay be speeded upå
æ check(Propagate(propNone)); kernel-error å
check(objStatus(d,c,reserv));
END;
æ do i/o å
check(IoBegin(buf,req.o.DMAaddress,i,i));
IF req.o.DMAaddress MOD 2 = 0 THEN BEGIN
req.o.DMAaddress:=req.o.DMAaddress+base; æstart of text in bufå
sendReq(complete,req,d.devno,c); æsend request to ipcå
END ELSE BEGIN
res:=genRes(-DataValueIllegal,Universal,3);
END;
check(IoEnd(buf,i,i,i));
IF NOT ((req.i.h0.statusClass=completion) AND
(req.i.h0.status=ok)) THEN
IF ((req.i.h0.statusClass=completion) AND
(req.i.h0.status=invalidDiskAddr)) THEN
exception(genRes(ok,0,0)) æeofå
ELSE IF ((req.i.h0.statusClass=completion) AND
(req.i.h0.status=notReady)) THEN BEGIN
c.breakÆd.devnoÅ:=true;
exception(genRes(BreakPending,IoFamily,0));
END ELSE
exception(genRes(PhysIoError,IoFamily,0));
æupdate driver positionå
d.currPos:=
(req.o.options æstart sector #å + req.i.blocks)*req.i.blockSize;
DO IF res.main=ok THEN res:=getException;
d.devReserved:=d.devReserved-1;
IF d.devReserved>0 THEN
check(schedQ.Signal) æstart next in queue to this deviceå
ELSE IF d.waitEmpty THEN BEGIN
d.waitEmpty:=false;
check(empty.Signal);
END;
DO IF res.main=ok THEN res:=getException;
check(ipc^^.ipcGate.Open);
END æwithå;
DO IF res.main=ok THEN res:=getException;
doIo:=res;
END æ***doIo***å;
æ$Eå
FUNCTION transfer
(VAR buf: bufRef;
bLength: integer;
VAR byteCount: integer;
direction: integer;
VAR pos: integer;
VAR d: drivData)
: ResultType;
VAR res: ResultType;
req: ipcRequest;
reserv: IoType;
BEGIN
res.main:=ok;
IN
IF pos MOD d.blockSize <> 0 THEN
exception(genRes(-DataValueIllegal,IoFamily,-3));
IF bLength < d.blockSize THEN
exception(genRes(-DataValueIllegal,Universal,4));
æ set up read request å
req.o.kind:=rwMess; æread/writeå
req.o.h0.stx:= stx;
req.o.h0.packetId:= 0;
req.o.h0.size:= rwSize;
req.o.h0.devno:= d.devno;
req.o.h0.chanCom:= direction;
CASE direction OF
readCom: req.o.h0.devCom:=ipcFormatted;
writeCom: req.o.h0.devCom:=ipcImage;
END;
req.o.blocks0:= bLength DIV d.blockSize;
req.o.blkSize0:= d.blockSize;
req.o.options:= pos DIV d.blockSize æround downå;
pos:=req.o.options*d.blockSize æactual pos usedå;
req.o.etx0:= etx;
if direction=readCom then reserv:=ReadRight else reserv:=WriteRight;
res:=doIo(buf,0,req,reserv,d);
byteCount:=req.i.blocks*d.blockSize;
DO IF res.main=ok THEN res:=getException;
transfer:=res;
END æ***transfer***å;
æ$Eå
ENTRY ReadSeq
æIN segment: bufRef; OUT byteCount: integerå
WITH RECORD
t: ^^;
buf: bufRef;
blockBuf: bufRef;
superBuf: bufRef;
END;
VAR
res: ResultType;
i,ioPos,pos,bufAddr,bufSize,sbufSize,sbufRel:integer;
bCount:integer;
head,tail:integer;
BEGIN
res.main:=ok;
in
check(normalGate.Lock);
byteCount:=0;
with b=segment^^ do begin
bufSize:= elements(b);
bufAddr:=byteAddr(bÆ1Å);
end ;
with d=localdata^^ do begin
pos:=d.currPos;
sbufRel:= pos mod d.blockSize;
head:=(d.blockSize-sbufRel) mod d.blockSize;
æbug 83-11-09/mikå
if head>=bufSize then tail:=0
else tail:=(pos+bufSize)mod d.blockSize;
æ#begin#
printVar('83-10-21: readseq, head= ',head);
printVar('83-10-21: readseq, tail= ',tail);
printVar('83-10-21: readseq, sbufRel= ',sbufRel);
printVar('83-10-21: readseq, bufSize= ',bufSize);
printVar('83-10-21: readseq, bufAddr= ',bufAddr);
#end#å
if ( ( bufAddr mod 2 = 0 æ buffer address even å ) and
( bufSize mod d.blockSize = 0 æ integral # blocks å ) and
( sbufRel = 0 æ integral block position å ) ) then begin
check(Copy(segment,buf)); æfor recidencyå
exception(transfer(buf,bufSize,byteCount,readCom,pos,d));
end ;
if (head>0) or (tail>0) then begin
check(newSeg(blockBuf,d.blockSize));
end;
if head>0 then begin
check(Copy(blockBuf,buf));
ioPos:= pos - sbufRel;
check(transfer(buf,d.blockSize,bCount,readCom,ioPos,d));
æ#begin#
printVar('83-10-21 readseq, after transfer/head, byteCount= ',bCount);
#end#å
if bCount > sbufRel+bufSize then bCount:=bufSize else
if bCount < sbufRel then bCount:= 0 else
bCount:=bCount-sbufRel;
end else bCount:=0;
byteCount:=byteCount+bCount;
end ; æ with då
with b=segment^^ , sb=blockBuf^^ do
for i:= 1 to bCount do
bÆiÅ:= sbÆi+sbufRelÅ ;
if bufSize-head-tail>0 then begin
with d=localdata^^ do begin
iopos:=pos+head;
æ#begin#
printVar('83-10-21 readseq: before NewSub ',i);
#end#å
with b=segment^^ do
check(NewSub(superBuf,var out bÆhead+1..(elements(b)-tail)Å));
æ#begin#
printVar('83-10-21 readseq: after NewSub ',i);
#end#å
check(Copy(superBuf,buf));
check(transfer(buf,bufSize-head-tail,bCount,readCom,ioPos,d));
æ#begin#
printVar('83-10-21 readseq: after transfer body: bytecount=',bCount);
#end#å
byteCount:=byteCount+bCount;
end;
end;
if tail>0 then begin
check(Copy(blockBuf,buf));
with d=localdata^^ do begin
iopos:=(pos+bufSize) div d.blockSize * d.blockSize;
check(transfer(buf,d.blockSize,bCount,readCom,ioPos,d));
æ#begin#
printVar('83-10-21 readseq: after transfer tail, bytecount= ',bCount);
#end#å
if bCount>tail then bCount:=tail;
byteCount:=byteCount+bCount;
end æwithå;
with b=segment^^ , sb=blockBuf^^ do
for i:= 1 to bCount do
bÆbufSize-tail+iÅ:=sbÆiÅ;
end;
do begin
res:=getException;
end ;
æ#begin#
printVar('83-10-21 readseq: return, bytecount= ',byteCount);
if byteCount>3000 then
with b=segment^^ do begin
printVar('83-10-25 readseq: segmÆ1..100Å= ',bÆ1..100Å);
printVar('83-10-25 readseq: segmÆbufsize-99..bufsizeÅ= ',
bÆelements(b)-99..elements(b)Å);
end;
#end#å
check(normalGate.Open);
ObjReturn(res);
END æ***ReadSeq***å;
ENTRY WriteSeq
æIN segment: bufRef; OUT byteCount: integerå
WITH RECORD
t: ^^;
buf: bufRef;
superBuf: bufRef;
END;
VAR bLength,
res: resultType;
i,ioPos,pos,bufAddr,bufSize,sbufSize,sbufRel,writeCount: integer;
BEGIN
in
check(normalGate.Lock);
with b=segment^^ do begin
bufSize:= elements(b);
bufAddr:= byteAddr(bÆ1Å);
end ;
with d=localdata^^ do begin
pos:=d.currPos;
sbufRel:= pos mod d.blocksize;
if ( ( bufAddr mod 2 = 0 æ buffer address even å ) and
( bufSize mod d.blockSize = 0 æ integral # blocks å ) and
( sbufRel = 0 æ integral block position å ) ) then begin
check(copy(segment,buf)); æfor residencyå
exception(transfer(buf,bufSize,byteCount,writeCom,pos,d));
end ;
ioPos:= pos - sbufRel;
sbufSize:=(bufSize+sbufRel+d.blockSize) div d.blockSize * d.blockSize;
check(newseg(superBuf,sbufSize));
check(copy(superBuf,buf)); æfor residencyå
check(transfer(buf,sbufSize,byteCount,readCom,ioPos,d));
writeCount:=byteCount;
if byteCount > sbufRel+bufSize then byteCount:= bufSize else
if byteCount < sbufRel then byteCount:= 0 else
byteCount:= byteCount-sbufRel;
end ; æwith då
with b=segment^^ , sb=superBuf^^ do
for i:= 1 to byteCount do
sbÆi+sbufRelÅ:= bÆiÅ;
if byteCount > 0 then begin
with d=localdata^^ do begin
res:=transfer(buf,writeCount,byteCount,writeCom,ioPos,d);
if byteCount > sbufRel+bufSize then byteCount:=bufSize else
if byteCount < sbufRel then byteCount:= 0 else
byteCount:= byteCount-sbufRel;
end ; æwith då
end ;
do begin
res:= getException;
end ;
check(normalGate.Open);
ObjReturn(res);
END æ***WriteSeq***å;
æ$Eå
ENTRY ReadRandom
æIN segment:bufRef;OUT byteCount:integer;pos:integer;OUT actualPos:integerå
WITH RECORD
t: ^^;
buf: bufRef;
blockBuf: bufRef;
superBuf: bufRef;
END;
VAR
res: ResultType;
i,ioPos,bufAddr,bufSize,sbufSize,sbufRel:integer;
bCount:integer;
head,tail:integer;
BEGIN
res.main:=ok;
in
check(normalGate.Lock);
byteCount:=0;
with b=segment^^ do begin
bufSize:= elements(b);
bufAddr:=byteAddr(bÆ1Å);
end ;
with d=localdata^^ do begin
sbufRel:= pos mod d.blockSize;
head:=(d.blockSize-sbufRel) mod d.blockSize;
æbug 83-11-09/mikå
if head>=bufSize then tail:=0
else tail:=(pos+bufSize)mod d.blockSize;
æ#begin#
printVar('83-10-21: ReadRand, head= ',head);
printVar('83-10-21: ReadRand, tail= ',tail);
printVar('83-10-21: ReadRand, bufSize= ',bufSize);
printVar('83-10-21: ReadRand, bufAddr= ',bufAddr);
#end#å
if ( ( bufAddr mod 2 = 0 æ buffer address even å ) and
( bufSize mod d.blockSize = 0 æ integral # blocks å ) and
( sbufRel = 0 æ integral block position å ) ) then begin
check(Copy(segment,buf)); æfor recidencyå
exception(transfer(buf,bufSize,byteCount,readCom,pos,d));
end ;
if (head>0) or (tail>0) then begin
check(newSeg(blockBuf,d.blockSize));
end;
if head>0 then begin
check(Copy(blockBuf,buf));
ioPos:= pos - sbufRel;
check(transfer(buf,d.blockSize,bCount,readCom,ioPos,d));
æ#begin#
printVar('83-10-21 ReadRand, after transfer/head, byteCount= ',bCount);
#end#å
if bCount > sbufRel+bufSize then bCount:=bufSize else
if bCount < sbufRel then bCount:= 0 else
bCount:=bCount-sbufRel;
end else bCount:=0;
byteCount:=byteCount+bCount;
end ; æ with då
with b=segment^^ , sb=blockBuf^^ do
for i:= 1 to bCount do
bÆiÅ:= sbÆi+sbufRelÅ ;
if bufSize-head-tail>0 then begin
with d=localdata^^ do begin
iopos:=pos+head;
with b=segment^^ do
check(NewSub(superBuf,var out bÆhead+1..(elements(b)-tail)Å));
check(Copy(superBuf,buf));
check(transfer(buf,bufSize-head-tail,bCount,readCom,ioPos,d));
æ#begin#
printVar('83-10-21 ReadRand: after transfer body: bytecount=',bCount);
#end#å
byteCount:=byteCount+bCount;
end;
end;
if tail>0 then begin
check(Copy(blockBuf,buf));
with d=localdata^^ do begin
iopos:=(pos+bufSize) div d.blockSize * d.blockSize;
check(transfer(buf,d.blockSize,bCount,readCom,ioPos,d));
æ#begin#
printVar('83-10-21 ReadRand: after transfer tail, bytecount= ',bCount);
#end#å
if bCount>tail then bCount:=tail;
byteCount:=byteCount+bCount;
end æwithå;
with b=segment^^ , sb=blockBuf^^ do
for i:= 1 to bCount do
bÆbufSize-tail+iÅ:=sbÆiÅ;
end;
do begin
res:=getException;
end ;
actualPos:=pos;
æ#begin#
printVar('83-10-21 ReadRand: return, bytecount= ',byteCount);
if byteCount>3000 then
with b=segment^^ do begin
printVar('83-10-25 readrand: segmÆ1..100Å= ',bÆ1..100Å);
printVar('83-10-25 readrand: segmÆbufsize-99..bufsizeÅ= ',
bÆelements(b)-99..elements(b)Å);
end;
#end#å
check(normalGate.Open);
ObjReturn(res);
END æ***ReadRandom***å;
æ$Eå
ENTRY WriteRandom
æIN segment:bufRef;OUT byteCount:integer;pos:integer;OUT actualPos:integerå
WITH RECORD t: ^^; buf: bufRef; superBuf: bufRef; END;
VAR res: ResultType;
i, ioPos, bufAddr, bufSize, sbufSize, sbufRel, writeCount: integer;
BEGIN
in
check(normalGate.Lock);
with b=segment^^ do begin
bufSize:= elements(b);
bufAddr:= byteAddr(bÆ1Å);
end ;
with d=localdata^^ do begin
sbufRel:= pos mod d.blocksize;
if ( ( bufAddr mod 2 = 0 æ buffer address even å ) and
( bufSize mod d.blockSize = 0 æ integral # blocks å ) and
( sbufRel = 0 æ integral block position å ) ) then begin
check(copy(segment,buf)); æfor residencyå
exception(transfer(buf,bufSize,byteCount,writeCom,pos,d));
end ;
ioPos:= pos - sbufRel;
sbufSize:=(bufSize+sbufRel+d.blockSize) div d.blockSize * d.blockSize;
check(newseg(superBuf,sbufSize));
check(copy(superBuf,buf)); æfor residencyå
check(transfer(buf,sbufSize,byteCount,readCom,ioPos,d));
writeCount:=byteCount;
if byteCount > sbufRel+bufSize then byteCount:= bufSize else
if byteCount < sbufRel then byteCount:= 0 else
byteCount:= byteCount-sbufRel;
end ; æwith då
with b=segment^^ , sb=superBuf^^ do
for i:= 1 to byteCount do
sbÆi+sbufRelÅ:= bÆiÅ;
if byteCount > 0 then begin
with d=localdata^^ do begin
res:=transfer(buf,writeCount,byteCount,writeCom,ioPos,d);
if byteCount > sbufRel+bufSize then byteCount:=bufSize else
if byteCount < sbufRel then byteCount:= 0 else
byteCount:= byteCount-sbufRel;
end ; æwith då
end ;
do begin
res:= getException;
end ;
check(normalGate.Open);
actualPos:=pos;
ObjReturn(res);
END æ***WriteRandom***å;
æ$Eå
ENTRY Seek
æbaseMode: BaseType; offset: integer; OUT pos: integerå
WITH RECORD t: ^^; END;
VAR res: ResultType;
BEGIN
res.main:=ok;
WITH d=localdata^^, c=ipc^^.localdata^^ DO BEGIN
check(ipc^^.ipcGate.Lock);
IN ægate lockedå
æenter scheduling queueå
d.devReserved:=d.devReserved+1;
IF d.devReserved>1 THEN BEGIN
æprintVar('... seek, schedQ ... devReserved= ',d.devReserved);å
æ check(Propagate(propReject)); kernel-errorå
check(schedQ.Wait); æcan be speeded up without harmå
æ check(Propagate(propNone)); kernel-errorå
END;
IF d.reserv=NoRights THEN
exception(genRes(-EntryIllegal,Universal,0));
IF c.breakÆd.devnoÅ THEN
exception(genRes(-BreakPending,IoFamily,0));
CASE baseMode OF
FromStart: pos:=offset;
FromCurrent: pos:=d.currPos+offset;
FromEnd: exception(genRes(-DataValueIllegal,Universal,-1));
END;
IF pos<0 THEN res:=genRes(-PosOutsideRange,IoFamily,-3)
ELSE d.currPos:=pos;
d.devReserved:=d.devReserved-1;
IF d.devReserved>0 THEN check(schedQ.Signal)
ELSE IF d.waitEmpty THEN BEGIN
d.waitEmpty:=false;
check(Empty.Signal);
END;
DO IF res.main=ok THEN res:=getException;
check(ipc^^.ipcGate.Open);
END æwithå;
ObjReturn(res);
END æ***Seek***å;
æ$Eå
ENTRY SetRights
WITH RECORD t: ^^; END;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY CheckRights
WITH RECORD t: ^^; END;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY MoveRights
WITH RECORD t: ^^; END;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY NewLink
WITH RECORD t: ^^; END;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY GetFileInf
WITH RECORD t: ^^; END;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY SetMode
WITH RECORD t: ^^; END;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY DataSize WITH tempRefs;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY AllocSize WITH tempRefs;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
æ$Eå
ENTRY WaitBreak
WITH RECORD t: ^^; END;
VAR res: resultType;
BEGIN
res.main:=ok;
WITH d=localdata^^, c=ipc^^.localdata^^ DO BEGIN
IN
check(ipc^^.ipcGate.Lock);
IN æipcGate lockedå
IF d.waitBreak THEN exception(genRes(-alreadyWaiting,IoFamily,0));
IF d.reserv=NoRights THEN exception(genRes(-EntryIllegal,Universal,0));
IF NOT c.breakÆd.devnoÅ THEN BEGIN
d.waitBreak:=true;
æ check(Propagate(propReject)); kernel-errorå
res:=breakCond.Wait;
æ check(Propagate(propNone));å
d.waitBreak:=false;
END;
DO IF res.main=ok THEN res:=getException;
check(ipc^^.ipcGate.Open);
DO IF res.main=ok THEN res:=getException;
END æwithå;
ObjReturn(res);
END æ***WaitBreak***å;
ENTRY WaitReady
WITH RECORD t: ^^; END;
VAR res:resultType;
BEGIN
res.main:=ok;
WITH d=localdata^^, c=ipc^^.localdata^^ DO BEGIN
check(ipc^^.ipcGate.Lock);
IN
IF d.reserv=NoRights THEN
exception(genRes(-EntryIllegal,Universal,0));
IF c.breakÆd.devnoÅ THEN BEGIN
IF d.devReserved>0 THEN BEGIN
æThis code should actually never be executed because of the
kernel's scheduling strategy for gates and conditionså
d.waitEmpty:=true; check(empty.Wait);
check(empty.signal); æif more processes are waitingå
END;
c.breakÆd.devnoÅ:=false;
END;
DO IF res.main=ok THEN res:=getException;
check(ipc^^.ipcGate.Open);
END æwithå;
ObjReturn(res);
END æ***WaitReady***å;
ENTRY Dup
with record t:^^; end;
begin
exception(genRes(-EntryIllegal,Universal,2));
end;
OTHERWISE DiskOther
WITH RECORD t: ^^; END;
BEGIN
exception(genRes(-EntryIllegal,Universal,2));
END æ***OtherFunc***å;
END æ lineImplement å;
æ$Eå
æ***** I P C O B J E C T I M P L E M E N T A T I O N *****å
æ*************************************************************å
PROGRAM udcImplement OBJECT IoSys WITH ipcLocals;
PRIVATE Close
(driver,env: ref ækernel suppliedå);
æ***** LOCAL ROUTINES *****å
FUNCTION same
(dirIndex: integer;
id: fullId;
VAR d: ipcData)
: boolean;
æcompares the two fullid'så
VAR i, length: integer;
stop: boolean;
BEGIN
length:=d.dirÆdirIndexÅ.nameLength;
stop:=length<>elements(id);
i:=1;
WHILE (i<=length) AND NOT stop DO BEGIN
stop:=d.dirÆdirIndexÅ.nameÆiÅ<>idÆiÅ;
i:=i+1;
END;
same:=NOT stop;
END æ***same***å;
FUNCTION search
(id: fullId;
VAR d: ipcData)
: devnos;
VAR i: integer;
found: boolean;
BEGIN
i:=minDevno;
found:=false;
WHILE (i<=maxDevno) AND NOT found DO BEGIN
found:=same(i,id,d);
IF NOT found THEN i:=i+1;
END;
IF NOT found THEN
exception(genRes(-FileNotFound,IoFamily,-1));
search:=i;
END æ***search***å;
æ$Eå
æ***** ENTRIES *****************************************å
æ*******************************************************å
ENTRY InitIpcSys
æIN vector, level: integer; IN chanAddr: addresså
WITH RECORD
t: ^^;
tempOwn:^^;
END;
VAR intprocAddr: address;
i: integer;
res: resultType;
BEGIN
printText(version);
res.main:=ok;
æcreate dirGateå
check(schedRef.NewGate(OUT dirGate));
æcreate ipcGateå
check(iSchedRef.NewGate(OUT tempOwn;level));
check(Copy(tempOwn,ipcGate));
check(MoveOwn(tempOwn,ownSet));
check(ipcGate.Resident(ipcGate));
æcreate interrupt ptrå
check(iSchedRef.NewChannel(OUT interruptPtr, IN code;
vector,level,kernelStack,addr(intudc)));
æis it necessary to make code segment resident?????å
æmake localdata residentå
check(Copy(ownLocalData,localdata));
check(ipcGate.Resident(localdata));
æinitialize localdataå
WITH d=localdata^^ DO BEGIN
d.chanAddr:=chanAddr;
d.vector:=vector;
d.level:=level;
FOR i:=minDevno TO maxDevno DO BEGIN
d.dirÆiÅ.nameLength:=0;
WITH d.countÆiÅ DO BEGIN
transfers:=0; repeats:=0;
q1:=0; q2:=0; q3:=0;
END;
END;
d.ipcReserved:=0;
d.ackFifoFirst:=minDevno+1; d.ackFifoLast:=minDevno;
END;
check(MakeReentrant(egoEnv));
ObjReturn(res);
END æ***ENTRY Init***å;
æ$Eå
ENTRY CreateFile
ædevName: fullId; devno: devnos (hwConfig, swConfig: integer)å
WITH RECORD
t:^^;
END;
VAR intPtr: ^integer;
i,length: integer;
res: resultType;
BEGIN
res.main:=ok;
check(dirGate.Lock);
IN ædirGate lockedå
IF NOT ((devno>=0) AND (devno<=7)) THEN
exception(genRes(-DataValueIllegal,Universal,-2));
WITH d=localdata^^ DO BEGIN
IF d.dirÆdevnoÅ.nameLength<>0 THEN
exception(genRes(-alreadyNamed,IoFamily,-2));
FOR i:=minDevno TO maxDevno DO
IF same(i,devName,d) THEN
exception(genRes(-FileNameExists,IoFamily,-1));
length:=elements(devName);
IF length>maxIdLength THEN length:=maxIdLength;
WITH d.dirÆdevnoÅ DO BEGIN
FOR i:=1 TO length DO nameÆiÅ:=devNameÆiÅ;
nameLength:=length;
END æwithå;
END æwithå;
DO res:=getException;
check(dirGate.Open);
ObjReturn(res);
END æ***ENTRY Create***å;
æ$Eå
ENTRY DeleteFile
ædevName: fullIdå
WITH RECORD
t:^^;
refDriver: ^^;
END;
VAR devno: devnos;
stop,
res: resultType;
BEGIN
res.main:=ok;
check(dirGate.Lock);
IN ædirGate lockedå
WITH d=localdata^^ DO BEGIN
devno:=search(devName,d);
IF NOT ((devno>=0) AND (devno<=7)) THEN
exception(genRes(-DataValueIllegal,Universal,-2));
d.dirÆdevnoÅ.nameLength:=0;
æabort any drivers open to the deviceå
stop:=FirstInSet(driversÆdevnoÅ,refDriver);
WHILE stop.main=ok DO BEGIN
check(Abort(refDriver));
stop:=NextInSet(driversÆdevnoÅ,refDriver);
END;
END æwithå;
DO IF res.main=ok THEN res:=getException;
check(dirGate.Open);
ObjReturn(res);
END æ***ENTRY Delete***å;
æ$Eå
ENTRY Assign
æOUT ownedFao: ref; IN fileName: fullId; ioRights: IoTypeå
WITH RECORD
t:^^;
tempMan: ^^drivLocals;
tempEnv: ^^drivLocals;
END;
VAR s: sizeType;
res, ignore: resultType;
i: integer;
devno: devnos;
req: ipcRequest;
BEGIN
res.main:=ok;
æcreate access objectå
check(ClearSize(s));
check(AddEnv(s,refs(drivLocals))); check(AddSeg(s,bytes(drivData)));
check(allocRef.NewObj(OUT ownedFao; makeSize(2000,500), OUT i));
check(ClearSize(s));
check(DeclGen(ownedFao,tempMan,tempEnv,refs(drivLocals),Close,s,s,
refs(diskImplement),bytes(diskImplement),0,
addr(diskImplement),s,true));
IN æenvelope createdå
check(Copy(code,tempMan^^.code));
check(Copy(egoEnv,tempMan^^.ipc));
check(ipcGate.Resident(tempMan^^.ipc));
check(schedRef.NewGate(OUT tempMan^^.normalGate));
æcomplete condå
check(ipcGate.NewCond(OUT tempMan^^.ownSet));
check(Copy(tempMan^^.ownSet,tempMan^^.complete));
IF ioRights<>NoRights THEN
check(ipcGate.Resident(tempMan^^.complete));
æbreakCondå
check(ipcGate.NewCond(OUT tempMan^^.ownSet));
check(Copy(tempMan^^.ownSet,tempMan^^.breakCond));
IF ioRights<>NoRights THEN
check(ipcGate.Resident(tempMan^^.breakCond));
æschedQå
check(ipcGate.NewCond(OUT tempMan^^.ownSet));
check(Copy(tempMan^^.ownSet,tempMan^^.schedQ));
IF ioRights<>NoRights THEN
check(ipcGate.Resident(tempMan^^.schedQ));
æemptyå
check(ipcGate.NewCond(OUT tempMan^^.ownSet));
check(Copy(tempMan^^.ownSet,tempMan^^.empty));
IF ioRights<>NoRights THEN
check(ipcGate.Resident(tempMan^^.empty));
ælocaldataå
check(NewSeg(tempMan^^.ownSet,bytes(drivData)));
check(Copy(tempMan^^.ownSet,tempMan^^.localdata));
IF ioRights<>NoRights THEN
check(ipcGate.Resident(tempMan^^.localdata));
check(dirGate.Lock);
IN ædirGate lockedå
WITH d=localdata^^ DO BEGIN
devno:=search(fileName,d);
WITH c=tempMan^^.localdata^^ DO BEGIN
c.devno:=devno;
c.reserv:=ioRights;
æc.mode.timeout:=?;å
c.devReserved:=0;
c.waitBreak:=false;
c.waitEmpty:=false;
c.currPos:=0;
c.blockSize:=256;
WITH c.count DO BEGIN
transfers:=0; repeats:=0;
q1:=0; q2:=0; q3:=0;
END;
END;
æcheck the ioRights reservationå
IF ioRights<>NoRights THEN BEGIN
IF SameEntity(currDriverÆdevnoÅ,void) THEN BEGIN
check(Copy(tempMan,currDriverÆdevnoÅ));
check(ipcGate.Resident(currDriverÆdevnoÅ));
d.breakÆdevnoÅ:=false;
END ELSE BEGIN
exception(genRes(-RightsOccupied,IoFamily,0));
END;
END;
END æwithå;
DO BEGIN
ignore:=dirGate.Open;
exception(getException);
END;
check(dirGate.Open);
check(MakeReentrant(tempMan));
check(MoveMan(tempMan,driversÆdevnoÅ));
DO BEGIN
ignore:=DelEnv(ownedFao,tempMan);
IF res.main=ok THEN res:=getException;
æ'ownedFao' is deleted automatically by kernel when result is rejectå
END;
ObjReturn(res);
END æ***ENTRY Assign***å;
æ$Eå
PRIVATE Close
æIN driver,env: ref (kernel supplied)å
WITH RECORD
t: ^^;
END;
VAR devno: devnos;
BEGIN
check(ipcGate.Lock);
WITH e=env:drivLocRef, c=e^^.localdata^^, d=localdata^^ DO BEGIN
devno:=c.devno;
d.countÆdevnoÅ:=c.count;
END;
check(ipcGate.Open);
check(DelEnv(driver,driversÆdevnoÅ));
check(Dealloc(driver,driver));
END æ***ENTRY Close***å;
ENTRY ScanFiles
WITH RECORD
t: ^^;
END;
BEGIN
exception(genRes(-EntryIllegal,Universal,2));
END æ***ENTRY InitScan***å;
ENTRY CreateLink WITH tempRefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
ENTRY DeleteLink WITH tempRefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
ENTRY RenameFile WITH tempRefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
ENTRY Exclude WITH tempRefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
ENTRY Include WITH tempRefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
ENTRY InitFileSys WITH tempRefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
OTHERWISE IpcOther
WITH RECORD t: ^^; END;
BEGIN
exception(genRes(-EntryIllegal,Universal,2));
ENDæ***OtherFunc***å;
entry clonefileenv with temprefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
entry clonecontrol with temprefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
entry waitsignal with temprefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
entry closeclone with temprefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
END æ mccmImplement å;
æ$Eå
æ$L-å
(*//////////////////////////////////////////////////////////////////////
TYPE addrSpace=ARRAY Æaddrmin..16777200Å OF byte;
æ**************************************************************************å
æ****************************** T E S T S T U B ***************************å
æ**************************************************************************å
object Stub;
entry BootInit;
entry e2;
end;
program implTeststub object stub
with record
code: ^^;
bootset: ownSet;
alloc,
sched,
intsched: ^^;
fullspace: ^^ ÆÅ addrSpace;
defvirt,
ego,
egoenv,
bootproc: ^^;
ipcObj: ^^IoSys; ipcMan: ^^;
fao0, fao4: ^^Fao;
p2: ^^;
buf: bufRef;
end;
procedure try (res:ResultType);
begin
printVar('##### T R Y #####, result= ',res);
end;
private termUdc with tempRefs;
begin printText('udcobj terminated') end;
entry BootInit with record t:^^; tempEnv: ^^ipcLocals; stack:^^; end;
const udcfirst=16#ff0000; udcvector=255; udclevel=3;
bufsize=256;
var s: sizeType;
count: integer;
pos: integer;
i: integer;
devno: devnos;
name4: string8;
res: ResultType;
begin
check(alloc.NewObj(ipcObj; makeSize(5000,2000),out count));
check(DeclGen(ipcObj,ipcMan,tempEnv,refs(ipcLocals),termUdc,
makeSize(0,0),makeSize(0,0),refs(udcImplement),
bytes(udcImplement),0,addr(udcImplement),
makeSize(0,0),true));
check(Copy(code, tempEnv^^.code));
check(Copy(ego, tempEnv^^.stubRef));
check(Copy(intsched,tempEnv^^.iSchedRef));
check(Copy(sched, tempEnv^^.schedRef));
check(Copy(alloc, tempEnv^^.allocRef));
check(Copy(tempEnv, tempEnv^^.egoEnv));
check(NewSeg(tempEnv^^.ownLocaldata,bytes(ipcData)));
check(ipcObj.InitIpcSys(;udcvector,udclevel,udcfirst));
check(alloc.NewObj(buf; makeSize(10000,1000),out count));
check(DeclSeg(buf,bufsize));
ætest of ipc objectå
printText('Start of test - ipc object');
name4:=str8('4 ');
try(ipcObj.Assign(out fao4; name4,ReadWrite)); æfile not foundå
devno:=8; try(ipcObj.CreateFile(;name4,devno)); æDataValueIllegalå
devno:=4; check(ipcObj.CreateFile(;name4,devno));
devno:=0; try(ipcObj.CreateFile(;name4,devno)); æFileNameExistså
check(ipcObj.Assign(out fao4; name4,ReadWrite));
check(fao4.ReadSeq(in buf; out count));
check(ipcObj.DeleteFile(;name4));
try(ipcObj.DeleteFile(;name4)); æFileNotFoundå
æ kernel-error 83-06-02
try(fao4.ReadSeq(in buf; out count)); æDummyfiedå
å
devno:=4; check(ipcObj.CreateFile(;name4,devno));
æ kernel-error 83-06-02
try(fao4.ReadSeq(in buf; out count)); æDummyfiedå
å
check(Dealloc(fao4,fao4));
check(ipcObj.Assign(out fao4; name4,ReadWrite));
check(fao4.ReadSeq(in buf; out count));
æ kernel error 83-06-02 (refEqual)
try(ipcObj.Assign(out fao0; name4,ReadWrite)); æRightsOccupiedå
å
check(ipcObj.Assign(out fao0; name4, NoRights));
try(fao0.ReadSeq(in buf; out count)); æEntryIllegalå
check(ipcObj.DeleteFile(;name4));
check(Dealloc(fao0,fao0)); check(Dealloc(fao4,fao4));
printText('End of test - ipc object ');
printText('Start of test - Disk object ');
devno:=4; check(ipcObj.CreateFile(;name4,devno));
check(ipcObj.Assign(out fao4; name4,ReadWrite));
with b=buf^^ do begin
for i:=1 to 16 do bÆiÅ:=i;
printVar('testbuf= ',b);
end;
check(fao4.WriteRandom(buf;out count,4*256,out pos));
if pos<>4*256 then printVar('test error 1: pos= ',pos);
check(fao4.ReadRandom(buf;out count,4*256,out pos));
with b=buf^^,b8=bÆ1..8Å do printVar('4. sector= ',b);
check(fao4.Seek(;FromCurrent,256,out pos));
check(fao4.Seek(;FromCurrent,-6*256,out pos));
if pos<>0 then printVar('test error 2: pos= ', pos);
for i:=1 to 5 do
check(fao4.ReadSeq(buf;out count));
with b=buf^^ do printVar('sector= ',b);
check(fao4.Seek(;FromStart,0,out pos));
i:=0;
repeat
printVar('start loop, i= ',i);
check(fao4.WaitBreak); check(fao4.WaitReady);
check(fao4.Seek(;FromCurrent,0,out pos));
printVar('pos= ',pos);
in repeat check(fao4.ReadSeq(buf;out count)); i:=i+1 until false;
do begin
res:=getException;
printVar('ATTENTION, res= ',res);
printVar('Attention, i= ',i);
if res.main=PosOutsideRange then exception(res);
check(fao4.WaitReady);
end;
until false;
end;
entry e2 with tempRefs;
begin end;
otherwise o with tempRefs;
begin printText('teststub.otherwise') end;
end æteststubå;
/////////////////////////////////////////////////////////////*)
æ$L+å
æ$Eå
INITIALIZE
udcImplement 'udc':
allocRef 'allocate',
schedRef 'scheduler',
iSchedRef 'intscheduler',
stubRef 'objdir',
egoEnv '**',
ownLocaldata
æ implTeststub 'teststub': å
END.
«eof»