Here are disk_$pv_assign_n results with 'stock' and patched kernels:

Drive   System  Type    Reported Blocks
-----   ------  ----    ---------------
8760    4500    608      a0f8c
4.5G    4500    71b      417a3
4.5G    5500    71b      105e8
2.1G    3500    7d6     1ff0c0
4.5G    4500    701     4417A3  (patched kernel)
4.5G    5500    701     1105e8  (patched kernel)

The read capacity command of the mts tool shows that the 4.5G drive
reports a capacity of 8924999 (0x882f47) blocks, with a block size of
512 bytes.

The problem is that the kernel code that determines the capacity of a
physical volume is not written for capacities that exceed 2^32 bytes. 
In the case of the 4.5G drive, the capacity is 8,924,999*512 bytes,
which comes to 4,569,599,488, or 0x1105e8e00.  This number exceeds 32
bits, and becomes 0x105e8e00, which divides by the page size of the node
to become either 0x105e8 or 0x417a3 blocks.  Note that the DN4500 has a
1K page size, and the DN5500 has a 4K page size.

The simplest fix for the problem is to reorder the code that does the
multiply/divide.  The compiler generates two LSR instructions for the
division.  If one of these is moved to operate on the blocksize, then
the multiply won't overflow.


*********************************************************************************
Kernel code that determines number of blocks ...  Note that it will overflow
 for a large drive.  Can we reorder the operations?
7A423CD0: MOVE.l      (a2),d0                       * d0 = numblocks
7A423CD2: MULS.l      ($4,a2),d0                    * d0 *= blocksize
7A423CD8: MOVE.l      d0,d1                         * d1=d0
7A423CDA: LSR.l       #$8,d1                        * d1 /= 4096 (page size)
7A423CDC: LSR.l       #$4,d1                        *
7A423CDE: MOVE.l      d1,($FFFFFFE0,a6)             * local_b_per_pvol = d1

Here is a proposed reordering that will support drives up to 1000G, assuming that
 the blocksize is 512 bytes:
 MOVE.l      ($4,a2),d0                    * d0 = blocksize
 LSR.l       #$8,d0                        * d0 /= 256  (assumes blocksize is multiple of 256)
 MULS.l      (a2),d0                       * d0 *= numblocks
 MOVE.l      d0,d1                         * d1=d0
 LSR.l       #$4,d1                        * d1 /= 16
 MOVE.l      d1,($FFFFFFE0,a6)             * local_b_per_pvol = d1

Here is a code fragment that will support drives up to ???G, without limitations on
 blocksize:
    move.l      (a2),d0
        2012
    mulu.l      (4,a2),d1:d0
        4c2a  0401  0004
    divu.l      #4096, d1:d0
        4cf4  0401  0000 1000
    move.l      d0,($ffffffe0,a6)
        2D40  FFE0
However, it does not fit in the 16 byte space that is required.

Here is an edit transcript for /sau14/domain_os.big:
$ rs fedit -w domain_os.big
editor, Version 0.0, May 16 1991
Operate on 'domain_os.big'
Last memory address is 00115AC7
edit> sea 0 115AC7 20 12 4c 2a0 0 0 4
Missing or invalid search pattern
edit> sea 0 115AC7 20 12 4c 2a 0 0 0 4
Pattern found at:
  00024CD0
edit> set 24cd0
00024CD0: 20 
00024CD1: 12 2a
00024CD2: 4C 0
00024CD3: 2A 4
00024CD4: 00 e0
00024CD5: 00 88
00024CD6: 00 4c
00024CD7: 04 12
00024CD8: 22 0
00024CD9: 00 0
00024CDA: E0 22
00024CDB: 89 0
00024CDC: E8 
00024CDD: 89 
00024CDE: 2D 
00024CDF: 41 .
edit> e
*********************************************************************************

    The d_type is still returned incorrectly.  It appears that for SCSI
drives, Domain/OS uses the lower byte of this field to indicate the
capacity, in 1E7 byte blocks.  For example, 0x7d6 is the proper d_type
for a 2.1GB drive, and 0xd6 comes to 214.  Netstat reports this drive as
a 2140MB drive.  This scheme allows a capacity of 255E7 bytes (about
2.5GB).  This would be reported by netstat as a 2550MB SCSI disk.
    The code-reordering I've done results in the low byte of the d_type
field being divided by an additional 256.  So a drive with a 2.56GB
capacity will be reported as 10MB.  So will a 5.11GB drive.  However, a
5.12GB drive will be reported as 20MB, and a 9.09GB drive will be
reported as 30MB.
    If the division results in a zero, then 1 is substituted.  If the
result is too large, then 0x700 is substituted.  This won't happen until
the capacity exceeds 255*256*1E7 bytes (approx. 652.8GB).
    There doesn't seem to be an easy way to correct the kernel in this
respect, but the error doesn't seem to cause a problem, so I'll let it
be.  Even if it could be fixed, there is a range problem (2.56GB
limit) in the current representation that HPollo chose.  A complete
fix of this could extend to many areas in Domain/OS, besides the kernel
and netstat.
    Using the patched kernel all of the time will cause "standard"
drives to be mis-reported by netstat, as well as the large drives.  So
far, this is the only downside I've seen to using the patched kernel all
of the time.

*********************************************************************************

Working with SR 10.3.5.15 ...

    The mechanism is similar in this case, but different registers are
used.  Here is a disassembled excerpt:
00020C38:  2012                        move.l        (a2),d0
00020C3A:  4C2A 0000 0004              mulu.l        (4.w,a2),d0
00020C40:  2C00                        move.l        d0,d6
00020C42:  E08E                        lsr.l         #8,d6
00020C44:  E88E                        lsr.l         #4,d6
00020C46:  122B 013C                   move.b        (13C.w,a3),d1
00020C4A:  4601                        not.b         d1
00020C4C:  0C86 00001400               cmpi.l        #1400,d6
00020C52:  52C7                        shi           d7
00020C54:  8207                        or.b          d7,d1
00020C56:  C22C 0161                   and.b         (161.w,a4),d1
00020C5A:  6B00 01F2                   bmi.w         20E4E
00020C5E:  4A2C 0161                   tst.b         (161.w,a4)
00020C62:  6B0A                        bmi.s         20C6E
00020C64:  0C86 00001400               cmpi.l        #1400,d6

The pattern solution is nearly identical to the SR10.4.1.2 fix:
00020c38:  202a 0004                   move.l        ($4,a2),d0
00020c3c:  e088                        lsr.l         #8,d0
00020c3e:  4c12 0000                   mulu.l        (a2),d0
00020c42:  2c00                        move.l        d0,d6

*********************************************************************************

In December 2000, working with a 36.7GB drive ...

The patch worked fine.  Here are excerpts from the installation:
------------------------
ROOT $ /systest/ssr_util/scsi_info
    [...]
Target 2:
Device Type: Disk 
Vendor: IBM
Product: DDYS-T36950N
Rev Level: S93E
ANSI version compliance: 3
Features supported: 16-Bit Data Xfer; Synchronous Data Xfer; Linked Commands; Command Queueing; 
0 bytes of vendor unique data
    [...]
ROOT $ invol
    [...]
Option: 7
WARNING: this option could destroy all data on the disk.  Normally, it only needs to be
    [...]
Select disk: [w=Winch|f=Floppy|q=Quit][ctrl#:][unit#] w2:0

Enter badspots to be ADDED between physical disk addresses 0 and 88BB94 (hex)
    [This means 0x88bb95 4K blocks, or 36,703,916,032 bytes]
Badspots must be input in (hex) physical disk address form.
  (The manufacturer supplied badspots are handled by the disk controller;  there
   is no need to manually add the badspots listed on the drive.)

Terminate badspot entry with a blank line.
: 
Is the badspot information you entered correct? y

This disk must be formatted before badspots are written.
   Milestones are not available during format of a logically addressed disk.
   Formatting.
    [This process took about 1 day]
Done.

Anything more to do? y
    [...]
Option: 1 -fn

Select disk: [w=Winch|f=Floppy|q=Quit][ctrl#:][unit#] w2:0

Physical volume name: Big36

Verification options are:
   1 - no verification
   2 - write all blocks on the volume
   3 - write and re-read all blocks on the volume

Enter verification option: 3
Expected average file size, in kB (CR for default, 5 kB):  15
    [...]
    Note that the maximum allowable logical volume size is roughly 4194304 kB
    (minus some for cylinder-alignment).

There are 35786208 kB  available.

volume 1:  all,lv1
Adjusted to 4194284 kB; now 31591924 kB  available.

volume 2:  all,lv2
Adjusted to 4194288 kB; now 27397636 kB  available.

volume 3:  all,lv3
Adjusted to 4194288 kB; now 23203348 kB  available.

volume 4:  all,lv4
Adjusted to 4194288 kB; now 19009060 kB  available.

volume 5:  all,lv5
Adjusted to 4194288 kB; now 14814772 kB  available.

volume 6:  all,lv6
Adjusted to 4194288 kB; now 10620484 kB  available.

volume 7:  all,lv7
Adjusted to 4194288 kB; now 6426196 kB  available.

volume 8:  all,lv8
Adjusted to 4194288 kB; now 2231908 kB  available.

volume 9:  all,lv9

Use pre-recorded badspot info? y
The pre-recorded badspot list is empty.

Writing logical volume 1.

   Writing all blocks... % complete:
       20
       40
       60
       80
      100

   Reading all blocks... % complete:
       20
       40
       60
       80
      100
Writing logical volume 2.

   Writing all blocks... % complete:
       20
    [...]
      100
Writing logical volume 9.

   Writing all blocks... % complete:
       20
       40
       60
       80
      100

   Reading all blocks... % complete:
       20
       40
       60
       80
      100

Initialization complete.

Anything more to do? n
    [...]
ROOT $ mtvol w2:0 1 /win_2_1
ROOT $ mtvol w2:0 2 /win_2_2
ROOT $ mtvol w2:0 3 /win_2_3
ROOT $ mtvol w2:0 4 /win_2_4
ROOT $ mtvol w2:0 5 /win_2_5
ROOT $ mtvol w2:0 6 /win_2_6
ROOT $ mtvol w2:0 7 /win_2_7
ROOT $ mtvol w2:0 8 /win_2_8
ROOT $ mtvol w2:0 9 /win_2_9
ROOT $ lvolfs

  # free   # total   % free         node id  entry directory
   33348    657664        5           2CEAC   /
   45096   4189912        1           2CEAC   /win_6_1
  255596    259452       99           2CEAC   /win_6_2
 4190288   4194280      100           2CEAC   /win_2_1
 4190292   4194284      100           2CEAC   /win_2_2
 4190292   4194284      100           2CEAC   /win_2_3
 4190292   4194284      100           2CEAC   /win_2_4
 4190292   4194284      100           2CEAC   /win_2_5
 4190292   4194284      100           2CEAC   /win_2_6
 4190292   4194284      100           2CEAC   /win_2_7
 4190292   4194284      100           2CEAC   /win_2_8
 2229768   2231904      100           2CEAC   /win_2_9
-------------------------------
36086140  40893200    88.24%      12 volumes.
ROOT $ netstat -config
    [...]
Net I/O:         total= 506373   rcvs =  90786   xmits = 415587
Ctlr_# = 2 Unit_# = 0
Winchester I/O:  total= 71683872   reads= 35842964   writes= 35840908
Ctlr_# = 6 Unit_# = 0
Winchester I/O:  total= 385848   reads= 369972   writes=  15876
Ctlr_# = 0 Unit_# = 0
Winchester I/O:  total=  24028   reads=   4894   writes=  19134
No ring hardware failure report.
System configured with 64.0 mb of memory.

  NODE CONFIGURATION
    Node Type:  DN5500
    Display type:  1280 x 1024 Desktop Visualization System display
    Peripheral configuration:
        Disks:  winchester
        Networks: Ring ETH802.3_AT
        Peripheral bus:  ISA-bus
        Tapes:  none
    Disk types:  140Mb SCSI Disk  10Mb SCSI Disk  MSD-760M  
    [Note that only the SCSI drives are mis-reported]
------------------------
