home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / PCI Driver Development Kit / • Samples / Driver Samples / SCSI samples / SCSI 950629 / NCR_DriverProject / Src / DriverPrepMemoryInit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-20  |  8.0 KB  |  210 lines  |  [TEXT/MPCC]

  1. /*                                DriverPrepMemoryInit.c                                */
  2. /*
  3.  * DriverPrepMemoryInit.c
  4.  * Copyright © 1994-95 Apple Computer Inc. All rights reserved.
  5.  *
  6.  * .
  7.  */
  8. /*    .___________________________________________________________________________________.
  9.       | Initialize the permanent memory areas that are shared between the driver and the    |
  10.       | NCR card: the SCSI script and the per-request record. If this is extended to        |
  11.       | support concurrent I/O (i.e. to support SCSI suspend/resume), we must create and    |
  12.       | prepare several per-request records. When an application calls PBRead or PBWrite,    |
  13.       | a separate, more complex, function will handle preparation of the actual I/O        |
  14.       | buffer.
  15.     .___________________________________________________________________________________.
  16. */
  17. #include "NCRDriverPrivate.h"
  18.  
  19. /*
  20.  * Create an I/O Preparation table for the global script. This is created once, when
  21.  * the driver starts. The NCR chip reads the script asynchronously. This function
  22.  * may serve as an example for a general global shared area.
  23.  */
  24. OSErr
  25. PrepareMemoryForScript(
  26.         AddressSpaceID            addressSpaceID
  27.     )
  28. {
  29.         OSErr                    status;
  30.         ItemCount                mapEntriesNeeded;
  31.  
  32.         Trace(PrepareMemoryForScript);
  33.         GLOBAL.ncrSCSIScript =
  34.             MemAllocatePhysicallyContiguous(gNCRSCSIScriptSize, FALSE);
  35.         if (GLOBAL.ncrSCSIScript == NULL) {
  36.             status = memFullErr;
  37.             CheckStatus(status, "\pNo memory for script copy");
  38.         }
  39.         else {
  40.             BlockCopy(gNCRSCSIScript, GLOBAL.ncrSCSIScript, gNCRSCSIScriptSize);
  41.             GLOBAL.scriptIOTable.options =
  42.                         ( (0 * kIOIsInput)                /* Chip won't write script    */
  43.                         | (1 * kIOIsOutput)                /* Chip reads the script    */
  44.                         | (0 * kIOMultipleRanges)        /* No scatter-gather list    */
  45.                         | (1 * kIOLogicalRanges)        /* Logical addresses        */
  46.                         | (0 * kIOMinimalLogicalMapping) /* Normal logical mapping    */
  47.                         | (1 * kIOShareMappingTables)    /* Share with Kernel        */
  48.                         | (0 * kIOCoherentDataPath)        /* No fancy data path        */
  49.                         );
  50.             GLOBAL.scriptIOTable.addressSpace = addressSpaceID;
  51.             GLOBAL.scriptIOTable.firstPrepared = 0;
  52.             GLOBAL.scriptIOTable.logicalMapping = NULL;
  53.             GLOBAL.scriptIOTable.rangeInfo.range.base = GLOBAL.ncrSCSIScript;
  54.             GLOBAL.scriptIOTable.rangeInfo.range.length = gNCRSCSIScriptSize;
  55.             mapEntriesNeeded = GetMapEntryCount(GLOBAL.ncrSCSIScript, gNCRSCSIScriptSize);
  56.             GLOBAL.scriptIOTable.mappingEntryCount = mapEntriesNeeded;
  57.             GLOBAL.scriptIOTable.physicalMapping = PoolAllocateResident(
  58.                         mapEntriesNeeded * sizeof (PhysicalAddress),
  59.                         TRUE
  60.                     );
  61.             status = (GLOBAL.scriptIOTable.physicalMapping != NULL) ? noErr : memFullErr;
  62.         }
  63.         CheckStatus(status, "\pAllocate Script PhysicalMapping");
  64.         if (status == noErr) {
  65.             status = PrepareMemoryForIO(&GLOBAL.scriptIOTable);
  66.             CheckStatus(status, "\pPrepareMemory for Script");
  67.         }
  68.         if (status == noErr)
  69.             status = CheckForContiguousPhysicalMapping(&GLOBAL.scriptIOTable);
  70.         if (status != noErr)
  71.             PublishInitFailureMsg(status, "\pPrepareMemoryForScript failed");
  72.         return (status);
  73. }
  74.  
  75. /*
  76.  * Dispose of the script I/O preparation table. This is called when the driver stops.
  77.  */
  78. void
  79. DisposeMemoryForScript(void)
  80. {
  81.         Trace(DisposeMemoryForScript);
  82.         CheckpointIOTable(&GLOBAL.scriptIOTable);
  83.         if (GLOBAL.scriptIOTable.physicalMapping != NULL)
  84.             (void) PoolDeallocate(GLOBAL.scriptIOTable.physicalMapping);
  85.         CLEAR(GLOBAL.scriptIOTable);
  86.         if (GLOBAL.ncrSCSIScript != NULL) {
  87.             MemDeallocatePhysicallyContiguous(GLOBAL.ncrSCSIScript);
  88.             GLOBAL.ncrSCSIScript = NULL;
  89.         }
  90. }
  91.  
  92. /*
  93.  * Create a PerRequest record and its I/O Preparation table. To create the table, we
  94.  * must first determine the number of physical mapping table entries we will need for
  95.  * the user I/O request and the PerRequestRecord itself.
  96.  *
  97.  * This is called when the driver starts. If we support concurrent I/O, we create
  98.  * several of these records. The per-request record is a small amount of memory that
  99.  * is shared between the NCR card and the driver.
  100.  */
  101. OSErr
  102. CreatePerRequestRecord(
  103.         AddressSpaceID            addressSpaceID
  104.     )
  105. {
  106.         OSErr                    status;
  107.         OSStatus                osStatus;
  108.         PerRequestDataPtr        perRequestDataPtr;
  109.         ItemCount                requestMapEntries;        /* PerRequestData only        */
  110.         ByteCount                mapTableSize;
  111. #define REQUEST    (*perRequestDataPtr)
  112.  
  113.         Trace(CreatePerRequestRecord);
  114.         perRequestDataPtr = (PerRequestDataPtr)
  115.                     MemAllocatePhysicallyContiguous(sizeof (PerRequestData), TRUE);
  116.         status = (perRequestDataPtr != NULL) ? noErr : memFullErr;
  117.         CheckStatus(status, "\pAllocate PerRequestRecord");
  118.         if (status == noErr) {
  119.             /*
  120.              * PrepareNextDMATransfer will be called (as a Software Task) to prepare
  121.              * a subsequent "chunk" of DMA if the original preparation is incomplete.
  122.              */
  123.             osStatus = CreateSoftwareInterrupt(
  124.                         PrepareNextDMATask,                /* Handler function            */
  125.                         CurrentTaskID(),                /* For my driver task        */
  126.                         perRequestDataPtr,                /* Handler parameter        */
  127.                         TRUE,                            /* Persistant                */
  128.                         &REQUEST.nextDMAInterruptID        /* Result                    */
  129.                     );
  130.             CheckStatus(osStatus, "\pCreateSoftwareInterrupt");
  131.         }
  132.         if (status == noErr) {        
  133.             GLOBAL.perRequestDataPtr = perRequestDataPtr;
  134.             /*
  135.              * Allocate a maximum-length physical mapping table that will be used for
  136.              * each user I/O request. By passing a dummy value that happens to fall
  137.              * at the end of the page, we'll get the as many entries as we need.
  138.              */
  139.             REQUEST.scsiMapEntries = GetMapEntryCount(
  140.                         (void *) (gPageSize - 1), kNCRDriverMaxTransfer);
  141.             requestMapEntries = GetMapEntryCount(perRequestDataPtr, sizeof (PerRequestData));
  142.             mapTableSize = (REQUEST.scsiMapEntries + requestMapEntries)
  143.                         * sizeof (PhysicalAddress);
  144.             REQUEST.physicalMapTables = PoolAllocateResident(mapTableSize, TRUE);
  145.             /*
  146.              * Initialize the constant part of the PerRequest mapping table. We leave
  147.              * this prepared "forever" for now. In the future, we may checkpoint it
  148.              * so it is only prepared while an I/O request is active.
  149.              */
  150.             REQUEST.perRequestIOTable.options =
  151.                     ( (0 * kIOIsInput)                    /* These will be set by        */
  152.                     | (0 * kIOIsOutput)                    /* calling CheckpointIO        */
  153.                     | (0 * kIOMultipleRanges)            /* No scatter-gather list    */
  154.                     | (1 * kIOLogicalRanges)            /* Logical addresses        */
  155.                     | (0 * kIOMinimalLogicalMapping)    /* Normal logical mapping    */
  156.                     | (1 * kIOShareMappingTables)        /* Share with Kernel        */
  157.                     | (0 * kIOCoherentDataPath)            /* No fancy data path        */
  158.                     );
  159.             REQUEST.perRequestIOTable.addressSpace = addressSpaceID;
  160.             REQUEST.perRequestIOTable.firstPrepared = 0;
  161.             REQUEST.perRequestIOTable.logicalMapping = NULL;
  162.             REQUEST.perRequestIOTable.rangeInfo.range.base = perRequestDataPtr;
  163.             REQUEST.perRequestIOTable.rangeInfo.range.length = sizeof (PerRequestData);
  164.             REQUEST.perRequestIOTable.physicalMapping =
  165.                         &REQUEST.physicalMapTables[REQUEST.scsiMapEntries];
  166.             REQUEST.perRequestIOTable.mappingEntryCount = requestMapEntries;
  167.             /*
  168.              * Note that the PerRequestData record is prepared once, and checkpointed
  169.              * before and after each transaction -- kMoreTransfers will be used so
  170.              * that system resources are not released.
  171.              */
  172.             status = PrepareMemoryForIO(&REQUEST.perRequestIOTable);
  173.             CheckStatus(status, "\pPrepareMemoryForIO perRequest");
  174.         }
  175.         if (status != noErr)
  176.             DisposePerRequestRecord(&GLOBAL.perRequestDataPtr);
  177.         if (status != noErr)
  178.             PublishInitFailureMsg(status, "\pPrepareMemoryForScript failed");
  179.         return (status);
  180. #undef REQUEST
  181. }
  182.  
  183. /*
  184.  * This is called when the driver is finalized.
  185.  */
  186. void
  187. DisposePerRequestRecord(
  188.         PerRequestDataPtr        *perRequestPtrAddr
  189.     )
  190. {
  191.         PerRequestDataPtr        perRequestDataPtr;
  192. #define REQUEST    (*perRequestDataPtr)
  193.  
  194.         Trace(DisposePerRequestRecord);
  195.         while ((perRequestDataPtr = *perRequestPtrAddr) != NULL) {
  196.             if (CompareAndSwap(
  197.                 (UInt32) perRequestDataPtr, NULL, (UInt32 *) perRequestPtrAddr)) {
  198.                 CheckpointIOTable(&REQUEST.scsiIOTable);
  199.                 CheckpointIOTable(&REQUEST.perRequestIOTable);
  200.                 if (REQUEST.nextDMAInterruptID != kInvalidID)
  201.                     (void) DeleteSoftwareInterrupt(REQUEST.nextDMAInterruptID);
  202.                 if (REQUEST.physicalMapTables != NULL)
  203.                     (void) PoolDeallocate(REQUEST.physicalMapTables);
  204.                 (void) PoolDeallocate(perRequestDataPtr);
  205.             }
  206.         }
  207. #undef REQUEST
  208. }
  209.  
  210.