HP11305 Disk Controller Microcode
---------------------------------
00 : 5ED18  Clear CtrlOut
            goto(18)
18 : 0BF19  Clear Data Path
            goto(19)
19 : 5FC1A  Set CRC to WD
            ClrSktst
            goto(1A)
1A : 3FD1B  Set SR A SOut En
            goto(1B)
1B : 7D71C  Clear SR A Sout En
            goto(1C)
1C : 05A1D  Clr SIn En
            Clear SR A En
            Clear A Sel
            goto(1D)
1D : 85B1E  Clear B Sel
            Clear SR to D
            goto(1E)
1E : 74B7E  Clear D to SR
            Clear CRC to WD
            goto(7E)

Power on initialisation.Disable shift registers and data transfer.

----
** Main Command Loop **
----

7E : 9BF1F  ClrCacheAddr
            goto(1F)
Start of main loop. Clear cache memory address counter

1F : ABF20  LdAddr
            goto(20)
Clear drive selected flag flip-flop (ROM PCB U8b)

20 : 5ED21  Clear CtrlOut
            goto(21)
21 : FFF22  goto(22)
22 : FFF23  goto(23)
23 : FFFF8  goto(F8)
Delay for 4 microcycles

F8 : FFFE3  pause(Request),goto(E3)
Wait for a calculator to request access to the disk controller.

E3 : 5FD13  ClrSktst
            pause(CalcStb),goto(13)
Clear seek error flag, wait for calculator to select drive

13 : FFF14  goto(14)
14 : FFFF5  goto(F5)
Wait for a couple of microcycles

F5 : AAE6F  LdAddr
            SetHdEn
            if(AddrSel)goto(6f,4f)
Strobe calculator outputs to address register. If AddrSel is asseted by 
the HP9830 at this point, the software has got out of step with the 
controller So treat this as an illegal command and do a restore, etc.

4F : FFF24  goto(24)
THis is a valid command

24 : B7B25  Set Head
            Clr SR A
            goto(25)
Set drive head and sector select. Clear first shift register 

25 : BF7F3  Stat
            goto(F3)
Send 'OK' to calculator

F3 : FFF26  pause(CalcStb),goto(26)

Wait for calculator strobe (to drive select latch). 

26 : ABF27  LdAddr
            goto(27)
Load Cylinder to address register

27 : 5BF28  Clear CycSel
            goto(28)
Clear cycle length select

28 : BED29  SetCylEn
            goto(29)
29 : FFF2A  goto(2A)
2A : BD72B  SetCyl
            goto(2B)

Set drive cylinder

2B : FFF2C  goto(2C)
2C : DEECE  SetCmd
            goto(CE)
Set drive command

CE : FFF6F  if(CmdOK)goto(6f,2f)
Is the command valid? Go to the illegal comamnd routine if the cylidner 
is out of range, or a similar problem.

2F : 37FE9  Tr On
            goto(E9)
Enable data transfer

E9 : FFFEF  pause(SectorFnd),goto(EF)
Wait for the sector to come round

EF : FFF7F  if(Format)goto(7f,7b)
Is this an initialise command (Init switch setting is checked in hardware)?

----
** Illegal Command Error **
----

6F : 9FD2D  Set Calc Ib
            goto(2D)
Restore. Send 'Command Error' to calculator

2D : BF72E  Stat
            goto(2E)
Send 'OK' to calculator.

2E : B577E  Set Head
            SetCyl
            goto(7E)
Asserting Set Cylinder and Set Head will cause the drive to restore to
cylinder 0. Then go back to get another command

----
** Initialise Command **
----

7B : 5FC30  Set CRC to WD
            ClrSktst
            goto(30)
Disable Shift register serial outputs, clear calculator status signals and 
cycle counter

30 : 7CB46  Clear CRC to WD
            goto(46)
Completely disable write data line to drive (other drivers disabled by 
previous instruction  Go to write sector routine


----
** Read and Write commands **
----

First read the header and check the sector address

7F : 5FE31  Set CRC to WD
            goto(31)
Disable shift register outputs

31 : 57D32  Tr Off
            ClrSktst
            goto(32)
Force drive into read mode (even if it's a write command)

32 : FFF33  goto(33)
skip a cycle

33 : DEE34  SetCmd
            goto(34)
Load drive command

34 : 17EFA  Set Inst SR Clock
            Clear SR A En
            goto(FA)
Disable shift register A

FA : A7F35  Set Ctrl Out
            pause(SectorPulse),goto(35)
Start reading and wait for sector pulse

35 : 78B36  Set MClkSel
            Clear CRC to WD
            goto(36)
Select PLL clock from data separator (for reading)

36 : 8BFE7  Clear SR B Load
            goto(E7)
Disable shift register B

E7 : 3CBC0  Set Rd Sync
            pause(RdFnd),goto(C0)
Wait for '1' bit in preamble

C0 : 1FD37  Set CCLk En
            pause(Cyc15),goto(37)
Start cycle counter, wait for rest of preamble

37 : 1AD38  Set SR B En
            Set SIn En
            goto(38)
38 : FFFC1  goto(C1)
C1 : FFF39  pause(HCyc7),goto(39)
Read first address byte into shift register B

39 : 8AE3A  Clear SR B Load
            Set SR A En
            goto(3A)
3A : FFFD1  goto(D1)
D1 : FFF3B  pause(HCyc7),goto(3B)
And second address byte into shift register A

3B : 03E3C  Clear Data Path
            Clr SIn En
            Clear SR A En
            goto(3C)
Disable shifting

3C : 7EE3D  Clear MClkSel
            goto(3D)
Select the crystal clock

3D : FFF3E  goto(3E)
3E : 5EDE6  Clear CtrlOut
            goto(E6)
Stop drive reading

E6 : FFF5F  if(AddrEq)goto(5f,57)
Is this the right sector?

5F : 37F6F  Tr On
            goto(6F)
No, go round again to get new address.

----
** Sector found, now start data transfer **
----

57 : BF3D3  Clr SR A
            Stat
            goto(D3)
Clear shift register A, send status signal to calculator

D3 : 37F3F  Tr On
            pause(CalcStb),goto(3F)
Wait for calculator strobe (offset address)

3F : BFE40  ClrCRC
            goto(40)
Clear CRC generator

40 : AAE42  LdAddr
            SetHdEn
            goto(42)
Load offset address into address register, enable head address to drive Outbus

42 : FFF44  goto(44)
44 : B7FF2  Set Head
            goto(F2)
Strobe head address into drive

F2 : 5FDD9  ClrSktst
            if(DrWr)goto(d9,c9)
Go to appropriate read or write sector routine

----
** Read Sector **
----

C9 : DEE63  SetCmd
            pause(SectorFnd),goto(63)
Send (read) command to drive, wait for drive hardware to find the sector

63 : FFF64  goto(64)
Wait for cable buffers to settle

64 : A7FEA  Set Ctrl Out
            goto(EA)
Strobe command into drive

EA : 5BF65  Clear CycSel
            pause(SectorPulse),goto(65)
Select short cycle counts and clear cycle counter. Wait for next sector pulse

65 : 7BF66  Set MClkSel
            goto(66)
Select PLL clock from data separator (for reading)

66 : FFF67  goto(67)
67 : 3CBF7  Set Rd Sync
            goto(F7)
F7 : FFFB0  pause(RdFnd),goto(B0)
Wait for header word '1' to be found

B0 : 1FC68  Clear SR A En
            Set CCLk En
            pause(Cyc15),goto(68)
Read rest of preamble

68 : 67F69  Set Sin to CRC
            goto(69)
69 : 47FD0  Set CRC Clock En
            goto(D0)
Start reading words into the CRC register

D0 : 8BF6A  Clear SR B Load
            pause(Cyc15),goto(6A)
Skip address word

6A : 12D6B  Set SR B En
            Set Inst SR Clock
            Set SIn En
            goto(6B)
6B : FFFFD  goto(FD)
FD : FFF6C  pause(HCyc7),goto(6C)
Read a byte into shift register B


6C : 8866D  Clear SR B Load
            Set SR A En
            Set B Sel(b)
            goto(6D)
Start reading into shift register A

6D : 6BF6E  Set SR to D
            goto(6E)
Enable transfer from shift register B to cache

6E : BE7BD  CacheStart
            goto(BD)
Start of data transfer loop. Write data into cache

BD : FFF70  pause(HCyc7),goto(70)
Wait for next byte to be transfered

70 : 1BE71  Set SR B En
            Clear SR A En
            goto(71)
Start reading data into shift register B

71 : 87FEB  Clear B Sel
            goto(EB)
EB : 3FB43  Set A Sel(a)
            if(EoCache)goto(43,41)
Enable transfer from shift register A to cache, check to see if entire 
sector has been read


43 : BE7DD  CacheStart
            goto(DD)
No, write next byte to cache

DD : FFF73  pause(HCyc7),goto(73)
Wait for byte to be read from disk

73 : 8AE74  Clear SR B Load
            Set SR A En
            goto(74)
74 : 3DB75  Clear A Sel
            goto(75)
Read data into shift register A

75 : BC76E  Set B Sel(b)
            goto(6E)
Enable transfer from shift register B to cache and go round again

41 : BE7CD  CacheStart
            goto(CD)
Yes, all data bytes have been read. Write final byte to cache

CD : FFF72  pause(HCyc7),goto(72)
72 : 89B76  Clear SR B Load
            Clear SR to D
            goto(76)
76 : FFFAD  goto(AD)
AD : 05B77  Clr SIn En
            Clear A Sel
            pause(HCyc7),goto(77)
Disable data shift registers, read CRC field into CRC register

77 : 0BF78  Clear Data Path
            goto(78)
Disable CRC register clock and cycle counter clock

78 : 7EE79  Clear MClkSel
            goto(79)
Select crystal clock

79 : FFFF4  goto(F4)
F4 : 5ED7D  Clear CtrlOut
            if(CRCZero)goto(7d,7c)
Check CRC to see if sector has been read correctly. If so, go to end of 
command routine


7D : 7EB17  Set Calc Ia
            goto(17)
CRC error : Set calculator error flag. Ia = CWE (Check Word Error)

17 : BF716  Stat
            goto(16)
And command completed flag

16 : FFF7E  goto(7E)
Go back and get another command

----
** Write Sector **
----
D9 : FFF46  pause(SectorFnd),goto(46)
Wait for drive to find sector, then start writing

----
** Write data to drive, used by write sector and initialise commands **
----

46 : DEE48  SetCmd
            goto(48)
Send command to drive

48 : BCB49  Set CycSel
            goto(49)
Select long cycle counts

49 : A7FF1  Set Ctrl Out
            goto(F1)
Send drive control strobe, start drive writing

F1 : 13D4A  Set SR B En
            Set Inst SR Clock
            Set CCLk En
            pause(HCyc7),goto(4A)
Enable clock to shift register B, enable shift register clock, enable 
cycle counter.

4A : 07F4B  Clr SIn En
            goto(4B)
Disable shift register B clock, force 1 so serial input

4B : FFFFC  goto(FC)
Skip a cycle

FC : FFF4C  pause(HCyc12),goto(4C)
Wait while writing preamble

4C : 5994D  Clear CycSel
            ClrSktst
            Set SR B SOut En
            goto(4D)
Select short cycle counts, clear cycle counter, select SR B and enable 
path to write data encoder

4D : 23F81  Set SR A Load
            Set SR B Load
            goto(81)
Enable loading of both shift registers,

81 : 3FD4E  Set SR A SOut En
            pause(HCyc7),goto(4E)
Enable shift register A to write data encoder, pause while transferred to 
drive -- write header sync word

4E : 12350  Set SR B En
            Set Inst SR Clock
            Set B Sel(a)
            Set Addr to SR
            goto(50)
Enable clock to Shift register B, enable shift register clock, enable 
buffers from address registers to SR,  load address words into shift 
registers

50 : BE791  CacheStart
            goto(91)
Read a word from the cache for the first time in the data write loop

91 : 83F51  Clear SR B Load
            Clear B Sel
            pause(HCyc7),goto(51)
Disable shift register B

51 : 9EC52  Set SR A En
            Set A Sel(b)
            goto(52)
Enable shift register A, enable data transfer to A

52 : 413A1  Set SOUT to CRC
            Set CRC Clock En
            Set SR B SOut En
            Clear SR A Sout En
            goto(A1)
Enable SR to CRC generator, start CRC generator running, select shift 
register B.

Preamble written, address words in shift registers, cache read. Now start 
the data transfer loop to write the address and data words to the disk.

--

A1 : 19A53  Set SR B En
            Clear SR A En
            Clear A Sel
            pause(HCyc7),goto(53)
Transfer SR B to drive, disable SR A 

53 : 26954  Set SR B Load
            Set D to SR
            Set B Sel(a)
            goto(54)
Load SR B from cache.

54 : 3FD55  Set SR A SOut En
            goto(55)
Enable shift register A to write data encoder and CRC generator

55 : 82E56  Clear SR B Load
            Clear B Sel
            Set SR A En
            goto(56)
Start shift register A transferring to drive and CRC generator

56 : BE7B1  CacheStart
            goto(B1)
Read next word from cache

B1 : FFF58  pause(HCyc7),goto(58)
Wait for shift register transfer to finish.

58 : 2BB59  Set SR A Load
            Set A Sel(a)
            goto(59)
Load shift A from cache

59 : 7D3FB  Set SR B SOut En
            Clear SR A Sout En
            goto(FB)
Enable shift register B to write data encoder and CRC generator

FB : 19A47  Set SR B En
            Clear SR A En
            Clear A Sel
            if(EoCache)goto(47,45)
Start shift register B transfer, test if at end of cache

47 : BE7A1  CacheStart
            goto(A1)
Round again if not at end of cache

45 : FFFE1  goto(E1)
Skip a cycle

E1 : 77F5A  Clear D to SR
            pause(HCyc7),goto(5A)
Disable cache transfers to shift registers

5A : 8BF5B  Clear SR B Load
            goto(5B)
5B : 3FDED  Set SR A SOut En
            goto(ED)
ED : 9EE5C  Set SR A En
            pause(HCyc7),goto(5C)
Complete writing last byte from cache


5C : 1FE5D  Clear SR A En
            goto(5D)
Disable data shift registers

5D : 5D6F0  Set CRC to WD
            Clear SR A Sout En
            goto(F0)
Start transferring CRC register to drive

F0 : FFF5E  pause(Cyc15),goto(5E)
Wait for this to complete

5E : 7CB60  Clear CRC to WD
            goto(60)
Disable CRC register

60 : FFFE0  goto(E0)
E0 : FFF15  pause(Cyc15),goto(15)
15 : FFFA0  goto(A0)
A0 : FFF61  pause(Cyc15),goto(61)
Write postamble (2 words of zeros)

61 : 5ED62  Clear CtrlOut
            goto(62)
Turn off drive write enable.

62 : 03F7C  Clear Data Path
            Clr SIn En
            goto(7C)
Stop CRC and cycle clocks

----
** End of command **
----

7C : BF77A  Stat
            goto(7A)
Send command complete signal to calculator

7A : 5FD7E  ClrSktst
            goto(7E)
End of command, back to start of main loop.

----
** Unused states **
----
01 : 0CF78  goto(78)
02 : 0CF78  goto(78)
03 : 0CF78  goto(78)
04 : 0CF78  goto(78)
05 : 0CF78  goto(78)
06 : 0CF78  goto(78)
07 : 0CF78  goto(78)
08 : 0CF78  goto(78)
09 : 0CF78  goto(78)
0A : 0CF78  goto(78)
0B : 0CF78  goto(78)
0C : 0CF78  goto(78)
0D : 0CF78  goto(78)
0E : 0CF78  goto(78)
0F : 0CF78  goto(78)
10 : 0CF78  goto(78)
11 : 0CF78  goto(78)
12 : 0CF78  goto(78)
80 : 0CF78  pause(Cyc15),goto(78)
82 : 0CF78  if(DrWr)goto(78,68)
83 : 0CF78  pause(CalcStb),goto(78)
84 : 0CF78  if(CRCZero)goto(78,78)
85 : 0CF78  if(AddrSel)goto(78,58)
86 : 0CF78  if(AddrEq)goto(78,70)
87 : 0CF78  pause(RdFnd),goto(78)
88 : 0CF78  pause(Request),goto(78)
89 : 0CF78  pause(SectorFnd),goto(78)
8A : 0CF78  pause(SectorPulse),goto(78)
8B : 0CF78  if(EoCache)goto(78,78)
8C : 0CF78  pause(HCyc12),goto(78)
8D : 0CF78  pause(HCyc7),goto(78)
8E : 0CF78  if(CmdOK)goto(78,38)
8F : 0CF78  if(Format)goto(78,78)
90 : 0CF78  pause(Cyc15),goto(78)
92 : 0CF78  if(DrWr)goto(78,68)
93 : 0CF78  pause(CalcStb),goto(78)
94 : 0CF78  if(CRCZero)goto(78,78)
95 : 0CF78  if(AddrSel)goto(78,58)
96 : 0CF78  if(AddrEq)goto(78,70)
97 : 0CF78  pause(RdFnd),goto(78)
98 : 0CF78  pause(Request),goto(78)
99 : 0CF78  pause(SectorFnd),goto(78)
9A : 0CF78  pause(SectorPulse),goto(78)
9B : 0CF78  if(EoCache)goto(78,78)
9C : 0CF78  pause(HCyc12),goto(78)
9D : 0CF78  pause(HCyc7),goto(78)
9E : 0CF78  if(CmdOK)goto(78,38)
9F : 0CF78  if(Format)goto(78,78)
A2 : 0CF78  if(DrWr)goto(78,68)
A3 : 0CF78  pause(CalcStb),goto(78)
A4 : 0CF78  if(CRCZero)goto(78,78)
A5 : 0CF78  if(AddrSel)goto(78,58)
A6 : 0CF78  if(AddrEq)goto(78,70)
A7 : 0CF78  pause(RdFnd),goto(78)
A8 : 0CF78  pause(Request),goto(78)
A9 : 0CF78  pause(SectorFnd),goto(78)
AA : 0CF78  pause(SectorPulse),goto(78)
AB : 0CF78  if(EoCache)goto(78,78)
AC : 0CF78  pause(HCyc12),goto(78)
AE : 0CF78  if(CmdOK)goto(78,38)
AF : 0CF78  if(Format)goto(78,78)
B2 : 0CF78  if(DrWr)goto(78,68)
B3 : 0CF78  pause(CalcStb),goto(78)
B4 : 0CF78  if(CRCZero)goto(78,78)
B5 : 0CF78  if(AddrSel)goto(78,58)
B6 : 0CF78  if(AddrEq)goto(78,70)
B7 : 0CF78  pause(RdFnd),goto(78)
B8 : 0CF78  pause(Request),goto(78)
B9 : 0CF78  pause(SectorFnd),goto(78)
BA : 0CF78  pause(SectorPulse),goto(78)
BB : 0CF78  if(EoCache)goto(78,78)
BC : 0CF78  pause(HCyc12),goto(78)
BE : 0CF78  if(CmdOK)goto(78,38)
BF : 0CF78  if(Format)goto(78,78)
C2 : 0CF78  if(DrWr)goto(78,68)
C3 : 0CF78  pause(CalcStb),goto(78)
C4 : 0CF78  if(CRCZero)goto(78,78)
C5 : 0CF78  if(AddrSel)goto(78,58)
C6 : 0CF78  if(AddrEq)goto(78,70)
C7 : 0CF78  pause(RdFnd),goto(78)
C8 : 0CF78  pause(Request),goto(78)
CA : 0CF78  pause(SectorPulse),goto(78)
CB : 0CF78  if(EoCache)goto(78,78)
CC : 0CF78  pause(HCyc12),goto(78)
CF : 0CF78  if(Format)goto(78,78)
D2 : 0CF78  if(DrWr)goto(78,68)
D4 : 0CF78  if(CRCZero)goto(78,78)
D5 : 0CF78  if(AddrSel)goto(78,58)
D6 : 0CF78  if(AddrEq)goto(78,70)
D7 : 0CF78  pause(RdFnd),goto(78)
D8 : 0CF78  pause(Request),goto(78)
DA : 0CF78  pause(SectorPulse),goto(78)
DB : 0CF78  if(EoCache)goto(78,78)
DC : 0CF78  pause(HCyc12),goto(78)
DE : 0CF78  if(CmdOK)goto(78,38)
DF : 0CF78  if(Format)goto(78,78)
E2 : 0CF78  if(DrWr)goto(78,68)
E4 : 0CF78  if(CRCZero)goto(78,78)
E5 : 0CF78  if(AddrSel)goto(78,58)
E8 : 0CF78  pause(Request),goto(78)
EC : 0CF78  pause(HCyc12),goto(78)
EE : 0CF78  if(CmdOK)goto(78,38)
F6 : 0CF78  if(AddrEq)goto(78,70)
F9 : 0CF78  pause(SectorFnd),goto(78)
FE : 0CF78  if(CmdOK)goto(78,38)
FF : 0CF78  if(Format)goto(78,78)
