• Please review our updated Terms and Rules here

Booting from units other than 0 on Emulex UCxx devices

Joined
Oct 4, 2021
Messages
23
Location
Silver Spring, MD
Greetings!

I have a PDP-11/23 and PDP-11/34 both running RT-11. Both machines have Emulex SCSI controllers (a QBUS UC07 and UNIBUS UC18 respectively) that are connected to SCSI2SD drives. The SCSI2SD drives each emulate four units, which are visible to RT-11 as DU0: through DU3:. I have an RT-11 bootable system volumes on DU0: and on DU2:. (Actually, DU2: on both machines contains Ian Hammond's excellent RUST/SJ system, which is compatible enough with RT-11 that this doesn't matter for my question below.)

The Emulex "UC07 and UC08 Intelligent Host Adapter Technical Manual" (see https://archive.org/details/bitsavers_emulexUC07_11161673/mode/2up, for instance) on page 130 (Section 7.5) gives a quick way to boot from DU0: on a PDP-11 that has ODT, e.g. my 11/23. The procedure is also easily adapted to the 11/34's front panel and/or boot ROM monitor.

Basically, you do the following:
Code:
@772150/000000 0
@772152/005400 30003                                                            
@772152/000400 40000
@RS/304
@R0/0
@R1/772150
@0G

This works pretty well, though you must wait for the MSCP reset timeout (that starts once you deposit the 40000) before you issue the start command at the end. This timeout is not documented in the Emulex manual, but the actual boot block load happens after the timeout is completed. Completion is easily verified by watching the drive's activity light or by examining the contents of address 000000. I've also found that the register setup isn't necessary for RT-11.

The above procedure loads the boot block from DU0: via DMA to address 000000. It should be noted that this is "not really" a bootstrap, since really what's happening is that you're issuing a (Emulex-specific?) command to the controller, requesting that it load the boot block into address 000000 via a DMA action. The CPU is otherwise idle while this happens.

My question is this: Is there a way to modify the procedure to load the boot block from some other unit, say DU2:?

I am well aware that I can use a boot ROM or key-in a bootstrap for the other units. That's not what I'm after here, since I am wondering about the Emulex controller's own capabilities :)

I do have some insight. Purely on a lark, I wondered if the first 0 that gets deposited might be a unit number, and so I tried
Code:
@772150/000000 2                                                                
@772152/005400 30003                                                            
@772152/000400 40000
! WAIT 10 seconds or so...!
@0G
and was quite surprised that this did in fact boot from DU2:.

However, the next time I tried this, the machine booted from DU0:.

From my continued experimentation with this, I've found the following:
  • On the 11/23 using the UC07, it looks like DU2: boots with the above procedure about 25% of the time, and DU0: boots the other 75% of the time. Sometimes what's loaded into address 000000 (and following) is corrupted!
  • This never works on the 11/34, which is using the UNIBUS version of the controller, a UC18.
  • Both machines work flawlessly once booted, even under extreme system load, so I know that both the hardware and RT-11 software setup is solid. My question is therefore isolated to the Emulex controller's boot-block-loading shortcut.
From scouring the Emulex manual, it seems that using the Emulex controller's boot procedure on DU2: might be an undocumented feature. Does anyone have any insight?

Thanks!
Michael
 
Interesting. To be clear, I have no trouble getting my setup booted to the way I like it. I'm just curious as to what it's actually doing!

Changing R0 to the unit number does seem to work. That is, the following does seem to ultimately boot from DU2:.
Code:
@772150/000000 0                                                                                                                                                           
@772152/005400 30003                                                                                                                                                       
@772152/000400 40000                                                                                                                                                       
@r0/000000 2                                                                                                                                                               
@r1/000000 772150                                                                                                                                                          
@rs/000000 304                                                                                                                                                             
@0g

I didn't know this trick before, which is odd because I had though I tried it previously :-/. Thanks @wa2flq.

However, doing this process is subtly different than what happens if I key in a bootstrap to boot from DU2: directly (like what @AK6DN does, which for the record also works for me). This suggests that there's some funniness going on. @Ian Hammond suggests that what I might be seeing is that boot block on DU0: (for RT-11) is being loaded, which is then passed the unit number (2) through R0, so that the second stage boot ultimately comes from DU2:. This would mean that the above procedure would not work if DU0: is not a bootable RT-11 system volume.

Well, that's a good thing to test... so now that I've got a working process, I'm going to investigate. I'll report back!

(BTW: assuming that WA2FLQ and AK6DN are your callsigns.. so it's only appropriate to sign like so, FB TNX OM de KB1DDS!)
 
Reporting back... The hypothesis to be tested is that "the Emulex controller boot shortcut process only loads the boot block from DU0:, but can pass unit numbers (to a compatible bootstrap) via R0".

Evidence in favor: Since the Emulex boot block load sequence is done entirely while the CPU is halted, and is done entirely by the controller itself, it doesn't have access to any of the CPU registers. Changing R0 should not change what the controller initially loads. Since it clearly loads from DU0: under the conditions specified in the Emulex manual, it is also loading from DU0: under other conditions.

This can be tested semi-destructively!

I'm going to duplicate the SD card that houses everything and then zero out the first few bytes of the DU0: partition. Obviously this will mean that I cannot boot DU0:. But more importantly, if the above hypothesis is correct, booting from DU2: should become impossible too!

Indeed, it should render the Emulex boot process completely useless until those bytes are restored. Since RUST/SJ has a very helpful patch utility, I'll use that for the job. Its use is self-explanatory.

Here's the prep-work, on my duplicated SD card:
Code:
@772150/000000 0
@772152/005400 30003
@772152/000400 40000
@r0/000000 2               ! Booting from DU2: as others on this thread have taught me...
@r1/000000 772150
@rs/000005 304
@0gBOOT V2.3
RUST/SJ V3.8
...
o ! I have the RUST prompt set to "o" so that I can tell at a glance if I'm in RUST or RT-11
o patch du0:
0         D ..  240     nop      | =0    ! Here I've zeroed out the first byte -> HALT
2        F* ..  415     br      36 | =0   ! Here I've zeroed out the second byte -> HALT
4           ..  0       halt     | x
o

That zeroed out the first few bytes of DU0:, so the boot block should be unusable. Note that I've patched the DU0: bootstrap even though RUST/SJ lives on DU2:, which booted above. A true "cold boot from DU2:" should be unaffected by this patch.

Let's try to instruct the Emulex to boot from DU2: as mentioned earlier.
Code:
@772150/000000 0
@772152/005400 30003
@772152/000400 40000
@r0/132652 2
@r1/150202 772150
@rs/000004 304
@0g
000002

Immediate halt!

Thus, I can conclusively state that passing R0=2 as @wa2flq suggests doesn't actually instruct the Emulex to load the boot block of DU2:. Instead, it still loads the boot block of DU0: and passes the corresponding bootstrap the value of R0 as a parameter. Helpfully, what's there is an RT-11 bootstrap, which interprets R0 as the unit number.

For daily use, this is a great shortcut because RUST/SJ is tolerant of being partially booted by RT-11's boot block. However, it leads to subtle behavioral differences in the boot process that I have been trying to track down and is therefore not quite the answer I was after.

So, my original question still stands, though should be refined a bit, Is there a way to modify the Emulex boot shortcut so that it loads the boot block of a non-zero unit, say DU2: directly, without going through DU0: first?

Given that this is likely an undocumented feature, I'm wondering if others have any further insight. (I'll keep poking of course!)

Thanks!
Michael
 
Well, you can look thru the disassembled ROM code for the UC17/18 controller. Version G143R (latest I believe, what I have) is attached.
ZIP file contains the ROM .BIN, and corresponding .ASM and .LST files.
Somebody posted these about 6 years ago it appears from the time stamps.
 

Attachments

  • G143R_disassembly.zip
    512.4 KB · Views: 7
There is also this from the UC17/18 Manual from bitsavers. I've never tried this (it says 11/24 only) since I use the standard M9312 DU boot prom.
Capture.PNG
 
@AK6DN, Thanks for the ROM listings! Assuming they are for what I think they're for (the CPU living on the UCxx board, which is an Intel machine of some sort), that is just what is needed to dig for undocumented features.

The page from the Emulex manual you attached is precisely what I've been using. The same sequence of deposits is used in my posts!

As I've shown in my earlier post, I've now determined that the "Logical unit number to boot from" is a bit of a red herring. It only works if the boot block on DU0: supports this parameter! What's irritating is that the pages before/after the excerpt are quite uninformative about any further details, like what other possibilities are available, if any.

@wa2flq, I can certainly provide boot block dumps!

The boot block on DU2: is the boot block for RUST/SJ; see below:
Code:
o dump/end=0 du2:                                                                                                                                                          
DU2: Block 0 (00)                                                                                                                                                          
000: 000240 000415 000000 000000 000000 000000 000000 000000 |................|
020: 000000 000000 000000 000000 000000 054020 103420 000400 |...........X....|
040: 000137 000510 000000 000000 000000 000000 000000 000000 |_.H.............|
060: 000000 000000 000000 000000 000400 001402 002404 003406 |................|
100: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
120: 113727 004722 000000 004567 000476 000114 006301 012727 |......w.>.L.....|
140: 000010 000010 000450 004567 000456 000122 005367 177762 |....(.w...R.....|
160: 100514 012705 172150 004567 000436 000111 012725 000000 |L...h.w...I.....|
200: 012703 000460 012704 004000 005715 100755 030415 001774 |..0..........1..|
220: 012315 006304 100371 012767 000510 000240 012767 000510 |........H.....H.|
240: 000236 004567 000362 000114 004567 000140 000011 012727 |..w...L.w.`.....|
260: 000001 000000 000415 006227 000001 103733 004567 000114 |............w.L.|
300: 000041 010064 000034 010164 000014 001436 010264 000020 |!.4...t.........|
320: 016705 177640 004567 000300 000117 012767 100000 000142 |....w...O.....b.|
340: 005725 005715 100700 005767 000130 100773 012767 100000 |........X.......|
360: 000114 005715 100670 005767 000104 100773 105764 000012 |L.......D.......|
400: 001262 006267 177654 103727 000207 000000 012704 000604 |................|
420: 004567 000204 000120 005044 020427 000504 001374 012724 |w...P.$..!D.....|
440: 000074 005724 016764 177454 000004 012564 000010 000205 |<.....,...t.....|
460: 100000 000474 000000 000001 000000 000000 000510 000000 |..<.........H...|
500: 000510 000000 000074 000000 012706 010000 042700 177770 |H...<........E..|
520: 010067 177400 012700 000002 012701 002000 012702 001000 |7...............|
540: 012746 000604 000167 177356 000000 000000 000000 000000 |....w...........|
560: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
600: 000000 000000 012737 000120 004730 012737 016110 004716 |......P.....H...|
620: 016737 177300 004722 000464 105737 177564 100375 112537 |......4...t..._.|
640: 177566 005205 000205 000000 000000 000000 000000 000000 |v...............|
660: 000000 000000 004167 000002 000753 012700 000740 012702 |....w...........|
700: 000722 004712 011100 004712 012700 000764 004712 000000 |....@...........|
720: 000776 105737 177564 100375 112037 177566 001372 000207 |....t.....v.....|
740: 005015 041077 047517 026524 026525 044400 047457 062440 |..?BOOT-U-.I/O e|
760: 071162 071157 005015 000012 177777 177777 177777 177777 |rror............|

(As noted, the boot block on DU2: is apparently never used by the boot process we've been discussing.)

For comparison, the boot block of DU0: is always loaded. Here's the original one (without the "drastic" patch performed in my earlier post), which is for RT-11:
Code:
o dump/end=0 du0:                                                                                                                                                          
DU0: Block 0 (00)                                                                                                                                                          
000: 000240 000415 000000 000000 000000 000000 000000 000000 |................|
020: 000000 000000 000000 000000 000000 054020 103420 000400 |...........X....|
040: 000137 000576 000000 000000 000000 000000 000000 000000 |_.~.............|
060: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
100: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
120: 005767 000506 001403 013727 004722 000000 012767 000010 |..F.............|
140: 000016 006301 006227 000001 103035 004767 000340 005327 |................|
160: 000000 002465 016705 000324 010425 012703 004000 012704 |..5.............|
200: 000404 005715 100764 031503 001774 012415 006303 100371 |......C3........|
220: 022424 010467 000262 010467 000252 004067 000110 000011 |.%7...7...7.H...|
240: 004767 000022 004067 000076 000041 010064 000034 010164 |....7.>.!.4...t.|
260: 000014 010264 000020 016703 000222 012704 000512 012714 |............J...|
300: 100000 012305 005713 100415 005714 100774 005744 012744 |................|
320: 100000 005713 100406 005714 100774 105767 000074 001152 |............<.j.|
340: 000207 005726 000704 012704 000500 005044 020427 000420 |........@.$..!..|
360: 101374 012764 000060 177774 012064 000010 016764 177532 |....0...4.....Z.|
400: 000004 000200 100000 000504 000000 000001 000000 000000 |......D.........|
420: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
440: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
460: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
500: 000000 000000 000000 000000 000000 000000 172150 010046 |............h.&.|
520: 013746 000010 010700 062700 000040 010037 000010 005000 |.......e .......|
540: 000007 020027 000004 001003 012767 176150 177736 012637 |... ......h.....|
560: 000010 012600 000207 052766 000001 000002 000002 012706 |.......U........|
600: 010000 010046 042716 177770 011667 177316 012700 000002 |..&..E..........|
620: 012701 002000 012702 001000 005027 000001 004767 177260 |................|
640: 012737 000120 004730 012737 016110 004716 012637 004722 |..P.....H.......|
660: 000137 001000 004167 000002 000753 012700 000740 012702 |_...w...........|
700: 000722 004712 011100 004712 012700 000764 004712 000000 |....@...........|
720: 000776 105737 177564 100375 112037 177566 001372 000207 |....t.....v.....|
740: 005015 041077 047517 026524 026525 044400 047457 062440 |..?BOOT-U-.I/O e|
760: 071162 071157 005015 000012 177777 177777 177777 177777 |rror............|

Notice that the boot block on DU0: is quite similar to the boot block on DU2:. I suspect this is why the process of passing R0 as the unit number works as well as it does...
 
The CPU on the UC17/18 is an 80C31 device. That is what runs the code version G143R posted back in #6.

Yup. I can spot Intel assembly at a distance :p

I just pulled the UC07 board from my 11/23 to confirm. Same CPU, same code rev.

I'm now poring over the binary dump you posted... hopefully I'll find something interesting! I've already found the messages for the Disk Firmware Resident Diagnostic and have likely succeded at isolating its associated code.

Thanks again!
 
@AK6DN, Thanks for the ROM listings! Assuming they are for what I think they're for (the CPU living on the UCxx board, which is an Intel machine of some sort), that is just what is needed to dig for undocumented features.

The page from the Emulex manual you attached is precisely what I've been using. The same sequence of deposits is used in my posts!

As I've shown in my earlier post, I've now determined that the "Logical unit number to boot from" is a bit of a red herring. It only works if the boot block on DU0: supports this parameter! What's irritating is that the pages before/after the excerpt are quite uninformative about any further details, like what other possibilities are available, if any.

@wa2flq, I can certainly provide boot block dumps!

The boot block on DU2: is the boot block for RUST/SJ; see below:
Code:
o dump/end=0 du2:                                                                                                                                                         
DU2: Block 0 (00)                                                                                                                                                         
000: 000240 000415 000000 000000 000000 000000 000000 000000 |................|
020: 000000 000000 000000 000000 000000 054020 103420 000400 |...........X....|
040: 000137 000510 000000 000000 000000 000000 000000 000000 |_.H.............|
060: 000000 000000 000000 000000 000400 001402 002404 003406 |................|
100: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
120: 113727 004722 000000 004567 000476 000114 006301 012727 |......w.>.L.....|
140: 000010 000010 000450 004567 000456 000122 005367 177762 |....(.w...R.....|
160: 100514 012705 172150 004567 000436 000111 012725 000000 |L...h.w...I.....|
200: 012703 000460 012704 004000 005715 100755 030415 001774 |..0..........1..|
220: 012315 006304 100371 012767 000510 000240 012767 000510 |........H.....H.|
240: 000236 004567 000362 000114 004567 000140 000011 012727 |..w...L.w.`.....|
260: 000001 000000 000415 006227 000001 103733 004567 000114 |............w.L.|
300: 000041 010064 000034 010164 000014 001436 010264 000020 |!.4...t.........|
320: 016705 177640 004567 000300 000117 012767 100000 000142 |....w...O.....b.|
340: 005725 005715 100700 005767 000130 100773 012767 100000 |........X.......|
360: 000114 005715 100670 005767 000104 100773 105764 000012 |L.......D.......|
400: 001262 006267 177654 103727 000207 000000 012704 000604 |................|
420: 004567 000204 000120 005044 020427 000504 001374 012724 |w...P.$..!D.....|
440: 000074 005724 016764 177454 000004 012564 000010 000205 |<.....,...t.....|
460: 100000 000474 000000 000001 000000 000000 000510 000000 |..<.........H...|
500: 000510 000000 000074 000000 012706 010000 042700 177770 |H...<........E..|
520: 010067 177400 012700 000002 012701 002000 012702 001000 |7...............|
540: 012746 000604 000167 177356 000000 000000 000000 000000 |....w...........|
560: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
600: 000000 000000 012737 000120 004730 012737 016110 004716 |......P.....H...|
620: 016737 177300 004722 000464 105737 177564 100375 112537 |......4...t..._.|
640: 177566 005205 000205 000000 000000 000000 000000 000000 |v...............|
660: 000000 000000 004167 000002 000753 012700 000740 012702 |....w...........|
700: 000722 004712 011100 004712 012700 000764 004712 000000 |....@...........|
720: 000776 105737 177564 100375 112037 177566 001372 000207 |....t.....v.....|
740: 005015 041077 047517 026524 026525 044400 047457 062440 |..?BOOT-U-.I/O e|
760: 071162 071157 005015 000012 177777 177777 177777 177777 |rror............|

(As noted, the boot block on DU2: is apparently never used by the boot process we've been discussing.)

For comparison, the boot block of DU0: is always loaded. Here's the original one (without the "drastic" patch performed in my earlier post), which is for RT-11:
Code:
o dump/end=0 du0:                                                                                                                                                         
DU0: Block 0 (00)                                                                                                                                                         
000: 000240 000415 000000 000000 000000 000000 000000 000000 |................|
020: 000000 000000 000000 000000 000000 054020 103420 000400 |...........X....|
040: 000137 000576 000000 000000 000000 000000 000000 000000 |_.~.............|
060: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
100: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
120: 005767 000506 001403 013727 004722 000000 012767 000010 |..F.............|
140: 000016 006301 006227 000001 103035 004767 000340 005327 |................|
160: 000000 002465 016705 000324 010425 012703 004000 012704 |..5.............|
200: 000404 005715 100764 031503 001774 012415 006303 100371 |......C3........|
220: 022424 010467 000262 010467 000252 004067 000110 000011 |.%7...7...7.H...|
240: 004767 000022 004067 000076 000041 010064 000034 010164 |....7.>.!.4...t.|
260: 000014 010264 000020 016703 000222 012704 000512 012714 |............J...|
300: 100000 012305 005713 100415 005714 100774 005744 012744 |................|
320: 100000 005713 100406 005714 100774 105767 000074 001152 |............<.j.|
340: 000207 005726 000704 012704 000500 005044 020427 000420 |........@.$..!..|
360: 101374 012764 000060 177774 012064 000010 016764 177532 |....0...4.....Z.|
400: 000004 000200 100000 000504 000000 000001 000000 000000 |......D.........|
420: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
440: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
460: 000000 000000 000000 000000 000000 000000 000000 000000 |................|
500: 000000 000000 000000 000000 000000 000000 172150 010046 |............h.&.|
520: 013746 000010 010700 062700 000040 010037 000010 005000 |.......e .......|
540: 000007 020027 000004 001003 012767 176150 177736 012637 |... ......h.....|
560: 000010 012600 000207 052766 000001 000002 000002 012706 |.......U........|
600: 010000 010046 042716 177770 011667 177316 012700 000002 |..&..E..........|
620: 012701 002000 012702 001000 005027 000001 004767 177260 |................|
640: 012737 000120 004730 012737 016110 004716 012637 004722 |..P.....H.......|
660: 000137 001000 004167 000002 000753 012700 000740 012702 |_...w...........|
700: 000722 004712 011100 004712 012700 000764 004712 000000 |....@...........|
720: 000776 105737 177564 100375 112037 177566 001372 000207 |....t.....v.....|
740: 005015 041077 047517 026524 026525 044400 047457 062440 |..?BOOT-U-.I/O e|
760: 071162 071157 005015 000012 177777 177777 177777 177777 |rror............|

Notice that the boot block on DU0: is quite similar to the boot block on DU2:. I suspect this is why the process of passing R0 as the unit number works as well as it does...
 
The boot code generally looks okay. I use UC07 which uses the same ROM.

I speculate that this code sets up the registers in the UC07/17/18 directly. I have not dug into the details of the ROM Don supplied, but I think it reads first block of the boot scsi device directly (not using the PDP-11/LSI-11 bootstrap or alternate bootstrap). Then it downloads it at address 0, perhaps by direct DMA (because it can). Next you supply the unit number and controller address. Then you should be off to the races. I haven't verified all of this.

Note that some/most versions of RT11 <v5.6 cannot MSCP boot from anything other than the first SCSI unit (#0).
 
I speculate that this code sets up the registers in the UC07/17/18 directly. I have not dug into the details of the ROM Don supplied, but I think it reads first block of the boot scsi device directly (not using the PDP-11/LSI-11 bootstrap or alternate bootstrap). Then it downloads it at address 0, perhaps by direct DMA (because it can). Next you supply the unit number and controller address.

That's my impression now too.

So my question is whether there's an (undocumented) way to get the Emulex to read something else for you instead of the first block of the boot SCSI device. There may or may not be, depending on exactly how this boot "routine" was written. I spent several hours yesterday digging through the ROM to isolate where this loading happens. I'm not there yet... but there's a lot of interesting activity that the controller has to orchestrate! It is, like most microcontroller code I've seen (and written!) a bit of a spaghetti mess...

Interesting finding thus far: the ROM seems to contain code for at least three CPUs,
  1. Intel 8051(actually 80C31 but it's the same instruction set)
  2. VAX (I realized last night that the reason why the code I thought was for PDP-11 but couldn't disassemble as such was because it's for VAX...)
  3. PDP-11 (haven't located this yet, but am strongly suspicious it's there)
Basically, the entirety of the drive diagnostics code (for VAX and PDP-11) appears to be on the same ROM as everything else. I haven't isolated the 8051 code that does the deed, but it looks like the diagnostics code is pulled wholesale from the ROM and sent over to the host via a DMA transaction. I had initially thought that there might be a second ROM that holds these diagnostics due to space constraints, but no, everything's apparently there. (This also means that there is extensive use of MOVC instructions to read from the program space.)
 
Back
Top