avatar_gertk

PCW FID file can only register two new drives?

Started by gertk, 11:58, 31 July 21

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

gertk

Hello,
Having made a homebrew IDE and SIO adapter for the PCW I am fiddling with the concept of multiple drives on one IDE (128 MB DOM) drive.
When my FID is loaded it seems I can only request two extra devices (C and D), when SVC_D_HOOK is called a third time I get the 'no device available' error. Needless to say I get a BDOS error 'invalid drive' when trying to access 'E:'

Any ideas on this ?
P.S. drive C and D work fine, both being 32 MByte

GeoffB17

JonB who did the uIDE setup that a number of  us are using will be the expert on this.   I expect that he'll comment.   His system happily assigns drives C: thru P: (excl M: which is already used).

This MAY be something to do with the address/memory space for the DPH?  Normally each drive needs it's own version, certainly of the PCW A:, B: and M: are all different.  But in this IDE situation, in fact, all the extra drives can use the same data, so once you've created one for C: then you don't need extra ones for D: etc, they can use the same address/memory space as C:.   Of course, to do this, then the extra drives MUST be all the same parameters.

Geoff

gertk

The C, D and E drives could use the same DPB (not DPH) if they were located on different hardware but since they share the same IDE device I need to adjust the track offset for each. I use the same basic data for the DPB but after the OS calls my FID_D_LOGON routine I alter the offset in the DPB according to the drive number/letter being called for.

GeoffB17

I'm trying to work out how JonB was able to work around the problem, and you are not.

The problem relates to the fact (as I understand things) that while CP/M provides space for 16 drives, and each space in this table points to a data structure (the info I have refers to the DPH, but it could be the DPB, but one of these points to the other anyway ?) but there is only so much space available for these structures.   JonB was hitting this limit too.  I was pestering him re 'Why CAN'T you use ALL the drives', when John Elliott suggested that it was possible that if the drives were the same then you could repeat the pointer in the table - and this proved to work.

Maybe the difference relates to what you say about your 'drives'?

In JonB's case, he has partitioned his 128Mb DOM as 13 @ 8Mb drives (devices).   His package includes a 'format' program to do a format of all the drives.   The 8Mb format is I understand a standard CP/M option.   So his system does not need any messing with offsets, etc.   Therefore his devices CAN all use the same DPB/DPH.

You are using a different system.  i.e. the 32Mb capacity for each drive (what does this do regarding the block size, # extents, directory entries I wonder?

Maybe this is causing your problem?  Can you maybe pre-format your DOM as (I assume) 4 identical devices, each using the same DPB/DPH?

Geoff

gertk

#4
Quote from: GeoffB17 on 22:39, 31 July 21
I'm trying to work out how JonB was able to work around the problem, and you are not.
Hi Geoff,
Appreciate any help and I also dug a bit deeper, I am using the CPM 3 system reference as a guide and the information on the seasip website.
Quote
The problem relates to the fact (as I understand things) that while CP/M provides space for 16 drives, and each space in this table points to a data structure (the info I have refers to the DPH, but it could be the DPB, but one of these points to the other anyway ?) but there is only so much space available for these structures.   JonB was hitting this limit too.  I was pestering him re 'Why CAN'T you use ALL the drives', when John Elliott suggested that it was possible that if the drives were the same then you could repeat the pointer in the table - and this proved to work.
Ah, yes I think I can figure out how he did it. Instead of telling the OS there is an offset he probably just stores the offset himself and re-use the existing DPB (and maybe even DPH, not sure how to do that).Upon a read or write sector request you can then simply use the self-stored track offset for that drive. Hmm..
Quote
Maybe the difference relates to what you say about your 'drives'?

In JonB's case, he has partitioned his 128Mb DOM as 13 @ 8Mb drives (devices).   His package includes a 'format' program to do a format of all the drives.   The 8Mb format is I understand a standard CP/M option.   So his system does not need any messing with offsets, etc.   Therefore his devices CAN all use the same DPB/DPH.

You are using a different system.  i.e. the 32Mb capacity for each drive (what does this do regarding the block size, # extents, directory entries I wonder?
CPM 3 should be able to handle 32 MB (and it seems it does, CPM 2.2 could only manage 8 MB)
It is a compromise between number of drives and usable space. I can go anywhere with my code.My DPB is now something like this:
; disk parameter block for 32 MByte starting at cylinder 1 (0 = reserved for future use)
; block size is 4096 bytes
; with 2048 directory entries we need 2048 x 32 = 65536 bytes space
; which would need 16 blocks of 4096 bytes hence all 16 bits of
; AL0 and AL1 are set.
; by using 1024 (128 byte) sectors per track we really get 256 physical sectors
; (of 512 bytes) per track. So the physical sector number can be directly used
; as the lower 8 bits of the LBA. The total number of tracks is also 256.
; By using an offset it would be possible to enable more CPM 'drives' on the same 
; IDE drive by setting this offset.
idedpb:
                defw    1024    ;   SPT  (in 128 byte sectors)
                defb    5       ;   BSH
                defb    31      ;   BLM
                defb    1       ;   EXM
                defw    8191    ;   DSM  total number of blocks
                defw    2047    ;   # of directory entries
                defb    0ffh    ;   AL0 bitmap (16 bits/blocks needed)
                defb    0ffh    ;   AL1 bitmap
                defw    8000h   ;   CKS fixed drive, no dir check
ideoffs:    defw    1       ;   OFF  offset from drive start
                defb    2       ;   PSH for 512 bytes physical sectors
                defb    3       ;   PHM  mask for 512 byte physical sectors

Quote
Maybe this is causing your problem?  Can you maybe pre-format your DOM as (I assume) 4 identical devices, each using the same DPB/DPH?
The DOM is 128 MB but has only 256000 sectors (available) so not really 128 MB (guess there are some spare/reserved sectors). That is why I now have declared only 3 identical 32 MB parts
I will tinker with the idea of identical DPB/DPH and storing the offset myself upon a 'disk logon request'.The information on how the SVC_D_HOOK function works is not entirely clear to me.
I assumed the IX register points to a space where I should copy my DPB into (and that seems to work) but it only states:


SVC_D_HOOK
Entered with:

       
  • B  = drive letter. 0 => A: ... 0Fh => P:. 0FFh => first available letter.
  • DE = address of disc device jumpblock (within the FID).
  • HL = maximum no. of bytes required for a double-bit allocation vector.
  • IX = maximum no. of bytes required for directory checksum vector.
  • IY = maximum no. of bytes required for hash table.
Returns:

       
  • Carry set if OK.

    •       
    • B = drive letter;
    • IX -> 17-byte DPB for drive.
    • A corrupt.
  • Carry clear if error.

    •       
    • A = reason:

      •          
      • 1 => out of memory.
      • 2 => drive letter in use.
    • B, IX corrupt.
  • C, DE, HL, IY corrupt.

JohnElliott

When a FID file calls SVC_D_HOOK, the FID loader allocates memory for the DPH, DPB, allocation vector and checksum vector. Of these, the DPB is the one most likely to cause trouble, because it gets allocated in common memory and there's very limited free space there. When I wrote JOYCEDRV.FID, I found that there was room for at most five DPBs before running out of space - fewer if you had other FIDs loaded that implemented character devices.

When JonB ran up against the same problem with his IDE driver, I took a look and realised that if all the drives use the exact same DPB, it's only necessary to allocate it once. After the first drive has been allocated, you patch SVC_D_HOOK to use the same DPB for the second and subsequent drives. The code to patch looks like this:f0b3  fd 73 00       720   1737                 ld      (iy+0), e
f0b6  fd 72 01       721   1738                 ld      (iy+1), d
f0b9  11 11 00       722   1739                 ld      de, 11h
f0bc  cd 98 f2       723   1740                 call    svc_alloc_tpa
f0bf  d2 59 f1       724   1741                 jp      nc, svc_d_hook_6
f0c2  fd 75 10       725   1742                 ld      (iy+10h), l
f0c5  fd 74 11       726   1743                 ld      (iy+11h), h
So you search for something like FD 75 10 FD 74 11 in the area of code after the SVC_D_HOOK entry point, back up the six bytes before that sequence, and replace them with 21 dpb_low dpb_high 00 00 00. Call SVC_D_HOOK for all the other drives you want to allocate, and then reinstate the original six bytes.

(Oh, and make sure you're running under CP/M first, so you don't try to patch the very different FID loader in LocoScript!)

gertk

#6
Found the start of SVC_D_HOOK at $F05C and the offset to the patchable area is $3F bytes further.Called SVC_D_HOOK with request for drive 'C' first, patched in the code, requested drive 'D', then tried to request drive 'E' but alas, same problem. Got no carry so the request failed, no drive 'E'..
SVC_D_HOOK starts at:

F05C: DD E5 DD 21 02 00 DD 39 FD E5 E5 D5 CD 49 F1 E5
F06C: 3E 02 D2 42 F1 11 1D 00 CD 7A F2 D2 40 F1 E5 FD
F07C: E1 54 5D 13 36 00 C5 01 1C 00 ED B0 C1 FD 70 02
F08C: DD 5E F8 DD 56 F9

F092: FD 73 00 FD 72 01 11 11 00

code to patch:

F09B: CD 76 F2 D2 37 F1

F0A1: FD 75 10 FD 74 11


Bytes to be replaced after first SVC_D_HOOK call start at
SVC_D_HOOK + $3F  (here $F09B)

Patchcode:

ld  hl,idedpb   ; my IDE DPB for all drives

nop
nop
nop
To confirm the patch is in place I send the 6 bytes in hex over the serial port to the laptop, first the 6 original bytes, then the patched bytes and finally after the calls have been made the restored bytes. They look fine.
CD 76 F2 D2 37 F1   21 BA 12 00 00 00   CD 76 F2 D2 37 F1
Could the problem be that I am using V107H (as V115 gives Gotek trouble) ?Maybe that CPM version just does not support more that two (extra) drives?

JohnElliott

This probably isn't related to your main issue, but

21 BA 12 00 00 00
doesn't look right to me. The DPB should have been allocated in common memory, so it should be something like

21 1F FF 00 00 00



GeoffB17

#8
My PCW has JonB's uIDE attachment, and I can use either 1.07H or 1.15 (or others) with no evident problem.  I don't use any Gotek.   I get all the expected drives operational.   If the system supports FID, then all is OK.   I do have to use a special FID version that limits the extra drives to 3 or 4 if I want to do something with LocoScript, but this is a quite different problem.   When LS starts up, it proceeds to fill ALL the data for the Disk Manager, which means ALL the drives/files visible.   C: thru F: is more than enough, and that takes LONG enough if the drives have any number of files on them.

Geoff

gertk

Quote from: JohnElliott on 21:09, 03 August 21
This probably isn't related to your main issue, but

21 BA 12 00 00 00
doesn't look right to me. The DPB should have been allocated in common memory, so it should be something like

21 1F FF 00 00 00
Ah yes, I see where that goes wrong.  I should have used the first IX pointed address (where I copy my idedpb to), it now uses the idedpb in my FID. Will try again this evening.

gertk

Ok, proved to be a different problem after all, but needs a similar solution to save memory with multiple drives I guess...
The device not available error (carry clear after call to SVC_D_HOOK) was caused by a lack of space for the 'double bit allocation'  bitmap.. I requested a bit too much, well, twice the amount I needed for the requested drive. I recalculated the amount of space and now it works even without patching: C, D and E are present and working..

With 8192 blocks (of 4096 bytes each) per drive total I calculate I need (8192 * 2)/8 bytes total, but this is also reserved per drive or can it be overlayed the same as for the DPB ?

JohnElliott

Allocation vectors have to be separate per drive, so can't be combined like a DPB. For a drive with 8192 blocks the size required is (8192 / 4) + 2 = 2050 bytes.
The calculations used to be online in the Spectrum +3 CP/M manual, but this seems to be a dead link at the moment so I'll copy-paste the relevant section.

Disc Driver Data StructuresThis section summarises the format of the Disc Parameter Block and the various sizes of the disc drive data structures.Functions
Floor(x)
= largest integer <= x.
Ceiling(x)
= smallest integer >= x.
Log2(x)
= logarithm to the base 2 of x.
High(x)
= Floor(x/256), i.e. most significant byte of 16 bits.
Low(x)
= x - 256 * High(x), i.e. least significant byte of 16 bits.
Let[/size]
BLOCK_SIZE
= allocation block size in bytes 1K,2K,4K,8K or 16K
OFF
= number of reserved tracks
NUM_TRACKS
= total number of tracks
NUM_SECTORS
= number of sectors per track
DIR_BLOCKS
= number of directory blocks 1..16
SEC_SIZE
= 512, sector size in bytes
REC_SIZE
= 128, record size in bytes
DIR_ENTRY_SIZE
= 32, directory entry size
Records per track
SPT = NUM_SECTORS * SEC_SIZE / REC_SIZE
Block shift
BLS = Log2 (BLOCK_SIZE / REC_SIZE)
Block mask
BLM = (BLOCK_SIZE / REC_SIZE) - 1
Highest block number
DSM = Floor((NUM_TRACKS - OFF) * NUM_SECTORS * SEC_SIZE / BLOCK_SIZE) - 1
Highest directory entry number
DRM = (DIR_BLOCKS * BLOCK_SIZE / DIR_ENTRY_SIZE) - 1
Directory allocation map, least significant
AL0 = High (216 - 2(16 - DIR_BLOCKS))
Directory allocation map, most significant
AL1 = Low (216 - 2(16 - DIR_BLOCKS))
Extent mask
EXM = if DSM < 256then (BLOCK_SIZE / 210) - 1else (BLOCK_SIZE / 211) - 1Checksum vector size
CKS = (DRM + 1) / 4
Physical sector shift
PSH = Log2 (SEC_SIZE / REC_SIZE)
Physical sector mask
PHM = (SEC_SIZE / REC_SIZE) - 1
Allocation vector size
ALS = Floor(DSM / 4) + 2
Hash table size size
HASH = 4 * (DRM + 1)
DPB format:
bytes
0..1
SPT
records per track
byte
2
BSH
block shift
byte
3
BLM
block mask
byte
4
EXM
extent mask
bytes
5..6
DSM
last block number
bytes
7..8
DRM
last directory entry number
byte
9
AL0
directory allocation
byte
10
AL1
directory allocation
bytes
11..12
CKS
checksum vector size, set bit 15 if fixed disc
bytes
13..14
OFF
reserved tracks
byte
15
PSH
physical sector shift
byte
16
PHM
physical sector mask
Note for a fixed disc set CKS = bit 15, this disabled directory checksumming and indicates that the disc cannot be removed.
If hashing is not required set the hash table size to 0.


gertk

Quote from: JohnElliott on 20:51, 04 August 21
Allocation vectors have to be separate per drive, so can't be combined like a DPB. For a drive with 8192 blocks the size required is (8192 / 4) + 2 = 2050 bytes.
The calculations used to be online in the Spectrum +3 CP/M manual, but this seems to be a dead link at the moment so I'll copy-paste the relevant section.
Ah, so I am missing two bytes in the allocation vector space, will change that and use as much of the other calculations to make the whole DPB more configurable.
The most annoying one to calculate automatically were the AL0 and AL1 bytes, good to see a formula for those.



gertk

Update:
I modified the code to dynamically calculate/divide the available sectors into 4 (equal) pieces and set up the corresponding DPB's  and two bit allocation bitmap space for that. Calling SVC_D_HOOK four times is working ok now (no patching needed).I kept one track of 256 sectors at the start of the IDE drive for storing the OS. In time I want to make a special bootsector on the floppy/Gotek  which inits the IDE and just loads in the OS from there.




Powered by SMFPacks Menu Editor Mod