/* Source code of RomDump - tool for dumping PCI boards ROMs to a file      */
/* It demonstrates use of prometheus.library.                               */

#define __NOLIBBASE__  /* we do not want to peeking library bases */

#include <proto/exec.h>
#include <exec/memory.h>
#include <proto/dos.h>
#include <proto/prometheus.h>

struct Library *SysBase, *DOSBase, *PrometheusBase, *AslBase;

const char *VString = "$VER: RomDump 1.1 (12.4.2001) © 2001 Matay.\n";

WORD SelectCard(WORD max)
 {
  LONG number, success = FALSE;
  BPTR stdin = Input(), stdout = Output();

  while (!success)
   {
    Printf("Input board number: ");
    Flush(stdout);
    Flush(stdin);
    number = FGetC(stdin) - 48;
    if (number > 0 && number < max) return number;
   }
 }


void WriteRom(ULONG address, ULONG size)
 {
  UBYTE *filename = "RAM:dump";
  BPTR dumpfile;
  UBYTE *buffer, *bufptr;
  WORD i, kb = 0;

  if (dumpfile = Open(filename, MODE_NEWFILE))
   {
    if (buffer = AllocMem(2048, MEMF_ANY))
     {
      for (bufptr = (UBYTE*)address; bufptr < (UBYTE*)address + size;
       bufptr += 2048)
       {
        for (i = 0; i < 2048; i++)
         {
          buffer[i] = bufptr[i];
          CacheClearU();
          buffer[i] = bufptr[i];
         }
        FWrite(dumpfile, buffer, 2048, 1);
        kb += 2;
        Printf("%ld kB read...     \r", kb);
       }    
      FreeMem(buffer,2048);
     }
    else Printf("Out of memory.\n");
    Close(dumpfile);
   }
  else Printf("Can't open file.\n");
 }


LONG Main(void)
 {
  Printf("\nRomDump 1.0 © 2001 Matay.\n");
  Printf("PCI cards with ROMs:\n-------------------------------------------------\n");

  if (AslBase = OpenLibrary("asl.library",38))
   {
    if (PrometheusBase = OpenLibrary("prometheus.library", 1))
     {
      APTR board = NULL;
      ULONG vendor, device, romaddr, romsize;
      ULONG addresses[4], sizes[4];
      WORD card = 1;

      while (board = Prm_FindBoardTags (board, TAG_END))
       {
        Prm_GetBoardAttrsTags(board,
         PRM_Vendor, (ULONG)&vendor,
         PRM_Device, (ULONG)&device,
         PRM_ROM_Address, (ULONG)&romaddr,
         PRM_ROM_Size, (ULONG)&romsize,
         TAG_END);
        if (romaddr && romsize)
         {
          addresses[card] = romaddr;
          sizes[card] = romsize;
          Printf("%ld. Vendor %04lx, device %04lx, %ld kB of ROM at $%08lx.\n", card,
           vendor, device, romsize >> 10, romaddr);
         }
        card++;
       }
      Printf ("\n");
      card = SelectCard(card);
      Printf("Selected card %ld with %ld kB of ROM at %08lx.\n", card,
       sizes[card] >> 10, addresses[card]);
      WriteRom(addresses[card], sizes[card]);
      CloseLibrary(PrometheusBase);
     }
    CloseLibrary(AslBase);
   }
  else Printf("No working Prometheus board found in the system.\n\n");
  return 0;
 }

