Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the board
Thread view  Mix view  Order
RayeR

Homepage

CZ,
13.07.2011, 14:58
(edited by RayeR, 13.07.2011, 16:26)
 

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi? (Developers)

I asked on DJGPP google groups but maybe someone other here will know - it's more generic DMPI question than DJGPP question:

Hi,
I'm programming a small ACPI info utility in DJGPP v2.04 and I need to
map and copy some small blocks of physical memory. I don't know exact
size before reading whole table. E.g. the header is only 36B long and
when I get it I will know the entire size and repeat the mapping and
reading of physical memory. I do it via
__dpmi_physical_address_mapping() but I read this function has some
limits like minimum size should be 4kB and in multiple of 4kB blocks
(and __dpmi_set_segment_limit should be >64kB). I found that it
works for me for small sizes (tested under DOS 6.22+CWSDPMI and Win98
DOS box) but I want to make it realiable. Of cource I can map large
enough (let's say 64kB) block and don't remap and don't change segment
limit then. But it may occur that base + size will exceed physical
memory top margin or 32bit adress range. E.g. base=0xFFFFF000 and
size=0xFFFF - I don't know if it cause something bad if I will not
read the memory beyond limit via movedata() function. If it is OK then
I'm safe. BTW why __dpmi_physical_address_mapping() needs size
paramerer at all? I checked that meminfo.address didn't changed when I
changed the size and call __dpmi_physical_address_mapping() again...

Current (experimentally working) code is here:


long copy_sdt(Byte *p_buffer, DWord phys_ptr) // returns SDT length, 0 if bad checksum, negative if read error
{
  ACPI_SDT_HEADER sdt_header;          // temporarly stored SDT header to obtain full SDT size
  __dpmi_meminfo meminfo;              // DPMI meminfo structure for physical memory mapping
  int sdt_selector;                    // selector of segment descriptor of mapped SDT

  meminfo.address=phys_ptr;            // mapped physical address
  meminfo.size=sizeof(ACPI_SDT_HEADER);// mapped physical area size
  if (__dpmi_physical_address_mapping(&meminfo)!=0) // map physical memory area to linear
    return(-2);                        // if failed return -2
  if ((sdt_selector=__dpmi_allocate_ldt_descriptors(1))<0) // allocate 1 descriptor (desribing our new segment) in LDT and return it's selector
    return(-1);                        // if failed return -1
  __dpmi_set_segment_base_address(sdt_selector, meminfo.address); // set segment base to linear ptr
  __dpmi_set_segment_limit(sdt_selector, meminfo.size-1); // set segment limit accorning to SDT header size
  movedata(sdt_selector, 0, _my_ds(), (unsigned)&sdt_header, sizeof(ACPI_SDT_HEADER)); // copy SDT header from physical memory to temp buffer
  if (sdt_header.length<sizeof(ACPI_SDT_HEADER)) // check SDT lenght
    return(0);                        // if less than SDT header return 0

// do I need this remapping step?
 meminfo.address=phys_ptr;           // mapped physical address
 meminfo.size=sdt_header.length;     // mapped physical area size
 if (__dpmi_physical_address_mapping(&meminfo)!=0) // map physical memory area to linear
   return(-1);                       // if failed return -2

  __dpmi_set_segment_base_address(sdt_selector, meminfo.address); // set segment base to linear ptr
  __dpmi_set_segment_limit(sdt_selector, sdt_header.length-1); // set segment limit accorning to full SDT length
  movedata(sdt_selector, 0, _my_ds(), (unsigned)p_buffer, sdt_header.length); // copy full SDT from physical memory to target buffer
  __dpmi_free_ldt_descriptor(sdt_selector); // free temporary allocated LDT descriptor
  if (calc_checksum(p_buffer, sdt_header.length)==0) // calculate checksum
    return(sdt_header.length);         // if match return full lenght
  else
    return(0);                         // else return 0
}


Utility can be tested here:
http://rayer.ic.cz/350d/ACPINFO.EXE

---
DOS gives me freedom to unlimited HW access.

Japheth

Homepage

Germany (South),
14.07.2011, 09:15

@ RayeR

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi?

> __dpmi_physical_address_mapping() but I read this function has some
> limits like minimum size should be 4kB and in multiple of 4kB blocks

> BTW why __dpmi_physical_address_mapping() needs size
> paramerer at all?

Because it consumes resources - linear address space and physical memory for page table entries. The larger the size, the more of these resources are needed.

> I checked that meminfo.address didn't changed when I
> changed the size and call __dpmi_physical_address_mapping() again...

Perhaps this will change if you do call int 31h, ax=0501h ( allocate memory ) between those calls?

---
MS-DOS forever!

RayeR

Homepage

CZ,
14.07.2011, 15:09

@ Japheth

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi?

> > __dpmi_physical_address_mapping() but I read this function has some
> > limits like minimum size should be 4kB and in multiple of 4kB blocks
>
> > BTW why __dpmi_physical_address_mapping() needs size
> > paramerer at all?
>
> Because it consumes resources - linear address space and physical memory
> for page table entries. The larger the size, the more of these resources
> are needed.

OK I understand. I didn't tried allocating mem between it.

What do you reccomend: should I better map let'say 64kB block and don't do the remapping or should I leave it as is when it's working. I would need to test it how it will behave with installed 4GB RAM when ACPI things will be probably close to 0xFFFFFFFF and mapping may roll over but when I will not read beyond...

---
DOS gives me freedom to unlimited HW access.

Laaca

Homepage

Czech republic,
15.07.2011, 12:47

@ RayeR

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi?

What about making it in real mode and use INT 15h/AH=87h instead?

---
DOS-u-akbar!

RayeR

Homepage

CZ,
17.07.2011, 02:06
(edited by RayeR, 17.07.2011, 14:50)

@ Laaca

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi?

> What about making it in real mode and use INT 15h/AH=87h instead?

I don't know if this function works with some linear adress or physical address. Also it may happen that I will need move >32kB and work even with larger data structures so I don't want loose the advantages of PM.

Next I simply want to know how should I correctly use DPMI mapping function.And nobody on djgpp google group neither here can tell me...

BTW even Microsoft cannot do their ACPI job well (quote from CoreBoot wiki):

Windows XP or Server 2003 setup might fail with an error message such as: "An
unexpected error (805262864) occurred at line 1768 of d:\xpclient\base\boot\
setup\arcdisp.c" The value 805262864 varies, and is the physical address, in
decimal, of one of the ACPI tables. The error message is displayed when a 1024
dword page table array used by setupldr runs out of space. This table is used
for mapping various physical addresses, such as those of ACPI tables (a
separate table identity maps the lower 16MB used by setupldr code and data).
Setupldr only looks at ACPI tables (FACP) to determine make and model of the
system. The make and model of the system is needed when setupldr scans the good/
bad bios lists contained in txtsetup.sif. The good/bad bios lists are used to
bypass installation of the ACPI enabled kernel on certain systems known to have
ACPI problems. The code loop that scans the lists creates a new mapping each
time it reads an ACPI table, and never frees mappings. The code uses FACP OEM
ID to determine the system model. The code sequentially reads tables listed in
the RSDT array until the FACP is found. Each read consumes one page table entry.
If more that 4 tables precede the FACP in the RSDT array, the 1024 entry page
table array will run out of space before the good/bad bios list processing
completes. BIOS can work around this Windows XP/Server 2003 limitation by
placing the FACP early in the RSDT array.


DJGPP/CWSDPMI seems to not support unmapping function so it may happen also there but mapping is freed when program exit...

int __dpmi_free_physical_address_mapping(__dpmi_meminfo *info);
Please refer to the DPMI Specification (DPMI Specification) for
details on DPMI function call operation. Also see the DPMI Overview
(DPMI Overview) for general information.

DPMI function AX = 0x0801 (DPMI 1.0 only). Not supported by CWSDPMI and
Windows.

---
DOS gives me freedom to unlimited HW access.

RayeR

Homepage

CZ,
17.07.2011, 14:47

@ RayeR

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi?

I tried to midify code for single mapping and then varied size of constant
BIOS_IMAGE_SIZE2 0x10000000
If it was less or equal 0x10000000 it works if greater then it crashed. I have installed 2GB RAM. I don't know how it will behave on 4GB sysatem wher ACPI SDT base will be higher close to 0xFFFFFFFF, probably it will crash with much smaller size when roll over...


//***************** copy SDT table from physical address to local buffer, parse header and calc checksum
long copy_sdt(Byte *p_buffer, DWord phys_ptr) // returns SDT length, 0 if bad checksum, negative if read error
{
  ACPI_SDT_HEADER sdt_header;          // temporarly stored SDT header to obtain full SDT size
  __dpmi_meminfo meminfo;              // DPMI meminfo structure for physical memory mapping
  int sdt_selector;                    // selector of segment descriptor of mapped SDT
#define BIOS_IMAGE_SIZE2 0x10000000
  meminfo.address=phys_ptr;            // mapped physical address
  meminfo.size=BIOS_IMAGE_SIZE2;        // mapped physical area size (128kB) large enough for SDT (possibly may roll-over 32bit range but will not be accessed)
  if (__dpmi_physical_address_mapping(&meminfo)!=0) // map physical memory area to linear
    return(-2);                        // if failed return -2
  if ((sdt_selector=__dpmi_allocate_ldt_descriptors(1))<0) // allocate 1 descriptor (desribing our new segment) in LDT and return it's selector
    return(-1);                        // if failed return -1
  __dpmi_set_segment_base_address(sdt_selector, meminfo.address); // set segment base to linear ptr
  __dpmi_set_segment_limit(sdt_selector, BIOS_IMAGE_SIZE2-1); // set segment limit to 128kB-1
  movedata(sdt_selector, 0, _my_ds(), (unsigned)&sdt_header, sizeof(ACPI_SDT_HEADER)); // copy SDT header from physical memory to temp buffer
  if (sdt_header.length<sizeof(ACPI_SDT_HEADER)) // check SDT lenght
    {                                  // if less than header size=invalid
    __dpmi_free_ldt_descriptor(sdt_selector); // free temporary allocated LDT descriptor
    return(0);                         // return 0
    }
  movedata(sdt_selector, 0, _my_ds(), (unsigned)p_buffer, sdt_header.length); // copy full SDT from physical memory to target buffer
  __dpmi_free_ldt_descriptor(sdt_selector); // free temporary allocated LDT descriptor
  if (calc_checksum(p_buffer, sdt_header.length)==0) // calculate checksum
    return(sdt_header.length);         // if match return full SDT lenght
  else                                 // data_length=full_length-header_length
    return(0);                         // else return 0
}

---
DOS gives me freedom to unlimited HW access.

RayeR

Homepage

CZ,
02.08.2011, 13:08

@ RayeR

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi?

> I don't know how it will behave on 4GB sysatem wher
> ACPI SDT base will be higher close to 0xFFFFFFFF, probably it will crash
> with much smaller size when roll over...

Well I tested it on machine with 8GB but surprisingly the ACPI BIOS tables are mapped to physical address 0xC9780000, not close to 0xFFFFFFFF. so I cannot test rollover. I asked also DJ Delorie but he told me he don't have such DPMI knowledges. I hoped someone here will know and help. I have no idea where else should I ask and search :(

---
DOS gives me freedom to unlimited HW access.

Rugxulo

Homepage

Usono,
05.08.2011, 22:25

@ RayeR

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi?

> Well I tested it on machine with 8GB but surprisingly the ACPI BIOS tables
> are mapped to physical address 0xC9780000, not close to 0xFFFFFFFF. so I
> cannot test rollover. I asked also DJ Delorie but he told me he don't have
> such DPMI knowledges. I hoped someone here will know and help. I have no
> idea where else should I ask and search :(

cwsdpmi _AT_ earthlink _DOT_ net

He's the guy who knows this stuff. Granted, he's always busy, but he's who I'd ask (and he seems friendly and helpful, in general).

Sorry I can't personally help much more: I'm just too dumb! :-| Can't know everything!

RayeR

Homepage

CZ,
06.08.2011, 11:56

@ Rugxulo

DJGPP - Mapping small blocks of physmem beyond 1MB - __dpmi?

> cwsdpmi _AT_ earthlink _DOT_ net
>
> He's the guy who knows this stuff. Granted, he's always busy, but he's who
> I'd ask (and he seems friendly and helpful, in general).
>
> Sorry I can't personally help much more: I'm just too dumb! :-| Can't
> know everything!

Mr Charless Sandmann? Yes I mailed him once 8 years ago... Well, I'll try to ask him, hope he's bussy less than me :)

---
DOS gives me freedom to unlimited HW access.

Back to the board
Thread view  Mix view  Order
22049 Postings in 2034 Threads, 396 registered users, 252 users online (1 registered, 251 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum