home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / util / misc / VMM_src.lha / VMM / pageio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-16  |  21.7 KB  |  746 lines

  1. #include <exec/types.h>
  2. #include "defs.h"
  3.  
  4. /* Handles all communication with DOS or the paging device */
  5.  
  6. static char rcsid [] = "$Id: pageio.c,v 3.6 95/12/16 18:36:42 Martin_Apel Exp $";
  7.  
  8. /* Params if PageDev == PD_FILE or PD_PSEUDO_PART */
  9. PRIVATE BPTR PageFile;
  10. PRIVATE LONG PageFileArg1;              /* Often used by packets */
  11. PRIVATE struct MsgPort *ReplyPort;
  12. PRIVATE struct MsgPort *PageFilePort;
  13. PRIVATE struct FileInfoBlock *PagingInfo;
  14. PRIVATE LONG BuffersAdded;
  15.  
  16. /* Data used for multi-page writing */
  17. PRIVATE struct IOStdReq *MultiPageReq;
  18. PRIVATE struct DosPacket *MultiPagePacket;
  19. PRIVATE struct MsgPort *MultiPagePort;
  20.  
  21. #define CHUNKSIZE (512L * 1024L)        /* write 512 K in one go */
  22.  
  23. #define MIN(a,b) (((a)<(b))?(a):(b))
  24.  
  25. /*****************************************************************/
  26.  
  27. PRIVATE void AddBuffersForFile (void)
  28.  
  29. {
  30. int rc;
  31. LONG CurrentBuffers;
  32. LONG DesiredBuffers;
  33. ULONG DiskType;
  34.  
  35. if (GetDiskType (PartWithColon, &DiskType) != SUCCESS)
  36.   return;
  37.  
  38. if (DiskType != ID_FFS_DISK && DiskType != ID_INTER_FFS_DISK)
  39.   return;                     /* no additional buffers for other filesystems */
  40.  
  41. rc = AddBuffers (PartWithColon, 0L);
  42.  
  43. if (rc == FALSE)
  44.   {
  45.   PRINT_DEB ("AddBuffersForFile failed", 0L);
  46.   return;
  47.   }
  48.  
  49. if (rc == DOSTRUE)                 /* see doc for AddBuffers */
  50.   CurrentBuffers = IoErr ();
  51. else
  52.   CurrentBuffers = rc;
  53.  
  54. DesiredBuffers = PartSize / 40 / 1024;    /* empirically determined */
  55.  
  56. PRINT_DEB ("CurrentBuffers = %ld", CurrentBuffers);
  57. PRINT_DEB ("DesiredBuffers = %ld", DesiredBuffers);
  58.  
  59. if (DesiredBuffers > CurrentBuffers)
  60.   {
  61.   rc = AddBuffers (PartWithColon, DesiredBuffers - CurrentBuffers);
  62.   if (rc == FALSE)
  63.     return;
  64.  
  65.   if (rc == DOSTRUE)
  66.     BuffersAdded = IoErr () - CurrentBuffers;
  67.   else 
  68.     BuffersAdded = rc - CurrentBuffers;
  69.   
  70.   PRINT_DEB ("Added %ld buffers", BuffersAdded);
  71.   }
  72. }
  73.  
  74. /*****************************************************************/
  75.  
  76. PRIVATE int OpenPageFileAsFile (void)
  77.  
  78. {
  79. char *tmp;
  80. int i;
  81. ULONG size;
  82.  
  83. /* First try to open existing file, if none exists, open a new one.
  84.  * C evaluation rules used.
  85.  */
  86. if (((PageFile = Open (CurrentConfig.PartOrFileName, MODE_OLDFILE)) == NULL) &&
  87.     ((PageFile = Open (CurrentConfig.PartOrFileName, MODE_NEWFILE)) == NULL))
  88.   {
  89.   PRINT_DEB ("OpenPageFileAsFile: Couldn't open paging file", 0L);
  90.   return (ERR_NO_PAGING_FILE);
  91.   }
  92.  
  93. PRINT_DEB ("OpenPageFileAsFile: File opened successfully", 0L);
  94.  
  95. PageFilePort = DeviceProc (CurrentConfig.PartOrFileName);
  96.  
  97. PageFileArg1 = ((struct FileHandle*)BADDR (PageFile))->fh_Arg1;
  98. PartSize = SetFileSize (PageFile, CurrentConfig.FileSize * 1024L * 1024L, 
  99.                         OFFSET_BEGINNING);
  100.  
  101. PRINT_DEB ("OpenPageFileAsFile: After SetFileSize", 0L);
  102.  
  103. /* Not all handlers support SetFileSize */
  104. if (PartSize != CurrentConfig.FileSize * 1024L * 1024L)
  105.   {
  106.   PRINT_DEB ("Couldn't make page file large enough", 0L);
  107.   PRINT_DEB ("Trying to write desired file size", 0L);
  108.  
  109.   if (IoErr () == ERROR_DISK_FULL)
  110.     return (ERR_NO_SPACE);
  111.  
  112.   size = Seek (PageFile, 0L, OFFSET_END);
  113.   PRINT_DEB ("Current file size is %ld bytes", size);
  114.   tmp = ((struct MemHeader*)(SysBase->MemList.lh_Head))->mh_Lower;
  115.  
  116.   /* Do it the slow, but secure way */
  117.   while (size < CurrentConfig.FileSize * 1024L * 1024L)
  118.     {
  119.     if (Write (PageFile, tmp, CHUNKSIZE) != CHUNKSIZE)
  120.       {
  121.       PRINT_DEB ("Not enough space on volume", 0L);
  122.       return (ERR_NO_SPACE);
  123.       }
  124.     size += CHUNKSIZE;
  125.     }
  126.  
  127.   PRINT_DEB ("Managed to create page file", 0L);
  128.   PartSize = CurrentConfig.FileSize * 1024L * 1024L;
  129.   }
  130.  
  131. if ((ReplyPort = CreateMsgPort ()) == NULL)
  132.   return (ERR_NOT_ENOUGH_MEM);
  133.  
  134. ReplySignal = ReplyPort->mp_SigBit;
  135.  
  136. if ((MultiPagePort = CreateMsgPort ()) == NULL)
  137.   return (ERR_NOT_ENOUGH_MEM);
  138.  
  139. PRINT_DEB ("OpenPageFileAsFile: Created Ports", 0L);
  140.  
  141. for (i = 0; i < MAX_FAULTS; i++)
  142.   {
  143.   /* dp_Arg7 is used as a pointer from the packet to the corresponding
  144.    * TrapStruct.
  145.    */
  146.   if ((TrapInfo[i].IOPacket = AllocDosObject (DOS_STDPKT, NULL)) == NULL)
  147.     return (ERR_NOT_ENOUGH_MEM);
  148.  
  149.   ((struct DosPacket*)TrapInfo[i].IOPacket)->dp_Arg7 = (LONG)&(TrapInfo [i]);
  150.  
  151.   /* Another packet is needed for the seek operation, which has to precede
  152.    * each read or write operation.
  153.    */
  154.   if ((TrapInfo[i].SeekPacket = AllocDosObject (DOS_STDPKT, NULL)) == NULL)
  155.     return (ERR_NOT_ENOUGH_MEM);
  156.  
  157.   ((struct DosPacket*)TrapInfo[i].SeekPacket)->dp_Arg7 = (LONG)&(TrapInfo [i]);
  158.   }
  159.  
  160. if ((MultiPagePacket = AllocDosObject (DOS_STDPKT, NULL)) == NULL)
  161.   return (ERR_NOT_ENOUGH_MEM);
  162.  
  163. PRINT_DEB ("OpenPageFileAsFile: Initialized Packets", 0L);
  164.  
  165. AddBuffersForFile ();
  166.  
  167. PRINT_DEB ("OpenPageFileAsFile: Added buffers", 0L);
  168.  
  169. return (SUCCESS);
  170. }
  171.  
  172. /*****************************************************************/
  173.  
  174. PRIVATE int OpenPageFileAsPartition (BOOL WritePermit)
  175.  
  176. {
  177. int i;
  178. char *buffer,
  179.      *tmp;
  180. struct EasyStruct MyRequest =
  181.   {
  182.   sizeof (struct EasyStruct),
  183.   0,
  184.   PROGNAME,
  185.   NULL,
  186.   NULL
  187.   };
  188.  
  189. /* Reserve first 512 bytes for ID */
  190. PartStart = PagingDevParams.low_cyl * PagingDevParams.heads *
  191.             PagingDevParams.secs_per_track * 512L + 512;
  192. PartSize = (PagingDevParams.high_cyl - PagingDevParams.low_cyl + 1) *
  193.             PagingDevParams.heads * PagingDevParams.secs_per_track * 512L - 512;
  194.  
  195. if (((ReplyPort = CreateMsgPort ()) == NULL) || 
  196.     ((MultiPagePort = CreateMsgPort ()) == NULL))
  197.   return (ERR_NOT_ENOUGH_MEM);
  198.  
  199. for (i = 0; i < MAX_FAULTS; i++)
  200.   {
  201.   if ((TrapInfo[i].IOPacket = CreateIORequest (ReplyPort,
  202.                sizeof (struct ExtIOReq))) == NULL)
  203.     return (ERR_NOT_ENOUGH_MEM);
  204.  
  205.   /* Install back pointer from IORequest to TrapInfo */
  206.   ((struct ExtIOReq*)TrapInfo[i].IOPacket)->TrapInfo = &(TrapInfo[i]);
  207.   }
  208.  
  209. if ((MultiPageReq = CreateIORequest (MultiPagePort, sizeof (struct IOStdReq))) == NULL)
  210.   return (ERR_NOT_ENOUGH_MEM);
  211.  
  212. if (OpenDevice (PagingDevParams.device->dd_Library.lib_Node.ln_Name,
  213.                 PagingDevParams.unit,
  214.                 (struct IORequest*)TrapInfo[0].IOPacket,
  215.                 PagingDevParams.flags))
  216.   {
  217.   char ErrorBuffer [80];
  218.   sprintf (ErrorBuffer, GetVMMString (msgNoDevice),
  219.            PagingDevParams.device->dd_Library.lib_Node.ln_Name);
  220.   ReportError (ErrorBuffer, ERR_CONTINUE);
  221.   return (ERR_MSG_POSTED);
  222.   }
  223.  
  224. for (i = 1; i < MAX_FAULTS; i++)
  225.   {
  226.   ((struct ExtIOReq*)TrapInfo [i].IOPacket)->ioreq.io_Device =
  227.                 ((struct ExtIOReq*)TrapInfo [0].IOPacket)->ioreq.io_Device;
  228.   ((struct ExtIOReq*)TrapInfo [i].IOPacket)->ioreq.io_Unit =
  229.                     ((struct ExtIOReq*)TrapInfo [0].IOPacket)->ioreq.io_Unit;
  230.   }
  231.  
  232. MultiPageReq->io_Device = ((struct ExtIOReq*)TrapInfo [0].IOPacket)->ioreq.io_Device;
  233. MultiPageReq->io_Unit   = ((struct ExtIOReq*)TrapInfo [0].IOPacket)->ioreq.io_Unit;
  234.  
  235. if (WritePermit)
  236.   {
  237.   /* Allocate enough memory for a LINUX page. LINUX marks its swap-space
  238.    * by a signature in the last bytes of the first page.
  239.    */
  240.   if ((buffer = DoOrigAllocMem (4096L, MEMF_PUBLIC)) == NULL)
  241.     return (ERR_NOT_ENOUGH_MEM);
  242.  
  243.   ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Command = CMD_READ;
  244.   ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Flags = 0;
  245.   ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Length = 4096;
  246.   ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Data = buffer;
  247.   ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Offset = PartStart - 512;
  248.   SendIO ((struct IORequest*)TrapInfo[0].IOPacket);
  249.   WaitIO ((struct IORequest*)TrapInfo[0].IOPacket);
  250.   if (((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Error != 0)
  251.     {
  252.     FreeMem (buffer, 4096L);
  253.     return (ERR_FAILED_IO);
  254.     }
  255.  
  256.   if (strcmp (PROGNAME, buffer) != 0)
  257.     {
  258.     tmp = PartWithColon;
  259.     MyRequest.es_TextFormat = GetVMMString (msgUnusedPartition);
  260.     MyRequest.es_GadgetFormat = GetVMMString (msgUseCancel);
  261.     if (strncmp (buffer + 4096 - 10, "SWAP-SPACE", 10) != 0 &&
  262.         !CxParams->ForceOverwrite && 
  263.         !EasyRequestArgs (NULL, &MyRequest, NULL, &tmp))
  264.       {
  265.       FreeMem (buffer, 4096L);
  266.       return (ERR_MSG_POSTED);
  267.       }
  268.     strcpy (buffer, PROGNAME);
  269.     ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Command = CMD_WRITE;
  270.     ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Flags = 0;
  271.     ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Length = 512;
  272.     ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Data = buffer;
  273.     ((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Offset = PartStart - 512;
  274.     SendIO ((struct IORequest*)TrapInfo[0].IOPacket);
  275.     WaitIO ((struct IORequest*)TrapInfo[0].IOPacket);
  276.     if (((struct IOStdReq*)TrapInfo[0].IOPacket)->io_Error != 0)
  277.       {
  278.       FreeMem (buffer, 4096L);
  279.       return (ERR_FAILED_IO);
  280.       }
  281.     }
  282.  
  283.   FreeMem (buffer, 4096L);
  284.   }
  285. ReplySignal = ReplyPort->mp_SigBit;
  286. return (SUCCESS);
  287. }
  288.  
  289. /*****************************************************************/
  290.  
  291. PRIVATE int OpenPageFileAsPseudoPart (void)
  292.  
  293. {
  294. ULONG first_block,
  295.       last_block;
  296. char *tmp;
  297. int rc;
  298.  
  299. struct EasyStruct DeleteRequest =
  300.   {
  301.   sizeof (struct EasyStruct),
  302.   0,
  303.   PROGNAME,
  304.   NULL,
  305.   NULL
  306.   };
  307.  
  308. if ((rc = IsValidFFSPartition ()) != SUCCESS)
  309.   return (rc);
  310.  
  311. if ((PagingInfo = AllocDosObject (DOS_FIB, NULL)) == NULL)
  312.   {
  313.   PRINT_DEB ("Not enough memory for FileInfoBlock", 0L);
  314.   return (ERR_NOT_ENOUGH_MEM);
  315.   }
  316.  
  317. /* First try to open existing file, if none exists, open a new one.
  318.  */
  319. if ((PageFile = Lock (CurrentConfig.PartOrFileName, EXCLUSIVE_LOCK)) != NULL)
  320.   {
  321.   /* File exists. Check if its a valid pseudo-part */
  322.   if (!Examine (PageFile, PagingInfo))
  323.     {
  324.     PRINT_DEB ("Couldn't find information about paging file", 0L);
  325.     return (ERR_NOT_ENOUGH_MEM);   /* Error to complicated to tell the user */
  326.     }
  327.  
  328.   if (PagingInfo->fib_DirEntryType > 0)
  329.     {
  330.     PRINT_DEB ("OpenPageFileAsPseudoPart: PageFile is a directory", 0L);
  331.     return (ERR_FILE_IS_DIR);
  332.     }
  333.  
  334.   if (PagingInfo->fib_Size == CurrentConfig.FileSize * 1024L * 1024L)
  335.     {
  336.     if (IsPseudoPart (PagingInfo->fib_DiskKey, &first_block, &last_block))
  337.       {
  338.       PRINT_DEB ("First block = %ld", first_block);
  339.       PRINT_DEB ("Last block  = %ld", last_block);
  340.  
  341.       PartStart = (PagingDevParams.low_cyl * PagingDevParams.heads *
  342.                    PagingDevParams.secs_per_track + first_block) * 512L;
  343.       PartSize = (last_block - first_block + 1) * 512L;
  344.       PRINT_DEB ("Found existing pseudopart. Start at %ld", PartStart);
  345.       PRINT_DEB ("                           Size  is %ld", PartSize);
  346.       return (SUCCESS);
  347.       }
  348.     }
  349.  
  350.   PRINT_DEB ("Found mismatching file. Deleting it", 0L);
  351.   UnLock (PageFile);
  352.   PageFile = NULL;       /* In case of an error not to be unlocked twice */
  353.  
  354.   tmp = CurrentConfig.PartOrFileName;
  355.   DeleteRequest.es_TextFormat = GetVMMString (msgDeleteFile);
  356.   DeleteRequest.es_GadgetFormat = GetVMMString (msgDeleteCancel);
  357.   if (!CxParams->ForceOverwrite && !EasyRequestArgs (NULL, &DeleteRequest, NULL, &tmp))
  358.     return (ERR_MSG_POSTED);
  359.  
  360.   /* No need to actually delete the file. It will be deleted as part
  361.    * of the opening with MODE_NEWFILE.
  362.    */
  363.   }
  364.  
  365.  
  366. /* Pagefile did not exist. Create a new one */
  367. if ((PageFile = Open (CurrentConfig.PartOrFileName, MODE_NEWFILE)) == NULL)
  368.   {
  369.   PRINT_DEB ("OpenPageFileAsPseudoPart: Couldn't open paging file", 0L);
  370.   return (ERR_NO_PAGING_FILE);
  371.   }
  372.  
  373. Close (PageFile);
  374. if ((PageFile = Lock (CurrentConfig.PartOrFileName, EXCLUSIVE_LOCK)) == NULL)
  375.   {
  376.   PRINT_DEB ("OpenPageFileAsPseudoPart: Internal error", 0L);
  377.   return (ERR_INTERNAL);
  378.   }
  379.  
  380. if (!Examine (PageFile, PagingInfo))
  381.   {
  382.   PRINT_DEB ("OpenPageFileAsPseudoPart: Can't examine new file", 0L);
  383.   return (ERR_NOT_ENOUGH_MEM);     /* Error too complicated to tell the user */
  384.   }
  385.  
  386. rc = CreatePseudoPart (PagingInfo->fib_DiskKey, &first_block, &last_block);
  387. if (rc != SUCCESS)
  388.   {
  389.   PRINT_DEB ("OpenPageFileAsPseudoPart: Couldn't create pseudo partition", 0L);
  390.   return (rc);
  391.   }
  392.  
  393. PRINT_DEB ("First block = %ld", first_block);
  394. PRINT_DEB ("Last block  = %ld", last_block);
  395.  
  396. PartStart = (PagingDevParams.low_cyl * PagingDevParams.heads *
  397.              PagingDevParams.secs_per_track + first_block) * 512L;
  398. PartSize = (last_block - first_block + 1) * 512L;
  399. PRINT_DEB ("Created new pseudopart. Start at %ld", PartStart);
  400. PRINT_DEB ("                        Size  is %ld", PartSize);
  401. return (SUCCESS);
  402. }
  403.  
  404. /*****************************************************************/
  405.  
  406. int OpenPageFile (void)
  407.  
  408. {
  409. int rc;
  410.  
  411. switch (CurrentConfig.PageDev)
  412.   {
  413.   case PD_FILE: PRINT_DEB ("Opening pagefile as file", 0L);
  414.                 return (OpenPageFileAsFile ());
  415.  
  416.   case PD_PART: PRINT_DEB ("Opening pagefile as partition", 0L);
  417.                 return (OpenPageFileAsPartition (TRUE));
  418.  
  419.   case PD_PSEUDOPART: PRINT_DEB ("Opening pagefile as pseudopart", 0L);
  420.                       if ((rc = OpenPageFileAsPartition (FALSE)) != SUCCESS)
  421.                         return (rc );
  422.                       return (OpenPageFileAsPseudoPart ());
  423. #ifdef DEBUG
  424.   default:      PRINT_DEB ("OpenPageFile: Unknown paging device", 0L);
  425.                 ColdReboot ();
  426.                 return (SUCCESS);       /* dummy */
  427. #endif
  428.   }
  429. }
  430.  
  431. /*****************************************************************/
  432.  
  433. void ClosePageFile ()
  434.  
  435. {
  436. int i;
  437.  
  438. switch (CurrentConfig.PageDev)
  439.   {
  440.   case PD_FILE: AddBuffers (PartWithColon, -BuffersAdded);
  441.                 for (i = 0; i < MAX_FAULTS; i++)
  442.                   {
  443.                   if (TrapInfo[i].IOPacket != NULL)
  444.                     FreeDosObject (DOS_STDPKT, TrapInfo[i].IOPacket);
  445.                   if (TrapInfo[i].SeekPacket != NULL)
  446.                     FreeDosObject (DOS_STDPKT, TrapInfo[i].SeekPacket);
  447.                   }
  448.  
  449.                 if (MultiPagePacket != NULL)
  450.                   FreeDosObject (DOS_STDPKT, MultiPagePacket);
  451.               
  452.                 if (ReplyPort != NULL)
  453.                   DeleteMsgPort (ReplyPort);
  454.  
  455.                 if (MultiPagePort != NULL)
  456.                   DeleteMsgPort (MultiPagePort);
  457.  
  458.                 if (PageFile != NULL)
  459.                   Close (PageFile);
  460.                 break;
  461.  
  462.   case PD_PSEUDOPART:
  463.                 if (PageFile != NULL)
  464.                   UnLock (PageFile);
  465.  
  466.                 if (PagingInfo != NULL)
  467.                   FreeDosObject (DOS_FIB, PagingInfo);
  468.                   
  469.                 /* fall through to device closing */
  470.  
  471.   case PD_PART: CloseDevice ((struct IORequest*)TrapInfo [0].IOPacket);
  472.                 for (i = 0; i < MAX_FAULTS; i++)
  473.                   DeleteIORequest ((struct IORequest*)TrapInfo [i].IOPacket);
  474.  
  475.                 DeleteIORequest ((struct IORequest*)MultiPageReq);
  476.  
  477.                 DeleteMsgPort (ReplyPort);
  478.                 DeleteMsgPort (MultiPagePort);
  479.                 break;
  480. #ifdef DEBUG
  481.   default:      PRINT_DEB ("ClosePageFile: Unknown paging device", 0L);
  482.                 ColdReboot ();
  483. #endif
  484.   }
  485. }
  486.  
  487. /*****************************************************************/
  488.  
  489. void WriteSinglePage (ULONG slot_num, struct TrapStruct *ThisTrap)
  490.  
  491. {
  492. struct DosPacket *SeekPacket,
  493.                  *WritePacket;
  494.  
  495. /* PRINT_DEB ("Writing page %ld", slot_num); */
  496.  
  497. PagesWritten++;
  498.  
  499. switch (CurrentConfig.PageDev)
  500.   {
  501.   case PD_FILE:
  502.     WritePacket = (struct DosPacket*)ThisTrap->IOPacket;
  503.     SeekPacket  = (struct DosPacket*)ThisTrap->SeekPacket;
  504.  
  505.     SeekPacket->dp_Port = ReplyPort;
  506.     SeekPacket->dp_Action = ACTION_SEEK;
  507.     SeekPacket->dp_Arg1 = PageFileArg1;
  508.     SeekPacket->dp_Arg2 = slot_num << PAGESIZESHIFT;
  509.     SeekPacket->dp_Arg3 = OFFSET_BEGINNING;
  510.     SendPkt (SeekPacket, PageFilePort, ReplyPort);
  511.  
  512.     WritePacket->dp_Port = ReplyPort;
  513.     WritePacket->dp_Action = ACTION_WRITE;
  514.     WritePacket->dp_Arg1 = PageFileArg1;
  515.     WritePacket->dp_Arg2 = ThisTrap->PhysAddr;
  516.     WritePacket->dp_Arg3 = PAGESIZE;
  517.     SendPkt (WritePacket, PageFilePort, ReplyPort);
  518.     break;
  519.  
  520.   case PD_PART:
  521.   case PD_PSEUDOPART:
  522.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Command = CMD_WRITE;
  523.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Flags = 0;
  524.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Length = PAGESIZE;
  525.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Data = (APTR)ThisTrap->PhysAddr;
  526.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Offset = slot_num * PAGESIZE + PartStart;
  527.  
  528.     if (((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Offset < PartStart ||
  529.         ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Offset > PartStart + PartSize)
  530.       FatalError (ERR_OUT_OF_BOUNDS);
  531.  
  532.     SendIO ((struct IORequest*)ThisTrap->IOPacket);
  533.     break;
  534.  
  535. #ifdef DEBUG
  536.   default:
  537.     PRINT_DEB ("WritePage: Unknown paging device", 0L);
  538.     ColdReboot ();
  539. #endif
  540.   }
  541. }
  542.  
  543. /*****************************************************************/
  544.  
  545. void ReadSinglePage (ULONG slot_num, struct TrapStruct *ThisTrap)
  546.  
  547. {
  548. struct DosPacket *SeekPacket,
  549.                  *ReadPacket;
  550.  
  551. /* PRINT_DEB ("Reading page %ld", slot_num); */
  552. PagesRead++;
  553.  
  554. switch (CurrentConfig.PageDev)
  555.   {
  556.   case PD_FILE:
  557.     ReadPacket = (struct DosPacket*)ThisTrap->IOPacket;
  558.     SeekPacket = (struct DosPacket*)ThisTrap->SeekPacket;
  559.  
  560.     SeekPacket->dp_Port = ReplyPort;
  561.     SeekPacket->dp_Action = ACTION_SEEK;
  562.     SeekPacket->dp_Arg1 = PageFileArg1;
  563.     SeekPacket->dp_Arg2 = slot_num << PAGESIZESHIFT;
  564.     SeekPacket->dp_Arg3 = OFFSET_BEGINNING;
  565.     SendPkt (SeekPacket, PageFilePort, ReplyPort);
  566.  
  567.     ReadPacket->dp_Port = ReplyPort;
  568.     ReadPacket->dp_Action = ACTION_READ;
  569.     ReadPacket->dp_Arg1 = PageFileArg1;
  570.     ReadPacket->dp_Arg2 = ThisTrap->PhysAddr;
  571.     ReadPacket->dp_Arg3 = PAGESIZE;
  572.     SendPkt (ReadPacket, PageFilePort, ReplyPort);
  573.     break;
  574.  
  575.   case PD_PART:
  576.   case PD_PSEUDOPART:
  577.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Command = CMD_READ;
  578.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Flags = 0;
  579.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Length = PAGESIZE;
  580.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Data = (APTR)ThisTrap->PhysAddr;
  581.     ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Offset = slot_num * PAGESIZE + PartStart;
  582.  
  583.     if (((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Offset < PartStart ||
  584.         ((struct ExtIOReq*)ThisTrap->IOPacket)->ioreq.io_Offset > PartStart + PartSize)
  585.       FatalError (ERR_OUT_OF_BOUNDS);
  586.  
  587.     SendIO ((struct IORequest*)ThisTrap->IOPacket);
  588.     break;
  589.  
  590. #ifdef DEBUG
  591.   default:
  592.     PRINT_DEB ("ReadPage: Unknown paging device", 0L);
  593.     ColdReboot ();
  594. #endif
  595.   }
  596. }
  597.  
  598. /*****************************************************************/
  599.  
  600. void WriteMultiplePages (ULONG slot_num, void *buffer, ULONG num_pages)
  601.  
  602. {
  603. /* Writes multiple pages to disk SYNCHRONOUSLY */
  604. BOOL ErrorOccurred;
  605. ULONG BytesToWrite;
  606. ULONG Offset;
  607. ULONG Location;
  608.  
  609. /* PRINT_DEB ("WriteMultiplePages called. %ld pages", num_pages); */
  610. PagesWritten += num_pages;
  611.  
  612. switch (CurrentConfig.PageDev)
  613.   {
  614.   case PD_FILE:
  615.     MultiPagePacket->dp_Port = MultiPagePort;
  616.     MultiPagePacket->dp_Action = ACTION_SEEK;
  617.     MultiPagePacket->dp_Arg1 = PageFileArg1;
  618.     MultiPagePacket->dp_Arg2 = slot_num << PAGESIZESHIFT;
  619.     MultiPagePacket->dp_Arg3 = OFFSET_BEGINNING;
  620.     SendPkt (MultiPagePacket, PageFilePort, MultiPagePort);
  621.     WaitPort (MultiPagePort);
  622.     GetMsg (MultiPagePort);
  623.  
  624.     MultiPagePacket->dp_Port = MultiPagePort;
  625.     MultiPagePacket->dp_Action = ACTION_WRITE;
  626.     MultiPagePacket->dp_Arg1 = PageFileArg1;
  627.     MultiPagePacket->dp_Arg2 = (long)buffer;
  628.     MultiPagePacket->dp_Arg3 = num_pages * PAGESIZE;
  629.     SendPkt (MultiPagePacket, PageFilePort, MultiPagePort);
  630.     WaitPort (MultiPagePort);
  631.     GetMsg (MultiPagePort);
  632.     ErrorOccurred = (MultiPagePacket->dp_Res1 != num_pages * PAGESIZE);
  633.     break;
  634.  
  635.   case PD_PART:
  636.   case PD_PSEUDOPART:
  637.     BytesToWrite = num_pages * PAGESIZE;
  638.     Location = (ULONG)buffer;
  639.     Offset = slot_num * PAGESIZE + PartStart;
  640.  
  641.     while (BytesToWrite > 0)
  642.       {
  643.       ULONG BytesThisTime = MIN (BytesToWrite, 
  644.                     ALIGN_DOWN (PagingDevParams.MaxTransfer + 1, PAGESIZE));
  645.  
  646.       PRINT_DEB ("Transferring %ld bytes", BytesThisTime);
  647.  
  648.       MultiPageReq->io_Command = CMD_WRITE;
  649.       MultiPageReq->io_Flags = 0;
  650.       MultiPageReq->io_Length = BytesThisTime;
  651.       MultiPageReq->io_Data = (APTR)Location;
  652.       MultiPageReq->io_Offset = Offset;
  653.  
  654.       if (MultiPageReq->io_Offset < PartStart ||
  655.           MultiPageReq->io_Offset > PartStart + PartSize)
  656.         FatalError (ERR_OUT_OF_BOUNDS);
  657.  
  658.       SendIO ((struct IORequest*)MultiPageReq);
  659.       WaitIO ((struct IORequest*)MultiPageReq);
  660.       ErrorOccurred = (MultiPageReq->io_Error != 0) || 
  661.                       (MultiPageReq->io_Actual != BytesThisTime);
  662.       BytesToWrite -= BytesThisTime;
  663.       Location += BytesThisTime;
  664.       Offset += BytesThisTime;
  665.       }
  666.  
  667.     break;
  668.  
  669. #ifdef DEBUG
  670.   default:
  671.     PRINT_DEB ("WriteMultiplePages: Unknown paging device", 0L);
  672.     ColdReboot ();
  673. #endif
  674.   }
  675.  
  676. if (ErrorOccurred)
  677.   {
  678.   PRINT_DEB ("IO to paging device failed", 0L);
  679. #ifdef DEBUG
  680.   ColdReboot ();
  681. #endif
  682.   FatalError (ERR_FAILED_IO);
  683.   }
  684. }
  685.  
  686. /*****************************************************************/
  687.  
  688. void HandleReturn (void)
  689.  
  690. {
  691. struct Message *RetMsg;
  692. struct DosPacket *RetPacket;
  693. struct TrapStruct *ThisFault;
  694. struct ExtIOReq *IO;
  695. BOOL WriteReady;
  696. ULONG ErrorOccurred;
  697.  
  698. while ((RetMsg = GetMsg (ReplyPort)) != NULL)
  699.   {
  700.   switch (CurrentConfig.PageDev)
  701.     {
  702.     case PD_FILE:
  703.       RetPacket = (struct DosPacket*)RetMsg->mn_Node.ln_Name;
  704.       if (RetPacket->dp_Action == ACTION_SEEK)
  705.         {
  706.         /* Ignore the return of seek packets */
  707.         continue;
  708.         }
  709.  
  710.       ThisFault = (struct TrapStruct*)RetPacket->dp_Arg7;
  711.       WriteReady = (RetPacket->dp_Action == ACTION_WRITE);
  712.       ErrorOccurred = (RetPacket->dp_Res1 != PAGESIZE);
  713.       break;
  714.  
  715.     case PD_PART:
  716.     case PD_PSEUDOPART:
  717.       IO = (struct ExtIOReq*)RetMsg;
  718.       ThisFault = IO->TrapInfo;
  719.       WriteReady = (IO->ioreq.io_Command == CMD_WRITE);
  720.       ErrorOccurred = ((IO->ioreq.io_Error != 0) ||
  721.                        (IO->ioreq.io_Actual != PAGESIZE));
  722.       break;
  723.  
  724. #ifdef DEBUG
  725.     default:
  726.       PRINT_DEB ("HandleReturn: Unknown paging device", 0L);
  727.       ColdReboot ();
  728. #endif
  729.     }
  730.  
  731.   if (ErrorOccurred)
  732.     {
  733.     PRINT_DEB ("IO to paging device failed", 0L);
  734. #ifdef DEBUG
  735.     ColdReboot ();
  736. #endif
  737.     FatalError (ERR_FAILED_IO);
  738.     }
  739.  
  740.   if (WriteReady)
  741.     WriteReturned (ThisFault);
  742.   else
  743.     ReadReturned (ThisFault);
  744.   }
  745. }
  746.