// InterDisk.bcpl
// Copyright Xerox Corporation 1979
//This is a little module that Lyle Ramshaw wrote to allow Oedit to
// reference disk files on any Diablo or Trident drive, without
// worrying about details like whether they had been Init'ed or not,
// and whether or not they needed fancy microcode.
//The primary exported procedures are SetUpInterDisk(zone), which
// takes a zone for disk space as the argument, and sets up the
// InterDisk static data structures. You should allow 1024*number
// of Trident files + (~125)*number of Trident drives + 256*number
// of Diablo files + (~100)*[DP1 open? 1, 0] + slop.
//After executing SetUpInterDisk, you can use InterDiskOpenFile instead
// of OpenFile, and it will parse the drive specifications on the
// file names, init the drive if necessary, and then open the file.
//InterDiskOpenFile only pays attention to its first three arguments.
//The zone argument to SetUpInterDisk is used for all space requirements.
// When you have either already opened a file on a Trident drive, or
// you know that you will never use any Trident drive, you may call
// the routine OverwriteLoadRam, and it will do a SetEndCode to
// get back the space taken up by LoadRam and TriconMC. A system using this
// feature should end its load command with "LoadRam TriconMC" in that
// order.
get "streams.d"
get "altodefs.d"
external [ //the exported procedures
SetUpInterDisk
InterDiskOpenFile
OverwriteLoadRam
]
external [
//from BFS package
BFSInit
BFSClose
//from TFS package
TFSInit
TFSClose
TFSSilentBoot
LoadRam
DiskRamImage
TFSSwatContextProc
//from the OS
lvUserFinishProc
lvSwatContextProc
SetEndCode
CallSwat
OpenFile
Allocate
sysDisk
Wl
Ws
]
static [ savedUFP; savedSCP ]
static [ triDisks; diDisk1; diskZone ]
structure UnPacked:
[
Type bit 1 //0 for Diablo, 1 for Trident
Num bit 15
]
manifest [ Diablo = 0; Trident = 1 ]
structure
[
Left byte
Right byte
]
structure Packed:
[
blank bit 11
FileSys bit 2 //For T-300's, says which file system
Num bit 3
]
structure Str:
[
Len byte
Char↑1,255 byte
]
let SetUpInterDisk(zone) be
[
//assign zone to static variable, to remember it
diskZone = zone
//set up disk objects to be 0, since no disks Init'ed
triDisks = Allocate(zone, 32)
for i=0 to 31 do triDisks!i=0
diDisk1=0
]
and OverwriteLoadRam() be
SetEndCode(LoadRam)
and InterDiskOpenFile(name, ksType, itemSize) = valof
[
let nameWordLength = (name>>Str.Len/2) + 1
let nameCopy = Allocate(diskZone, nameWordLength)
AssignStr(nameCopy, name)
let drive=ParseDriveSpec(nameCopy)
if drive eq -1 then resultis 0
if drive eq 0 then resultis //means use DP0 = sysDisk
OpenFile(nameCopy,ksType,itemSize,0,0,0,diskZone,0,sysDisk)
let type = drive<<UnPacked.Type
let num = drive<<UnPacked.Num
switchon type into
[
case Diablo:
if num ne 1 then resultis 0
if diDisk1 eq 0 then InitDP1()
resultis OpenFile(nameCopy,ksType,itemSize,0,0,0,diskZone,0,diDisk1)
case Trident:
[
let triDrive, fileSys = num<<Right, num<<Left
if (triDrive ls 0) % (triDrive gr 7) then resultis 0
if (fileSys ls 0) % (fileSys gr 2) then resultis 0
let packed = 0
packed<<Packed.FileSys = fileSys
packed<<Packed.Num = triDrive
if triDisks!packed eq 0 then InitTridentDrive(num, packed)
resultis
OpenFile(nameCopy,ksType,itemSize,0,0,0,diskZone,0,triDisks!packed)
]
]
]
and InitDP1(num) be
[
let res = BFSInit(diskZone, true, 1)
if res eq 0 then Bitch("Couldn't operate DP1.")
diDisk1 = res
]
and InitTridentDrive(unpacked, packed) be
[
test @lvUserFinishProc eq Finish
ifso
[
let res = TFSInit(diskZone, true, unpacked)
if res eq 0 then
[
let message = "Couldn't operate TPn."
message>>Str.Char↑20 = (unpacked<<Right) + $0
Bitch(message)
]
triDisks!packed = res
]
ifnot
//Time to load the RAM with the Trident microcode
[
let load = LoadRam(DiskRamImage, true)
let AltoVersion=(table [ #61014; #1401 ] )()
let eng=AltoVersion<<VERS.eng
if (eng le 3) & (load ls 0) then Bitch("Couldn't load the RAM.")
//otherwise, assume that correct microcode is loaded on a
//Dolphin or Dorado, and pluge on
savedUFP = @lvUserFinishProc
@lvUserFinishProc = Finish
savedSCP = @lvSwatContextProc
@lvSwatContextProc = TFSSwatContextProc
InitTridentDrive(unpacked, packed)
]
]
and Bitch(msg) be
[
Wl(msg)
let AltoVersion=(table [ #61014; #1401 ] )()
test AltoVersion<<VERS.eng ge 4
ifso Ws("Correct microcode loaded? ")
ifnot Ws("Therefore, farewell! ")
abort
]
//The following routine reads the "DP1:" portion of the file name
and ParseDriveSpec(str) = valof
[
let colonIndex = Contains(str, $:)
test colonIndex
ifnot
[ //default drive is DP0=sysDisk
resultis 0
]
ifso
[
let res, num = nil, nil
if colonIndex ls 3 then resultis -1
if (str>>Str.Char↑2 ne $P)&(str>>Str.Char↑2 ne $p) then
resultis -1
num = 0
for i=3 to colonIndex-1 do
num = (num lshift 3) + str>>Str.Char↑i - $0
res<<UnPacked.Num = num
switchon str>>Str.Char↑1 into
[
case $D: case $d:
res<<UnPacked.Type = Diablo
RemoveDriveSpec(str, colonIndex)
resultis res
case $T: case $t:
res<<UnPacked.Type = Trident
RemoveDriveSpec(str, colonIndex)
resultis res
default:
resultis -1
]
]
]
and RemoveDriveSpec(str, index) be
[
str>>Str.Len = str>>Str.Len - index
for i=1 to str>>Str.Len do
str>>Str.Char↑i = str>>Str.Char↑(i+index)
]
and Contains(str, char) = valof
[
for i=1 to str>>Str.Len do
if str>>Str.Char↑i eq char then resultis i
resultis 0
]
and AssignStr(str1, str2) be
[
str1>>Str.Len = str2>>Str.Len
for i=1 to str1>>Str.Len do
str1>>Str.Char↑i = str2>>Str.Char↑i
]
and Finish() be
[
for i=0 to 31 do
if triDisks!i then TFSClose(triDisks!i)
if diDisk1 then BFSClose(diDisk1)
@lvUserFinishProc = savedUFP
@lvSwatContextProc = savedSCP
TFSSilentBoot()
]