// AltIOUtilb.bcpl -- utility routines for AltIO
// Last modified April 17, 1978 2:38 PM
get "streams.d"
get "altio.decl"
external
[
//outgoing procedures
LoadSaveFile; ZeroMaxcMem; BootMicroExec
MemReadBlock32; MemWriteBlock32; MemReadBlock40; MemWriteBlock40
MemZero; RMWBitAbsolute; RMWBitRelative
//incoming procedures
OpenFile; Ws; PutTemplate; Gets; Closes; Endofs; SysErr
MyFrame; GotoFrame; Zero; Usc
MemRead; MemWrite; MemRMW; DoubleIncrement; DoubleAdd; Block
MemReadBlock32A; MemWriteBlock32A; MemReadBlock40A
MemWriteBlock40A; MemZeroA; SetOneMaxcBit
MemReadAbsolute; MemWriteAbsolute; MemRMWAbsolute
MemReadRelative; MemWriteRelative; MemRMWRelative
AltIOReset; StartMaxc; StopMaxc; ResetMaxc; ConfigureMemory
DisplayMemCode
//incoming statics
dsp; sysZone; adrMTBS; numMemCabs
MaxcBootLoader; lenMaxcBootLoader
]
// ---------------------------------------------------------------------------
let LoadSaveFile(s) = valof
// ---------------------------------------------------------------------------
//load into Maxc memory a save-format file whose name is the
//string s.
[
let str = OpenFile(s, ksTypeReadOnly, charItem)
if str eq 0 then
[ PutTemplate(dsp, "File $S not found", s); resultis false ]
StopMaxc()
unless ZeroMaxcMem() resultis false
str>>ST.error = LoadErrors //catch running off end of file
str>>ST.par1 = MyFrame()
let maxcAdr, maxcData = vec 2, vec 3
let errorCode = 0
[
unless GetMaxcWord(str, maxcData) do
[
Ws("Premature end of file, probable bad format")
errorCode = -1
break
]
if maxcData!0 ge 0 then
[
unless Endofs(str) do
[
Ws("End block before eof, probable bad format")
errorCode = -1
break
]
//end block, put starting address in location 7
maxcData!0 = 0; maxcData!1 = maxcData!1 & #37777
MemWriteAbsolute(aSTADR, maxcData)
//put something reasonable in MTBS and DLSBS
maxcData!1 = #200 rshift 4; maxcData!2 = 0
MemWriteAbsolute(aMTBS, maxcData)
maxcData!1 = #600 rshift 4
MemWriteAbsolute(aDLSBS, maxcData)
AltIOReset() //reset Alto state
ResetMaxc() //reset Maxc so "Resume" will start program
break
]
//this is an iowd, set up to transfer data block
if (maxcData!0 & #140000) ne #140000 then
[
Ws("Block size larger than 2↑16, probable bad format")
errorCode = -1
break
]
let count = maxcData!0 lshift 2 + maxcData!1 rshift 14
maxcAdr!0 = maxcData!1 & #37777
maxcAdr!1 = maxcData!2
[
DoubleIncrement(maxcAdr, #10000)
unless GetMaxcWord(str, maxcData) break
errorCode = MemWrite(maxcAdr, maxcData)
count = count+1
] repeatuntil count eq 0 % errorCode ne 0
] repeatwhile errorCode eq 0
if errorCode gr 0 then DisplayMemCode(errorCode)
Closes(str)
resultis errorCode eq 0
]
// ---------------------------------------------------------------------------
and GetMaxcWord(str, maxcData) = valof
// ---------------------------------------------------------------------------
[
let b1 = Gets(str)
let b2 = Gets(str)
let b3 = Gets(str)
let b4 = Gets(str)
let b5 = Gets(str)
maxcData!0 = b1 lshift 12 + b2 lshift 4 + b3 rshift 4
maxcData!1 = b3 lshift 12 + b4 lshift 4 + b5 rshift 4
maxcData!2 = b5 lshift 12
resultis true
]
// ---------------------------------------------------------------------------
and LoadErrors(str, ec) be
// ---------------------------------------------------------------------------
[
test ec eq 1302
ifso GotoFrame(str>>ST.par1, false) //end of file
ifnot SysErr(str, ec) //other error
]
// ---------------------------------------------------------------------------
and ZeroMaxcMem() = valof
// ---------------------------------------------------------------------------
//zeroes all of Maxc memory in preparation for loading a program.
[
let maxcAdr = vec 2
Zero(maxcAdr, 2)
for i = 0 to 4*numMemCabs-1 do
[
let code = MemZero(maxcAdr, #100000) //do 2↑15 words
if code ne 0 then [ DisplayMemCode(code); resultis false ]
]
resultis true
]
// ---------------------------------------------------------------------------
and BootMicroExec(diskUnit, saveArea, autoStart) = valof
// ---------------------------------------------------------------------------
//loads into Maxc memory and starts the disk boot loader which
//in turn starts Micro-Exec. diskUnit and saveArea specify
//the disk address to load Micro-Exec from, and autoStart
//supplies the top 16 bits of the "switches" (Micro-Exec
//does an automatic start of Tenex if bit 0 is set).
[
manifest loaderPage = #347 //page in which loader runs
//normalize processor state
ResetMaxc()
ConfigureMemory(0, 0)
//setup the first word of the loader to contain the unit number
//in bits 11-13 and #6221 - #40*saveArea in bits 18-35.
MaxcBootLoader!0 = diskUnit lshift 2
let diskAdr = #6221 - #40*saveArea
MaxcBootLoader!1 = diskAdr rshift 4
MaxcBootLoader!2 = diskAdr lshift 12
//copy the loader to Maxc memory
let v = vec 2
v!0 = loaderPage lshift 5
v!1 = 0
let code = MemWriteBlock40(v, MaxcBootLoader, lenMaxcBootLoader)
if code ne 0 then [ DisplayMemCode(code); resultis false ]
//set starting address and auto-start parameter, then go.
MemWriteAbsolute(aSTADR, table [ 0; loaderPage lshift 5; #10000 ])
v!0 = autoStart
v!1, v!2 = 0, 0
MemWriteAbsolute(aSWICH, v)
StartMaxc()
resultis true
]
// ---------------------------------------------------------------------------
and MemReadBlock32(maxcAdr, maxcData, count) =
// ---------------------------------------------------------------------------
MemBlockTransfer(MemReadBlock32A, maxcAdr, maxcData, count, 2)
// ---------------------------------------------------------------------------
and MemWriteBlock32(maxcAdr, maxcData, count) =
// ---------------------------------------------------------------------------
MemBlockTransfer(MemWriteBlock32A, maxcAdr, maxcData, count, 2)
// ---------------------------------------------------------------------------
and MemReadBlock40(maxcAdr, maxcData, count) =
// ---------------------------------------------------------------------------
MemBlockTransfer(MemReadBlock40A, maxcAdr, maxcData, count, 3)
// ---------------------------------------------------------------------------
and MemWriteBlock40(maxcAdr, maxcData, count) =
// ---------------------------------------------------------------------------
MemBlockTransfer(MemWriteBlock40A, maxcAdr, maxcData, count, 3)
// ---------------------------------------------------------------------------
and MemZero(maxcAdr, count) =
// ---------------------------------------------------------------------------
MemBlockTransfer(MemZeroA, maxcAdr, nil, count, 3)
// ---------------------------------------------------------------------------
and MemBlockTransfer(Operation, maxcAdr, maxcData, count, inc) = valof
// ---------------------------------------------------------------------------
//Perform some flavor of Maxc memory block transfer.
//The transfer is done a piece at a time with calls to Block()
//interspersed to prevent excessive latency to other contexts.
//inc is the Alto address increment for each Maxc word
[
let code = nil
while count ne 0 do
[
let c = Usc(count, maxBlt) ls 0? count, maxBlt
code = Operation(maxcAdr, maxcData, c)
if code ne 0 break
maxcData = maxcData + c*inc
count = count-c
Block()
]
resultis code
]
// ---------------------------------------------------------------------------
and RMWBitAbsolute(adr, bitNumber) = valof
// ---------------------------------------------------------------------------
//set bit "bitNumber" in Maxc location "adr"
[
let maxcData = vec 3
SetOneMaxcBit(maxcData, bitNumber)
resultis MemRMWAbsolute(adr, maxcData)
]
// ----------------------------------------------------------------
and RMWBitRelative(displacement, bitNumber, base; numargs na) = valof
// ----------------------------------------------------------------
//set bit "bitNumber" in Maxc location "adr" relative to "base"
[
let maxcData = vec 3
SetOneMaxcBit(maxcData, bitNumber)
resultis MemRMWRelative(displacement, maxcData, (na ls 3? adrMTBS, base))
]