Adaptation/GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3" xml:lang="en"><title>Migration
       
    13 Tutorial: Demand Paging and Media Drivers</title><shortdesc>Describes how to change media drivers when demand paging is used.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>Demand paging is a change made from Symbian platform v9.3 to how the Kernel
       
    15 uses RAM and storage media. This topic </p>
       
    16 <section id="GUID-AD70C4EE-F7E8-473D-B917-819B9852CB31"><title>Introduction</title> <p>If the ROM has been built with paging
       
    17 enabled, the image is divided into two sections: an unpaged section and a
       
    18 paged section. In addition to this, code that is not part of the ROM can be
       
    19 loaded on demand into RAM from other non-XIP partitions and/or media, for
       
    20 example FAT or ROFS partitions. </p> <p>Two types of paging are currently
       
    21 supported: </p> <ul>
       
    22 <li id="GUID-E838F239-2F8A-5441-AE76-59382AA75FF6"><p>ROM paging - paging
       
    23 from the paged section of the ROM image </p> </li>
       
    24 <li id="GUID-28970AFC-33C6-56B7-BBD3-383220359A90"><p>code paging - paging
       
    25 from non-removable media, for example, a FAT partition on an internal Multi
       
    26 Media Card (MMC) drive or an internal NAND ROFS/FAT partition. </p> <p>See
       
    27 also <xref href="GUID-90B5FDD9-7D59-5035-BF53-2B177655DCD6.dita">Paging from an
       
    28 internal MMC</xref>. </p> </li>
       
    29 </ul> <p> <note>: A difference between ROM paging and code paging is that
       
    30 all ROM pages are contiguous, whereas code that is paged from other drives
       
    31 may be split over several potentially non-contiguous clusters. This puts an
       
    32 extra burden on the paging subsystem as it needs to identify the layout of
       
    33 the DLL on the media before it is deemed pageable. This is achieved by using
       
    34 the file servers blockmap API.</note> </p> <p>Media drivers are typically
       
    35 PDDs with a filename of <filepath>med.pdd</filepath>. Normally they are declared
       
    36 in the <filepath>rombuild.oby</filepath> file with the keyword <codeph>extension</codeph> or <codeph>device</codeph> and
       
    37 are therefore flagged as unpaged. That is, once loaded their code and read-only
       
    38 data sections are not paged out. </p> <p>A media driver that is capable of
       
    39 servicing page requests from the paging subsystem must ensure that the thread
       
    40 in which the media driver runs takes the page fault itself otherwise a deadlock
       
    41 could occur. In theory, the only time this can happen is when a media driver
       
    42 accepts a write request from a user side client that points to data in the
       
    43 paged section of the ROM or to code that has been loaded into RAM from code
       
    44 paging enabled media. To remedy this, the local media subsystem has been modified
       
    45 to lock write requests to paging media drivers before they are dispatched
       
    46 and to split large write requests into a series of smaller ones to avoid exhausting
       
    47 available RAM. </p> <p>The two initial stages relevant to this discussion
       
    48 are: </p> <ul>
       
    49 <li id="GUID-02D2CBAA-8393-52C2-B940-31603B4AF9FA"><p>the kernel extension
       
    50 entry point - identified by the <codeph>DECLARE_STANDARD_EXTENSION</codeph> macro </p> </li>
       
    51 <li id="GUID-1EFE9978-780D-507C-B408-E0C3AE97A0A7"><p>the PDD entry point
       
    52 - identified by the <codeph>DECLARE_EXTENSION_PDD</codeph> macro. </p> </li>
       
    53 </ul> <p>To enable demand paging as soon as possible in the boot sequence
       
    54 it is desirable to instantiate and install the PDD factory object earlier,
       
    55 for example in the kernel extension entry point. </p> <p> <note> Some media
       
    56 drivers have no kernel extension entry point defined, the MMC media driver
       
    57 is an example. These drivers have a <xref href="GUID-73947402-2F32-35C7-94C4-22B4D63D5FB3.dita"><apiname>DECLARE_STANDARD_PDD</apiname></xref> macro
       
    58 defined rather than <xref href="GUID-52853C0D-CA98-3B92-B7D4-FF1C1F06C1A6.dita"><apiname>DECLARE_EXTENSION_PDD</apiname></xref>. They require
       
    59 modification to have a <xref href="GUID-52853C0D-CA98-3B92-B7D4-FF1C1F06C1A6.dita"><apiname>DECLARE_EXTENSION_PDD</apiname></xref> and a <xref href="GUID-8B6DF6D7-4995-3564-9303-272500D7E747.dita"><apiname>DECLARE_STANDARD_EXTENSION</apiname></xref>.</note> </p> <p>The
       
    60 steps needed to support ROM and/or code paging are as follows: </p> <ol id="GUID-CADDDC61-A3A2-5AC3-AD69-739FD61FA9CC">
       
    61 <li id="GUID-4D14D36E-5F3A-55E6-BAB8-A45243B34928"><p>determine whether code
       
    62 paging is supported, and if so, identify the relevant local drive number or
       
    63 numbers </p> </li>
       
    64 <li id="GUID-F97B3965-020F-5C16-9D09-5861C0B6C695"><p> <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-77FBA53A-CC78-5CD1-8FDF-F6A8001DE466">modify variantmediadef.h</xref>  </p> </li>
       
    65 <li id="GUID-D608C61F-E297-5A0C-B0FD-4F0F98B36EEF"><p> <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-686EFEF4-A514-51BC-8378-962A8899F270">modify the media drivers kernel extension entry point</xref> to register
       
    66 the media driver with the paging subsystem and to instantiate and install
       
    67 the <xref href="GUID-A5484A7F-94B9-34C7-9F88-82B1BF516930.dita"><apiname>DPhysicalDevice</apiname></xref> derived factory object </p> </li>
       
    68 <li id="GUID-5DEA2654-8954-52EC-B498-066AE05AB209"><p> <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-C32CF25E-553B-5786-88ED-4587AC0DF3BA">modify the DLocalDrive::Ecaps() handling</xref>  </p> </li>
       
    69 <li id="GUID-CED0CA1D-44EF-51DC-BC56-60B88A9D0494"><p>modify the media drivers <xref href="GUID-A0D4EB25-0BA4-39EE-874B-465EB9628DCC.dita#GUID-A0D4EB25-0BA4-39EE-874B-465EB9628DCC/GUID-EB244422-0BEC-3D3F-BDDA-3F050A2697A7"><apiname>DMediaDriver::Request</apiname></xref> function
       
    70 to accept the four new <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-AE44672E-F60D-563C-BB6A-B70AF187C366">paging
       
    71 request</xref> types </p> </li>
       
    72 <li id="GUID-A7CFB8AA-4D95-5DD3-AF3F-0FAB0448F218"><p> <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-0EA673E6-FEE4-51F6-9C84-9411316D7357">Handling fragmented write requests</xref>. </p> </li>
       
    73 </ol> </section>
       
    74 <section id="GUID-77FBA53A-CC78-5CD1-8FDF-F6A8001DE466"><title>Changes to
       
    75 variantmediadef.h</title> <p>The following should be defined using appropriate
       
    76 names in the variant's <i>variantmediadef.h</i> file: </p> <ul>
       
    77 <li id="GUID-F5EFB1C8-B7C4-52AD-88A2-8A7659527373"><p> <codeph>PAGING_TYPE</codeph> -
       
    78 flags that indicate whether code paging and/or ROM paging is supported </p> </li>
       
    79 <li id="GUID-2745304A-2FAF-5DCB-88D3-74BD56B475E0"><p> <codeph>NAND_PAGEDRIVELIST</codeph> -
       
    80 a list of the paging drives </p> </li>
       
    81 <li id="GUID-507FB105-E254-501E-B22A-33E93C3CABA5"><p> <codeph>NAND_PAGEDRIVECOUNT</codeph> -
       
    82 the total number of paging drives </p> </li>
       
    83 <li id="GUID-F3D6494E-A14D-5FB1-A3E7-3D75D3753E12"><p> <codeph>NUM_PAGES</codeph> -
       
    84 if a write request points to data that resides in paged ROM, the request is
       
    85 split up into separate fragments of the specified size. This value needs to
       
    86 be chosen with care, as if it is too small writes can take too long to finish. </p> </li>
       
    87 </ul><p> <note> Normal write requests which point to data that is not in paged
       
    88 ROM are not fragmented. However, large requests are split up into smaller
       
    89 requests by the file server, providing clients with a more responsive system.</note> </p> <p>The
       
    90 macros defined in the file <i>variantmediadef.h</i> are passed to <xref href="GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF.dita#GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF/GUID-5FDD89C6-C34A-3A0D-A422-D148DDE23E42"><apiname>LocDrv::RegisterPagingDevice()</apiname></xref>.
       
    91 This function is similar to <xref href="GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF.dita#GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF/GUID-647D0858-FE04-3A4F-99CE-81CD0B34CE7B"><apiname>LocDrv::RegisterMediaDevice()</apiname></xref> in
       
    92 that it takes a drive list as a parameter, but it identifies the drive or
       
    93 drives to be used for code paging. If code only ROM paging is needed, set
       
    94 the drive count to zero. </p> <p>Changes made to support paging on NAND: </p> <codeblock id="GUID-1425F457-8F28-5CD7-B8A4-3FC3D2777D73" xml:space="preserve">// Variant parameters for NAND flash media driver (mednand.pdd)
       
    95 #define NAND_DRIVECOUNT 8
       
    96 #define NAND_DRIVELIST 2,3,5,6,7,9,10,11
       
    97 #define NAND_NUMMEDIA 1
       
    98 #define NAND_DRIVENAME "Nand"
       
    99 
       
   100 #define PAGING_TYPE DPagingDevice::ERom | DPagingDevice::ECode
       
   101 
       
   102 // code paging from writeable FAT, Composite FAT and first ROFS
       
   103 #define NAND_PAGEDRIVELIST 2,5,6    
       
   104 #define NAND_PAGEDRIVECOUNT 3
       
   105 
       
   106 // defines the size of fragment
       
   107 #define NUM_PAGES 8</codeblock> </section>
       
   108 <section id="GUID-686EFEF4-A514-51BC-8378-962A8899F270"><title>Changes to
       
   109 the media driver kernel extension point</title> <p>The kernel-extension entry
       
   110 point must create a DFC queue to satisfy any page fault that occurs in the
       
   111 drive thread. Failure to do so results in a kernel fault. The entry point
       
   112 must then create a <xref href="GUID-3715787E-9ADD-39E7-B22A-62CBBD2CEF1B.dita"><apiname>DPrimaryMediaBase</apiname></xref> object and register
       
   113 it with the local media subsystem. To support paging, the entry point needs
       
   114 altering to register the paging device with the demand paging subsystem and
       
   115 instantiate and install the factory object. </p> <codeblock id="GUID-885C8178-46FB-5F4B-9755-E048A48C42A7" xml:space="preserve">DECLARE_STANDARD_EXTENSION()
       
   116     {   
       
   117     TInt r=Kern::DfcQInit(&amp;TestMediaDfcQ,KTestThreadPriority,&amp;KTestMediaThreadName);
       
   118     if (r|=KErrNone)
       
   119         return r;
       
   120  
       
   121     DPrimaryMediaBase* pM=new DPrimaryMediaBase;
       
   122     if (!pM)
       
   123         return r;
       
   124 
       
   125     pM-&gt;iDfcQ=&amp;TestMediaDfcQ;
       
   126     r=LocDrv::RegisterMediaDevice(
       
   127         MEDIA_DEVICE_NAND,
       
   128         NAND_DRIVECOUNT,
       
   129         NAND_DRIVELIST,
       
   130         pM,
       
   131         NAND_NUMMEDIA,
       
   132         NAND_DRIVENAME);
       
   133     if (r != KErrNone)
       
   134         return r;
       
   135 
       
   136     r = LocDrv::RegisterPagingDevice(
       
   137         pM,
       
   138         NAND_PAGEDRIVELIST,
       
   139         NAND_PAGEDRIVECOUNT,
       
   140         PAGING_TYPE,
       
   141         SECTOR_SHIFT,
       
   142         NUM_PAGES);
       
   143     if (r == KErrNone)
       
   144         {
       
   145         device = new DPhysicalDeviceMediaTest;
       
   146         if (device == NULL)
       
   147             return KErrNoMemory;
       
   148         r = Kern::InstallPhysicalDevice(device);
       
   149         }
       
   150     // Ignore error if demand paging not supported by kernel
       
   151     else if (r == KErrNotSupported)
       
   152         r = KErrNone;
       
   153     else
       
   154         return r;
       
   155 
       
   156     pM-&gt;iMsgQ.Receive();
       
   157     return KErrNone;
       
   158     }</codeblock> <p>The fifth parameter passed to the function <xref href="GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF.dita#GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF/GUID-5FDD89C6-C34A-3A0D-A422-D148DDE23E42"><apiname>LocDrv::RegisterPagingDevice()</apiname></xref> named <codeph>SECTOR_SHIFT</codeph> is the log2 of the sector size for the given media. For example, passing
       
   159 a value of 9 corresponds to a sector size of 512 for most media. </p> <p> <note> The <xref href="GUID-52853C0D-CA98-3B92-B7D4-FF1C1F06C1A6.dita"><apiname>DECLARE_EXTENSION_PDD</apiname></xref> entry
       
   160 point is called some time later when the file server tries to load all the
       
   161 media drivers in the system. When this happens a second factory object is
       
   162 created by the media driver, but this is deleted by the kernel when it discovers
       
   163 that another factory object bearing the same name is already in its internal
       
   164 list.</note> </p> </section>
       
   165 <section id="GUID-C32CF25E-553B-5786-88ED-4587AC0DF3BA"><title>Changes to
       
   166 DLocalDrive::ECaps handling</title> <p>The <xref href="GUID-C57F8D34-DAB5-388F-A99F-A952916B7EA6.dita"><apiname>TLocalDriveCaps</apiname></xref> structure
       
   167 needs to be modified so that: </p> <ul>
       
   168 <li id="GUID-FECDE295-A9D3-5373-BD01-F2A7EAB83897"><p>the <xref href="GUID-FF7F3425-9F7C-3146-BA0A-FB68D1A2381C.dita"><apiname>KMediaAttPageable</apiname></xref> flag
       
   169 is set in <xref href="GUID-722A1F4D-3A76-3BE3-95AB-2AA7745930D0.dita"><apiname>iMediaAtt</apiname></xref>  </p> </li>
       
   170 <li id="GUID-82EC6B7C-FF34-5E2C-BFF1-832C0769B517"><p>the <xref href="GUID-ED80FF32-9226-31E4-8717-D4A29948A75B.dita"><apiname>KDriveAttPageable</apiname></xref> flag
       
   171 is set if a particular drive has been registered as code paging. This is determined
       
   172 by testing <xref href="GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C.dita#GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C/GUID-F5F80522-E23D-3A3D-86B5-6DC6C9E5C3B1"><apiname>TLocDrvRequest::Drive()</apiname></xref> <codeph>-&gt;iPagingDrv</codeph>. </p> </li>
       
   173 </ul> <p>Additionally, the <xref href="GUID-C57F8D34-DAB5-388F-A99F-A952916B7EA6.dita"><apiname>TLocalDriveCaps</apiname></xref> <codeph>::iDriveAtt</codeph> must
       
   174 have the <xref href="GUID-89ABFCAC-65EF-3DF3-83B8-2B0A169CCAFA.dita"><apiname>KDriveAttLocal</apiname></xref> and <xref href="GUID-78343374-6F5D-365D-BF3E-9AD19C77FB80.dita"><apiname>KDriveAttInternal</apiname></xref> bits
       
   175 set and the <xref href="GUID-88C9C181-3BC3-35FB-BF82-A81C40EEDEB8.dita"><apiname>KDriveAttRemovable</apiname></xref> bit cleared. </p> <codeblock id="GUID-04F15DFB-144E-5966-88B5-227B7FC97B55" xml:space="preserve">TInt DMediaDriverTest::Request(TLocDrvRequest&amp; aRequest)
       
   176     {
       
   177     TInt r=KErrNotSupported;
       
   178     TInt id=aRequest.Id();
       
   179 
       
   180     if (id == DLocalDrive::ECaps)
       
   181         {
       
   182         TLocDrv* drive = aRequest.Drive();
       
   183         TLocalDriveCapsV4&amp; c = *(TLocalDriveCapsV4*)aRequest.RemoteDes();   
       
   184         r=Caps(*drive,c);
       
   185         }
       
   186     // etc…
       
   187     }
       
   188 
       
   189 TInt DMediaDriverTest::Caps(TLocDrv&amp; aDrive, TLocalDriveCapsV4&amp; caps)
       
   190     {
       
   191     // fill in rest of caps structure as usual…
       
   192 
       
   193     if(aDrive.iPrimaryMedia-&gt;iPagingMedia)
       
   194         caps.iMediaAtt|=KMediaAttPageable;
       
   195     if(aDrive.iPagingDrv)
       
   196         caps.iDriveAtt|=KDriveAttPageable; 
       
   197     }</codeblock> </section>
       
   198 <section id="GUID-AE44672E-F60D-563C-BB6A-B70AF187C366"><title>Handling page
       
   199 requests</title> <p>Four new request types need to be handled to support paging: </p> <ul>
       
   200 <li id="GUID-703713F1-9276-583A-9963-325C04F8D4B6"><p> <xref href="GUID-951FB996-24B3-3340-8386-24B1A895EA16.dita"><apiname>EWriteRequestFragment</apiname></xref> marks
       
   201 the start and middle of a sequence of writes. </p> </li>
       
   202 <li id="GUID-F40CCE14-17DF-52EB-937F-CEBC2B78CC94"><p>Each sequence is terminated
       
   203 by a <xref href="GUID-8B4109E6-B9F8-3C18-9F9A-0AB20FDA5E86.dita"><apiname>EWriteRequestFragmentLast</apiname></xref> request as long as none
       
   204 of the prior requests completed with an error. </p> </li>
       
   205 <li id="GUID-47C8C482-77B4-5447-8497-E8185BF1350B"><p> <xref href="GUID-F20251F4-A72D-32E5-B2AF-87F71CD5CD87.dita"><apiname>ERomPageInRequest</apiname></xref> is
       
   206 treated as a normal read except that: </p> <ol id="GUID-DEEF7484-32E1-5739-839D-D1257A51B83C">
       
   207 <li id="GUID-A90D4A45-05E4-5F9C-B47E-26F67F5462EE"><p>the list of partitions
       
   208 reported by <xref href="GUID-A0D4EB25-0BA4-39EE-874B-465EB9628DCC.dita#GUID-A0D4EB25-0BA4-39EE-874B-465EB9628DCC/GUID-B2F42829-028C-341A-B34D-A8243CA434EB"><apiname>DMediaDriver::PartitionInfo</apiname></xref> does not normally
       
   209 include the partition containing the ROM image. Therefore, the local media
       
   210 subsystem does not know the absolute position from the start of the media
       
   211 of a particular ROM page. The position stored in <xref href="GUID-F20251F4-A72D-32E5-B2AF-87F71CD5CD87.dita"><apiname>ERomPageInRequest</apiname></xref> is
       
   212 offset from the start of the ROM image, rather than the start of the media.
       
   213 Therefore, the media driver must add the offset of the start of the ROM image
       
   214 to the position stored in <xref href="GUID-F20251F4-A72D-32E5-B2AF-87F71CD5CD87.dita"><apiname>ERomPageInRequest</apiname></xref> to obtain the
       
   215 absolute position before issuing a read request. </p> </li>
       
   216 <li id="GUID-E020A5D1-82FA-5857-AB1D-42A59D337EFD"><p>when the read is complete
       
   217 the media driver needs to call <xref href="GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C.dita#GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C/GUID-362AB6B2-9C3D-342F-BB4A-F252ECD7EF3A"><apiname>TLocDrvRequest::WriteToPageHandler</apiname></xref> to
       
   218 write the data back to the client, rather than <xref href="GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C.dita#GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C/GUID-2AC4DBA4-5C87-39C7-B6CF-95ECB7286339"><apiname>TLocDrvRequest::WriteRemote</apiname></xref> as
       
   219 for a normal read, </p> </li>
       
   220 </ol> </li>
       
   221 <li id="GUID-50298F39-D1A0-5731-8E50-D18514941D70"><p> <xref href="GUID-E42B407D-8E18-337B-9CBB-4DCDD0AABBE9.dita"><apiname>ECodePageInRequest</apiname></xref> is
       
   222 treated as a normal read, except that the function <xref href="GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C.dita#GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C/GUID-362AB6B2-9C3D-342F-BB4A-F252ECD7EF3A"><apiname>TLocDrvRequest::WriteToPageHandler</apiname></xref> should
       
   223 be used to write the data back to the demand paging subsystem. However, the
       
   224 position in the request is offset from the start of the media as for a normal
       
   225 read. </p> </li>
       
   226 </ul> <p>These request types are enumerated in the <xref href="GUID-6C039CFA-BF2F-3272-80FE-71430C12F0F4.dita"><apiname>DMediaPagingDevice</apiname></xref> class: </p> <codeblock id="GUID-AD9B48CF-7757-5C8A-A2EF-B27F2DC9BDD8" xml:space="preserve">NONSHARABLE_CLASS(DMediaPagingDevice) : public DPagingDevice
       
   227     {
       
   228 public:
       
   229     enum TPagingRequestId
       
   230         {
       
   231         /** 
       
   232         Identifies any middle fragment of a Write request on a partition of a media that supports paging.
       
   233         */
       
   234         EWriteRequestFragment = 
       
   235             DLocalDrive::EFirstReqNumberReservedForPaging,
       
   236 
       
   237         /** 
       
   238         Identifies the last fragment of a Write request on a partition of a media that supports paging.
       
   239         */
       
   240         EWriteRequestFragmentLast = 
       
   241             DLocalDrive::EFirstReqNumberReservedForPaging+1,
       
   242 
       
   243         /** 
       
   244         Request for paging in (read) data from the ROM store area.
       
   245         */
       
   246         ERomPageInRequest =
       
   247             DLocalDrive::EFirstReqNumberReservedForPaging+2,
       
   248 
       
   249         /** 
       
   250         Request for paging in (read) data from the code store area.
       
   251         */
       
   252         ECodePageInRequest =
       
   253             DLocalDrive::ELastReqNumberReservedForPaging
       
   254         };
       
   255         //etc…
       
   256     }</codeblock> </section>
       
   257 <section id="GUID-0EA673E6-FEE4-51F6-9C84-9411316D7357"><title>Handling fragmented
       
   258 write requests</title> <p>In many respects, <xref href="GUID-951FB996-24B3-3340-8386-24B1A895EA16.dita"><apiname>EWriteRequestFragment</apiname></xref> and <xref href="GUID-8B4109E6-B9F8-3C18-9F9A-0AB20FDA5E86.dita"><apiname>EWriteRequestFragmentLast</apiname></xref> can
       
   259 be treated as normal write requests. It should be noted however, that these
       
   260 write requests can be interleaved with requests from other file server threads
       
   261 if the media supports more than one partition, the resulting operations may
       
   262 be perceived as a functional break in behaviour. </p> <p>If it is important
       
   263 to maintain backwards compatibility and to prevent write requests from being
       
   264 interleaved, the media driver must keep track of the current write-request
       
   265 chain and defer requests from other drive threads while a write-fragment chain
       
   266 is in progress by: </p> <ul>
       
   267 <li id="GUID-311A0DF2-601D-5623-A059-7E20FAFEEF1C"><p>ensuring the local media
       
   268 subsystem LDD has been built with the <codeph>__ALLOW_CONCURRENT_FRAGMENTATION__</codeph> macro
       
   269 undefined. This ensures that the local media subsystem never issues more than
       
   270 one write fragment at a time </p> </li>
       
   271 <li id="GUID-9504A0D1-2147-5968-AB8C-2B9D99A48C0F"><p>modifying the paging-media
       
   272 driver so that it keeps track of write-request chains and defers any read
       
   273 or format requests received after the first fragment and before the last in
       
   274 a sequence. When undefined, the macro subsystem does not issue more than one
       
   275 write-request chain at a time. </p> </li>
       
   276 </ul><p><note> Write fragments should never be deferred, only read or format
       
   277 requests may be deferred. </note></p>  <p>To achieve this the media driver
       
   278 can maintain a bit mask, each bit of which represents a write in progress
       
   279 flag for a particular drive: </p> <codeblock id="GUID-CB127C9B-51D5-5D1A-BAF6-4F8CEF308912" xml:space="preserve">iFragmenting|=(0x1&lt;&lt;iCurrentReq-&gt;Drive()-&gt;iDriveNumber);</codeblock> <p>If a read or format request is received while any of the bits in <codeph>iFragmenting</codeph> are
       
   280 set, that request may be deferred. </p> </section>
       
   281 </conbody></concept>