roelandjansen / pcmos386v501

PC-MOS/386 v5.01 and up, including cdrom driver sources.
GNU General Public License v3.0
418 stars 60 forks source link

MOSDDBLK: always reserve 2 drives for floppies [fixes #21] #23

Closed stsp closed 7 years ago

stsp commented 7 years ago

This is a quick-fix that prevents HDD from moving to A:. It is not clear why HDD does not work on A:, maybe it should? Maybe someone else can code up the more intrusive fix.

roelandjansen commented 7 years ago

assuming "HDD" is a hard disk:

MS-DOS/PC DOS since version 5.0, and later operating systems, assigns drive letters according to the following algorithm:

Assign the drive letter A: to the first floppy disk drive (drive 0), and B: to the second floppy disk drive (drive 1). If only one physical floppy is present, drive B: will be assigned to a phantom floppy drive mapped to the same physical drive and dynamically assigned to either A: or B: for easier floppy file operations. If no physical floppy drive is present, DOS 4.0 will assign both A: and B: to the non-existent drive, whereas DOS 5.0 and higher will invalidate these drive letters. If more than two physical floppy drives are present, DOS versions prior to 5.0 will assign subsequent drive letters, whereas DOS 5.0 and higher will remap these drives to higher drive letters at a later stage; see below. Assign a drive letter to the first active primary partition recognized upon the first physical hard disk. DOS 5.0 and higher will ensure that this will become drive letter C:, so that the boot drive will either have drive letter A: or C:. Assign subsequent drive letters to the first primary partition upon each successive physical hard disk drive (DOS versions prior to 5.0 will probe for only two physical harddisks, whereas DOS 5.0 and higher support eight physical harddisks). Assign subsequent drive letters to every recognized logical partition present in the first extended partition, beginning with the first hard drive and proceeding through successive physical hard disk drives. DOS 5.0 and higher: Assign drive letters to all remaining primary partitions, beginning with the first hard drive and proceeding through successive physical hard disk drives. DOS 5.0 and higher: Assign drive letters to all physical floppy drives beyond the second physical floppy drive. Assign subsequent drive letters to any block device drivers loaded in CONFIG.SYS via DEVICE statements, e.g. RAM disks. Assign subsequent drive letters to any dynamically loaded drives via CONFIG.SYS INSTALL statements, in AUTOEXEC.BAT or later, i.e. additional optical disc drives (MSCDEX etc.), PCMCIA / PC Card drives, USB or Firewire drives, or network drives. Only partitions of recognized partition types are assigned letters. In particular, "hidden partitions" (those with their type ID changed to an unrecognized value, usually by adding 10h) are not. MS-DOS/PC DOS versions 4.0 and earlier assign letters to all of the floppy drives before considering hard drives, so a system with four floppy drives would call the first hard drive E:. Starting with DOS 5.0, the system ensures that drive C: is always a hard disk, even if the system has more than two physical floppy drives.

So a: and b: are always floppy disk drives. (real/phantom)

stsp commented 7 years ago

So a: and b: are always floppy disk drives. (real/phantom)

No because of this: whereas DOS 5.0 and higher will invalidate these drive letters. Unfortunately this invalidation doesn't seem to work without my patch. But I admit that my patch was made w/o knowing enough of the context. Do you happen to know where is the code that is supposed to invalidate the first 2 drive letters?

stsp commented 7 years ago

If no physical floppy drive is present, DOS 4.0 will assign both A: and B: to the non-existent drive, whereas DOS 5.0 and higher will invalidate these drive letters.

In fact, my patch makes it to the 4.0 way - assign both to non-existing. If only I knew what is the difference: assign to non-existing or to invalidate? Can I suppose there is no difference for the user, just some coding detail differes?

roelandjansen commented 7 years ago

well that's a good question Let's see if I can find out via the interrupt list of Ralf Brown. Or maybe someone else got an idea here.

The question is -- if we invalidate a drive. is that only towards the user interface or are they still reserved but differently error'd out?

stsp commented 7 years ago

I've also found out that setting maxdrv to 1 has the same effect of fixing this problem. But the drives are not invalidated in both cases: I can still go to A: and only if I do some dir there, then I see an error. Perhaps the better fix would be the one that will return an error when you just typed A:.

roelandjansen commented 7 years ago

so:

1) a drive select does not error, 2) accessing it (if the disk is not there or the drive) gives an error.

Let's see how that affects compatibility regarding DOS v5 itself.

stsp commented 7 years ago

so:

With both changes I tried - yes. W/o changes - I don't know as then it doesn't boot.

stsp commented 7 years ago

I'll try to debug a bit more.

stsp commented 7 years ago

OK, I uploaded the new patch. Now it fully complies to the quoted docs: A and B are now invalid when no FDD installed.

stsp commented 7 years ago

I've found the disparity:

diff --git a/SOURCES/src/kernel/MOSINIT2.ASM b/SOURCES/src/kernel/MOSINIT2.ASM
index 04e6732..4400ed1 100644
--- a/SOURCES/src/kernel/MOSINIT2.ASM
+++ b/SOURCES/src/kernel/MOSINIT2.ASM
@@ -3448,7 +3448,6 @@ notvna:
 ; partition #)

        and     al,7fh                  ; set mos drive id
-       add     al,2                    ; start hard drives at c
        push    es
        push    ax
        int     12h                     ; get memory size

So if this addition of 2 is removed, then MOS boots fine from A:. So either that, or reserve 2 when no floppies are found, as in my patch - then it boots from C and A,B are invalidated.

stsp commented 7 years ago

So I think now all bits and pieces are connected. Let me know what kind of fix do you prefer.

andrewbird commented 7 years ago

What does DOS 5 do when there are no floppies, is its boot drive C: or A: ?

stsp commented 7 years ago

C of course. Rhetorical question? :)

stsp commented 7 years ago
diff --git a/SOURCES/src/kernel/MOSDDINT.ASM b/SOURCES/src/kernel/MOSDDINT.ASM
index 9e29790..14efb6e 100644
--- a/SOURCES/src/kernel/MOSDDINT.ASM
+++ b/SOURCES/src/kernel/MOSDDINT.ASM
@@ -581,6 +581,15 @@ ddinit0 proc near
        pop     es
        pop     bx
        mov     es:[bx+10],dl           ; number of drives actually installed
+       cmp     [scbdevs],0             ; see if assigning floppies
+       jne     ddi02
+       cmp     dl,scbhddmin
+       jae     ddi01
+       mov     dl,scbhddmin
+ddi01:
+       mov     [scbflops],dl
+ddi02:
+       inc     [scbdevs]
        add     [scbdrivs],dl           ; increasing total number of drives in system
        jmp     ddi0b
 ddi0a:
diff --git a/SOURCES/src/kernel/MOSINIT2.ASM b/SOURCES/src/kernel/MOSINIT2.ASM
index 04e6732..ae63ad6 100644
--- a/SOURCES/src/kernel/MOSINIT2.ASM
+++ b/SOURCES/src/kernel/MOSINIT2.ASM
@@ -3448,7 +3448,7 @@ notvna:
 ; partition #)

        and     al,7fh                  ; set mos drive id
-       add     al,2                    ; start hard drives at c
+       add     al,[scbflops]           ; start hard drives at c
        push    es
        push    ax
        int     12h                     ; get memory size
diff --git a/SOURCES/src/kernel/MOSSCBDF.INC b/SOURCES/src/kernel/MOSSCBDF.INC
index 371dbcd..2661d57 100644
--- a/SOURCES/src/kernel/MOSSCBDF.INC
+++ b/SOURCES/src/kernel/MOSSCBDF.INC
@@ -114,7 +114,7 @@ public scblastw1, scblastw2, scbrdriv, scbirqd0a, scbirqd0b, scbirqd0c
 public scbirqd0d, scbirqd0e, scbirqd0f, scbinit, scbirqbnk, SCBSAVE, scbcon417
 public scbkbrate, scbout60, scbin60, scbmconly, scbi15off, scbnorst
 public scbpost, SCB_COM_owner, SCB_COM_timeout, scbdrtcb, scbnoi5
-public scbvdrflg, scbdopflg, scbdosver
+public scbvdrflg, scbdopflg, scbdosver, scbflops, scbdevs, scbhddmin

 scbtcbpf       dw      0       ;* pointer to first task control block
 scbtcbpl       dw      0       ;* pointer to last tcb
@@ -211,6 +211,9 @@ scbcursz    dw      0ffffh  ; used in mosheman
 scbcurad       dw      0       ; used in mosheman
 scbavsiz       dw      0       ; used in mosheman
 scbdrivs       db      0       ; # active drive units
+scbflops       db      0       ; # active floppy units
+scbhddmin      equ     2       ; start hdd from c or above
+scbdevs                db      0       ; # active block devices
 scbnoswt       db      0,0     ; mos no switch flag (like dos critical flag)
                                ; to be set if no task switch is to occur
                                ; a 0 byte follows since some apps check the word
diff --git a/SOURCES/src/kernel/MOSSCBEX.INC b/SOURCES/src/kernel/MOSSCBEX.INC
index ef9a912..b67a815 100644
--- a/SOURCES/src/kernel/MOSSCBEX.INC
+++ b/SOURCES/src/kernel/MOSSCBEX.INC
@@ -57,6 +57,9 @@ extrn scbcursz:word   ; mosheman usage
 extrn scbcurad:word    ; mosheman usage
 extrn scbavsiz:word    ; mosheman usage
 extrn scbdrivs:byte    ; # active drive units
+extrn scbflops:byte    ; # active floppy units
+extrn scbdevs:byte     ; # active block devices
+extrn scbhddmin:abs    ; start hdd from this number or more
 extrn scbnoswt:byte    ; mos no switch flag
 extrn scbtskfg:byte    ; task selection flags
 extrn scbdrvr:dword    ; -> first device driver in list

Something like this should work as a full-featured fix. But unfortunately updated externs require the full rebuild, whereas I can only rebuild the kernel. :(

roelandjansen commented 7 years ago

I'll keep the PR open and see if I can set up a full build system.

Currently some health things slow down the stuff a bit.

stsp commented 7 years ago

@dcoshea maybe you can rebuild with the patch and put the binaries somewhere? If the patch works as expected, I will convert it into the PR. So far this PR has a minimal patch that was tested and works fine.

galazwoj commented 7 years ago

How about this change? SOURCES/src/kernel/MOSINIT2.ASM @@ -4091,7 +4091,7 @@ no286a:

    mov [tcbcdbpf],0    ; clear pointer to cdb
    mov [tcbcdbpc],0    ; clear pointer to cdb
    mov [tcbndriv],0    ; clear # of drives
-   mov [scbdrivs],0    ; clear any count of drives for re-init
+   mov [scbdrivs],2    ; clear any count of drives for re-init (always make room for A: and B: floppies)
    mov [scbbdbpf],0    ; clear pointer to 1st block device
stsp commented 7 years ago

How do you expect this to work when there are floppies? We only need to compensate when there are none, or, alternatively, tell the boot code to evaluate to A properly. My last patch does this, but not tested as of yet. I will work on getting it tested.

galazwoj commented 7 years ago

Sure my naive change will not work. BTW I think I found another bug SOURCES/src/kernel/MOSDDINT.ASM @@ -871,7 +871,7 @@ mosbd1b:

 mosbd2:
    pop es          ; address of bdb
    push    ax          ; save error code
-   mov al,1              
+   mov ah,1                 ; the intention is to remove memory block
    mov al,'B'
stsp commented 7 years ago

Yes, good catch! But this bug isn't observable for me, as I believe it only produces the memory leak. You should try to submit this fix as a separate PR.

roelandjansen commented 7 years ago

merged. As stsp states -- please have a separate PR for the memleak.

stsp commented 7 years ago

OK, in this case I'll open a new PR once I have the bigger patch finally tested.