|
|
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: 52736 (0xce00)
Types: TextFile
Names: »MCCM.SA«
└─⟦2322e079b⟧ Bits:30009789/_.ft.Ibm2.50006594.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »MCCM.SA«
└─⟦311ba069f⟧ Bits:30009789/_.ft.Ibm2.50006625.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »MCCM.SA«
└─⟦49237ce80⟧ Bits:30009789/_.ft.Ibm2.50006627.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »MCCM.SA«
æ*****************************************************************
Copyright 1984 by
NCR Corporation
Dayton, Ohio U.S.A.
All Rights Reserved
******************************************************************
EOS Software produced by:
NCR Systems Engineering - Copenhagen
Copenhagen
DENMARK
*****************************************************************å
æ
MMMM MMMM CCCCCCCCC CCCCCCCCC MMMM MMMM
MMMMM MMMMM CCCCCCCCCCC CCCCCCCCCCC MMMMM MMMMM
MMMMMM MMMMMM CCCCC CCCCC MMMMMM MMMMMM
MMMM MM MM MMMM CCCC CCCC MMMM MM MM MMMM
MMMM MMM MMMM CCCC CCCC MMMM MMM MMMM
MMMM MMMM CCCCC CCCCC MMMM MMMM
MMMM MMMM CCCCCCCCCCC CCCCCCCCCCC MMMM MMMM
MMMM MMMM CCCCCCCCC CCCCCCCCC MMMM MMMM
M C C M
I P C
M O D U L E
(DRIVER MODULE FOR MOTOROLA'S MCCM CONTROLLER)
EOS Operating System
The MCCM Ipc Module drives Motorkla's Multi-Channel Communications Module
through the Intelligent Peripheral Controller interface.
The module adheres to the EOS architectural standard for i/o-families.
The MCCM object manages a number of driver objects. A driver object is an
access object which the MCCM object creates on call to the Assign-entry.
The driver object is the 'access-path' to one of the devices (terminal
or printer) which are operated by the MCCM controller. The controller
operates up to eight devices numbered 0 through 7.
The driver object (or Line 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 Line objects opened to the
same device may have the exclusive i/o-reservation.
Copyright NCR Corporation 1983
Written: April 1983
By: Peter Mikkelsen, SE-Copenhagen.
Version id: 00/02 83-06-21
Last update: 83-09-12
To be changed:
å
æ$Eå
æ$H=0å
æ
OVERVIEW OF THE MODULE'S TEXT: PAGE
==============================
Export description
Import description
Constants and types
Global routines:
å
OBJECT PROGRAM Mccm;
æ$L-å
æ$F=FAMILY.UNIV.IDå
æ$F=FAMILY.KNEL.IDå
æ$F=FAMILY.ALLOC.IDå
æ$F=FAMILY.SCHED.IDå
æ$F=FAMILY.OBJDIR.IDå
const OrgSys=4002;
æ$F=PASINCLU.MIKTYPES.SAå
æ$L+å
æ$Eå
(* removed 83-06-02
æ***** E X P O R T D E S C R I P T I O N *****å
æ***********************************************å
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 ReadWriteRight) å
ENTRY DeleteFile
(IN devName: fullId);
æ Deletes a device description. Drivers open to the device are
abortedå
æ$Eå
OBJECT Line; ære-entrantå
æ This object acts as an access-path to a terminal or printer.
Although several line 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;
ENTRY ReadSeq
(IN segment: bufRef;
OUT byteCount: integer);
æ Returns one or more text- and/or command-records from the
input stream. The call returns as soon as a record is avail-
able from the stream or when 'buf' can hold no more records.
Example: A text-record and a NL-record are often returned
together because both records become available at the same
time when a NL is received from the device.
'Buf' must be able to hold at least a text-record with one
character and a NL-record (i.e. 'buf's minimum length is
6 bytes).
'Count' returns the number of bytes defined in 'buf'. å
ENTRY WriteSeq
(IN segment: bufRef;
OUT byteCount: integer);
æ Gives the driver object a number of text- and/or command-
records to put on the output stream. Only complete records
are treated; incomplete records are ignored (i.e. no error
reaction). 'Count' returns the number of bytes used from
'buf'. 'Count' may be less than 'buf's length if
(1) a device error or break condition occured preventing
the complete transfer. 'Count' corresponds to the last
byte of the last record to be successfully transmitted.
Result <> ok.
(2) 'buf' contains an incomplete record. 'Count' indicates
how many complete records was accepted (by pointing
to the last byte of the last record to be accepted).
Result = ok. å
æ$Eå
ENTRY ReadRandom; æ reject å
ENTRY WriteRandom; æ reject å
ENTRY Seek( IN baseMode; IN offset; OUT pos);
ENTRY SetMode; æ not demo å
ENTRY GetFileInf
(OUT ioSys: ref;
OUT localId: integer;
OUT fileName: fullId;
OUT devClass: devClass;
OUT bytesAllocated: integer; OUT dataBytes: integer;
OUT minBufSize: integer; OUT cylSize æ=no of repeats å);
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 æLineå;
CONST IoFamily=4;
æ***** ERROR CONSTANTS *****å
CONST
FileNotFound =3;
FileNameExists =4;
RightsOccupied =6;
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 *)
æ$F=FAMILY.IOSYS.IDå
CONST
ænon-standard error constantså
alreadyNamed=100; æCreate: devno is already namedå
alreadyWaiting=101; æWaitBreak: one process already waiting for breakå
æotherå
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;
æ text format records å
nlLength=-3; æ 2 bytes å
nlCom=cr; æ 1 byte å
æ module constants å
maxIdLength=48; æ # significant characters of a fullId in this module å
kernelStack=100; æsupervisor stack on interrupt å
æ default device constants å
defOptions=0; æecho, don't configure, conversational modeå
defHwConfig=16#8E4E00FF; æ8E: 8 bits, no parity, 1 stop bit, configure
4E: 9600 bps, direct connect, EOT turnaround
00: -
FF: max line size=255å
defSwConfig=16#80000000; æ80: echo, configure
00: conversational mode
00: (poll chars)
00: --"--å
æ Ipc constants å
æpacket sizeså
rwSize=21;
configSize=15;
haltSize=7;
æchannel commandså
readCom=16#10;
writeCom=16#20;
configCom=16#40;
haltCom=16#50;
ædevice commandså
ipcFormatted=16#01;
ipcImage=16#02;
stdDevCom=16#01;
æstatus classeså
completion=16#70;
abortClass=16#71;
solicited=16#72;
unsolicited=16#80;
æstatus valueså
noErrors= 0;
endConfig= 1;
breakSt= 2;
notReady= 3;
outOfPaper= 7;
devBusy= 16#C;
æ$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å
egoObj : ^^;
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;
rbBase,
rbLast: integer; æspecifies used part of readBufå
afterNL: integer; æonly used in UNIX modeå
æ only for disk
currPos: integer;
discSize,
cylSize,
blockSize: integer å
END;
buf256= ARRAY Æ1..256Å OF char;
buf1024=ARRAY Æ1..1024Å OF char;
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'å
auxBuf: ^^buf1024; æfor Unix writeså
readBuf: ^^buf256; æline read-a-head in UNIX modeå
readFifo: ^^Gate; æprotects readBufå
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 intmccm;
FORWARD;
æ$Eå
æ***** G L O B A L P R O C E D U R E S *****å
æ*********************************************å
procedure checkOk
(res: resultType);
ægenerates exception on a bad result, but does not test outputå
begin
if res.main<>ok then exception(res);
end;
æ GetLength and putLength are used to insert, resp. retrieve, the length
fields in the text record format å
TYPE
tagMode=(wordMode,byteMode);
convInt=RECORD
fill: byte; æto align word and byteså
CASE tag: tagMode OF
wordMode: (w: word);
byteMode: (u1,u2: byte);
END;
FUNCTION getLength
(VAR b: blockPtr)
: integer;
VAR conv: convInt;
BEGIN
conv.tag:=byteMode;
conv.u1:=bÆ1Å; conv.u2:=bÆ2Å;
conv.tag:=wordMode;
getLength:=conv.w;
END æ***getLength***å;
PROCEDURE putLength
(VAR b: blockPtr;
length: integer);
VAR conv: convInt;
BEGIN
conv.tag:=wordMode;
conv.w:=length;
conv.tag:=byteMode;
bÆ1Å:=conv.u1; bÆ2Å:=conv.u2;
END æ***putLength***å;
PROCEDURE putNL
(VAR b: blockPtr);
BEGIN
putLength(b,nlLength);
bÆ3Å:=nlCom;
END æ***putNL***å;
æ$Eå
æ----- 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);
var i: integer;
BEGIN
c.ackFifoLast:=(c.ackFifoLast+1) MOD (maxDevno+1);
c.ackFifoÆc.ackFifoLastÅ:=devno;
æ#b# i:=c.ackFifoFirst;
printVar('^^^^putAckFifo, first= ', i);
i:=c.ackFifoLast;
printVar('^^^^putAckFifo, last= ', i);
printVar('^^^^putAckFifo, ackfifo= ',c.ackFifo);
#e#å
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;
retry: boolean;
BEGIN
c.requestsÆdevnoÅ:=req;
REPEAT
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;
retry:=(c.requestsÆdevnoÅ.i.h0.statusClass=completion) AND
(c.requestsÆdevnoÅ.i.h0.status=devBusy);
UNTIL NOT retry;
req.i:=c.requestsÆdevnoÅ.i; æreturn answerå
END æ***sendReq***å;
æ$Eå
æ***** L I N E O B J E C T I M P L E M E N T A T I O N *****å
æ***************************************************************å
PROGRAM lineImplement 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=ReadWriteRight) 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å
checkOk(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));
req.o.DMAaddress:=req.o.DMAaddress+base; æstart of text in bufå
sendReq(complete,req,d.devno,c); æsend request to ipcå
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=2)) THEN
BEGIN
check(breakCond.Signal);
exception(genRes(-BreakPending,IoFamily,0));
END ELSE BEGIN
printVar('mccm: bad result, req.i= ', req.i);
exception(genRes(PhysIoError,IoFamily,0));
END;
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å
ENTRY ReadSeq
æIN segment: bufRef; OUT byteCount: integerå
WITH RECORD
t: ^^;
buf: bufRef;
END;
CONST
readComOverhead=6; æ# bytes which must be available for overhead in Readå
lf=10; cr=13; ctrlD=4;
VAR
readLength: integer;
i: integer;
res: ResultType;
req: ipcRequest;
mode: integer;
intPtr: ^ integer;
echoLF: boolean;
c: char;
base, last: integer;
stop: boolean;
BEGIN
res.main:=ok;
echoLF:=false;
check(readFifo.Lock);
IN
IF NextValArg(intPtr) THEN BEGIN
mode:=intPtr^;
IF NOT ((mode=Image) OR (mode=Unix) OR (mode=Formatted)) THEN
exception(genRes(-DataValueIllegal,Universal,-2));
END ELSE mode:=Image;
æ printVar('Readseq called, mode= ',mode); å
IF mode=Unix THEN BEGIN æinserted 83-09-12å
WITH d=localdata^^ DO BEGIN
IF d.rbBase=d.rbLast THEN BEGIN
æreadBuf is empty - read a new lineå
æ 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:= readCom;
req.o.h0.devCom:=ipcFormatted;
req.o.blocks0:= 1;
req.o.blkSize0:= 80;
req.o.options:= d.mode.options;
req.o.etx0:= etx;
checkOk(doIo(readBuf,0,req,ReadRight,d));
d.rbBase:=0;; d.rbLast:=req.i.blockSize+1 ælfå;
WITH b=readBuf^^ DO bÆd.rbLastÅ:=chr(lf);
END;
base:=d.rbBase; last:=d.rbLast;
END æwith localdataå;
i:=1; stop:=false; byteCount:=0;
WITH dest=segment^^, source=readBuf^^ DO BEGIN
REPEAT
c:=sourceÆbase+iÅ;
IF c=chr(cr) THEN c:=chr(lf);
IF c<>chr(ctrlD) THEN BEGIN
destÆiÅ:=ord(c);
byteCount:=byteCount+1;
END;
i:=i+1;
stop:=(c=chr(ctrlD)) OR (c=chr(lf)) OR (base+i>last)
OR (i>elements(dest));
UNTIL stop;
END æwith dest,sourceå;
WITH d=localdata^^ DO d.rbBase:=base+i-1;
END ELSE BEGIN
check(Copy(segment,buf)); æbecause of Resident-operationå
WITH b=buf^^ DO readLength:=elements(b);
IF mode=Formatted THEN readLength:=readLength-readComOverhead;
IF readLength<=0 THEN
exception(genRes(-DataValueIllegal,Universal,4));
WITH d=localdata^^ DO BEGIN
æ 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:= readCom;
IF readLength=1 THEN req.o.h0.devCom:=ipcImage
ELSE req.o.h0.devCom:=ipcFormatted;
req.o.blocks0:= 1;
req.o.blkSize0:= readLength;
req.o.options:= d.mode.options;
req.o.etx0:= etx;
CASE mode OF
Unix,
Image: checkOk(doIo(buf,0,req,ReadRight,d));
Formatted: checkOk(doIo(buf,2,req,ReadRight,d));
END;
WITH b=buf^^ DO BEGIN
byteCount:=req.i.blockSize;
IF mode=Unix THEN BEGIN
IF readLength=1 THEN BEGIN
IF bÆ1Å=13 æcrå THEN BEGIN
bÆ1Å:=10 ælfå;
æimage mode: only carriage return echoedå
echoLF:=true;
d.afterNL:=0;
END;
END ELSE BEGIN
IF byteCount<readLength THEN BEGIN
byteCount:=byteCount+1;
bÆbyteCountÅ:=10;
d.afterNL:=0;
æformatted mode: newline echoed okå
END;
END;
END ELSE BEGIN
IF mode=Formatted THEN BEGIN
IF byteCount=readLength THEN BEGIN
byteCount:=byteCount+2;
putLength(b,byteCount);
END ELSE BEGIN
IF byteCount>0 THEN BEGIN
byteCount:=byteCount+2;
putLength(b,byteCount);
END;
WITH b2=bÆbyteCount+1..byteCount+3Å DO putNL(b2);
byteCount:=byteCount+3;
d.afterNL:=0;
END æelseå;
END; æFormattedå
END æelseå;
END æwithå;
IF echoLF THEN BEGIN
æmodify 'req' to echo a single LF charå
req.o.h0.chanCom:=writeCom;
req.o.h0.devCom:=ipcImage;
req.o.blkSize0:=1;
checkOk(doIo(buf,byteCount-1,req,WriteRight,d));
END;
END æwithå;
END æif-then-elseå;
DO IF res.main=ok THEN res:=getException;
check(readFifo.Open);
æ printVar('readseq, bytecount= ',bytecount); å
ObjReturn(res);
END æ***ReadSeq***å;
æ$Eå
ENTRY WriteSeq
æIN segment: bufRef; OUT byteCount: integerå
WITH RECORD
t: ^^;
buf: bufRef;
END;
CONST ht=9; space=32;
VAR bLength,
recLength: integer;
mode: integer;
intPtr: ^ integer;
u3: byte;
res: resultType;
finish: boolean;
req: ipcRequest;
sourcePos: integer;
destPos: integer;
afterNL: integer;
BEGIN
res.main:=ok;
IN
IF NextValArg(intPtr) THEN BEGIN
mode:=intPtr^;
IF NOT ((mode=Formatted) OR (mode=Unix) OR (mode=Image)) THEN
exception(genRes(-DataValueIllegal,Universal,-2));
END ELSE mode:=Image;
IF mode=Unix THEN BEGIN
sourcePos:=1;
destPos:=1;
WITH d=localdata^^ Do afterNL:=d.afterNL;
WITH source=segment^^, dest=auxBuf^^ DO BEGIN
bLength:=elements(source);
WHILE (sourcePos<=bLength) AND
(destPos<=bytes(buf1024)) DO BEGIN
IF sourceÆsourcePosÅ=ht THEN BEGIN ætab modulo 8å
REPEAT
destÆdestPosÅ:=chr(space);
destPos:=destPos+1;
afterNL:=afterNL+1;
UNTIL (afterNL MOD 8 = 0) OR (destPos>bytes(buf1024));
END ELSE BEGIN
destÆdestPosÅ:=chr(sourceÆsourcePosÅ);
destPos:=destPos+1;
afterNL:=afterNL+1;
IF sourceÆsourcePosÅ=10 THEN BEGIN
destÆdestPosÅ:=chr(13);
destPos:=destPos+1;
afterNL:=0;
END;
END;
sourcePos:=sourcePos+1;
END;
bLength:=destPos-1;
END;
with d=localdata^^ do d.afterNL:=afterNL;
check(Copy(auxBuf,buf));
END ELSE BEGIN
check(Copy(segment,buf)); æbecause of Resident-operationå
WITH b=buf^^ DO bLength:=elements(b);
END;
WITH d=localdata^^ DO BEGIN
byteCount:=0;
CASE mode OF
Unix,
Image: BEGIN
req.o.kind:=rwMess;
WITH req.o DO BEGIN
h0.stx:= stx;
h0.packetId:=0;
h0.size:=rwSize;
h0.devno:=d.devno;
h0.chanCom:=writeCom;
h0.devCom:=ipcImage;
END;
req.o.blocks0:=1;
req.o.options:=d.mode.options;
req.o.etx0:=etx;
req.o.blksize0:=bLength;
checkOk(doIo(buf,0,req,WriteRight,d));
byteCount:=req.i.blockSize;
d.afterNL:=afterNL;
END;
Formatted: BEGIN
finish:=bLength<3 æminimum rec sizeå;
WHILE NOT finish DO BEGIN
WITH b=buf^^, b2=bÆbyteCount+1..bLengthÅ DO BEGIN
recLength:=getLength(b2);
u3:=b2Æ3Å;
END;
finish:=(recLength=0 æstop sentinelå) OR
(bLength<byteCount+abs(recLength) æincomplete recordå);
IF NOT finish THEN BEGIN
æ prepare 'req': fill in default values å
req.o.kind:=rwMess; æread/writeå
WITH req.o DO BEGIN
h0.stx:= stx;
h0.packetId:=0;
h0.size:=rwSize;
h0.devno:=d.devno;
h0.chanCom:=writeCom;
h0.devCom:=ipcImage;
END;
req.o.blocks0:=1;
æ'req.o.blkSize0' must be suppliedå
æreq.o.DMAaddress to be supplied later when buffer
becomes fixed in the memory (IoBegin) å
req.o.options:=d.mode.options;
req.o.etx0:=etx;
IF recLength>0 THEN BEGIN ætext recordå
req.o.blkSize0:=recLength-2 æfor length fieldå;
checkOk(doIo(buf,byteCount+2,req,WriteRight,d));
byteCount:=byteCount+recLength;
END ELSE BEGIN
IF (recLength=nlLength) AND (u3=nlCom) THEN BEGIN ænl-recordå
æoutput a single CR character -- use the one in buf (nlCom)å
req.o.h0.devCom:=ipcFormatted;
req.o.blkSize0:=1; æcr charå
checkOk(doIo(buf,byteCount+2,req,WriteRight,d));
byteCount:=byteCount+3;
END ELSE BEGIN
ætext format errorå
exception(genRes(-DataValueIllegal,Universal,4));
END;
END;
END æif not finishå;
finish:=finish OR (bLength-byteCount<3 æminimum rec sizeå);
END æwhileå;
END;
END æcaseå;
END æwithå;
DO IF res.main=ok THEN res:=getException;
ObjReturn(res);
END æ***WriteSeq***å;
æ$Eå
ENTRY ReadRandom
WITH RECORD t: ^^; END;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY WriteRandom
WITH RECORD t: ^^; END;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
ENTRY Seek æ baseMode, offset, out pos å
WITH RECORD t: ^^; END;
BEGIN
if ( baseMode=fromEnd ) and ( offset = 0 ) then
with d=localdata^^ do
d.rbBase:= d.rbLast; æposition:= after last charå
pos:=0; ædummyå
END;
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;
CONST shift16=16#10000;
VAR i,j:integer;
BEGIN
checkOk( copy(ipc^^.egoObj,ioSys));
with d=localdata^^ , ip=ipc^^.ownLocaldata^^ do begin
localId:= (256+ip.vector) * shift16 + d.devno;
if maxIdLength >= elements(fileName)
then i:= elements(filename)
else i:= maxIdLength - 1;
for j:= 1 to i do filenameÆjÅ:=ip.dirÆd.devnoÅ.nameÆjÅ;
fileNameÆi+1Å:= chr(0);
devClass:= 1; æ 1=terminal å
bytesAllocated:= d.rbLast - d.rbBase;
dataBytes:= bytesAllocated;
minBufSize := 1;
cylSize:= d.count.repeats;
end æwithå;
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 temprefs;
BEGIN ObjReturn(genRes(-EntryIllegal,Universal,2)); END;
OTHERWISE LineOther
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 mccmImplement OBJECT IoSys WITH ipcLocals;
PRIVATE Close
(IN 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
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(intmccm)));
æ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å
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;
æoptional parameterså
IF NextValArg(intPtr) THEN hwConfig:=intPtr^
ELSE hwConfig:=defHwConfig;
IF NextValArg(intPtr) THEN swConfig:=intPtr^
ELSE swConfig:=defSwConfig;
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);
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å
ignore:=ClearSize(s);
ignore:=AddEnv(s,refs(drivLocals)); ignore:=AddSeg(s,bytes(drivData));
check(allocRef.NewObj(OUT ownedFao; makeSize(2000,500), OUT i));
ignore:=ClearSize(s);
check(DeclGen(ownedFao,tempMan,tempEnv,refs(drivLocals),Close,s,s,
refs(lineImplement),bytes(lineImplement),0,
addr(lineImplement),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^^.readFifo));
æ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));
æauxBufå
check(NewSeg(tempMan^^.auxBuf,bytes(buf1024)));
æreadBufå
check(NewSeg(tempMan^^.ownSet,bytes(buf256)));
check(Copy(tempMan^^.ownSet,tempMan^^.readBuf));
IF ioRights<>NoRights THEN
check(ipcGate.Resident(tempMan^^.readBuf));
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.options:=defOptions;
æc.mode.timeout:=?;å
c.devReserved:=0;
c.waitBreak:=false;
c.waitEmpty:=false;
c.afterNL:=0;
c.rbBase:=0;
c.rbLast:=c.rbBase; æi.e., emptyå
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);
IF ioRights<>NoRights THEN BEGIN
æconfigurate deviceå
WITH req.o, d=localdata^^ DO BEGIN
kind:=configMess; æconfigureå
h3.stx:=stx;
h3.packetId:=2;
h3.size:=configSize;
h3.devno:=devno;
h3.chanCom:=configCom;
h3.devCom:=stdDevCom;
hwConfig:=d.dirÆdevnoÅ.hwConfig;
swConfig:=d.dirÆdevnoÅ.swConfig;
etx3:=etx;
check(ipcGate.Resident(tempEnv)); æmust be resident for i/oå
check(ipcGate.Lock); æmust be locked to do i/oå
sendReq(tempEnv^^.complete,req,devno,d);
check(ipcGate.Open);
req.i.kind:=mccmStAnsw; æconfig completed -- hopefullyå
IF NOT ((req.i.h4.statusClass=solicited) AND
(req.i.h4.status=endConfig)) THEN
exception(genRes(PhysIoError,IoFamily,0));
END æwithå;
END æifå;
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;
entry cloneFil with temprefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
entry clonecon with temprefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
entry waitsign with temprefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
private closeclon with temprefs;
BEGIN exception(genRes(-EntryIllegal,Universal,2)); END;
OTHERWISE IpcOther
WITH RECORD t: ^^; END;
BEGIN
exception(genRes(-EntryIllegal,Universal,2));
ENDæ***OtherFunc***å;
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: ^^;
mccmOwn:IoSysRefType; mccmMan:^^; mccmChannel:^^; tao0,tao1:^^FaoRefType;
p2: ^^;
end;
type textLine=array Æ1..90Å of byte;
procedure putline (UNIV s: blockPtr; t: blockPtr);
var i,length: integer;
begin
length:=elements(s);
if length>80 then length:=80;
putLength(t,length+2);
for i:= 1 to length do tÆi+2Å:=sÆiÅ;
with tt=tÆlength+3..length+5Å do putNL(tt);
end;
private termMccm with tempRefs;
begin printText('mccmobj terminated') end;
entry BootInit with record t:^^; tempEnv: ^^ipcLocals; stack:^^; end;
const mccmfirst=16#ff1000; mccmvector=247; mccmlevel=4;
var s: sizeType;
count: integer;
i: integer;
devno: devnos;
term0,term1: string8;
buf: textLine;
prompt, attPrompt: textLine;
res: ResultType;
begin
in
check(alloc.NewObj(mccmOwn;makeSize(5000,2000),out count));
check(DeclGen(mccmOwn,mccmMan,tempEnv,refs(ipcLocals),termMccm,
makeSize(0,0),makeSize(0,0),refs(mccmImplement),
bytes(mccmImplement),0,addr(mccmImplement),
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(mccmOwn.InitIpcSys(;mccmvector,mccmlevel,mccmfirst));
term0:=str8('term0 ');
term1:=str8('term1 ');
devno:=0; check(mccmOwn.CreateFile(;term0,devno));
devno:=1; check(mccmOwn.CreateFile(;term1,devno));
æ check(alloc.NewObj(stack;makeSize(50000,10000),out count));
check(CallExtend(stack,mccmOwn,Assign,out tao;ReadWriteRight,termName));
å
check(mccmOwn.Assign(out tao0; term0,ReadWriteRight));
check(mccmOwn.Assign(out tao1; term1,ReadWriteRight));
check(tao0.WaitBreak);
check(tao0.WaitReady);
putline('input:',prompt);
putline('att0',attPrompt);
check(sched.NewProc(out p2; makeSize(50000,10000)));
check(DeclProc(p2,e2));
printText('BEGIN copy-loop ');
æcopy from term0 to term1å
repeat
IN
repeat
check(tao0.Writeseq(var in out prompt; out count));
check(tao0.ReadSeq(var in out buf; out count));
res:=tao1.WriteSeq(var in out buf; out count);
until false;
DO BEGIN
printText('**********attention on term0**********');
check(tao0.WaitReady);
check(tao0.WriteSeq(var in out attPrompt; out count));
END;
until false;
do printText('teststub.Init exception');
end;
entry e2 with tempRefs;
var s: sizeType;
count: integer;
i: integer;
devno: devnos;
term0,term1: string8;
buf: textLine;
prompt, attPrompt: textLine;
res: ResultType;
begin
in
putline('input:',prompt);
putline('att1',attPrompt);
printText('BEGIN att-loop ');
æcopy from term1 to term0, but only on attå
repeat
IN
repeat
check(tao1.WaitBreak); check(tao1.WaitReady);
check(tao1.Writeseq(var in out prompt; out count));
check(tao1.ReadSeq(var in out buf; out count));
res:=tao0.WriteSeq(var in out buf; out count);
until false;
DO BEGIN
printText('**********error on term1**********');
END;
until false;
do printText('teststub.e2 exception');
end; æe2å
otherwise o with tempRefs;
begin printText('teststub.otherwise') end;
end æteststubå;
////////////////////////////////////////////////////////////////////*)
æ$L+å
æ$Eå
INITIALIZE
mccmImplement 'mccm':
allocRef 'allocate',
schedRef 'scheduler',
iSchedRef 'intscheduler',
stubRef 'objdir',
egoEnv '**',
egoObj '*',
ownLocaldata
æ implTeststub 'teststub':å
END.
«eof»