home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Sample Code / RAMDisk sample / Sources / RamDRVR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-31  |  11.3 KB  |  407 lines  |  [TEXT/MPS ]

  1. #define __DebugVersion    1
  2. /*
  3. **    Apple Macintosh Developer Technical Support
  4. **
  5. **    RamDRVR.c: Driver for RamDisk Sample
  6. **
  7. **    by Gordon Sheridan and Jim Luther
  8. **  modified by Brian Bechtel
  9. **
  10. **    File:        RamDRVR.c
  11. **
  12. **    Copyright © 1992-1994 Apple Computer, Inc.
  13. **    All rights reserved.
  14. **
  15. **    You may incorporate this sample code into your applications without
  16. **    restriction, though the sample code has been provided "AS IS" and the
  17. **    responsibility for its operation is 100% yours.  However, what you are
  18. **    not permitted to do is to redistribute the source as "DTS Sample Code"
  19. **    after having made changes. If you're going to re-distribute the source,
  20. **    we require that you make it clear in the source that the code was
  21. **    descended from Apple Sample Code, but that you've made changes.
  22. **
  23. **    Change History (most recent first):
  24. **
  25. **    Change History (most recent first):
  26. **
  27. **         <7>    08/12/94    BL°B    Use BlockMoveData where appropriate.  Added
  28. **                                    some more clarifying comments.  Nil out dCtlStorage
  29. **                                    in DrvrClose.
  30. **         <6>    06/10/94    BL°B    Converted to work with Symantec as well.
  31. **         <5>    05/19/94    BL°B    Converted to work with Metrowerks.  Added 
  32. **                                     conditionally compiled main routine for Metrowerks.
  33. **         <4>    10/23/93    JML        Added check for valid globals before accepting
  34. **                                     Prime, Control, or Status calls (except the control
  35. **                                    and status routines that get and set the globals).
  36. **         <3>    10/14/93    JML        Added support for the following Control and Status
  37. **                                    calls: physicalIconCC, mediaIconCC, driveInfoCC,
  38. **                                    formatListSC.  driveStatusSC now returns a copy
  39. **                                    of our DrvQEl.  Prime, Control and Status now checks
  40. **                                    that ioVRefNum = our drive number.  Prime now updates
  41. **                                    dCtlPosition so I/O using fsFromMark will work. All
  42. **                                    debugging code now hidden with "Panic" macros. Prime
  43. **                                    now checks for block aligned I/O (since this is a
  44. **                                    block device).  All calls now return appropriate error
  45. **                                    results.
  46. **        <2+>     7/26/93    gs        Set result = noErr for Status csCode = 8.
  47. **         <2>     6/29/93    gs        Return Drive Stats, miscellaneous clean up.
  48. **         <1>     6/13/93    gs        Allocate space for disk from driver. Clean up comments.
  49. **         <0>     1/17/90    gs        11:58 PM, first version.
  50. **/
  51.  
  52.  
  53. #include "RamDisk.h"
  54.  
  55. /*****************************************************************************/
  56. /*
  57. **    Prototypes
  58. */
  59.  
  60. pascal    OSErr    DRVROpen    (ParmBlkPtr pb, DCtlPtr dce);
  61. pascal    OSErr    DRVRPrime    (ParmBlkPtr pb, DCtlPtr dce);
  62. pascal    OSErr    DRVRControl    (ParmBlkPtr pb, DCtlPtr dce);
  63. pascal    OSErr    DRVRStatus    (ParmBlkPtr pb, DCtlPtr dce);
  64. pascal    OSErr    DRVRClose    (ParmBlkPtr pb, DCtlPtr dce);
  65.  
  66. /*****************************************************************************/
  67.  
  68. pascal    OSErr    DRVROpen (ParmBlkPtr pb, DCtlPtr dce)
  69. {
  70.     DrvrGlobals       *globe;
  71.     OSErr            result = noErr;
  72.  
  73. #pragma unused (pb)
  74.  
  75.     /* set device flags because Device Mgr copied header */
  76.     dce->dCtlFlags |= dCtlEnable | dStatEnable | dWritEnable | dReadEnable | dNeedLock;
  77.     dce->dCtlDelay = 0;
  78.  
  79.  
  80.     if (!dce->dCtlStorage)    /* is driver already open ? */
  81.     {
  82.         dce->dCtlStorage = (Handle)NewPtrSysClear(sizeof(DrvrGlobals));
  83.         if (!(Ptr)dce->dCtlStorage)
  84.         {
  85.             result = MemError();
  86.             Panic("\pDRVROpen:NewPtr returned nil");
  87.         }
  88.             
  89.         globe = (DrvrGlobals *)dce->dCtlStorage;
  90.     }
  91.     else
  92.         Panic("\pDRVROpen:2nd open attempt");    /* you might consider whether this is an error */
  93.                                                 /* when you are writing a driver.  We make       */
  94.                                                 /* this Panic call for diagnostic purposes       */
  95.     
  96.     return (result);
  97. }
  98.  
  99. /*****************************************************************************/
  100.  
  101. pascal    OSErr    DRVRPrime (ParmBlkPtr pb, DCtlPtr dce)
  102. {
  103.     DrvrGlobals        *globe;
  104.     unsigned long    position;
  105.     unsigned long    count;
  106.     short            calltype;
  107.     OSErr            result;
  108.  
  109.     if (dce->dCtlStorage)
  110.     {
  111.         globe = (DrvrGlobals *)dce->dCtlStorage;
  112.         
  113.         if (globe->driveNumber != 0) /* accept no calls, before the globals are initialized */
  114.         {
  115.             position = dce->dCtlPosition;
  116.             count = pb->ioParam.ioReqCount;
  117.             
  118.             /* Preflight the request for block alignment, size, and range */
  119.             if (((position % 512) == 0) &&
  120.                 ((count % 512) == 0) &&
  121.                 ((count + position) <= globe->ramSize))
  122.             {
  123.                 calltype = 0x00FF & pb->ioParam.ioTrap;
  124.                 switch(calltype)
  125.                 {
  126.                     case aRdCmd:
  127.                         /* Read the data */
  128.                         BlockMoveData(&globe->ramDisk[position], pb->ioParam.ioBuffer, count);
  129.                         break;
  130.                     case aWrCmd:
  131.                         /* Write the data */
  132.                         BlockMoveData(pb->ioParam.ioBuffer, &globe->ramDisk[position], count);
  133.                         break;
  134.                     default:        
  135.                         Panic("\pDRVRPrime: Call wasn't _Read or _Write");
  136.                         break;
  137.                 }
  138.                 
  139.                 dce->dCtlPosition += count;        /* Update the position */
  140.                 pb->ioParam.ioActCount = count;    /* Return the actual count */
  141.                 
  142.                 result = noErr;
  143.             }
  144.             else
  145.             {
  146.                 Panic("\pDRVRPrime: Invalid block request");
  147.                 result = paramErr;
  148.             }
  149.         }
  150.         else
  151.         {
  152.             Panic("\pDRVRPrime: Globals aren't initialized");
  153.             result = nsDrvErr;
  154.         }
  155.     }
  156.     else
  157.     {
  158.         Panic("\pDRVRPrime: No dCtlStorage");
  159.         result = notOpenErr;
  160.     }
  161.     
  162.     return (result);
  163. }
  164.  
  165. /*****************************************************************************/
  166.  
  167. pascal    OSErr    DRVRControl (ParmBlkPtr pb, DCtlPtr dce)
  168. {
  169.     DrvrGlobals       *globe;
  170.     OSErr            result = controlErr;
  171.     long            size;
  172.     long            i;
  173.     
  174.     if (dce->dCtlStorage)
  175.     {
  176.         globe = (DrvrGlobals *)dce->dCtlStorage;
  177.         
  178.         /* Accept only setGlobalsCC call, before the globals are initialized */
  179.         if (pb->cntrlParam.csCode == setGlobalsCC)
  180.         {
  181.             /* Initialize DrvrGlobals */
  182.             BlockMoveData( *(Ptr *)pb->cntrlParam.csParam,(Ptr)globe, sizeof(DrvrGlobals));
  183.             result = noErr;
  184.         }
  185.         else if (globe->driveNumber != 0)
  186.         {
  187.             switch(pb->cntrlParam.csCode)
  188.             {
  189.                 case killIOCC:
  190.                     /* What's there to kill?  A BlockMove? sure...         */
  191.                     /* We'll issue a Panic here for debugging purposes    */
  192.                     Panic("\pDRVRControl: KillIO on Ram Disk?");
  193.                     break;
  194.                 
  195.                 case verifyDiskCC:
  196.                     result = noErr;
  197.                     break;
  198.                 
  199.                 case formatDiskCC:
  200.                     /* zero out ram disk memory */
  201.                     size = globe->ramSize / 4;
  202.                     for (i = 0 ; i < size; i++)
  203.                         ((long *)globe->ramDisk)[i] = 0;
  204.                     result = noErr;
  205.                     break;
  206.                         
  207.                 case ejectDiskCC:
  208.                     /* we aren't returning a specific error code here      */
  209.                     /* we're leaving this case here for your convenience */
  210.                     /* be sure and set result before the break!             */
  211.                      break;
  212.                             
  213.                 case physicalIconCC:
  214.                     /* return pointer to icon and where string */
  215.                     *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->physicalIcon;
  216.                     result = noErr;
  217.                     break;
  218.                 
  219.                 case mediaIconCC:
  220.                     /* return pointer to icon and where string */
  221.                     *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->mediaIcon;
  222.                     result = noErr;
  223.                     break;
  224.     
  225.                 case driveInfoCC:
  226.                     /* high word (bytes 2 & 3) clear */
  227.                     /* byte 1 = primary + fixed media + internal */
  228.                     /* byte 0 = drive type (0x10 = RAM disk) */
  229.                     *(unsigned long *)pb->cntrlParam.csParam = 0x00000410;
  230.                     result = noErr;
  231.                     break;
  232.                 
  233.                 case 24:    /* ••• Return SCSI csCode Partition Size */
  234.                     *(unsigned long *)pb->cntrlParam.csParam = globe->ramSize >> 9;
  235.                     result = noErr;
  236.                     break;
  237.     
  238.                 case accRun:
  239.                     result = noErr;
  240.                     break;
  241.     
  242.                 default:
  243.                     Panic("\pUnrecognized control call");
  244.                     break;
  245.             }
  246.         }
  247.         else
  248.         {
  249.             Panic("\pDRVRControl: Globals not initialized");
  250.         }
  251.     }
  252.     else
  253.     {
  254.         Panic("\pDRVRControl: No dCtlStorage");
  255.         result = notOpenErr;
  256.     }
  257.         
  258.     return (result);
  259. }
  260.  
  261. /*****************************************************************************/
  262.  
  263. pascal    OSErr    DRVRStatus (ParmBlkPtr pb, DCtlPtr dce)
  264. {
  265.     DrvrGlobals            *globe;
  266.     OSErr                result = statusErr;
  267.     DrvSts                *driveStats;
  268.     DrvQElPtr            driveQEl;
  269.     
  270.     if (dce->dCtlStorage)
  271.     {
  272.         globe = (DrvrGlobals *)dce->dCtlStorage;
  273.     
  274.         /* Accept only getGlobalsSC call, before the globals are initialized */
  275.         if (pb->cntrlParam.csCode == getGlobalsSC)
  276.         {
  277.             *(long *)pb->cntrlParam.csParam = globe->ramSize;
  278.             if (globe->ramSize == 0)
  279.             {
  280.                 Panic("\pDRVRStatus: ramSize is zero");
  281.             }
  282.             result = noErr;
  283.         }
  284.         else if (globe->driveNumber != 0)
  285.         {
  286.             switch(pb->cntrlParam.csCode)
  287.             {
  288.                 case driveStatusSC:
  289.                     if (pb->cntrlParam.ioVRefNum != globe->driveNumber)
  290.                         break;
  291.                     
  292.                     /* Drive Stats... */
  293.                     driveStats = (DrvSts *)pb->cntrlParam.csParam;
  294.                     driveStats->track        = 0;    /* not applicable */
  295.                     driveStats->writeProt    = 0;    /* write enabled */
  296.                     driveStats->diskInPlace    = 0x08;    /* non-ejectable */
  297.                     driveStats->installed    = 1;    /* drive installed */
  298.                     driveStats->sides        = 0;    /* not applicable */
  299.                     driveStats->twoSideFmt    = 0;    /* not applicable */
  300.                     driveStats->needsFlush    = 0;    /* not applicable */
  301.                     driveStats->diskErrs    = 0;    /* not applicable */
  302.                     
  303.                     /* Copy qLink through dQFSID from our DrvQEl */
  304.                     driveQEl = (DrvQElPtr)(GetDrvQHdr()->qHead);
  305.                     while(driveQEl != nil)
  306.                     {
  307.                         if (driveQEl->dQDrive == globe->driveNumber)
  308.                         {
  309.                             driveStats->qLink = driveQEl->qLink;
  310.                             driveStats->qType = driveQEl->qType;
  311.                             driveStats->dQDrive = driveQEl->dQDrive;
  312.                             driveStats->dQRefNum = driveQEl->dQRefNum;
  313.                             driveStats->dQFSID = driveQEl->dQFSID;
  314.     
  315.                             break; /* while(driveQEl != nil) */
  316.                         }
  317.                         driveQEl = (DrvQElPtr)(driveQEl->qLink);
  318.                     }
  319.                     
  320.                     result = noErr;
  321.                     break;
  322.                 
  323.                 default:
  324.                     break;
  325.             }
  326.         }
  327.         else
  328.         {
  329.             Panic("\pDRVRStatus: Globals not initialized");
  330.         }
  331.     }
  332.     else
  333.     {
  334.         Panic("\pDRVRStatus: No dCtlStorage");
  335.         result = notOpenErr;
  336.     }
  337.  
  338.     return (result);
  339. }
  340.  
  341. /*****************************************************************************/
  342.  
  343. pascal    OSErr    DRVRClose (ParmBlkPtr pb, DCtlPtr dce)
  344. {
  345.     DrvrGlobals    *globe;
  346.  
  347. #pragma unused (pb)
  348.         
  349.     if (dce->dCtlStorage)
  350.     {
  351.         globe = (DrvrGlobals *)dce->dCtlStorage;
  352.         
  353.         if (globe->ramDisk)
  354.             DisposPtr(globe->ramDisk);
  355.         
  356.         DisposPtr((Ptr)dce->dCtlStorage);
  357.     }
  358.     
  359.     dce->dCtlStorage = nil;    
  360.     return (noErr);
  361. }
  362.  
  363. /*****************************************************************************/
  364. #if (defined(__MWERKS__) || defined(THINK_C))
  365. /*****************************************************************************/
  366. /* Metrowerks specific main routine.  This isn't used in MPW; we use an      */
  367. /* assembly language header instead.                                         */
  368. /*****************************************************************************/
  369.  
  370. OSErr main(ParmBlkPtr paramBlock,DCtlPtr devCtlEnt,short dispatch)
  371. {
  372. //
  373. //    Here A4 is already setup to point to our data segment. There is no need
  374. //    to call long oldA4=SetCurrentA4();/SetA4(oldA4); as in code resources.
  375. //
  376. //    However you have to still have to use "#include <SetupA4.h>;RememberA4();..."
  377. //    when using callback functions.
  378. //
  379. // If your routine returns 1 (asynch request can't be completed right away)
  380. // the Metrowerks startup code will correctly jump to jIODone.  You don't need
  381. // to worry about this issue in this driver.
  382. //
  383.     OSErr    err = noErr;
  384.     
  385.     switch(dispatch)
  386.     {
  387.     case 0: //    Open
  388.         err = DRVROpen(paramBlock, devCtlEnt);
  389.         break;
  390.     case 1: //    Prime        return 1 if async request cannot be completed right away
  391.         err = DRVRPrime(paramBlock, devCtlEnt);
  392.         break;
  393.     case 2: //    Control        return 1 if async request cannot be completed right away
  394.         err = DRVRControl(paramBlock, devCtlEnt);
  395.         break;
  396.     case 3: //    Status        return 1 if async request cannot be completed right away
  397.         err = DRVRStatus(paramBlock, devCtlEnt);
  398.         break;
  399.     case 4: //    Close
  400.         err = DRVRClose(paramBlock, devCtlEnt);
  401.         break;
  402.     }
  403.     return err;
  404. }
  405. #endif // __MWERKS__ or THINK_C
  406.  
  407.