// DiskProms.bcpl
// last modified January 18, 1982 11:22 AM by Taft
external DiskProms
get "DoradoProms.defs"
external [ Min ]
static addr
manifest
[
Pin1 = #200; Pin2 = #100; Pin3 = #40; Pin4 = #20
Pin5 = #10; Pin6 = 4; Pin7 = 2; Pin9 = 1
]
let DiskProms(mem) be
[
let buff = vec 300
if StEq(mem,"DskEth") then mem!0 = DoAll
if StEq(mem,"DiskWrite") & ICtype eq MC10139 then // define the write Prom
[
MakeCont(buff,false)
Header("DiskWrite",8,buff,32,8)
PromCommand("Disk-a20")
]
if StEq(mem,"DiskRead") & ICtype eq MC10139 then // define the read Prom
[
MakeCont(buff,true)
Header("DiskRead",8,buff,32,8)
PromCommand("Disk-a21")
]
if StEq(mem,"DiskTag") & ICtype eq MC10149 then // define the Tag Timing Prom
[
MakeTagTiming(buff)
Header("DiskTag",4,buff,32,12)
PromCommand("Disk-d21")
]
if StEq(mem,"DiskFifo") & ICtype eq MC10149 then // define the Fifo Pointers Prom
[
MakeFifoPointers(buff)
Header("DiskFifo",4,buff,256,12)
PromCommand("Disk-b14")
]
if StEq(mem,"DiskUnits") & ICtype eq N74288 then //now define the Drive Select Prom
[
MakeDriveSelect(buff)
Header("DiskUnits",8,buff,32,8)
PromCommand("Disk-d05")
]
]
and MakeCont(buff,ReadFlag) be
[
//first define a bunch of constants
manifest
[
LoadSR = Pin1; ReadSR = Pin1
CompECC = Pin2//configure ECC generator for genoration
NewBlock = Pin3//shift command reginster AT START OF THIS INSTRUCTIOM
Tag = Pin4//Load value addressed by RAM into Tag register
//otherwose load value addressed by RAM into the count register
]
manifest
[ //These define the LOCATION of parameters within the RAM register
Count0 = 0 //Number of words in block 0.
Count1 = 1 //Number of words in block 1.
Count2 = 2 //Number of words in block 2.
Count3 = 3 //Number of words in block 3.
ReadComm=4+Tag //Tag Command to cause a Read operation.
WriteComm =5+Tag //Tag Command to cause a Write operation.
InitComm =6+Tag //Tag Command leading to a read or write.
ResetComm =7+Tag //Tag Command to zero all bits of TAG register.
WrDlyFirst=8 //Number of "0 words" to Write before the data of 1st block.
WrDlyNext=9 //Number of "0 words" to Write before the data of other blocks.
RdDlyFirst=10 //Number of words to wait before reading the 1st block.
RdDlyNext=11 //Number of words to wait before other reads.
Delay3=12 //used for ECC count plus 1
Delay2 = 13 //used for ECC count and Head select delay.
Delay1=14 //Minimum count time.
]
//~~~~~~~~~~~~
//now "Program" the READ/WRITE proms
test ReadFlag
ifso //define all the commands necessary to read all blocks of the disk
[ //NOTE: the controller may sitch from Read to Write after executing "NewBlock"
//Initialization
buff!00 = InitComm // enable the heads
buff!01 = Delay2 // wait for disk to settle
//Commands for Reading the first Block
buff!02 = RdDlyFirst //wait for heads over zeros
buff!03 = ReadComm //waits for the "sync" pattern
buff!04 = Count0 + CompECC + ReadSR //read in the "block" words
buff!05 = Delay2 + CompECC + ReadSR //read the ECC words
buff!06 = InitComm + ReadSR //read one word of ECC,turn off read
buff!07 = Delay1 + ReadSR //read last word of ECC
buff!08 = Delay1 + NewBlock //get the next block
//Commands for Reading the second Block
buff!09 = RdDlyNext //wait for heads over zeros
buff!10 = ReadComm //waits for the "sync" pattern
buff!11 = Count1 + CompECC + ReadSR //read in the "block" words
buff!12 = Delay2 + CompECC + ReadSR //read the ECC words
buff!13 = InitComm + ReadSR //read one word of ECC,turn off read
buff!14 = Delay1 + ReadSR //read last word of ECC
buff!15 = Delay1 + NewBlock //get the next block
//Commands for Reading the third Block
buff!16 = RdDlyNext //wait for heads over zeros
buff!17 = ReadComm //waits for the "sync" pattern
buff!18 = Count2 + CompECC + ReadSR //read in the "block" words
buff!19 = Delay2 + CompECC + ReadSR //read the ECC words
buff!20 = InitComm + ReadSR //read one word of ECC,turn off read
buff!21 = Delay1 + ReadSR //read last word of ECC
buff!22 = Delay1 + NewBlock //get the next block
//Commands for Reading the fourth Block
buff!23 = RdDlyNext //wait for heads over zeros
buff!24 = ReadComm //waits for the "sync" pattern
buff!25 = Count3 + CompECC + ReadSR //read in the "block" words
buff!26 = Delay2 + CompECC + ReadSR //read the ECC words
buff!27 = InitComm + ReadSR //read one word of ECC,turn off read
buff!28 = Delay1 + ReadSR //read last word of ECC
buff!29 = Delay1 + NewBlock //get the next block
//Reset the Tag register and clear out commands
buff!30 = ResetComm+NewBlock
buff!31 = ResetComm+NewBlock
]
ifnot //define all the commands necessary to write all blocks of the disk
[ //NOTE: the controller may sitch from Read to Write after executing "NewBlock"
//Initialization
buff!00 = InitComm // enable the heads
buff!01 = Delay2 // wait for disk to settle
//Commands for Writing the first Block
buff!02 = WriteComm //send a tag with write bit on
buff!03 = WrDlyFirst //now wait for disk to settle
buff!04 = Delay1 + CompECC+ LoadSR //send the "sync" word
buff!05 = Count0 + CompECC+ LoadSR //send the "block" words
buff!06 = Delay1 + CompECC //compute ECC on last word
buff!07 = Delay3 //shift out ECC plus word of zero's
buff!08 = Delay1 + NewBlock //get the next block
//Commands for Writing the second Block
buff!09 = WriteComm //send a tag with write bit on
buff!10 = WrDlyNext //now wait for disk to settle
buff!11 = Delay1 + CompECC+ LoadSR //send the "sync" word
buff!12 = Count1 + CompECC+ LoadSR //send the "block" words
buff!13 = Delay1 + CompECC //compute ECC on last word
buff!14 = Delay3 //shift out ECC plus word of zero's
buff!15 = Delay1 + NewBlock //get the next block
//Commands for Writing the third Block
buff!16 = WriteComm //send a tag with write bit on
buff!17 = WrDlyNext //now wait for disk to settle
buff!18 = Delay1 + CompECC+ LoadSR //send the "sync" word
buff!19 = Count2 + CompECC+ LoadSR //send the "block" words
buff!20 = Delay1 + CompECC //compute ECC on last word
buff!21 = Delay3 //shift out ECC plus word of zero's
buff!22 = Delay1 + NewBlock //get the next block
//Commands for Writing the fourth Block
buff!23 = WriteComm //send a tag with write bit on
buff!24 = WrDlyNext //now wait for disk to settle
buff!25 = Delay1 + CompECC+ LoadSR //send the "sync" word
buff!26 = Count3 + CompECC+ LoadSR //send the "block" words
buff!27 = Delay1 + CompECC //compute ECC on last word
buff!28 = Delay3 //shift out ECC plus word of zero's
buff!29 = Delay1 + NewBlock //get the next block
//Reset the Tag register and clear out commands
buff!30 = ResetComm+NewBlock
buff!31 = ResetComm+NewBlock
]
]
and MakeTagTiming(buff) be
[
manifest [ TagStrobe = 4; TagDone = 2; CntOff = 1 ]
Zero(buff,256)
for adr = 0 to 31 do
[
let Active = adr
let Cnt = adr
let output = 0
if (Cnt ge 3) & (Cnt le 13) then buff!adr = TagStrobe
if (Cnt eq 12) & (Active ne 0) then buff!adr = buff!adr % CntOff
if Cnt eq 15 then buff!adr = TagDone
]
]
and MakeFifoPointers(buff) be
[
manifest [ Full = #10; WriteEn = 4; ReadEn = 2; Empty = 1 ]
Zero(buff,256)
let InvertBits = WriteEn % ReadEn
for adr = 0 to 255 do
[
let Waddr = adr rshift 4
let Raddr = adr & #17
let Delta = (Waddr-Raddr)
if Delta eq 0 then buff!adr = Empty
if Delta eq 15 then buff!adr =Full // 14B. change to accommodate lost fix
if Delta ge 2 then buff!adr = buff!adr % ReadEn
if Delta ls 12 then buff!adr = buff!adr % WriteEn
buff!adr = buff!adr xor InvertBits
]
]
and MakeDriveSelect(buff) be
[
structure Input:
[
blank bit 11
select bit 1 // 1 => select addressed drive
driveNum bit 4 // drive number
]
structure Output:
[
blank bit 8
select0 bit 1 // select drive 0 (unary encoded)
select1 bit 1 // select drive 1
select2 bit 1 // select drive 2
select3 bit 1 // select drive 3
driveNum bit 2 // addressed drive (binary encoded)
blank bit 2
]
for adr = 0 to 31 do
[
let output = 0
// drive numbers greater than 3 address drive 3
output<<Output.driveNum = Min(adr<<Input.driveNum, 3)
if adr<<Input.select then
switchon adr<<Input.driveNum into
[
case 0: output<<Output.select0 = 1; endcase
case 1: output<<Output.select1 = 1; endcase
case 2: output<<Output.select2 = 1; endcase
default: output<<Output.select3 = 1; endcase
]
buff!adr = output
]
]