home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / e2fltsrc.zip / e2part.c < prev    next >
C/C++ Source or Header  |  1995-07-25  |  10KB  |  283 lines

  1. /************************************************************************/
  2. /*  Linux partition filter (C) Deon van der Westhuysen.                 */
  3. /*                                                                      */
  4. /*  Dedicated to Jesus Christ, my Lord and Saviour.                     */
  5. /*                                                                      */
  6. /*  Permission is granted to freely use and modify this code for non-   */
  7. /*  profit use on the condition that this notice is not removed. All    */
  8. /*  other rights are reserved. No warranty, etc.                        */
  9. /*                                                                      */
  10. /*  This code is still under development; expect some rough edges.      */
  11. /*                                                                      */
  12. /************************************************************************/
  13.  
  14. #include "debug.h"
  15. #include "e2data.h"
  16. #include "e2router.h"
  17. #include "e2part.h"
  18. #include "e2iocmd.h"
  19. #include "e2virtio.h"
  20. #include "e2wrap.h"
  21.  
  22. /* All IORBs for the virtual units (containing the virtual partitions) */
  23. /* arrive here. From here it is routed to the function to service the */
  24. /* command. */
  25. void PartHandler (PIORB pIORB)
  26. {
  27.  NPVirtUnitRec    pUnitRec;            /* Pointer to unit record */
  28.  USHORT        Command;            /* Command to executed */
  29.  USHORT        Modifier;            /* Modifier for the command */
  30.  
  31.  Command= pIORB->CommandCode;            /* Get command to execute */
  32.  Modifier= pIORB->CommandModifier;        /* Get modifier for command */
  33.  if (Command==IOCC_CONFIGURATION)
  34.   pUnitRec= VirtUnits;                /* Default unit for the */
  35.                         /* configuration request */
  36.  else
  37.   pUnitRec= (NPVirtUnitRec) pIORB->UnitHandle;    /* Get unit record for IORB */
  38.  
  39.  /* Route request to appropiate service routine. */
  40.  switch (Command)
  41.  {
  42.   case IOCC_CONFIGURATION:
  43.         switch (Modifier)
  44.         {
  45.          case IOCM_GET_DEVICE_TABLE:
  46.                 PartGetDeviceTable (pUnitRec,pIORB);
  47.                 break;
  48.          default:    BadCommand (pUnitRec,pIORB);
  49.                 break;
  50.         }
  51.         break;
  52.   case IOCC_UNIT_CONTROL:
  53.         switch (Modifier)
  54.         {
  55.          case IOCM_CHANGE_UNITINFO:
  56.                 PartChangeUnitInfo (pUnitRec,pIORB);
  57.                 break;
  58.          default:    BadCommand (pUnitRec,pIORB);
  59.                 break;
  60.         }
  61.         break;
  62.   case IOCC_GEOMETRY:
  63.         switch (Modifier)
  64.         {
  65.          case IOCM_GET_MEDIA_GEOMETRY:
  66.          case IOCM_GET_DEVICE_GEOMETRY:
  67.                 PartGetGeometry (pUnitRec,pIORB);
  68.                 break;
  69.          default:    BadCommand (pUnitRec,pIORB);
  70.                 break;
  71.         }
  72.         break;
  73.   case IOCC_EXECUTE_IO:
  74.         switch (Modifier)
  75.         {
  76.          case IOCM_READ:
  77.          case IOCM_READ_VERIFY:
  78.          case IOCM_WRITE:
  79.          case IOCM_WRITE_VERIFY:
  80.                 PartDoIO (pUnitRec,pIORB);
  81.                 break;
  82.          default:    BadCommand (pUnitRec,pIORB);
  83.                 break;
  84.         }
  85.         break;
  86.   case IOCC_UNIT_STATUS:
  87.         switch (Modifier)
  88.         {
  89.          case IOCM_GET_UNIT_STATUS:
  90.                 PartGetUnitStatus (pUnitRec,pIORB);
  91.                 break;
  92.          default:    BadCommand (pUnitRec,pIORB);
  93.                 break;
  94.         }
  95.         break;
  96.   defualt:    BadCommand (pUnitRec,pIORB);
  97.         break;
  98.  }
  99. }
  100.  
  101. /* This function is called by the original device driver after the IORB */
  102. /* request is satisfied. We restore the IORB before we pass it back to the */
  103. /* caller. */
  104. void PartNotify (PIORB pIORB)
  105. {
  106. #define pIOXIO        ((PIORB_EXECUTEIO) pIORB)
  107.  
  108.  NPVirtUnitRec    pUnitRec;            /* Ptr to unit record */
  109.  ULONG        PatchOffset;            /* Used to fix up boot sec */
  110.  ULONG        PatchValue;
  111.  
  112.  if (pIORB->CommandCode==IOCC_CONFIGURATION)    /* If configuration IORB */
  113.   pUnitRec= VirtUnits;                /* Default unit for the */
  114.                         /* configuration request */
  115.  else
  116.   pUnitRec= (NPVirtUnitRec) pIORB->Reserved_1;    /* Get unit record from IORB */
  117.  
  118.  /* Reverse any mappings that may have been done... */
  119.  pIORB->UnitHandle= pIORB->Reserved_1;        /* Restore IORB fields */
  120.  pIORB->RequestControl= pUnitRec->SaveReqCtrl; 
  121.  pIORB->Reserved_1= pUnitRec->SaveReserved;
  122.  pIORB->NotifyAddress= pUnitRec->SaveNotify;
  123.  if (pIORB->CommandCode==IOCC_EXECUTE_IO)    /* If request involded IO */
  124.  {
  125.   /* Restore RBA and BlockCount fields, modify BlocksXferred... */
  126.   pIOXIO->RBA= pUnitRec->SaveRBA;        
  127.   pIOXIO->BlockCount= pUnitRec->SaveBlockCount;
  128.   pIOXIO->BlocksXferred+= pUnitRec->SectorsDone;
  129.  
  130.   /* If the scatter/gather list was modified then restore it as well. */
  131.   if ((pUnitRec->SGOffset)&&(pIORB->CommandModifier!=IOCM_READ_VERIFY))
  132.   {
  133.    /* If we didn't run out of SG list elements... */
  134.    if (pIOXIO->cSGList)
  135.     memcpy (pIOXIO->pSGList,&(pUnitRec->SaveSGEntry),sizeof(SCATGATENTRY));
  136.    pIOXIO->cSGList= pUnitRec->SavecSGList;
  137.    pIOXIO->pSGList= pUnitRec->SavepSGList;
  138.    pIOXIO->ppSGList= pUnitRec->SaveppSGList;
  139.   }
  140.  
  141.   /* OK first 'patch' here: if the FS type is FAT and the bootsector was */
  142.   /* read them we must change the 'Hidden Sectors' field. */
  143.   if ((pUnitRec->FSType==FS_DOSFAT)&&
  144.       (pIOXIO->RBA<=pUnitRec->NumExtraSectors)&&
  145.       ((pIOXIO->RBA+pIOXIO->BlockCount)>pUnitRec->NumExtraSectors))
  146.   {
  147.    PatchOffset= 0x1C+(pUnitRec->NumExtraSectors-pIOXIO->RBA)*SECTOR_SIZE;
  148.    if ((pIORB->CommandModifier==IOCM_READ)||
  149.        (pIORB->CommandModifier==IOCM_WRITE)||
  150.        (pIORB->CommandModifier==IOCM_WRITE_VERIFY))  
  151.    {
  152.     PatchValue= pUnitRec->NumExtraSectors-
  153.                 (pUnitRec->pSourceUnitRec->GeoNumHeads*
  154.                  pUnitRec->pSourceUnitRec->GeoTrackSec); 
  155.     CopyToSGList (&PatchValue,sizeof(PatchValue),
  156.                   pIOXIO->pSGList,pIOXIO->cSGList,PatchOffset);
  157.    }
  158.   }
  159.  }
  160.  /* Notify the caller and restart the queue. */
  161.  PartCommandDone (pUnitRec,pIORB);
  162.  
  163. #undef pIOXIO
  164. }
  165.  
  166. /* Pass the IORB to the base unit containing the source data for the virtual */
  167. /* unit. Remap IO addresses to map virtual partition unto base data. */
  168. void PartFilterIORB (NPVirtUnitRec pUnitRec, PIORB pIORB)
  169. {
  170. #define pIOXIO        ((PIORB_EXECUTEIO) pIORB)
  171.  
  172.  USHORT        SectorsDone;            /* Num virtual sectors */
  173.                         /* allready serviced */
  174.  ULONG        XferOffset;            /* Offset in SG to start IO */
  175.  ULONG        PatchOffset;            /* Used to fix up boot sec */
  176.  
  177.  pUnitRec->SaveReqCtrl= pIORB->RequestControl;    /* Save request control */
  178.  pUnitRec->SaveReserved= pIORB->Reserved_1;    /* Save reserved field */
  179.  pUnitRec->SaveNotify= pIORB->NotifyAddress;    /* Save old notify address */
  180.  pIORB->Reserved_1= pIORB->UnitHandle;        /* Save our old handle */
  181.  
  182.  pIORB->RequestControl|= IORB_ASYNC_POST;    /* Ask for notification */
  183.  pIORB->RequestControl&= ~IORB_CHAIN;        /* Disable chained request */
  184.  pIORB->NotifyAddress= &PartNotifyWrapper;    /* Set our notify address */
  185.  pIORB->UnitHandle= (USHORT) pUnitRec->pSourceUnitRec;
  186.                         /* Handle for our filter */
  187.  
  188.  /* Patch up IORB further for IO requests. */
  189.  if (pIORB->CommandCode==IOCC_EXECUTE_IO)    /* If IO command... */
  190.  {
  191.   /* Patch value written to boot sector of FAT partitions!!! */
  192.   if ((pUnitRec->FSType==FS_DOSFAT)&&
  193.       (pIOXIO->RBA<=pUnitRec->NumExtraSectors)&&
  194.       ((pIOXIO->RBA+pIOXIO->BlockCount)>pUnitRec->NumExtraSectors))
  195.   {
  196.    PatchOffset= 0x1C+(pUnitRec->NumExtraSectors-pIOXIO->RBA)*SECTOR_SIZE;
  197.    if ((pIORB->CommandModifier==IOCM_WRITE)||
  198.        (pIORB->CommandModifier==IOCM_WRITE_VERIFY))  
  199.    {
  200.     CopyToSGList (&pUnitRec->FATHiddenSectors,sizeof(ULONG),
  201.                   pIOXIO->pSGList,pIOXIO->cSGList,PatchOffset);
  202.     /* In real life this value IS WRONG. FIX IT!!! */
  203.  
  204.    }
  205.   }
  206.  
  207.   pUnitRec->SaveBlockCount= pIOXIO->BlockCount;    /* Save IORB IO fields */
  208.   pUnitRec->SectorsDone= pIOXIO->BlocksXferred;
  209.   pUnitRec->SaveRBA= pIOXIO->RBA;
  210.  
  211.   pIOXIO->BlockCount-= pIOXIO->BlocksXferred;    /* Subtract num blocks we */
  212.                         /* allready transfered
  213.   pIOXIO->BlocksXferred= 0;            /* Reset transfer count */
  214.  
  215.   /* Calculate the start sector for the request... */
  216.   if (pIOXIO->RBA<pUnitRec->NumVirtualSectors)        
  217.   {                        /* Includes virtual sectors */
  218.    XferOffset= (pUnitRec->NumVirtualSectors-pIOXIO->RBA)*SECTOR_SIZE;
  219.                         /* Calculate number of bytes */
  220.                         /* to skip past virt sectors */ 
  221.    pIOXIO->RBA= pUnitRec->NumVirtualSectors-pUnitRec->NumExtraSectors+
  222.                 pUnitRec->StartRBA;        /* Calc starting RBA address */
  223.   }
  224.   else
  225.   {                        /* Past virtual sectors */
  226.    XferOffset= 0;                /* No need to skip bytes */
  227.    pIOXIO->RBA= pIOXIO->RBA-pUnitRec->NumExtraSectors+pUnitRec->StartRBA;
  228.                         /* Calc starting RBA address */
  229.   }
  230.   pUnitRec->SGOffset= XferOffset;        /* Save transfer offset */
  231.  
  232.   /* CHECK WAYS OF CHOPPING BLOCK COUNT */
  233.   /* Safety net: chop block count if neccessary: */
  234.   if ((pIOXIO->RBA+pIOXIO->BlockCount)>        /* If past source data */
  235.       (pUnitRec->StartRBA+pUnitRec->NumSectors))    
  236.   {
  237.    BREAK
  238.    pIOXIO->BlockCount= 0;            /* Tough: kill request... */
  239.   }
  240.  
  241.   /* Also modify scatgat list if neccessary... */
  242.   if ((XferOffset)&&(pIORB->CommandModifier!=IOCM_READ_VERIFY))
  243.   {
  244.    /* First save original pointers... */
  245.    pUnitRec->SavecSGList= pIOXIO->cSGList;
  246.    pUnitRec->SavepSGList= pIOXIO->pSGList;
  247.    pUnitRec->SaveppSGList= pIOXIO->ppSGList;
  248.  
  249.    /* Seek to the offset to start IO */
  250.    while ((pIOXIO->cSGList)&&(pIOXIO->pSGList->XferBufLen<=XferOffset))
  251.    {                        /* Skip past SG entries */
  252.     XferOffset-=(pIOXIO->pSGList++)->XferBufLen;
  253.     pIOXIO->cSGList--;
  254.     pIOXIO->ppSGList+= sizeof (SCATGATENTRY);
  255.    }
  256.  
  257.    /* If we didn't run out of SG list elements... */
  258.    if (pIOXIO->cSGList)
  259.    {
  260.     memcpy (&(pUnitRec->SaveSGEntry),pIOXIO->pSGList,sizeof(SCATGATENTRY));
  261.     pIOXIO->pSGList->XferBufLen-= XferOffset;
  262.     pIOXIO->pSGList->ppXferBuf+= XferOffset;
  263.    }
  264.   }
  265.  }
  266.  E2FilterIORB (pIORB);        /* Ask our handler to handle it further... */
  267.  
  268. #undef pIOXIO
  269. }
  270.  
  271. /* Function that is called when the routine that services the IORB has */
  272. /* finished processing that IORB. We notify the caller and try to restart */
  273. /* the IORB queue. */
  274. void PartCommandDone (NPVirtUnitRec pUnitRec, PIORB pIORB)
  275. {
  276.  NPIORBQueue    pQueue;                /* Pointer to IORB queue */
  277.  
  278.  pQueue= &(pUnitRec->Hdr.IORBQueue);        /* Get pointer to queue */
  279.  pQueue->Flags&=~F_REQUEST_BUSY;        /* Indicate queue finished */
  280.  NotifyDone (pIORB);                /* Notify caller */
  281.  StartIORBQueue (pQueue);            /* Try to restart queue */
  282. }
  283.