delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1998/10/09/12:33:12

From: waa AT codex DOT cis DOT upenn DOT edu (William A. Arbaugh)
Newsgroups: comp.os.msdos.djgpp
Subject: Mapping a PCI Expansion ROM - Problems
Date: 9 Oct 1998 16:24:45 GMT
Organization: University of Pennsylvania
Lines: 93
Message-ID: <6vldcd$2vo$1@netnews.upenn.edu>
NNTP-Posting-Host: codex.cis.upenn.edu
X-Newsreader: TIN [version 1.2 PL2-upenn1.3]
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

I have a real mode program written in MASM that maps in the expansion ROM 
of a PCI card.  It works fine.  I've tried to convert that program into a 
C version using DJGPP for a number of reasons.  Unfortunately, when I map 
the address into a high address I get a SEGV.  I assume because there is 
no memory there (I am using near ptrs BTW).  When I map the ROM low 
(0x70000), I don't get the SEGV but the ROM isn't mapped either.  I'm 
very confused as to why this isn't working.  I've attached some code 
below that tries to do the mapping.  Any and all help is greatly appreciated.

		Thanks, Bill

I have included nearptr.h and pc.h.  The IO port commands are macros for 
the DJGPP versions.


void
Map(struct pci_config_reg *pcr)
{
  unsigned long ulConfigCmd;
  unsigned long ulPrevROM = pcr->_baserom;
  unsigned long ulMapAddr;
  unsigned char *pucMemAddr;

  // The steps performed here are taken from PCI Hardware
  // and Software Architecture and Design by Solari and Willse:
  // ISBN 0-929392-32-9. I indicate the page number where appropriate.

  // The original code incorrectly determines the baserom address.
  // The value found above could be the uncleared value SET by the
  // BIOS rather than the actual valid range.  We do it right, p. 723.

  ulConfigCmd = PCI_EN | (pcr->_pcibuses[pcr->_pcibusidx]<<16) |
               (pcr->_cardnum<<11);
  PCIWriteDWORD(ulConfigCmd | 0x30, 0xFFFFFFFE);        // step 1a, p.723
  pcr->_baserom = inl(PCI_DATA);                        //      1b
  if (pcr->_baserom == 0) {                              //      1c
    printf("Error: Base ROM not really supported\n");
    return;
  }
  
  // We'll just use the baserom given since nothing in DOS should be
  // up there anyway. Begin by enabling the memory space
  // bit of the command register (b1 of offset 4). step 3, p. 723
  PCIWriteDWORD(ulConfigCmd | 0x04, pcr->_status_command | 2);   // write it out
  								// with b1 set

  // Now enable the expansion ROM address decode enable bit. 
  // b0 offset 0x30, step 4, p. 724.
  PCIWriteDWORD(ulConfigCmd | 0x30, 0x70001);

  // CHECK TO SEE IF THINGS ARE SET UP PROPERLY
  outl(PCI_INDEX, ulConfigCmd | 0x04); ulMapAddr  = inl(PCI_DATA);
  printf ("Status command is 0x%08X\n", ulMapAddr);

  outl(PCI_INDEX, ulConfigCmd | 0x30); ulMapAddr  = inl(PCI_DATA);
  printf ("Base is 0x%08X\n", ulMapAddr);



  // Now check to ensure the mapping worked correctly.
  // First we need to enable the proper segment selector limit (4GB).
  if (__djgpp_nearptr_enable() == 0) {
    // This isn't likely to happen.
    printf("DJGPP ERROR setting data segment selector offset\n");
    return;
  }


  // Now look for the ROM id 0xAA55
  pucMemAddr = (unsigned char *)0x70000 + __djgpp_conventional_base;
  if (*((unsigned short *)pucMemAddr) == 0xAA55) {
    printf ("ROM mapped correctly.\n");
  } else {
    printf ("ROM mapped incorrectly.\n");
  }


  __djgpp_nearptr_disable();

  // Disable the ROM decode by writing the old baserom
  // Base address register (offset 0x30), step 14 p. 725.
  PCIWriteDWORD(ulConfigCmd | 0x30, pcr->_baserom);          // ROM unmapped
  PCIWriteDWORD(ulConfigCmd | 0x4, pcr->_status_command);

  return;
}


--
-----------------------------------------------------------------------
Bill Arbaugh			   
email:  waa AT dsl DOT cis DOT upenn DOT edu 
-----------------------------------------------------------------------  

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019