Fixing the “Not a heap block” error with networking with PCPro

I was trying to get the PC compatibility card (a Gemini II) in my Risc PC (StrongARM, running RISC OS 3.70) onto the network. However, when starting the emulated PC, I would get a “Not a heap block” error, and the emulated PC wouldn’t have its emulated network card.

It turns out this is because the program it invokes to find the most appropriate interface (this is called ScanDCI4) doesn’t actually work. This causes the script to fail, and not actually load the emulated NE2000 support module. To fix this, we’ll need to patch the script that starts the PC card networking support.

You can see the Obey script (stored in !PC.PCBits.NetLinks.Startup) here:

| Generic Netlinks startup

| Load network driver
|   Note that it is NOT recommended to do this here; use Acorn's !Internet
|   configuration where possible.  But if you only use the network card
|   on the PC side, and the modules in your ROM are not recent enough, 
|   replace Ether? with the correct driver module for your card and remove 
|   the first | from the lines below:
|RMEnsure MbufManager   0.13 RMReinit MbufManager
|RMEnsure MbufManager   0.13 RMLoad System:Modules.Network.MManager
|RMEnsure MbufManager   0.13 Error System:Modules.Network.MManager not found or too old
|RMLoad System:Modules.Network.Ether?
|RMEnsure Ether?       4.00 Error System:Modules.Network.Ether? not found or too old

| Sensibly decide what network driver to use
|  (this program sets <Diva$SuggestedInterface> to em0 / eb0 / ec1 etc.
|   preferring virtual interfaces to normal ones, and ignoring point-to-
|   -point links)
Wimpslot -min 16k -max 16k
Unset Diva$SuggestedInterface
Run <Obey$Dir>.ScanDCI4
If "<Diva$SuggestedInterface>"="" Then Obey

| PCNE2 should now load its options from the NE2000Basic and NE2000Advanced
| parameters of <Diva$ConfigFile>, and takes the -d option from
| <Diva$SuggestedInterface> if it's not specified there.
RMEnsure PCNE2         1.83 RMLoad <Obey$Dir>.PCNE2 -f
RMEnsure PCNE2         1.83 Set Diva$Error PCNE2 did not load successfully (or too old)

To fix this, comment out (comments in Obey use a pipe character) the lines that involve unsetting and checking the output of the program (Unset, Run, and If after Wimpslot). Then, I substituted this check with hardcoding the interface I would use, by adding Set Diva$SuggestedInterface eh1 after the commented lines. You should use ehinfo or ifconfig -a from a command line to determine which interface you should be using; make sure you have a virtual interface configured if needed. I also added a parameter to the advanced options in !PCConfig to use eh1, so adding this might be redundant.

Sidebar: ScanDCI4 is written in BASIC, and is in the same directory as the NetLinks startup script. It seems to call a system API to get interface information (via an OS_ServiceCall SWI), but that information seems heap allocated, and that the caller must free. In each loop, where it checks interface information, it frees a block with OS_Module, and it fails here. I haven’t done further investigation into why it fails for me; I haven’t seen it mentioned before. The source for this is shown below for reference:

   10 REM ScanDCI4
   20 :
   30 REM Scans through network driver chain, and picks out a suitable interface
   40 REM for PCNE2 to use -- will reject point to point links, and choose virtual
   50 REM interfaces over real ones.
   60 :
   80 :
   90 DIM b 256
  100 DIM swibase%(63),name$(63),unit%(63),flags%(63)
  110 :
  120 REM Get interface modules to stand and be counted
  130 SYS "OS_ServiceCall",0,&9B TO list%
  140 IF list%=0 THEN OSCLI"Set Diva$Error NetLinks: Couldn't find any network drivers!  Please install one, or remove the NetLinks directory from !PC.PCBits."
  150 :
  160 drivers%=0
  170 REPEAT
  180   REM Get address of this driver information block
  190   dib%=list%!4
  200   REM Copy name, unit number and flags into our list
  210   name$(drivers%)=FNz(dib%!4):unit%(drivers%)=dib%!8:flags%(drivers%)=dib%!28
  220   REM Next driver...
  230   to_free%=list%:list%=!list%:drivers%+=1
  240   REM Free space for each DIB because OS doesn't do it for us
  250   SYS "OS_Module",7,,to_free%
  260 UNTIL list%=0
  300 *cdir <Wimp$ScrapDir>.PC
  301 a%=OPENOUT "<Wimp$ScrapDir>.PC.EtherX"
  310 FOR X=0 TO drivers%-1
  320   SYS "OS_SWINumberToString",swibase%(X),b,256 TO ,,l:b?l=13
  350   BPUT#a%, (name$(X));
  351   BPUT#a%, " "+(STR$ ~swibase%(X));
  352   BPUT#a%, " "+(STR$ ~unit%(X));
  353   BPUT#a%, " "+(STR$ ~flags%(X))
  360 NEXT
  370 CLOSE#a%
  380 *SetType <Wimp$ScrapDir>.PC.EtherX FFF
  390 :
  400 REM Now decide which driver to take (flag bit 7 = 'virtual')
  410 suggestion_made%=0
  420 FOR X=drivers%-1 TO 0
  430   IF (flags%(X) AND 128)=0 AND suggestion_made%=0 THEN OSCLI"Set Diva$SuggestedInterface "+name$(X)+STR$unit%(X):suggestion_made%=1
  440   IF (flags%(X) AND 128)=0 AND (flags%(X) AND 1024)<>0 AND suggestion_made%<2 THEN OSCLI"Set Diva$SuggestedInterface "+name$(X)+STR$unit%(X):suggestion_made%=2
  450 NEXT
  460 IF suggestion_made%=0 THEN OSCLI"Set Diva$Error NetLinks: Couldn't find any suitable network interfaces!"
  470 END
  480 :
  490 REM Read zero-terminated string
  500 DEFFNz(a%):LOCAL z$:WHILE (?a%<>0):z$+=CHR$?a%:a%+=1:ENDWHILE:=z$

Leave a Reply

Your email address will not be published. Required fields are marked *