home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / OS2DASD / DMIOCTL.C < prev    next >
C/C++ Source or Header  |  1995-04-14  |  82KB  |  2,520 lines

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  4. /*                                                                           */
  5. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  6. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  7. /*    drivers. You may use this code in accordance with the IBM License      */
  8. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  9. /*    Copyright statement may not be removed.                                */
  10. /*                                                                           */
  11. /*****************************************************************************/
  12. /*static char *SCCSID = "src/dev/dasd/os2dasd/dmioctl.c, dsdm, basedd 93/10/11";*/
  13. #define SCCSID  "src/dev/dasd/os2dasd/dmioctl.c, dsdm, basedd 93/10/11"
  14.  
  15. /**************************************************************************
  16.  *
  17.  * SOURCE FILE NAME = DMIOCTL.C
  18.  *
  19.  * DESCRIPTIVE NAME = OS2DASD.DMD - OS/2 DASD Device Manager
  20.  *
  21.  *
  22.  *
  23.  * VERSION = V2.0
  24.  *
  25.  * DATE
  26.  *
  27.  * DESCRIPTION : IOCTL handling routines for OS/2 DASD Device Mgr
  28.  *
  29.  *
  30.  *
  31. */
  32. #include "dmh.h"
  33.  
  34. typedef struct _IOCTL_TABLE_ENTRY
  35. {
  36.    USHORT Function;
  37.    USHORT (NEAR *pIOCTL_Routine)(NPCWA);
  38. } IOCTL_TABLE_ENTRY;
  39.  
  40. /*------------------------------------------------------------------------
  41. ;
  42. ;** f_DriveGenIOCTL - Category 8/9 IOCTL routines
  43. ;
  44. ;   Category 8/9 IOCTL routines and IOCTL function router.
  45. ;
  46. ;   USHORT f_DriveGenIOCTL (PRP_GENIOCTL pRP, NPVOLCB pVolCB)
  47. ;
  48. ;   ENTRY:    pRP              - Request Packet
  49. ;             pVolCB           - Pointer to VolCB
  50. ;
  51. ;   RETURN:   USHORT           - Packet Status word
  52. ;
  53. ;   NOTES:    SGL was here.
  54. ;
  55. ------------------------------------------------------------------------*/
  56.  
  57. USHORT FAR f_DriveGenIOCTL (pRP, pVolCB)
  58.  
  59. PRP_GENIOCTL  pRP;
  60. NPVOLCB       pVolCB;
  61.  
  62. {
  63.  
  64.    /* Category 8 - Logical Disk Control Command Router Table */
  65.  
  66.    static IOCTL_TABLE_ENTRY Cat8_IOCTL_Table[] =
  67.    {
  68.       {IOPD_ED, GIO_AliasDrive},         /* 22H - Install Drive alias      */
  69.       {IODC_RC, GIO_RemovMedControl},    /* 40H - Removable media control  */ /*@V51531*/
  70.       {IODC_SP, GIO_SetDeviceParms},     /* 43H - set device parameters    */
  71.       {IODC_WT, GIO_RWVTrack},           /* 44H - write track              */
  72.       {IODC_FT, GIO_FormatVerify},       /* 45H - format & verify track    */
  73.       {IOPD_DM, GIO_SetDASDMgrParms},    /* 47H - Set DASD Mgr Parameters  */ /*@V74404*/
  74.       {IODC_QD, GIO_DsktControl},        /* 5DH - quiesce/restart diskette */
  75.       {IOPD_RB, GIO_ReadBack},           /* 5EH - DMA readback function    */
  76.       {IODC_MS, GIO_MediaSense},         /* 60H - get media sense          */
  77.       {IODC_GP, GIO_GetDeviceParms8},    /* 63H - get device parameters    */
  78.       {IODC_RT, GIO_RWVTrack},           /* 64H - read track               */
  79.       {IODC_VT, GIO_RWVTrack},           /* 65H - verify track             */
  80.       {IODC_ST, GIO_DriveStatus},        /* 66H - Drive Status             */ /*@V51531*/
  81.       {-1},                              /** End of Table                  */
  82.    };
  83.  
  84.    /* Category 9 - Physical Disk Control Command Router Table */
  85.  
  86.    static IOCTL_TABLE_ENTRY Cat9_IOCTL_Table[] =
  87.    {
  88.       {IODC_WT, GIO_RWVTrack},           /* 44H - write track              */
  89.       {IODC_FT, GIO_FormatVerify},       /* 45H - format & verify track    */
  90.       {IOPD_DM, GIO_SetDASDMgrParms},    /* 47H - Set DASD Mgr Parameters  */ /*@V74404*/
  91.       {IODC_GP, GIO_GetDeviceParms9},    /* 63H - get device parameters    */
  92.       {IODC_RT, GIO_RWVTrack},           /* 64H - read track               */
  93.       {IODC_VT, GIO_RWVTrack},           /* 65H - verify track             */
  94.       {-1},                              /* End of Table                   */
  95.    };
  96.  
  97.  
  98.    /* Category 88H - Disk Fault Tolerance Control Command Router Table */
  99.  
  100.    static IOCTL_TABLE_ENTRY Cat88_IOCTL_Table[] =
  101.    {
  102.       {FT_IOCTL_Func, GIO_FaultTolerance},  /* 51H - Fault Tolerance IOCTL */
  103.       {-1},                                 /* End of Table                */
  104.    };
  105.  
  106.  
  107.    NPCWA   pCWA;
  108.    USHORT  rc, Unit, i;
  109.    USHORT (NEAR *pIOCTL_Routine)(NPCWA);
  110.    IOCTL_TABLE_ENTRY *pTable;
  111.  
  112.  
  113.    /* Verify it's an IOCTL Category the disk driver supports */
  114.    /* and point to the appropriate function table.           */
  115.  
  116.    switch (pRP->Category)
  117.    {
  118.       case IOC_DC:
  119.          pTable = Cat8_IOCTL_Table;
  120.          break;
  121.  
  122.       case IOC_PD:
  123.          pTable = Cat9_IOCTL_Table;
  124.          break;
  125.  
  126.       case FT_IOCTL_Cat:
  127.          pTable = Cat88_IOCTL_Table;
  128.          break;
  129.  
  130.       default:
  131.          return (STERR + STDON + ERROR_I24_BAD_COMMAND);
  132.    }
  133.  
  134.    /* Verify it's an IOCTL Function the disk driver supports */
  135.    /* and get the entry point of the IOCTL function to call */
  136.  
  137.    for (i = 0; pTable[i].Function != -1; i++)
  138.    {
  139.       if (pRP->Function == pTable[i].Function)
  140.       {
  141.          pIOCTL_Routine = pTable[i].pIOCTL_Routine;
  142.          break;
  143.       }
  144.    }
  145.  
  146.    if (pTable[i].Function == -1)
  147.       return (STERR + STDON + ERROR_I24_BAD_COMMAND);
  148.  
  149.  
  150.    /* Valid Category and Command Code.  Set up to call the appropriate */
  151.    /* Function command routine.                                        */
  152.  
  153.    Unit = pRP->rph.Unit;
  154.  
  155.    if (pRP->Category == IOC_PD)         /* if cat 9, then unit 0x80 based */
  156.       Unit += 0x80;
  157.  
  158.    if ((rc = f_Get_VolCB_Addr (Unit, (PVOID) &pVolCB)) == ERROR)
  159.       return (STDON + STERR + ERROR_I24_BAD_UNIT);
  160.  
  161.    if ((rc = BuildCWA (pRP, pVolCB, (NPCWA FAR *) &pCWA)) == ERROR)
  162.       return (STDON + STERR + ERROR_I24_GEN_FAILURE);
  163.  
  164.    rc = (*pIOCTL_Routine)(pCWA);     /* call the appropriate function routine */
  165.  
  166.    ReleaseCWA (pCWA);                /* release the CWA and return */
  167.  
  168.    return (rc);
  169.  
  170. }
  171.  
  172.  
  173.  
  174. /*------------------------------------------------------------------------
  175. ;
  176. ;** GIO_RWVTrack - Process the IOCTLs Read/Write/Verify Track.
  177. ;
  178. ;   Process the IOCTLs Read/Write/Verify Track.
  179. ;
  180. ;   USHORT GIO_RWVTrack (NPCWA pCWA)
  181. ;
  182. ;   ENTRY:    pCWA             - CWA
  183. ;
  184. ;   RETURN:   USHORT           - Packet Status word
  185. ;
  186. ;
  187. ------------------------------------------------------------------------*/
  188. USHORT GIO_RWVTrack (pCWA)
  189.  
  190. NPCWA pCWA;
  191.  
  192. {
  193.    USHORT rc;
  194.    PRP_INTERNAL pIRP;
  195.  
  196.    if ((rc = CheckRWVPacket(pCWA)) & STERR)
  197.       return(rc);
  198.  
  199.    if (CheckFloppy(pCWA) & STERR)
  200.       return(STDON + STERR + ERROR_I24_BAD_UNIT);
  201.  
  202.    if (DevHelp_AllocReqPacket(0, (PBYTE *) &(pCWA->pIRP)) != NO_ERROR)
  203.       return(STDON + STERR + ERROR_I24_GEN_FAILURE);
  204.  
  205.    pIRP = pCWA->pIRP;
  206.  
  207.    pIRP->rph.Unit = pCWA->pRP->rph.Unit;
  208.  
  209.    pIRP->rph.Flags = RPF_Internal;
  210.  
  211.    pIRP->SectorSize = 512;              /* Default sector size is 512 */
  212.  
  213.    switch (pCWA->pRP->Function)
  214.    {
  215.       case IODC_RT:                                /* Read track */
  216.          pIRP->rph.Cmd = CMDINPUT;
  217.          break;
  218.  
  219.       case IODC_WT:                                /* Write track */
  220.          pIRP->rph.Cmd = CMDOUTPUT;
  221.          break;
  222.  
  223.       case IODC_VT:                                /* Verify Track */
  224.          pIRP->rph.Cmd = CMDInternal;
  225.          pIRP->Function = DISKOP_READ_VERIFY;
  226.          break;
  227.  
  228.       default:
  229.          return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  230.    }
  231.  
  232.    if (pCWA->Flags & (TT_NOT_CONSEC + TT_NOT_SAME_SIZE + TT_NON_STD_SECTOR))
  233.       rc = ExecRWVMultiPass(pCWA);
  234.    else
  235.       rc = ExecRWVOnePass(pCWA);
  236.  
  237.    return(rc);
  238. }
  239.  
  240. /*------------------------------------------------------------------------
  241. ;
  242. ;** CheckRWVPacket - Check Read, Write Verify IOCTL packets.
  243. ;
  244. ;   Check the read, write, verify IOCTL packets.
  245. ;
  246. ;   USHORT CheckRWV (NPCWA pCWA)
  247. ;
  248. ;   ENTRY:    pCWA             - CWA
  249. ;
  250. ;   RETURN:   USHORT           - Packet Status word
  251. ;
  252. ;
  253. ------------------------------------------------------------------------*/
  254. USHORT CheckRWVPacket (pCWA)
  255.  
  256. NPCWA pCWA;
  257.  
  258. {
  259.    USHORT rc, i, LockFlag;
  260.    ULONG  BufferSize = 0;
  261.    PDDI_RWVPacket_param   pRWVP;
  262.    USHORT MinCylLimit, MaxCylLimit;                                  /*@V89787*/
  263.  
  264.    pRWVP = (PDDI_RWVPacket_param) pCWA->pParmPkt;
  265.  
  266.    /* Verify access to the parameter packet */
  267.  
  268.    if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
  269.                             sizeof(DDI_RWVPacket_param))) & STERR)
  270.  
  271.       return(rc);
  272.  
  273.    /*
  274.       The parameter packet is safe to read and at least one
  275.       entry in the track table is accessible.  We must now
  276.       determine if we will have to go past this entry in the
  277.       track table.  If we do, LockUserPacket will have to be
  278.       called again with a new size.
  279.    */
  280.  
  281.    if  ( (pRWVP->FirstSector + pRWVP->NumSectors) > 1)
  282.    {
  283.         if (DevHelp_VMUnLock(plDataSeg +
  284.                             (ULONG) ((USHORT)(&(pCWA->hLockParmPkt)))) != 0)
  285.            return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  286.  
  287.         pCWA->Flags &= ~LOCKED_PARMPKT;
  288.  
  289.         if ((rc = LockUserPacket( pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
  290.                 sizeof(DDI_RWVPacket_param) +
  291.                 (sizeof(TLT) * (pRWVP->FirstSector + pRWVP->NumSectors - 1)))
  292.                     & STERR) )
  293.             return(rc);
  294.     }
  295.  
  296.  
  297.    /*----------------------------------------------------------*/    /*@V89787*/
  298.    /* Validate the cylinder and head values are ok             */    /*@V89787*/
  299.    /*                                                          */    /*@V89787*/
  300.    /* For Cat 9 IOCTLs cylinder 0 starts at physical rba 0.    */    /*@VVVVVV*/
  301.    /*                                                          */
  302.    /* The entire disk is available for read/write. Accesses    */
  303.    /* to the last (partial cylinder are allowed).              */
  304.    /*                                                          */
  305.    /* For Cat 8 IOCTLs cylinder 0 starts at the MBR/EBR        */
  306.    /* containing the the logical drive parition entry.         */
  307.    /*                                                          */
  308.    /* The cylinders between the MRB/EBR and the logical drive  */
  309.    /* do not belong to the logical drive being accessed and    */
  310.    /* are only readable.                                       */
  311.    /*                                                          */
  312.    /* Read/Write access to cylinder 0 head 0 are always        */
  313.    /* allowed.                                                 */
  314.    /*                                                          */
  315.    /*----------------------------------------------------------*/
  316.  
  317.  
  318.    MinCylLimit = 0;
  319.    MaxCylLimit = pCWA->pVolCB->NumLogCylinders;
  320.  
  321.    if ( pCWA->pRP->Category == IOC_DC )
  322.    {
  323.       if ( pCWA->pRP->Function == IODC_WT )
  324.       {
  325.          MinCylLimit = pCWA->pVolCB->BootRecCyl;
  326.       }
  327.    }
  328.  
  329.    if ( (pRWVP->Cylinder || pRWVP->Head) && (pRWVP->Cylinder < MinCylLimit) )
  330.    {
  331.       return (STDON+STERR+ERROR_I24_INVALID_PARAMETER);
  332.    }
  333.  
  334.    if ( pRWVP->Cylinder > MaxCylLimit )
  335.    {
  336.       return (STDON+STERR+ERROR_I24_INVALID_PARAMETER);
  337.    }
  338.  
  339.    if ( pRWVP->Head >= pCWA->pVolCB->MediaBPB.NumHeads )
  340.    {                                                                 /*@VAAAAA*/
  341.       return (STDON+STERR+ERROR_I24_INVALID_PARAMETER);              /*@V89787*/
  342.    }                                                                 /*@V89787*/
  343.  
  344.  
  345.    /* Initialize the required fields in the CWA */
  346.  
  347.    pCWA->StartSector = pRWVP->FirstSector;
  348.    pCWA->Cylinder = pRWVP->Cylinder;
  349.    pCWA->Head = pRWVP->Head;
  350.    pCWA->NumSectors = pRWVP->NumSectors;
  351.    pCWA->TTSectors = pRWVP->FirstSector + pRWVP->NumSectors;
  352.  
  353.    /*
  354.       Determine:
  355.  
  356.       1) Whether sector table starts with sector number 1.
  357.       2) Whether sectors in track table are consecutive.
  358.       3) Whether sectors in track table are all the same size.
  359.       4) Total buffer length.
  360.    */
  361.  
  362.    if (pRWVP->TrackTable[0].SectorNumber != 1)
  363.       pCWA->Flags |= TT_START_NOT_SECTOR_ONE;
  364.  
  365.    for (i = 0; i < pCWA->TTSectors; i++)
  366.    {
  367.       if (i > 0 && pRWVP->TrackTable[i].SectorNumber !=
  368.                    (pRWVP->TrackTable[i-1].SectorNumber + 1) )
  369.          pCWA->Flags |= TT_NOT_CONSEC;
  370.  
  371.  
  372.       if (pRWVP->TrackTable[i].SectorSize != pRWVP->TrackTable[0].SectorSize)
  373.          pCWA->Flags |= TT_NOT_SAME_SIZE;
  374.  
  375.       if (i >= pRWVP->FirstSector)
  376.          BufferSize += pRWVP->TrackTable[i].SectorSize;
  377.    }
  378.  
  379.    /* Non standard sector sizes and tables with different sector sizes */
  380.    /* are only supported for diskettes.  Return error for fixed disks. */
  381.  
  382.    if ( (pRWVP->TrackTable[0].SectorSize != 512) ||
  383.         (pCWA->Flags & TT_NOT_SAME_SIZE) )
  384.    {
  385.       if (pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  386.          pCWA->Flags |= TT_NON_STD_SECTOR;
  387.       else
  388.          return (STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  389.    }
  390.  
  391.    if (pRWVP->Command == RWV_SIMPLE_TRACK_TABLE)
  392.    {
  393.       if (pCWA->Flags & (TT_START_NOT_SECTOR_ONE | TT_NOT_CONSEC))
  394.          return (STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  395.    }
  396.    else if (pRWVP->Command != RWV_COMPLEX_TRACK_TABLE)
  397.          return (STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  398.  
  399.    /* Lock down the data buffer for a read or write */
  400.  
  401.    if (pCWA->pRP->Function == IODC_RT || pCWA->pRP->Function == IODC_WT)
  402.    {
  403.       LockFlag = LOCK_DATAPKT;
  404.  
  405.       if (pCWA->pRP->Function == IODC_RT)  /* if read, then writing TO memory */
  406.          LockFlag |= LOCK_WRITE;
  407.  
  408.       rc = LockUserPacket (pCWA, LockFlag, BufferSize);
  409.    }
  410.  
  411.    return (rc);
  412. }
  413.  
  414. /*------------------------------------------------------------------------
  415. ;
  416. ;** ExecRWVOnePass - Execute single pass Read/Write/Verify operation.
  417. ;
  418. ;   Setup a Read/Write/Verify IORB and submit it for processing.
  419. ;
  420. ;   USHORT ExecRWVOnePass (NPCWA pCWA)
  421. ;
  422. ;   ENTRY:    pCWA             - CWA
  423. ;
  424. ;   RETURN:   USHORT           - Packet Status word
  425. ;
  426. ;
  427. ------------------------------------------------------------------------*/
  428. USHORT ExecRWVOnePass (pCWA)
  429.  
  430. NPCWA pCWA;
  431. {
  432.   USHORT rc;
  433.   PDDI_RWVPacket_param   pRWVP;
  434.   PRP_INTERNAL pIRP;
  435.  
  436.   pIRP = pCWA->pIRP;
  437.   pRWVP = (PDDI_RWVPacket_param) pCWA->pParmPkt;
  438.  
  439.   if (pCWA->pDataPkt != 0)
  440.      pIRP->XferAddr = pCWA->ppDataPkt;     /* Save physical data xfer addr */
  441.  
  442.   /* Calculate RBA from Cylinder, Head and Starting Sector Number in    */
  443.   /* the track table.                                                   */
  444.  
  445.   pIRP->rba = f_CHS_to_RBA(pCWA->pVolCB, pCWA->Cylinder, (UCHAR) pCWA->Head, 1) +
  446.               pCWA->pVolCB->PartitionOffset - 1 +
  447.               pRWVP->TrackTable[pCWA->StartSector].SectorNumber;
  448.  
  449.   pCWA->pVolCB->Flags |= vf_ForceRdWrt;
  450.  
  451.   /* Issue a synchronous I/O call which waits until the I/O is done */
  452.  
  453.   pIRP->NumSectors = pCWA->NumSectors;
  454.   rc = IOCTL_IO( (PBYTE)pIRP, pCWA->pVolCB );
  455.  
  456.   /* If Uncertain Media error, then retry the I/O */
  457.  
  458.   if (rc == STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA)
  459.   {
  460.      pIRP->NumSectors = pCWA->NumSectors;
  461.      rc = IOCTL_IO ( (PBYTE) pIRP, pCWA->pVolCB);
  462.   }
  463.   return (rc);
  464. }
  465.  
  466. /*------------------------------------------------------------------------
  467. ;
  468. ;** ExecRWVMultiPass - Execute multiple pass Read/Write/Verify operation.
  469. ;
  470. ;   Setup a Read/Write/Verify IORB and submit it for processing.
  471. ;
  472. ;   USHORT ExecRWVMultiPass (NPCWA pCWA)
  473. ;
  474. ;   ENTRY:    pCWA             - CWA
  475. ;
  476. ;   RETURN:   USHORT           - Packet Status word
  477. ;
  478. ;
  479. ------------------------------------------------------------------------*/
  480.  
  481. USHORT ExecRWVMultiPass (pCWA)
  482.  
  483. NPCWA  pCWA;
  484. {
  485.   PRP_INTERNAL pIRP;
  486.   PDDI_RWVPacket_param   pRWVP;
  487.   ULONG  TrackRBA, Buf;
  488.   USHORT i, rc;
  489.   PCHS_ADDR pCHS;
  490.  
  491.   pRWVP = (PDDI_RWVPacket_param) pCWA->pParmPkt;
  492.  
  493.   pIRP = pCWA->pIRP;
  494.  
  495.   if (pCWA->pDataPkt != 0)
  496.      pIRP->XferAddr = pCWA->ppDataPkt;     /* Save physical data xfer addr */
  497.  
  498.   /* If the request is for a diskette, then use CHS addressing for the */
  499.   /* non-standard diskette layout, otherwise use RBA addressing.       */
  500.  
  501.   if (pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  502.   {
  503.      pCHS = (PCHS_ADDR) &(pIRP->rba);
  504.      pCHS->Cylinder = pCWA->Cylinder;
  505.      pCHS->Head = (UCHAR) pCWA->Head;
  506.      pIRP->rph.Flags |= RPF_CHS_ADDRESSING;
  507.   }
  508.   else
  509.   {
  510.      /* Calculate RBA for the start of the track.   */
  511.  
  512.      TrackRBA = f_CHS_to_RBA(pCWA->pVolCB,pCWA->Cylinder,(UCHAR)pCWA->Head,1) +
  513.                 pCWA->pVolCB->PartitionOffset;
  514.   }
  515.  
  516.   Buf = pCWA->ppDataPkt;
  517.  
  518.   /* Process each entry in the track table from starting sector on.   */
  519.  
  520.   for (i = 0; i < pCWA->NumSectors; i++ )
  521.   {
  522.      pIRP->rph.Status = 0;
  523.      pIRP->XferAddr = Buf;
  524.  
  525.      if (pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  526.      {
  527.         pCHS->Sector = (UCHAR) pRWVP->TrackTable[i].SectorNumber - 1;
  528.         pIRP->SectorSize = pRWVP->TrackTable[i].SectorSize;
  529.      }
  530.      else
  531.      {
  532.         pIRP->rba = TrackRBA + pRWVP->TrackTable[i].SectorNumber - 1;
  533.      }
  534.  
  535.      pCWA->pVolCB->Flags |= vf_ForceRdWrt;
  536.  
  537.      /* Issue a synchronous I/O call which waits until the I/O is done */
  538.  
  539.      pIRP->NumSectors = 1;
  540.      rc = IOCTL_IO ( (PBYTE)pIRP, pCWA->pVolCB);
  541.  
  542.      /* If Uncertain Media error, then retry the I/O */
  543.  
  544.      if (rc == STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA)
  545.      {
  546.         pIRP->NumSectors = 1;
  547.         rc = IOCTL_IO ( (PBYTE)pIRP, pCWA->pVolCB);
  548.      }
  549.  
  550.      if (rc != NO_ERROR)
  551.         break;
  552.  
  553.      Buf += pRWVP->TrackTable[i].SectorSize;
  554.   }
  555.  
  556.   return(pIRP->rph.Status);
  557. }
  558.  
  559.  
  560.  
  561. /*------------------------------------------------------------------------
  562. ;
  563. ;** GIO_FormatVerify - Process a Format & Verify track IOCTL
  564. ;
  565. ;   Format, then verify a track.  For diskettes, if a standard formatting
  566. ;   is requested, then invoke the diskette state machine to do a
  567. ;   format/verify operation.  If non-standard diskette formatting
  568. ;   is requested, first do the formatting, and then perform a separate
  569. ;   verify operation.
  570. ;
  571. ;   USHORT ExecFormatVerify (NPCWA pCWA)
  572. ;
  573. ;   ENTRY:    pCWA             - CWA
  574. ;
  575. ;   RETURN:   USHORT           - Packet Status word
  576. ;
  577. ;
  578. ------------------------------------------------------------------------*/
  579. USHORT GIO_FormatVerify (pCWA)
  580.  
  581. NPCWA pCWA;
  582.  
  583. {
  584.    PDDI_FormatPacket_param   pFP;
  585.    USHORT rc;
  586.    PRP_INTERNAL pIRP;
  587.  
  588.    pFP = (PDDI_FormatPacket_param) pCWA->pParmPkt;
  589.  
  590.    if ((rc = CheckFormatPacket(pCWA)) & STERR)
  591.       return(rc);
  592.  
  593.    if ((rc = CheckFloppy(pCWA)) & STERR)
  594.       return(rc);
  595.  
  596.    if (DevHelp_AllocReqPacket(0, (PBYTE *) &(pCWA->pIRP)) != NO_ERROR)
  597.       return(STDON + STERR + ERROR_I24_GEN_FAILURE);
  598.  
  599.    pIRP = pCWA->pIRP;
  600.  
  601.    pIRP->rph.Unit = pCWA->pRP->rph.Unit;
  602.  
  603.    pIRP->rph.Flags = RPF_Internal;
  604.  
  605.    pIRP->SectorSize = 512;              /* Default sector size is 512 */
  606.  
  607.    if (pFP->Command == FP_COMMAND_MULTITRACK)
  608.       rc = ExecMultiTrkVerify(pCWA);
  609.  
  610.    else if (pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  611.    {
  612.       /* Perform separate verify step for non-standard diskettes. */
  613.  
  614.       if ( ((rc = ExecDisketteFormat(pCWA)) == NO_ERROR) &&
  615.            (pCWA->Flags & (TT_NOT_CONSEC | TT_NOT_SAME_SIZE |
  616.                              TT_NON_STD_SECTOR)) )
  617.  
  618.          rc = ExecCheckTrack(pCWA);
  619.    }
  620.    else
  621.       rc = ExecCheckTrack(pCWA);
  622.  
  623.    return(rc);
  624. }
  625.  
  626. /*------------------------------------------------------------------------
  627. ;
  628. ;** CheckFormatPacket - Check the Format IOCTL packet.
  629. ;
  630. ;   Check the Format IOCTL packet.
  631. ;
  632. ;   USHORT CheckFormatPacket (NPCWA pCWA)
  633. ;
  634. ;   ENTRY:    pCWA             - CWA
  635. ;
  636. ;   RETURN:   USHORT           - Packet Status word
  637. ;
  638. ;
  639. ------------------------------------------------------------------------*/
  640. USHORT CheckFormatPacket (pCWA)
  641.  
  642. NPCWA (pCWA);
  643. {
  644.    USHORT rc, i;
  645.    PDDI_FormatPacket_param   pFP;
  646.  
  647.    pFP = (PDDI_FormatPacket_param) pCWA->pParmPkt;
  648.  
  649.    /* Lock down the parameter packet since the format track   */
  650.    /* table is passed to the diskette controller and it must  */
  651.    /* locked down first.                                      */
  652.  
  653.    if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT,
  654.                             sizeof(DDI_FormatPacket_param))) & STERR)
  655.       return(rc);
  656.  
  657.    /*
  658.       The parameter packet is safe to read and at least one
  659.       entry in the track table is accessible.  We must now
  660.       determine if we will have to go past this entry in the
  661.       track table.  If we do, LockUserPacket will have to be
  662.       called again with a new size.
  663.    */
  664.  
  665.    if (pFP->Command != FP_COMMAND_MULTITRACK)                        /*@V46624*/
  666.       pCWA->TTSectors = pFP->NumSectors;
  667.    else
  668.       pCWA->TTSectors = 1;
  669.  
  670.    if (pCWA->TTSectors > 1)
  671.    {
  672.         if (DevHelp_VMUnLock(plDataSeg +
  673.                             (ULONG) ((USHORT)(&(pCWA->hLockParmPkt)))) != 0)
  674.             return(rc);
  675.  
  676.         pCWA->Flags &= ~LOCKED_PARMPKT;
  677.  
  678.         if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT,
  679.           sizeof(DDI_FormatPacket_param) +
  680.           (sizeof(FTT) * (pCWA->TTSectors - 1))) & STERR) )
  681.  
  682.             return(rc);
  683.    }
  684.  
  685.    /* Validate the cylinder and head values are ok */
  686.  
  687.    if ( (pFP->Cylinder >= pCWA->pVolCB->NumPhysCylinders) ||
  688.         (pFP->Head >= pCWA->pVolCB->MediaBPB.NumHeads) )
  689.  
  690.       return (STDON+STERR+ERROR_I24_INVALID_PARAMETER);
  691.  
  692.  
  693.    /* Initialize the required fields in the CWA */
  694.  
  695.    pCWA->Cylinder = pFP->Cylinder;
  696.    pCWA->Head = pFP->Head;
  697.    pCWA->NumSectors = pFP->NumSectors;
  698.  
  699.    /*
  700.       Determine:
  701.  
  702.       1) Whether sector table starts with sector number 1.
  703.       2) Whether sectors in track table are consecutive.
  704.       3) Whether sectors in track table are all the same size.
  705.       4) Whether CH ids in the track table matches the CH information
  706.          in the parameter packet.
  707.    */
  708.  
  709.    if (pFP->FmtTrackTable[0].Sector != 1)
  710.  
  711.         pCWA->Flags |= TT_START_NOT_SECTOR_ONE;
  712.  
  713.    if (SectorIndexToSectorSize(pFP->FmtTrackTable[0].BytesPerSectorIndex)!=512)
  714.  
  715.         pCWA->Flags |= TT_NON_STD_SECTOR;
  716.  
  717.  
  718.    for (i = 0; i < pCWA->TTSectors; i++)
  719.    {
  720.       if (i > 0 && pFP->FmtTrackTable[i].Sector !=
  721.                    (pFP->FmtTrackTable[i-1].Sector + 1) )
  722.  
  723.             pCWA->Flags |= TT_NOT_CONSEC;
  724.  
  725.  
  726.       if (pFP->FmtTrackTable[i].BytesPerSectorIndex !=
  727.           pFP->FmtTrackTable[0].BytesPerSectorIndex)
  728.  
  729.             pCWA->Flags |= TT_NOT_SAME_SIZE;
  730.  
  731.       if (pCWA->Cylinder != pFP->Cylinder || pCWA->Head != pFP->Head)
  732.  
  733.             return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  734.    }
  735.  
  736.    /* Now that we have all the track table flag bits set, make */
  737.    /* sure the track layout is valid for the command specified */
  738.  
  739.    if (pFP->Command == FP_COMMAND_SIMPLE)
  740.    {
  741.       if (pCWA->Flags & (TT_START_NOT_SECTOR_ONE | TT_NOT_CONSEC))
  742.          return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  743.    }
  744.    else if (pFP->Command == FP_COMMAND_MULTITRACK)
  745.    {
  746.       if (pCWA->Flags & TT_NON_STD_SECTOR)
  747.          return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  748.    }
  749.    else if (pFP->Command != FP_COMMAND_COMPLEX)
  750.          return(STDON + STERR + ERROR_I24_BAD_COMMAND);
  751.  
  752.    return (STDON);
  753.  
  754. }
  755.  
  756. /*------------------------------------------------------------------------
  757. ;
  758. ;** ExecDisketteFormat - Format a diskette
  759. ;
  760. ;   Format a diskette.
  761. ;
  762. ;   USHORT ExecDisketteFormat (NPCWA pCWA)
  763. ;
  764. ;   ENTRY:    pCWA             - CWA
  765. ;
  766. ;   RETURN:   USHORT           - Packet Status word
  767. ;
  768. ;
  769. ------------------------------------------------------------------------*/
  770. USHORT ExecDisketteFormat (pCWA)
  771.  
  772. NPCWA pCWA;
  773.  
  774. {
  775.   USHORT rc;
  776.   PRP_INTERNAL pIRP;
  777.   PCHS_ADDR pCHS;
  778.   PDDI_FormatPacket_param   pParmPkt;
  779.  
  780.   pIRP = pCWA->pIRP;
  781.   pParmPkt = (PDDI_FormatPacket_param) pCWA->pParmPkt;
  782.  
  783.  
  784.   /* First set the media geometry prior to the format */
  785.  
  786.   pIRP->rph.Cmd = CMDInternal;
  787.   pIRP->Function = DISKOP_SET_MEDIA_GEOMETRY;
  788.   pIRP->NumSectors = (USHORT) pCWA->pVolCB;  /* Store pVolCB in IRP */
  789.  
  790.   rc = IOCTL_IO ( (PBYTE)pIRP, pCWA->pVolCB);
  791.  
  792.   if (rc & STERR)
  793.      return(rc);
  794.  
  795.  
  796.   /* If non-standard track layout, then verify the sectors in a
  797.   /* separate operation. */
  798.  
  799.   if (pCWA->Flags & (TT_NOT_CONSEC | TT_NOT_SAME_SIZE | TT_NON_STD_SECTOR))
  800.      pIRP->Function = DISKOP_FORMAT;
  801.   else
  802.      pIRP->Function = DISKOP_FORMAT_VERIFY;
  803.  
  804.   pIRP->XferAddr = pCWA->ppParmPkt + sizeof(DDI_FormatPacket_param)
  805.                                    - sizeof(FTT);
  806.   pIRP->NumSectors = pCWA->NumSectors;
  807.  
  808.   pIRP->SectorSize =
  809.        SectorIndexToSectorSize(pParmPkt->FmtTrackTable[0].BytesPerSectorIndex);
  810.  
  811.   pIRP->rba = f_CHS_to_RBA (pCWA->pVolCB, pParmPkt->Cylinder,
  812.                                           (UCHAR) pParmPkt->Head, 1) +
  813.               pCWA->pVolCB->PartitionOffset;
  814.  
  815.   pCWA->pVolCB->Flags |= vf_ForceRdWrt;
  816.  
  817.  
  818.   /* Issue a synchronous I/O call which waits until the I/O is done */
  819.  
  820.   rc = IOCTL_IO ( (PBYTE)pIRP, pCWA->pVolCB);
  821.  
  822.   /* If Uncertain Media error, then retry the I/O */
  823.  
  824.   if (rc == STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA)
  825.   {
  826.      pIRP->NumSectors = pCWA->NumSectors;
  827.      rc = IOCTL_IO ( (PBYTE)pIRP, pCWA->pVolCB);
  828.   }
  829.  
  830.   pCWA->pVolCB->Flags |= vf_ChangedByFormat;
  831.  
  832.   return(rc);
  833. }
  834.  
  835. /*------------------------------------------------------------------------
  836. ;
  837. ;** ExecCheckTrack - Execute multiple pass verify operation.
  838. ;
  839. ;   Verify operation for each entry in the format track table.
  840. ;
  841. ;   USHORT ExecCheckTrack (NPCWA pCWA)
  842. ;
  843. ;   ENTRY:    pCWA             - CWA
  844. ;
  845. ;   RETURN:   USHORT           - Packet Status word
  846. ;
  847. ;
  848. ------------------------------------------------------------------------*/
  849. USHORT ExecCheckTrack (pCWA)
  850.  
  851. NPCWA pCWA;
  852. {
  853.   USHORT i, rc;
  854.   ULONG  TrackRBA;
  855.  
  856.   PRP_INTERNAL pIRP;
  857.   PCHS_ADDR pCHS;
  858.   PDDI_FormatPacket_param pParmPkt;
  859.  
  860.   pIRP = pCWA->pIRP;
  861.   pParmPkt = (PDDI_FormatPacket_param) pCWA->pParmPkt;
  862.  
  863.   pIRP->rph.Cmd = CMDInternal;
  864.   pIRP->Function = DISKOP_READ_VERIFY;
  865.  
  866.   /* If the request is for a diskette, then use CHS addressing,        */
  867.   /* otherwise use RBA addressing.                                     */
  868.  
  869.   if (pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  870.   {
  871.      pCHS = (PCHS_ADDR) &(pIRP->rba);
  872.      pCHS->Cylinder = pCWA->Cylinder;
  873.      pCHS->Head = (UCHAR) pCWA->Head;
  874.      pIRP->rph.Flags |= RPF_CHS_ADDRESSING;
  875.   }
  876.   else
  877.   {
  878.      TrackRBA=f_CHS_to_RBA(pCWA->pVolCB,pCWA->Cylinder,(UCHAR)pCWA->Head,1) +
  879.               pCWA->pVolCB->PartitionOffset;
  880.   }
  881.  
  882.   pIRP->XferAddr = 0;                      /* No data to transfer */
  883.  
  884.   for (i = 0; i < pCWA->NumSectors; i++)
  885.   {
  886.      if (pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  887.      {
  888.        pCHS->Sector = pParmPkt->FmtTrackTable[i].Sector - 1;
  889.        pIRP->SectorSize =
  890.         SectorIndexToSectorSize(pParmPkt->FmtTrackTable[i].BytesPerSectorIndex);
  891.      }
  892.      else
  893.      {
  894.         pIRP->rba = TrackRBA + pParmPkt->FmtTrackTable[i].Sector - 1;
  895.      }
  896.  
  897.      pCWA->pVolCB->Flags |= vf_ForceRdWrt;
  898.  
  899.      /* Issue a synchronous I/O call which waits until the I/O is done */
  900.  
  901.      pIRP->NumSectors = 1;
  902.      rc = IOCTL_IO ( (PBYTE)pIRP, pCWA->pVolCB);
  903.  
  904.      /* If Uncertain Media error, then retry the I/O */
  905.  
  906.      if (rc == STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA)
  907.      {
  908.         pIRP->NumSectors = 1;
  909.         rc = IOCTL_IO ( (PBYTE)pIRP, pCWA->pVolCB);
  910.      }
  911.  
  912.      if (rc & STERR)
  913.         break;
  914.   }
  915.   return(rc);
  916. }
  917.  
  918. /*------------------------------------------------------------------------
  919. ;
  920. ;** ExecMultiTrkVerify - Perform multitrack verify
  921. ;
  922. ;   The input IOCTL points to a parameter packet which
  923. ;   indicates the starting Cylinder/Head and the length of the
  924. ;   verify in Tracks/Sectors. The input IOCTL also points to
  925. ;   a data packet which contains a byte which indicates the
  926. ;   starting sector for the verify.
  927. ;
  928. ;   If a nonrecoverable verify error is encountered, this routine
  929. ;   performs an inverse mapping from RBA to CHS, saves this
  930. ;   information back into the user's parameter packet, and
  931. ;   sets a return code indicating that an error had occurred.
  932. ;
  933. ;   Returning this information back to the 'Formatting Program'
  934. ;   will allow it to continue after marking the appropriate
  935. ;   area of the disk as defective.
  936. ;
  937. ;   USHORT ExecMultiTrkVerify (NPCWA pCWA)
  938. ;
  939. ;   ENTRY:    pCWA             - CWA
  940. ;
  941. ;   RETURN:   USHORT           - Packet Status word
  942. ;
  943. ;
  944. ------------------------------------------------------------------------*/
  945. USHORT ExecMultiTrkVerify (pCWA)
  946.  
  947. NPCWA pCWA;
  948.  
  949. {
  950.   PRP_INTERNAL pIRP;
  951.   PDDI_FormatPacket_param pFP;
  952.   PDDI_FormatPacket_data  pFD;
  953.   NPVOLCB pVolCB;
  954.   ULONG rba, StartRBA, ErrorRBA, TrksDone;
  955.   USHORT CurrentNumSectors, SectorsLeftToDo, i, rc;
  956.   CHS_ADDR chs;
  957.  
  958.   pIRP = pCWA->pIRP;
  959.   pFP = (PDDI_FormatPacket_param) pCWA->pParmPkt;
  960.   pFD = (PDDI_FormatPacket_data) pCWA->pDataPkt;
  961.   pVolCB = pCWA->pVolCB;
  962.  
  963.   /* MultiTrack only supported for fixed disks */
  964.  
  965.   if ( (pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) &&
  966.        ( ! (pVolCB->pUnitCB->Flags & UCF_REMOVABLE_NON_FLOPPY) ) )
  967.   {
  968.      pFP->NumTracks = ERROR_MTF_NOT_SUPPORTED;
  969.      return(STDON);
  970.   }
  971.  
  972.   pIRP->rph.Cmd = CMDInternal;
  973.   pIRP->Function = DISKOP_READ_VERIFY;
  974.  
  975.   rba = f_CHS_to_RBA(pVolCB, pCWA->Cylinder, (UCHAR) pCWA->Head,
  976.                   (UCHAR)(pFD->StartSector+1)) + pCWA->pVolCB->PartitionOffset;
  977.   StartRBA = rba;
  978.   pIRP->rba = rba;
  979.   pIRP->XferAddr = 0;                      /* No data to transfer */
  980.  
  981.   /* Calculate number of sectors in multitrack verify */
  982.  
  983.   SectorsLeftToDo = pFP->NumTracks * pVolCB->MediaBPB.SectorsPerTrack;
  984.  
  985.   pCWA->NumSectors = SectorsLeftToDo;
  986.   pIRP->NumSectors = SectorsLeftToDo;
  987.   CurrentNumSectors = SectorsLeftToDo;
  988.  
  989.   do
  990.   {
  991.      /* Setup internal request packet and do the I/O */
  992.  
  993.      pIRP->rba = rba;
  994.      pIRP->rph.Status = 0;
  995.      rc = IOCTL_IO ( (PBYTE) pIRP, pVolCB);
  996.  
  997.      /* If there is an error, then find the exact RBA of the     sector */
  998.      /* by calling DISKIO_Wait one sector at a time, starting after     */
  999.      /* the point where we know the I/O was successful.                 */
  1000.  
  1001.      if (rc & STERR)
  1002.      {
  1003.         for (i = 0, pIRP->rba = rba; i < CurrentNumSectors; i++, pIRP->rba++)
  1004.         {
  1005.            pIRP->NumSectors = 1;
  1006.            rc = IOCTL_IO ( (PBYTE) pIRP, pVolCB);
  1007.  
  1008.            /* See if this is the failing sector */
  1009.            if (rc & STERR)
  1010.            {
  1011.               /* Subtract out completed tracks.  Round Start and  */
  1012.               /* end points downwards to nearest track.  Do not   */
  1013.               /* count first (partial) track.  Save the number of */
  1014.               /* tracks remaining to be done in pFP->NumSectors.  */
  1015.  
  1016.               ErrorRBA = pIRP->rba - pVolCB->PartitionOffset;
  1017.               TrksDone = (ErrorRBA / pVolCB->MediaBPB.SectorsPerTrack) -
  1018.                          ((StartRBA - pVolCB->PartitionOffset) /
  1019.                             pVolCB->MediaBPB.SectorsPerTrack) + 1;
  1020.  
  1021.               pFP->NumSectors = pFP->NumTracks - TrksDone;
  1022.  
  1023.               /* Convert ErrorRBA to Cylinder/Head/Sector and save in RP */
  1024.  
  1025.               RBA_to_CHS(pCWA->pVolCB, ErrorRBA, (PVOID) &chs);
  1026.  
  1027.               pFP->Cylinder = chs.Cylinder;
  1028.               pFP->Head = chs.Head;
  1029.               pFD->StartSector = chs.Sector;
  1030.  
  1031.               pFP->NumTracks = ERROR_MTF_VERIFY_FAILURE;
  1032.               return(STDON);
  1033.            }
  1034.         }
  1035.      }
  1036.      rba += CurrentNumSectors;
  1037.      SectorsLeftToDo -= CurrentNumSectors;
  1038.  
  1039.   } while (SectorsLeftToDo > 0);
  1040.  
  1041.  
  1042.   pFP->NumTracks = MTF_SUCCESSFUL;
  1043.  
  1044.   return(STDON);
  1045. }
  1046.  
  1047.  
  1048. /*------------------------------------------------------------------------
  1049. ;
  1050. ;** GIO_GetDeviceParms8 - Process Cat 8 Get Device Parameters IOCTL
  1051. ;
  1052. ;   Transfers the BPB, Number of Cylinders, Device Type and Device
  1053. ;   attributes to the IOCTL data packet from the Volume Control Block.
  1054. ;
  1055. ;   USHORT GIO_GetDeviceParms8 (NPCWA pCWA)
  1056. ;
  1057. ;   ENTRY:    pCWA             - CWA
  1058. ;
  1059. ;   RETURN:   USHORT           - Packet Status word
  1060. ;
  1061. ------------------------------------------------------------------------*/
  1062. USHORT GIO_GetDeviceParms8(pCWA)
  1063.  
  1064. NPCWA pCWA;
  1065. {
  1066.    PDDI_DeviceParameters_param pParmPkt;
  1067.    PDDI_DeviceParameters_data pDataPkt;
  1068.    NPUNITCB pUnitCB;
  1069.    USHORT rc;
  1070.    UCHAR DeviceType;
  1071.  
  1072.    pParmPkt = (PDDI_DeviceParameters_param) pCWA->pParmPkt;
  1073.    pDataPkt = (PDDI_DeviceParameters_data) pCWA->pDataPkt;
  1074.  
  1075.    /* Lock the Parameter and Data Packets */
  1076.  
  1077.    if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
  1078.                             sizeof(DDI_DeviceParameters_param))) & STERR)
  1079.      return(rc);
  1080.  
  1081.  
  1082.    if ((rc = LockUserPacket(pCWA, LOCK_DATAPKT + LOCK_VERIFYONLY,
  1083.                             sizeof(DDI_DeviceParameters_data))) & STERR)
  1084.      return(rc);
  1085.  
  1086.  
  1087.    /* Determine whether to return recommended BPB or media BPB */
  1088.  
  1089.    pUnitCB = pCWA->pVolCB->pUnitCB;                                  /*@V63867*/
  1090.  
  1091.    if (pParmPkt->Command == GDP_RETURN_REC_BPB)
  1092.    {
  1093.       /* Some REMOVABLE devices do not 'KNOW' their capacity */      /*@V63867*/
  1094.       /* until media is actually inserted. For Removable     */      /*@V63867*/
  1095.       /* non-floppy devices we ask the ADD again at this     */      /*@V63867*/
  1096.       /* time for the device geometry and update the BPB     */      /*@V63867*/
  1097.       /* accordingly.                                        */      /*@V63867*/
  1098.                                                                      /*@V63867*/
  1099.       if (pUnitCB->Flags & UCF_REMOVABLE_NON_FLOPPY)                 /*@V63867*/
  1100.       {                                                              /*@V63867*/
  1101.         /* An error on this call is not reported. We just */         /*@V63867*/
  1102.         /* use the current device geometry.               */         /*@V63867*/
  1103.                                                                      /*@V63867*/
  1104.         UpdateRecBPB(pCWA);                                          /*@V63867*/
  1105.       }                                                              /*@V63867*/
  1106.       pDataPkt->bpb = pCWA->pVolCB->RecBPB;
  1107.    }
  1108.    else
  1109.    {
  1110.       if ( !(pCWA->pVolCB->Flags & vf_ReturnFakeBPB) &&
  1111.             ((rc = BuildNewBPB(pCWA)) & STERR) )
  1112.  
  1113.          return(rc);
  1114.  
  1115.       pDataPkt->bpb = pCWA->pVolCB->MediaBPB;
  1116.    }
  1117.  
  1118.    /* Return the Number of Cylinders, Device Type and Device Attributes */
  1119.  
  1120.  
  1121.    if ( !(pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) )
  1122.    {
  1123.       pDataPkt->DeviceType = TYPE_FIXED_DISK;
  1124.       pDataPkt->NumCylinders = pCWA->pVolCB->NumLogCylinders;
  1125.    }
  1126.    else
  1127.    {
  1128.       pDataPkt->NumCylinders = pCWA->pVolCB->NumPhysCylinders;
  1129.  
  1130.       switch (pCWA->pVolCB->RecBPB.TotalSectors)
  1131.       {
  1132.          case 5760:
  1133.             pDataPkt->DeviceType = TYPE_288MB;
  1134.             break;
  1135.          case 2880:
  1136.             pDataPkt->DeviceType = TYPE_144MB;
  1137.             break;
  1138.          case 1440:
  1139.             pDataPkt->DeviceType = TYPE_720KB;
  1140.             break;
  1141.          case 2400:
  1142.             pDataPkt->DeviceType = TYPE_12MB;
  1143.             break;
  1144.          default:
  1145.             if (pUnitCB->Flags & UCF_REMOVABLE_NON_FLOPPY)
  1146.                pDataPkt->DeviceType = TYPE_144MB;
  1147.             else
  1148.                pDataPkt->DeviceType = TYPE_360KB;
  1149.             break;
  1150.       }
  1151.    }
  1152.  
  1153.    pDataPkt->DeviceAttr = 0;
  1154.  
  1155.    if ( !(pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) )
  1156.       pDataPkt->DeviceAttr |= DP_DEVICEATTR_NON_REMOVABLE;
  1157.  
  1158.    if (pUnitCB->UnitInfo.UnitFlags & UF_CHANGELINE)
  1159.       pDataPkt->DeviceAttr |= DP_DEVICEATTR_CHANGELINE;
  1160.  
  1161.    if (pUnitCB->Flags & UCF_16M)
  1162.       pDataPkt->DeviceAttr |= DP_DEVICEATTR_GT16MBSUPPORT;
  1163.  
  1164.    return(STDON);
  1165. }
  1166.  
  1167. /*------------------------------------------------------------------------
  1168. ;
  1169. ;** BuildNewBPB - Build a new BPB for the medium in the drive
  1170. ;
  1171. ;   BuildNewBPB builds the BPB for the drive by first reading the
  1172. ;   boot sector and passing it on to BPBFromBoot.  The sequence of
  1173. ;   events is the same as for the BuildBPB command.
  1174. ;
  1175. ;   USHORT BuildNewBPB (NPCWA pCWA)
  1176. ;
  1177. ;   ENTRY:    pCWA             - CWA
  1178. ;
  1179. ;   RETURN:   USHORT           - Packet Status word
  1180. ;
  1181. ------------------------------------------------------------------------*/
  1182. USHORT BuildNewBPB (pCWA)
  1183.  
  1184. NPCWA pCWA;
  1185.  
  1186. {
  1187.    USHORT rc;
  1188.  
  1189.    /* First check to make sure right logical unit attached */
  1190.  
  1191.    if ((rc = CheckFloppy(pCWA)) & STERR)
  1192.       return(rc);
  1193.  
  1194.    /* Wait for scratchbuffer and read in boot sector         */
  1195.    /* If it's a valid boot sector, build the BPB from the    */
  1196.    /* boot sector copy, otherwise build BPB from scratch.    */
  1197.  
  1198.    f_SWait(&ScratchBufSem);
  1199.  
  1200.    if (f_ReadSecInScratch_RBA(pCWA->pVolCB, 0, 0) == NO_ERROR)
  1201.    {
  1202.       rc = f_BPBFromBoot(pCWA->pVolCB, (PDOSBOOTREC) &ScratchBuffer);
  1203.       f_SSig(&ScratchBufSem);
  1204.       if (rc != NO_ERROR)
  1205.          rc = f_BPBFromScratch(pCWA->pVolCB);
  1206.    }
  1207.    else
  1208.    {
  1209.       f_SSig(&ScratchBufSem);
  1210.       rc = STDON + STERR + ERROR_I24_NOT_DOS_DISK;
  1211.    }
  1212.  
  1213.    return(rc);
  1214. }
  1215.  
  1216. /*------------------------------------------------------------------------
  1217. ;
  1218. ;** UpdateRecBPB -
  1219. ;
  1220. ;
  1221. ;   USHORT
  1222. ;
  1223. ;   ENTRY:    pCWA             - CWA
  1224. ;
  1225. ;   RETURN:   USHORT           - Packet Status word
  1226. ;
  1227. ------------------------------------------------------------------------*/
  1228. USHORT UpdateRecBPB (pCWA)
  1229.                                                                      /*@V63867*/
  1230. NPCWA pCWA;                                                          /*@V63867*/
  1231.                                                                      /*@V63867*/
  1232. {                                                                    /*@V63867*/
  1233.    PRP_INTERNAL      pIRP;                                           /*@V63867*/
  1234.    USHORT            rc;                                             /*@V63867*/
  1235.                                                                      /*@V63867*/
  1236.    /* First check to make sure right logical unit attached */        /*@V63867*/
  1237.                                                                      /*@V63867*/
  1238.    if ((rc = CheckFloppy(pCWA)) & STERR)                             /*@V63867*/
  1239.       return(rc);                                                    /*@V63867*/
  1240.                                                                      /*@V63867*/
  1241.    if (DevHelp_AllocReqPacket(0, (PBYTE *)&(pCWA->pIRP)) != NO_ERROR)/*@V63867*/
  1242.       return( STDON + STERR + ERROR_I24_GEN_FAILURE );               /*@V63867*/
  1243.                                                                      /*@V63867*/
  1244.    pIRP = (PRP_INTERNAL) pCWA->pIRP;                                 /*@V63867*/
  1245.                                                                      /*@V63867*/
  1246.    f_ZeroCB((PBYTE)pIRP, sizeof(RP_INTERNAL));                       /*@V63867*/
  1247.                                                                      /*@V63867*/
  1248.    pIRP->rph.Len    = sizeof(RP_INTERNAL);                           /*@V63867*/
  1249.    pIRP->rph.Cmd    = CMDInternal;                                   /*@V63867*/
  1250.    pIRP->rph.Unit   = pCWA->pRP->rph.Unit;                           /*@V63867*/
  1251.    pIRP->rph.Flags  = RPF_Internal;                                  /*@V63867*/
  1252.    pIRP->Function   = DISKOP_UPDATE_REC_BPB;                         /*@V63867*/
  1253.    pIRP->NumSectors = (USHORT) pCWA->pVolCB;                         /*@V63867*/
  1254.                                                                      /*@V63867*/
  1255.    rc = IOCTL_IO((PBYTE)pIRP, pCWA->pVolCB);                         /*@V63867*/
  1256.                                                                      /*@V63867*/
  1257.    return(rc);                                                       /*@V63867*/
  1258. }
  1259.  
  1260. /*------------------------------------------------------------------------
  1261. ;
  1262. ;** GIO_SetDeviceParms - Process Cat 8 Set Device Parameters IOCTL
  1263. ;
  1264. ;   Transfers the BPB, Number of Cylinders, Device Type and Device
  1265. ;   attributes from the IOCTL data packet to the Volume Control Block.
  1266. ;
  1267. ;   USHORT ExecSetDeviceParms (NPCWA pCWA)
  1268. ;
  1269. ;   ENTRY:    pCWA             - CWA
  1270. ;
  1271. ;   RETURN:   USHORT           - Packet Status word
  1272. ;
  1273. ------------------------------------------------------------------------*/
  1274. USHORT GIO_SetDeviceParms(pCWA)
  1275.  
  1276. NPCWA pCWA;
  1277.  
  1278. {
  1279.   USHORT rc;
  1280.   PDDI_DeviceParameters_param pParmPkt;
  1281.   PDDI_DeviceParameters_data  pDataPkt;
  1282.  
  1283.   /* Lock the Parameter and Data Packets */
  1284.  
  1285.   if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
  1286.                             sizeof(DDI_DeviceParameters_param))) & STERR)
  1287.     return(rc);
  1288.  
  1289.  
  1290.   if ((rc=LockUserPacket(pCWA, LOCK_DATAPKT + LOCK_VERIFYONLY,
  1291.                           sizeof(DDI_DeviceParameters_data))) & STERR)
  1292.     return(rc);
  1293.  
  1294.  
  1295.   /* Determine the subcommand of this IOCTL and process accordingly */
  1296.  
  1297.   pParmPkt = (PDDI_DeviceParameters_param) pCWA->pParmPkt;
  1298.   pDataPkt = (PDDI_DeviceParameters_data) pCWA->pDataPkt;
  1299.  
  1300.   switch (pParmPkt->Command)
  1301.   {
  1302.      case SDP_USE_MEDIA_BPB:
  1303.  
  1304.          /* Revert to building the BPB off the medium for all subsequent  */
  1305.          /* BuildBPB calls.  This is used after a format operation        */
  1306.          /* to reset the device parameters to their original state.       */
  1307.  
  1308.          pCWA->pVolCB->Flags &= ~vf_ReturnFakeBPB;
  1309.          break;
  1310.  
  1311.      case SDP_TEMP_BPB_CHG:
  1312.  
  1313.          /* Change the Recommended BPB for the physical device in the VolCB */
  1314.          /* to the BPB passed as input in the data packet of the IOCTL.     */
  1315.  
  1316.          /* Make sure not changing Removable bit */
  1317.  
  1318.          if ( ((pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) &&
  1319.               !(pDataPkt->DeviceAttr & DP_DEVICEATTR_NON_REMOVABLE))  ||
  1320.              ( !(pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) &&
  1321.                (pDataPkt->DeviceAttr & DP_DEVICEATTR_NON_REMOVABLE)) )
  1322.          {
  1323.             /* Update the Recommended physical BPB in the VolCB with the   */
  1324.             /* BPB specified as input in the data packet of the IOCTL.     */
  1325.  
  1326.             pCWA->pVolCB->RecBPB = pDataPkt->bpb;
  1327.  
  1328.             pCWA->pVolCB->NumLogCylinders = pDataPkt->NumCylinders;
  1329.  
  1330.             if (pDataPkt->DeviceAttr & DP_DEVICEATTR_CHANGELINE)
  1331.                pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags |= UF_CHANGELINE;
  1332.             else
  1333.                pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags &= !(UF_CHANGELINE);
  1334.          }
  1335.          else
  1336.            rc = STDON + STERR + ERROR_I24_INVALID_PARAMETER;
  1337.  
  1338.          break;
  1339.  
  1340.      case SDP_PERM_BPB_CHG:
  1341.  
  1342.          /* Update the Media BPB in the VolCB with the BPB              */
  1343.          /* specified as input in the data packet of the IOCTL.         */
  1344.          /* This is used to prepare the device for a format media       */
  1345.          /* operation according to the device parms specified.          */
  1346.  
  1347.          pCWA->pVolCB->MediaBPB = pDataPkt->bpb;
  1348.          pCWA->pVolCB->NumLogCylinders = pDataPkt->NumCylinders;
  1349.  
  1350.          /* If formatting 360KB media in 1.2M drive, must update */
  1351.          /* the NumLogCylinders field to match the 360KB media   */
  1352.  
  1353.          if (pCWA->pVolCB->MediaBPB.TotalSectors <= 720)
  1354.             pCWA->pVolCB->NumLogCylinders = 40;
  1355.  
  1356.          pCWA->pVolCB->Flags |= vf_ReturnFakeBPB;
  1357.          break;
  1358.  
  1359.      default:                           /* Invalid command code */
  1360.          rc = STDON + STERR + ERROR_I24_INVALID_PARAMETER;
  1361.   }
  1362.   return(rc);
  1363.  
  1364. }
  1365.  
  1366.  
  1367. /*------------------------------------------------------------------------
  1368. ;
  1369. ;** GIO_GetDeviceParms9 - Execute Cat 9 Get Device Parameters IOCTL
  1370. ;
  1371. ;   Returns device parameters for a physical device.
  1372. ;
  1373. ;   USHORT ExecPhysGetDevParms (NPCWA pCWA)
  1374. ;
  1375. ;   ENTRY:    pCWA             - CWA
  1376. ;
  1377. ;   RETURN:   USHORT           - Packet Status word
  1378. ;
  1379. ------------------------------------------------------------------------*/
  1380.  
  1381. USHORT GIO_GetDeviceParms9(pCWA)
  1382.  
  1383. NPCWA pCWA;
  1384. {
  1385.   USHORT rc;
  1386.   NPVOLCB pVolCB;
  1387.  
  1388.   PDDI_PhysDeviceParameters_data pDataPkt;
  1389.  
  1390.   pDataPkt = (PDDI_PhysDeviceParameters_data) pCWA->pDataPkt;
  1391.  
  1392.   /* Verify access to data packet */
  1393.  
  1394.   if ((rc=LockUserPacket(pCWA, LOCK_DATAPKT + LOCK_VERIFYONLY,
  1395.                           sizeof(DDI_PhysDeviceParameters_data))) & STERR)
  1396.       return(rc);
  1397.  
  1398.   /* Return required device parms in data packet */
  1399.  
  1400.   pDataPkt->NumCylinders = pCWA->pVolCB->NumPhysCylinders;
  1401.   pDataPkt->NumHeads = pCWA->pVolCB->MediaBPB.NumHeads;
  1402.   pDataPkt->SectorsPerTrack = pCWA->pVolCB->MediaBPB.SectorsPerTrack;
  1403.  
  1404.   return(STDON);
  1405. }
  1406.  
  1407.  
  1408. /*------------------------------------------------------------------------
  1409. ;
  1410. ;** GIO_ReadBack - Process DMA ReadBack IOCTL packet.
  1411. ;
  1412. ;   Execute DMA ReadBack IOCTL packet.
  1413. ;
  1414. ;   USHORT GIO_ReadBack (NPCWA pCWA)
  1415. ;
  1416. ;   ENTRY:    pCWA             - CWA
  1417. ;
  1418. ;   RETURN:   USHORT           - Packet Status word
  1419. ;
  1420. ;   NOTES: We're not supporting the ReadBack subcommands Query Readback
  1421. ;          Statistics and Reset Readback statistics.
  1422. ;
  1423. ------------------------------------------------------------------------*/
  1424. USHORT GIO_ReadBack(pCWA)
  1425.  
  1426. NPCWA pCWA;
  1427.  
  1428. {
  1429.    PDDI_ReadBack_param pParmPkt;
  1430.    PDDI_ReadBack_data  pDataPkt;
  1431.  
  1432.    USHORT rc = STDON;
  1433.  
  1434.    pParmPkt = (PDDI_ReadBack_param) pCWA->pParmPkt;
  1435.    pDataPkt = (PDDI_ReadBack_data) pCWA->pDataPkt;
  1436.  
  1437.    /* Verify access to the parameter packet.        */
  1438.  
  1439.    if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
  1440.                             sizeof(DDI_ReadBack_param))) & STERR)
  1441.       return(rc);
  1442.  
  1443.  
  1444.    /* Process the command */
  1445.  
  1446.    switch (pParmPkt->Command)
  1447.    {
  1448.       case DMA_SET_READBACK_FLAG:
  1449.          DDFlags |= DDF_DMAReadBack;
  1450.          break;
  1451.  
  1452.       case DMA_RESET_READBACK_FLAG:
  1453.          DDFlags &= ~DDF_DMAReadBack;
  1454.          break;
  1455.  
  1456.       case DMA_QUERY_READ_STATS:        /* Not supported fully */
  1457.  
  1458.          /* Verify access to the data packet */
  1459.  
  1460.          if ((rc = LockUserPacket(pCWA, LOCK_DATAPKT + LOCK_VERIFYONLY,
  1461.                             sizeof(DDI_ReadBack_data))) & STERR)
  1462.             return(rc);
  1463.  
  1464.          pDataPkt->DmaOverrunCount = 0;
  1465.          pDataPkt->Count = 0;
  1466.          pDataPkt->Miscompares = 0;
  1467.          pDataPkt->Action = !(DDFlags & DDF_DMAReadBack);
  1468.          break;
  1469.  
  1470.       case DMA_RESET_READ_STATS:        /* Not supported */
  1471.          break;
  1472.  
  1473.       default:
  1474.          rc = STDON + STERR + ERROR_I24_INVALID_PARAMETER;
  1475.    }
  1476.  
  1477.    return(rc);
  1478. }
  1479.  
  1480.  
  1481. /*------------------------------------------------------------------------
  1482. ;
  1483. ;** GIO_MediaSense - Get media sense in the drive.
  1484. ;
  1485. ;   This function senses what media is present in the drive.
  1486. ;
  1487. ;   USHORT GIO_MediaSense (NPCWA pCWA)
  1488. ;
  1489. ;   ENTRY:    pCWA             - CWA
  1490. ;
  1491. ;   RETURN:   USHORT           - Packet Status word
  1492. ;
  1493. ------------------------------------------------------------------------*/
  1494. USHORT GIO_MediaSense(pCWA)
  1495.  
  1496. NPCWA pCWA;
  1497.  
  1498. {
  1499.  
  1500.    NPIORB_UNIT_STATUS pIORB;
  1501.    USHORT rc = STDON;
  1502.  
  1503.    PDDI_MediaSense_data  pDataPkt;
  1504.    pDataPkt = (PDDI_MediaSense_data) pCWA->pDataPkt;
  1505.  
  1506.    /* Verify access to the data packet */
  1507.  
  1508.    if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
  1509.                             sizeof(DDI_MediaSense_data))) & STERR)
  1510.       return(rc);
  1511.  
  1512.  
  1513.    /* If non-removable unit then cant determine media type */
  1514.  
  1515.    pDataPkt->MediaSense = 0;
  1516.  
  1517.    if ( !(pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) )
  1518.         return(STDON);
  1519.  
  1520.    /* If       psuedo drive then return error */
  1521.  
  1522.    if ((rc = CheckFloppy(pCWA)) & STERR)
  1523.         return(rc);
  1524.  
  1525.    if (DevHelp_AllocReqPacket(0, (PBYTE *) &(pCWA->pIRP)) != NO_ERROR)
  1526.       return(STDON + STERR + ERROR_I24_GEN_FAILURE);
  1527.  
  1528.    pCWA->pIRP->rph.Cmd = CMDInternal;
  1529.    pCWA->pIRP->rph.Unit = pCWA->pRP->rph.Unit;
  1530.    pCWA->pIRP->rph.Flags = RPF_Internal;
  1531.    pCWA->pIRP->Function = DISKOP_GET_MEDIA_SENSE;
  1532.  
  1533.    /* Call the adapter driver to get the media sense info.  If the   */
  1534.    /* driver doesnt support it, then just return Unable to Determine */
  1535.    /* Media Type in the media sense information.                     */
  1536.  
  1537.    rc = IOCTL_IO( (PBYTE)pCWA->pIRP, pCWA->pVolCB );
  1538.  
  1539.    if ( !(rc & STERR) )
  1540.       pDataPkt->MediaSense = (UCHAR) pCWA->pIRP->RetStatus;
  1541.    else                                                               //@V62853
  1542.       return(rc);                                                     //@V62853
  1543.  
  1544.    return(STDON);
  1545. }
  1546.  
  1547.               /* F26083 */
  1548. /*------------------------------------------------------------------------
  1549. ;
  1550. ;** GIO_RemovMedControl - Locks/Unlocks/Eject Drive(Media).
  1551. ;
  1552. ;   This function locks the drive and prevents user from removing or
  1553. ;   inserting media, or unlocks the drive and allows user to remove or
  1554. ;   insert media from or in a previously locked drive.
  1555. ;   It'll eject the media out of the drive when the Eject IOCTL is received
  1556. ;   and the drive is not locked.
  1557. ;
  1558. ;   USHORT GIO_RemovMedControl (NPCWA pCWA)
  1559. ;
  1560. ;   ENTRY:    pCWA             - CWA
  1561. ;
  1562. ;   RETURN:   USHORT           - Packet Status word
  1563. ;
  1564. ------------------------------------------------------------------------*/
  1565. USHORT GIO_RemovMedControl(pCWA)
  1566.  
  1567. NPCWA pCWA;
  1568.  
  1569. {
  1570.  
  1571.    PDDI_DsktRemovMediaCtl_param pParmPkt;
  1572.    NPIORB_DEVICE_CONTROL pIORB;
  1573.    USHORT rc = STDON;
  1574.    PDDI_DsktRemovMediaCtl_data  pDataPkt;
  1575.  
  1576.    pParmPkt = (PDDI_DsktRemovMediaCtl_param) pCWA->pParmPkt;
  1577.  
  1578.    /* If non-removable unit then don't lock */
  1579.  
  1580.    if ( !(pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) )
  1581.         return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  1582.  
  1583.    /* If       psuedo drive then return error */
  1584.  
  1585.    if ((rc = CheckFloppy(pCWA)) & STERR)
  1586.         return(rc);
  1587.  
  1588.    /* Verify access to the parameter packet.        */
  1589.  
  1590.    if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
  1591.                             sizeof(DDI_ReadBack_param))) & STERR)
  1592.       return(rc);
  1593.  
  1594.    if (DevHelp_AllocReqPacket(0, (PBYTE *) &(pCWA->pIRP)) != NO_ERROR)
  1595.       return(STDON + STERR + ERROR_I24_GEN_FAILURE);
  1596.  
  1597.    pCWA->pIRP->rph.Cmd = CMDInternal;
  1598.    pCWA->pIRP->rph.Unit = pCWA->pRP->rph.Unit;
  1599.    pCWA->pIRP->rph.Flags = RPF_Internal;
  1600.  
  1601.       switch(pParmPkt->Command) {
  1602.          case UNLOCK_MEDIA:
  1603.             pCWA->pIRP->Function = DISKOP_UNLOCKMEDIA;
  1604.             break;
  1605.          case LOCK_MEDIA:
  1606.             pCWA->pIRP->Function = DISKOP_LOCKMEDIA;
  1607.             break;
  1608.          case EJECT_MEDIA:                                           /*@V51531*/
  1609.                pCWA->pIRP->Function = DISKOP_EJECTMEDIA;             /*@V51531*/
  1610.             break;                                                   /*@V51531*/
  1611.          default:
  1612.             return(STDON + STERR + ERROR_I24_BAD_COMMAND);
  1613.             break;
  1614.       }
  1615.  
  1616.    /* Call the adapter driver to lock the drive. */
  1617.  
  1618.       if ( (rc = IOCTL_IO( (PBYTE)pCWA->pIRP, pCWA->pVolCB)) & STERR)
  1619.         return( rc);
  1620.  
  1621.    return(STDON);
  1622. }
  1623.                                                                      /*@V51531*/
  1624. /*------------------------------------------------------------------------
  1625. ;
  1626. ;** GIO_DriveStatus - Status Drive(Media).
  1627. ;
  1628. ;   This function reports status on the drive
  1629. ;   It'll also return status information after receiving the status IOCTL.
  1630. ;
  1631. ;   USHORT GIO_DriveStatus (NPCWA pCWA)
  1632. ;
  1633. ;   ENTRY:    pCWA             - CWA
  1634. ;
  1635. ;   RETURN:   USHORT           - Packet Status word
  1636. ;
  1637. ------------------------------------------------------------------------*/
  1638. USHORT GIO_DriveStatus(pCWA)
  1639.  
  1640. NPCWA pCWA;
  1641.  
  1642. {
  1643.  
  1644.    PDDI_DsktRemovMediaCtl_param pParmPkt;
  1645.    NPIORB_UNIT_STATUS pIORB;
  1646.    USHORT rc = STDON;
  1647.    PDDI_DsktRemovMediaCtl_data  pDataPkt;
  1648.  
  1649.    pDataPkt = (PDDI_DsktRemovMediaCtl_data) pCWA->pDataPkt;
  1650.  
  1651.    pParmPkt = (PDDI_DsktRemovMediaCtl_param) pCWA->pParmPkt;
  1652.  
  1653.    /* If       psuedo drive then return error */
  1654.  
  1655.    if ((rc = CheckFloppy(pCWA)) & STERR)
  1656.         return(rc);
  1657.  
  1658.    if (DevHelp_AllocReqPacket(0, (PBYTE *) &(pCWA->pIRP)) != NO_ERROR)
  1659.       return(STDON + STERR + ERROR_I24_GEN_FAILURE);
  1660.  
  1661.    pCWA->pIRP->rph.Cmd = CMDInternal;
  1662.    pCWA->pIRP->rph.Unit = pCWA->pRP->rph.Unit;
  1663.    pCWA->pIRP->rph.Flags = RPF_Internal;
  1664.  
  1665.    pCWA->pIRP->Function = DISKOP_GET_UNIT_STATUS;                    /*@V51531*/
  1666.    if ((rc = LockUserPacket(pCWA, LOCK_DATAPKT + LOCK_VERIFYONLY,
  1667.              sizeof(DDI_DsktRemovMediaCtl_data))) & STERR)
  1668.        return(rc);
  1669.  
  1670.    /* Call the adapter driver to get unit status. */
  1671.  
  1672.    rc = IOCTL_IO( (PBYTE)pCWA->pIRP, pCWA->pVolCB);
  1673.  
  1674.    pDataPkt->Status=0;                                               /*@V51531*/
  1675.    if (pCWA->pIRP->RetStatus & US_READY)                             /*@V51531*/
  1676.       pDataPkt->Status |= MEDIA_IN_DRIVE;                            /*@V51531*/
  1677.                                                                      /*@V51531*/
  1678.    if (pCWA->pVolCB->pUnitCB->Flags & UCF_REMOVABLE_NON_FLOPPY)      /*@V51531*/
  1679.       pDataPkt->Status |= STATUS_NOT_SUPPORTED;                      /*@V51531*/
  1680.    else {                                                            /*@V51531*/
  1681.       pCWA->pIRP->Function = DISKOP_GET_LOCK_STATUS;                 /*@V51531*/
  1682.       if (IOCTL_IO( (PBYTE)pCWA->pIRP, pCWA->pVolCB) & STERR)        /*@V51531*/
  1683.          pDataPkt->Status |= NOT_SUPPORTED;                          /*@V51531*/
  1684.       else if (pCWA->pIRP->RetStatus & US_LOCKED)                    /*@V51531*/
  1685.          pDataPkt->Status |= DRIVE_LOCKED;                           /*@V51531*/
  1686.       else                                                           /*@V51531*/
  1687.          pDataPkt->Status |= DRIVE_UNLOCKED;                         /*@V51531*/
  1688.    }                                                                 /*@V51531*/
  1689.  
  1690.    return(STDON);
  1691. }
  1692.  
  1693.  
  1694. /*------------------------------------------------------------------------
  1695. ;
  1696. ;** GIO_AliasDrive - Install alias drive for a floppy
  1697. ;
  1698. ;   Install an alias drive for a floppy.
  1699. ;
  1700. ;   USHORT GIO_AliasDrive (NPCWA pCWA)
  1701. ;
  1702. ;   ENTRY:    pCWA             - CWA
  1703. ;
  1704. ;   RETURN:   USHORT           - Packet Status word
  1705. ;
  1706. ------------------------------------------------------------------------*/
  1707. USHORT GIO_AliasDrive(pCWA)
  1708.  
  1709. NPCWA pCWA;
  1710. {
  1711.    PRPINITOUT pRP;
  1712.  
  1713.    NPVOLCB pVolCBNew, pVolCBx, pVolCBLast, pVolCBNext;
  1714.    PDDI_DriveAlias_param pParmPkt;
  1715.    USHORT rc;
  1716.    USHORT VolCBfound = NO;
  1717.  
  1718.    pParmPkt = (PDDI_DriveAlias_param) pCWA->pParmPkt;
  1719.    pRP = (PRPINITOUT) pCWA->pRP;
  1720.  
  1721.    /* First make sure a free VolCB exists to allocate an alias drive */
  1722.  
  1723.    if (NumExtraVolCBs == 0)
  1724.       return(STDON + STERR + ERROR_I24_BAD_COMMAND);
  1725.  
  1726.    pVolCBNew = pExtraVolCBs;
  1727.  
  1728.    /* Perform aliasing */
  1729.  
  1730.    for (pVolCBx = VolCB_Head; pVolCBx != NULL; pVolCBx = pVolCBx->pNextVolCB)
  1731.    {
  1732.       if (pVolCBx->PhysDriveNum == pParmPkt->PhysDriveNum)
  1733.       {
  1734.          if ( !(pVolCBx->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) )
  1735.             return(STDON + STERR + ERROR_I24_BAD_UNIT);
  1736.  
  1737.          /* Set up the new Volume Control Block */
  1738.  
  1739.          pVolCBx->Flags |= vf_AmMult;           /* Indicate aliases exist */
  1740.  
  1741.          *pVolCBNew = *pVolCBx;
  1742.          pVolCBNew->MediaBPB = pParmPkt->rbpb;
  1743.          pVolCBNew->RecBPB = pParmPkt->rbpb;
  1744.          pVolCBNew->PhysDriveNum = pParmPkt->PhysDriveNum;
  1745.          pVolCBNew->LogDriveNum = NumLogDrives;
  1746.          pVolCBNew->NumPhysCylinders = pParmPkt->cCyln;
  1747.          pVolCBNew->NumLogCylinders = pParmPkt->cCyln;
  1748.          pVolCBNew->Flags &= ~vf_OwnPhysical;   /*  Dont own physical drive   */
  1749.          break;
  1750.       }
  1751.    }
  1752.    /* If a VolCB wasnt found for this physical drive, then return an error */
  1753.  
  1754.    if (pVolCBx == NULL)
  1755.       return(STDON + STERR + ERROR_I24_BAD_UNIT);
  1756.  
  1757.  
  1758.    /* Link this VolCB into the VolCB Chain */
  1759.  
  1760.    rc = f_Get_VolCB_Addr(NumLogDrives - 1, (PVOID) &pVolCBLast);
  1761.  
  1762.    DISABLE;
  1763.  
  1764.    pVolCBNext = pVolCBLast->pNextVolCB;
  1765.    pVolCBLast->pNextVolCB = pVolCBNew;
  1766.    pVolCBNew->pNextVolCB = pVolCBNext;
  1767.  
  1768.    NumLogDrives++;
  1769.    NumVolCBs++;
  1770.    NumExtraVolCBs--;
  1771.    pExtraVolCBs++;
  1772.  
  1773.    ENABLE;
  1774.  
  1775.    /* Return unit number and pointer to BPB array in original RP */
  1776.  
  1777.    pRP->rph.Unit = pVolCBNew->LogDriveNum;
  1778.  
  1779.    DummyBPB = (PVOID) ( &(pVolCBNew->MediaBPB) );
  1780.  
  1781.    pRP->BPBArray = (PVOID) (&DummyBPB);
  1782.  
  1783.    return(STDON);
  1784. }
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790. /*------------------------------------------------------------------------
  1791. ;
  1792. ;** GIO_DsktControl - Suspend/Resume diskette driver I/O
  1793. ;
  1794. ;   This IOCTL provides for Internal Tape Support. An Internal
  1795. ;   Tape Drive is an option which plugs into a diskette drive
  1796. ;   slot. A separate OS/2 device driver directly programs the
  1797. ;   diskette controller to provide support for this option.
  1798. ;
  1799. ;   This IOCTL is issued by the tape utilities prior to using
  1800. ;   the tape drive. The Diskette Driver performs an orderly suspension
  1801. ;   or restart of diskette activity as requested by this IOCTL.
  1802. ;
  1803. ;   USHORT ExecDsktControl (NPCWA pCWA)
  1804. ;
  1805. ;   ENTRY:    pCWA             - CWA
  1806. ;
  1807. ;   RETURN:   USHORT           - Packet Status word
  1808. ;
  1809. ------------------------------------------------------------------------*/
  1810. USHORT GIO_DsktControl (pCWA)
  1811.  
  1812. NPCWA pCWA;
  1813.  
  1814. {
  1815.    PDDI_DsktControl_param pParmPkt;
  1816.  
  1817.    USHORT RetData;
  1818.    USHORT rc = STDON;
  1819.  
  1820.    pParmPkt = (PDDI_DsktControl_param) pCWA->pParmPkt;
  1821.  
  1822.    if (NumRemovableDisks == 0)
  1823.       return (STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  1824.  
  1825.    if (DevHelp_AllocReqPacket(0, (PBYTE *) &(pCWA->pIRP)) != NO_ERROR)
  1826.       return(STDON + STERR + ERROR_I24_GEN_FAILURE);
  1827.  
  1828.    pCWA->pIRP->rph.Cmd = CMDInternal;
  1829.    pCWA->pIRP->rph.Flags = RPF_Internal;
  1830.  
  1831.    /* Make sure this request gets to the diskette controller */
  1832.  
  1833.    pCWA->pIRP->rph.Unit = 0;
  1834.    pCWA->pVolCB = pVolCB_DriveA;
  1835.  
  1836.    switch (pParmPkt->Command)
  1837.    {
  1838.       case DSKT_SUSPEND:
  1839.          if (DDFlags & DDF_DsktSuspended)
  1840.             rc = STDON + STERR + ERROR_I24_INVALID_PARAMETER;
  1841.          else
  1842.          {
  1843.             pCWA->pIRP->Function = DISKOP_SUSPEND_DEFERRED;
  1844.  
  1845.             IOCTL_IO( (PBYTE)pCWA->pIRP, pCWA->pVolCB );
  1846.  
  1847.             if ( !(pCWA->pIRP->rph.Status & STERR) )
  1848.                DDFlags |= DDF_DsktSuspended;
  1849.          }
  1850.          break;
  1851.  
  1852.       case DSKT_RESUME:
  1853.          if ( !(DDFlags & DDF_DsktSuspended) )
  1854.             rc = STDON + STERR + ERROR_I24_INVALID_PARAMETER;
  1855.          else
  1856.          {
  1857.             pCWA->pIRP->Function = DISKOP_RESUME;
  1858.  
  1859.             IOCTL_IO( (PBYTE)pCWA->pIRP, pCWA->pVolCB);
  1860.  
  1861.             if ( !(pCWA->pIRP->rph.Status & STERR) )
  1862.                DDFlags &= ~DDF_DsktSuspended;
  1863.          }
  1864.          break;
  1865.  
  1866.       case DSKT_QUERY:
  1867.          if ( (pCWA->pVolCB->pUnitCB->NumReqsInProgress != 0) ||
  1868.               (pCWA->pVolCB->pUnitCB->NumReqsWaiting != 0) )
  1869.  
  1870.             rc = STDON + STERR + ERROR_I24_DISK_CHANGE;
  1871.  
  1872.          break;
  1873.  
  1874.       default:
  1875.          rc = STDON + STERR + ERROR_I24_INVALID_PARAMETER;
  1876.          break;
  1877.    }
  1878.    return(rc);
  1879. }
  1880.  
  1881. /*------------------------------------------------------------------------
  1882. ;
  1883. ;** GIO_ChangePartition - Process Change Partition type IOCTL
  1884. ;
  1885. ;   This IOCTL was used to indicate whether caching should be enabled
  1886. ;   or disabled when FORMAT changes the partition type to HPFS or
  1887. ;   FAT.  Since caching is no longer in the device driver, this routine
  1888. ;   simply returns with status done.
  1889. ;
  1890. ;   USHORT GIO_ChangePartition (NPCWA pCWA)
  1891. ;
  1892. ;   ENTRY:    pCWA             - CWA
  1893. ;
  1894. ;   RETURN:   USHORT           - Packet Status word
  1895. ;
  1896. ------------------------------------------------------------------------*/
  1897. USHORT GIO_ChangePartition (pCWA)
  1898.  
  1899. NPCWA   pCWA;
  1900.  
  1901. {
  1902.  return(STDON);
  1903.  
  1904. }
  1905.  
  1906. /*---------------------------------------------------------------
  1907. ;
  1908. ;** GIO_SetDASDMgrParms - Set DASD Manager parameters
  1909. ;
  1910. ;
  1911. -----------------------------------------------------------------*/
  1912. USHORT GIO_SetDASDMgrParms(pCWA)                                     /*@V74404*/
  1913.                                                                      /*@V74404*/
  1914. NPCWA pCWA;                                                          /*@V74404*/
  1915. {                                                                    /*@V74404*/
  1916.    PDDI_QueueControl_param pQCPP;                                    /*@V74404*/
  1917.    NPUNITCB pUnitCB;                                                 /*@V74404*/
  1918.    USHORT rc = STDON;                                                /*@V74404*/
  1919.                                                                      /*@V74404*/
  1920.    pQCPP = (PDDI_QueueControl_param) pCWA->pParmPkt;                 /*@V74404*/
  1921.                                                                      /*@V74404*/
  1922.    /* Lock the Parameter and Data Packets */                         /*@V74404*/
  1923.                                                                      /*@V74404*/
  1924.    if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,    /*@V74404*/
  1925.                             sizeof(DDI_QueueControl_param))) & STERR)/*@V74404*/
  1926.      goto QueueControl_Exit;                                         /*@V74404*/
  1927.                                                                      /*@V74404*/
  1928.    pUnitCB = pCWA->pVolCB->pUnitCB;                                  /*@V74404*/
  1929.                                                                      /*@V74404*/
  1930.    if ( pQCPP->Command == SET_QUEUING_CONTROL )                      /*@V74404*/
  1931.    {                                                                 /*@V74404*/
  1932.       USHORT QueueMethod;                                            /*@V74404*/
  1933.       USHORT QueueDepth;                                             /*@V74404*/
  1934.       USHORT SortMethod;                                             /*@V74404*/
  1935.                                                                      /*@V74404*/
  1936.       switch (QueueMethod=pQCPP->QueueMethod)                        /*@V74404*/
  1937.       {                                                              /*@V74404*/
  1938.          case QUEUE_METHOD_NOPRIORITY:                               /*@V74404*/
  1939.          case QUEUE_METHOD_PRIORITY:                                 /*@V74404*/
  1940.             break;                                                   /*@V74404*/
  1941.                                                                      /*@V74404*/
  1942.          case QUEUE_METHOD_DEFAULT:                                  /*@V74404*/
  1943.             QueueMethod = QUEUE_METHOD_PRIORITY;                     /*@V74404*/
  1944.             break;                                                   /*@V74404*/
  1945.                                                                      /*@V74404*/
  1946.          case QUEUE_METHOD_CURRENT:                                  /*@V74404*/
  1947.             QueueMethod = pUnitCB->QueueMethod;                      /*@V74404*/
  1948.             break;                                                   /*@V74404*/
  1949.                                                                      /*@V74404*/
  1950.          default:                                                    /*@V74404*/
  1951.             rc |= (STERR | ERROR_I24_INVALID_PARAMETER);             /*@V74404*/
  1952.             goto QueueControl_Exit;                                  /*@V74404*/
  1953.       }                                                              /*@V74404*/
  1954.                                                                      /*@V74404*/
  1955.       switch (SortMethod=pQCPP->SortMethod)                          /*@V74404*/
  1956.       {                                                              /*@V74404*/
  1957.          case SORT_METHOD_ELEVATOR:                                  /*@V74404*/
  1958.          case SORT_METHOD_FIFO:                                      /*@V74404*/
  1959.             break;                                                   /*@V74404*/
  1960.                                                                      /*@V74404*/
  1961.          case SORT_METHOD_DEFAULT:                                   /*@V74404*/
  1962.             SortMethod = SORT_METHOD_ELEVATOR;                       /*@V74404*/
  1963.             break;                                                   /*@V74404*/
  1964.                                                                      /*@V74404*/
  1965.          case SORT_METHOD_CURRENT:                                   /*@V74404*/
  1966.             SortMethod = pUnitCB->SortMethod;                        /*@V74404*/
  1967.             break;                                                   /*@V74404*/
  1968.                                                                      /*@V74404*/
  1969.          default:                                                    /*@V74404*/
  1970.             rc |= (STERR | ERROR_I24_INVALID_PARAMETER);             /*@V74404*/
  1971.             goto QueueControl_Exit;                                  /*@V74404*/
  1972.       }                                                              /*@V74404*/
  1973.                                                                      /*@V74404*/
  1974.       switch (QueueDepth=pQCPP->QueueDepth)                          /*@V74404*/
  1975.       {                                                              /*@V74404*/
  1976.          case QUEUE_DEPTH_DEFAULT:                                   /*@V74404*/
  1977.             QueueDepth = pUnitCB->UnitInfo.QueuingCount;             /*@V74404*/
  1978.             break;                                                   /*@V74404*/
  1979.                                                                      /*@V74404*/
  1980.          case  QUEUE_DEPTH_CURRENT:                                  /*@V74404*/
  1981.             QueueDepth = pUnitCB->QueueDepth;                        /*@V74404*/
  1982.             break;                                                   /*@V74404*/
  1983.                                                                      /*@V74404*/
  1984.          default:                                                    /*@V74404*/
  1985.             if ( QueueDepth > 255 )                                  /*@V74404*/
  1986.             {                                                        /*@V74404*/
  1987.                rc |= (STERR | ERROR_I24_INVALID_PARAMETER);          /*@V74404*/
  1988.                goto QueueControl_Exit;                               /*@V74404*/
  1989.             }                                                        /*@V74404*/
  1990.       }                                                              /*@V74404*/
  1991.                                                                      /*@V74404*/
  1992.       pUnitCB->QueueDepth  = QueueDepth;                             /*@V74404*/
  1993.       pUnitCB->QueueMethod = QueueMethod;                            /*@V74404*/
  1994.       pUnitCB->SortMethod  = SortMethod;                             /*@V74404*/
  1995.                                                                      /*@V74404*/
  1996.    }                                                                 /*@V74404*/
  1997.    else                                                              /*@V74404*/
  1998.       rc |= (STERR | ERROR_I24_INVALID_PARAMETER);                   /*@V74404*/
  1999.                                                                      /*@V74404*/
  2000. QueueControl_Exit:                                                   /*@V74404*/
  2001.    return ( rc );                                                    /*@V74404*/
  2002.                                                                      /*@V74404*/
  2003. }                                                                    /*@V74404*/
  2004.  
  2005.  
  2006. /*------------------------------------------------------------------------
  2007. ;
  2008. ** CheckFloppy - Check to ensure the correct floppy is in the drive
  2009. ;
  2010. ;   Checks to ensure the correct floppy disk is in the drive.
  2011. ;   This is required for drives that have more than one logical
  2012. ;   drive assigned to them.
  2013. ;
  2014. ;   USHORT CheckFloppy (NPCWA pCWA)
  2015. ;
  2016. ;   ENTRY:    pCWA             - Returned pointer to CWA
  2017. ;
  2018. ;   RETURN:   USHORT           - Packet Status word
  2019. ;
  2020. ;
  2021. ------------------------------------------------------------------------*/
  2022.  
  2023. USHORT CheckFloppy (pCWA)
  2024.  
  2025. NPCWA pCWA;
  2026.  
  2027. {
  2028.    USHORT rc = STDON;
  2029.  
  2030.    if ( (pCWA->pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) &&
  2031.         (f_CheckPseudoChange(pCWA->pRP->rph.Unit, pCWA->pVolCB) == -1) )
  2032.          rc = STDON + STERR + ERROR_I24_DISK_CHANGE;
  2033.  
  2034.    return(rc);
  2035. }
  2036.  
  2037.  
  2038.  
  2039. /*------------------------------------------------------------------------
  2040. ;
  2041. ** BuildCWA - Build Common Work Area for IOCTL processing
  2042. ;
  2043. ;   Obtains a work area for interroutine communication from the
  2044. ;   device driver storage pool and initializes it.
  2045. ;
  2046. ;   USHORT BuildCWA (PRP_GENIOCTL pRP, NPVOLCB pVolCB, NPCWA *pCWA)
  2047. ;
  2048. ;   ENTRY:    pRP              - Request Packet
  2049. ;             pVolCB           - VolCB
  2050. ;             pCWA             - Returned pointer to CWA
  2051. ;
  2052. ;   RETURN:   USHORT           - Packet Status word
  2053. ;
  2054. ;
  2055. ------------------------------------------------------------------------*/
  2056. USHORT BuildCWA (pRP, pVolCB, pCWA)
  2057.  
  2058. PRP_GENIOCTL pRP;
  2059. NPVOLCB      pVolCB;
  2060. NPCWA        FAR *pCWA;
  2061.  
  2062. {
  2063.    AllocCWA_Wait (pCWA);
  2064.  
  2065.    if (pRP->Category == IOC_PD)         /* if cat 9, then unit 0x80 based */
  2066.       pRP->rph.Unit += 0x80;
  2067.  
  2068.    (*pCWA)->pRP = pRP;
  2069.    (*pCWA)->pVolCB = pVolCB;
  2070.    (*pCWA)->pParmPkt = pRP->ParmPacket;
  2071.    (*pCWA)->pDataPkt = pRP->DataPacket;
  2072.  
  2073.    return (NO_ERROR);
  2074. }
  2075.  
  2076.  
  2077.  
  2078. /*------------------------------------------------------------------------
  2079. ;
  2080. ;** ReleaseCWA - Release Common Work Area
  2081. ;
  2082. ;   Release the Common Work Area and unlock any locked buffers.
  2083. ;
  2084. ;   VOID ReleaseCWA (NPCWA pCWA)
  2085. ;
  2086. ;   ENTRY:    pCWA             - Common work area
  2087. ;
  2088. ;   RETURN:   VOID
  2089. ;
  2090. ;
  2091. ------------------------------------------------------------------------*/
  2092. VOID ReleaseCWA (pCWA)
  2093.  
  2094. NPCWA pCWA;
  2095.  
  2096. {
  2097.    if (pCWA != NULL)
  2098.    {
  2099.       if (pCWA->Flags & LOCKED_PARMPKT)
  2100.         DevHelp_VMUnLock((LIN)(plDataSeg+(ULONG) ((USHORT)&(pCWA->hLockParmPkt))));
  2101.  
  2102.       if (pCWA->Flags & LOCKED_DATAPKT)
  2103.         DevHelp_VMUnLock((LIN)(plDataSeg+(ULONG) ((USHORT)&(pCWA->hLockDataPkt))));
  2104.  
  2105.       if (pCWA->pIRP != 0)
  2106.          DevHelp_FreeReqPacket((PBYTE)pCWA->pIRP);        /* Free internal RP   */
  2107.  
  2108.       FreeCWA (pCWA);
  2109.    }
  2110. }
  2111.  
  2112. /*------------------------------------------------------------------------
  2113. ;
  2114. ;** IOCTL_IO - Perform IOCTL I/O
  2115. ;
  2116. ;   Calls f_DiskIO_Wait and blocks this thread until the operation
  2117. ;   is complete, i.e. the STDON bit is set in the request packet.
  2118. ;
  2119. ;   USHORT IOCTL_IO (PBYTE pRPH, NPVOLCB pVolCB)
  2120. ;
  2121. ;   ENTRY:    pRP              - Request Packet
  2122. ;             pVolCB           - Pointer to VolCB
  2123. ;
  2124. ;   RETURN:   USHORT           - Packet Status word
  2125. ;
  2126. ;   EFFECTS:
  2127. ;
  2128. ------------------------------------------------------------------------*/
  2129. USHORT NEAR IOCTL_IO (pRP, pVolCB)
  2130.  
  2131. PBYTE pRP;
  2132. NPVOLCB pVolCB;
  2133. {
  2134.    USHORT rc;
  2135.  
  2136.    /* Do access validation check */
  2137.  
  2138.    if ((rc = Chk_AccValidate( (PRP_RWV) pRP, pVolCB)) == 0 )
  2139.       rc = f_DiskIO_Wait(pRP, pVolCB);
  2140.    else
  2141.       ((PRP_RWV)pRP)->rph.Status = rc;
  2142.  
  2143.    return(rc);
  2144. }
  2145.  
  2146. /*------------------------------------------------------------------------
  2147. ;
  2148. ;** Chk_AccValidate - Check access validation for IOCTLs
  2149. ;
  2150. ;   Determines if access to the partition is allowed via IOCTL I/O/
  2151. ;
  2152. ;   USHORT Chk_AccValidate (PRP_RWV pRP, NPVOLCB pVolCB)
  2153. ;
  2154. ;   ENTRY:    pRP              - Request Packet
  2155. ;             pVolCB           - Pointer to VolCB
  2156. ;
  2157. ;   RETURN:   USHORT           - Packet Status word
  2158. ;
  2159. ;   EFFECTS:
  2160. ;
  2161. ------------------------------------------------------------------------*/
  2162. USHORT Chk_AccValidate (pRP, pVolCB)
  2163.  
  2164. PRP_RWV pRP;
  2165. NPVOLCB pVolCB;
  2166. {
  2167.    USHORT Destructive = NO;
  2168.    USHORT rc;
  2169.    NPVOLCB pVolCBx;
  2170.    ULONG PartitionSize;
  2171.  
  2172.    if (pFSD_AccValidate == 0)     /* Only validate if requested     */
  2173.       return(0);
  2174.  
  2175.    if (pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  2176.       return(0);                  /* Only validate for fixed disks  */
  2177.  
  2178.  
  2179.    switch (pRP->rph.Cmd)
  2180.    {
  2181.       case CMDINPUT:
  2182.          break;
  2183.  
  2184.       case CMDOUTPUT:
  2185.       case CMDOUTPUTV:
  2186.          Destructive = YES;
  2187.          break;
  2188.  
  2189.       case CMDInternal:
  2190.          if  ( ((PRP_INTERNAL)pRP)->Function != DISKOP_READ_VERIFY )
  2191.             return(0);
  2192.          break;
  2193.  
  2194.      default:
  2195.          return(0);
  2196.    };
  2197.  
  2198.    /* If request is to the boot sector or to an HPFS partition then */
  2199.    /* it must be validated.                                         */
  2200.  
  2201.    if (pRP->rba == 0 || pVolCB->PartitionType == PARTITION_IFS)
  2202.       goto Validate;
  2203.  
  2204.    if ( !(pRP->rph.Unit & 0x80) )
  2205.      return(0);
  2206.  
  2207.    for (pVolCBx = pVolCB_DriveC; pVolCBx != 0; pVolCBx = pVolCBx->pNextVolCB)
  2208.    {
  2209.       /* Quit when we get to physical VolCBs */
  2210.  
  2211.       if (pVolCBx->LogDriveNum & 0x80)
  2212.          return(0);
  2213.  
  2214.       /* See if volume is on the same physical unit */
  2215.       /* and rba falls within the partition.        */
  2216.  
  2217.       if (pVolCBx->PhysDriveNum == pVolCB->PhysDriveNum)
  2218.       {
  2219.           if (pVolCBx->MediaBPB.TotalSectors != 0)
  2220.              PartitionSize = pVolCBx->MediaBPB.TotalSectors;
  2221.           else
  2222.              PartitionSize = pVolCBx->MediaBPB.BigTotalSectors;
  2223.  
  2224.           if ( (pRP->rba >= pVolCBx->PartitionOffset)  &&
  2225.                (pRP->rba < (pVolCBx->PartitionOffset + PartitionSize)) )
  2226.           {
  2227.              if (pVolCBx->PartitionType == PARTITION_IFS)
  2228.                 goto Validate;
  2229.              else
  2230.                 return(0);
  2231.           }
  2232.       }
  2233.    }
  2234. Validate:
  2235.    rc = f_FSD_AccValidate(Destructive);
  2236.    if (rc)
  2237.       rc = ERROR_I24_WRITE_PROTECT | STERR;
  2238.  
  2239.    return(rc);
  2240.  
  2241. }
  2242.  
  2243. /*------------------------------------------------------------------------
  2244. ;
  2245. ;** RBA_to_CHS - Convert RBA to Cylinder/Head/Sector
  2246. ;
  2247. ;   Convert RBA to Cylinder/Head/Sector format using device
  2248. ;   information in the VolCB.
  2249. ;
  2250. ;   VOID RBA_to_CHS (NPVOLCB pVolCB, ULONG rba, PULONG *chs)
  2251. ;
  2252. ;   ENTRY:    pVolCB           - Volume Control Block
  2253. ;             rba              - rba to convert
  2254. ;             pCHS             - returned chs information
  2255. ;
  2256. ;
  2257. ;   RETURN:   VOID
  2258. ;
  2259. ;
  2260. ------------------------------------------------------------------------*/
  2261. VOID RBA_to_CHS (pVolCB, rba, pCHS)
  2262.  
  2263. NPVOLCB   pVolCB;
  2264. ULONG     rba;
  2265. CHS_ADDR  FAR *pCHS;
  2266.  
  2267. {
  2268.    ULONG Tracks;
  2269.  
  2270.    Tracks = rba / pVolCB->MediaBPB.SectorsPerTrack;
  2271.  
  2272.    pCHS->Sector = rba % pVolCB->MediaBPB.SectorsPerTrack;
  2273.  
  2274.    pCHS->Cylinder = Tracks / pVolCB->MediaBPB.NumHeads;
  2275.  
  2276.    pCHS->Head = Tracks % pVolCB->MediaBPB.NumHeads;
  2277.  
  2278. }
  2279.  
  2280.  
  2281. /*------------------------------------------------------------------------
  2282. ;
  2283. ;** LockUserPacket -  Verify/Lock parameter or data packet in IOCTL
  2284. ;                     request packet.
  2285. ;
  2286. ;   This routine will either:
  2287. ;
  2288. ;      1) Provide a verify only lock which will verify access to the
  2289. ;         parameter or data packets.  This is used for all packets
  2290. ;         which do not need to be physically locked or made contiguous.
  2291. ;
  2292. ;      2) Lock the data or parameter packet in place and make it
  2293. ;         contiguous.  This is required for packets which are used
  2294. ;         in DMA operations, or packets which contain a format track
  2295. ;         table which is passed to the diskette controller.
  2296. ;
  2297. ;   USHORT LockUserPacket (NPCWA pCWA, USHORT LockFlags, USHORT Length, )
  2298. ;
  2299. ;   ENTRY:    pCWA             - pointer to CWA
  2300. ;             LockFlags        - Lock Flags
  2301. ;                                 LOCK_PARMPKT = Lock Parameter Packet
  2302. ;                                 LOCK_DATAPKT = Lock Data Packet
  2303. ;                                 LOCK_WRITE = Lock for write access
  2304. ;                                 LOCK_VERIFYONLY
  2305. ;                                       0 = LOCK and VERIFY;
  2306. ;                                       1 = VERIFY ONLY;
  2307. ;             Length           - Length to Lock/verify
  2308. ;
  2309. ;   RETURN:   USHORT           - Packet status word
  2310. ;
  2311. ------------------------------------------------------------------------*/
  2312. USHORT LockUserPacket (pCWA, LockFlags, Length)
  2313.  
  2314. NPCWA   pCWA;
  2315. USHORT  LockFlags;
  2316. ULONG   Length;
  2317.  
  2318. {
  2319.    USHORT rc;
  2320.    ULONG plPkt;                /* Linear address of Parm or Data Packet */
  2321.    ULONG plLockHandle;
  2322.    ULONG plPhysAddr;
  2323.    ULONG PageListCount;
  2324.    ULONG VMLockFlags;
  2325.  
  2326.    if (LockFlags & LOCK_PARMPKT)    /* Parm Packet */
  2327.    {
  2328.       rc = DevHelp_VirtToLin(SELECTOROF(pCWA->pParmPkt),
  2329.                             (ULONG) OFFSETOF(pCWA->pParmPkt),
  2330.                             (PVOID) &plPkt);
  2331.  
  2332.       plLockHandle = plDataSeg + (ULONG) ((USHORT) &(pCWA->hLockParmPkt));
  2333.       plPhysAddr =   plDataSeg + (ULONG) ((USHORT) &(pCWA->ppParmPkt));
  2334.    }
  2335.    else                 /* Data Packet */
  2336.    {
  2337.       rc = DevHelp_VirtToLin(SELECTOROF(pCWA->pDataPkt),
  2338.                             (ULONG) OFFSETOF(pCWA->pDataPkt),
  2339.                             (PVOID) &plPkt);
  2340.  
  2341.       plLockHandle = plDataSeg + (ULONG) ((USHORT) &(pCWA->hLockDataPkt));
  2342.       plPhysAddr   = plDataSeg + (ULONG) ((USHORT) &(pCWA->ppDataPkt));
  2343.    }
  2344.  
  2345.    /* Issue the DevHelp to verify access to the packet */
  2346.  
  2347.    if (LockFlags & LOCK_VERIFYONLY)
  2348.       VMLockFlags = VMDHL_VERIFY;
  2349.    else
  2350.       VMLockFlags = VMDHL_16M + VMDHL_CONTIGUOUS;
  2351.  
  2352.    if (LockFlags & LOCK_WRITE)
  2353.       VMLockFlags |= VMDHL_WRITE;
  2354.  
  2355.    if (DevHelp_VMLock(VMLockFlags, plPkt, Length, plPhysAddr,
  2356.                   plLockHandle, (PULONG) &PageListCount) != 0)
  2357.  
  2358.       return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  2359.  
  2360.    if (LockFlags & LOCK_PARMPKT)
  2361.       pCWA->Flags |= LOCKED_PARMPKT;
  2362.    else
  2363.       pCWA->Flags |= LOCKED_DATAPKT;
  2364.  
  2365.    return(STDON);
  2366. }
  2367.  
  2368. /*------------------------------------------------------------------------
  2369. ;
  2370. ;** AllocCWA_Wait - Allocate a CWA for IOCTL processing
  2371. ;
  2372. ;   Allocates a Common Work Area (CWA) from the Control Block pool
  2373. ;   for IOCTL processing.  Since IOCTL requests can block, this
  2374. ;   routine will block until a CWA is available for allocation.
  2375. ;
  2376. ;   VOID   AllocCWA_Wait  (NPCWA *pCWA)
  2377. ;
  2378. ;   ENTRY:    pCWA              - returned pointer to CWA
  2379. ;
  2380. ;   RETURN:
  2381. ;
  2382. ;   EFFECTS:
  2383. ;
  2384. ------------------------------------------------------------------------*/
  2385. VOID  AllocCWA_Wait(pCWA)
  2386.  
  2387. NPCWA FAR *pCWA;
  2388.  
  2389. {
  2390.    USHORT Allocated = FALSE;
  2391.    NPCWA  npCWA;
  2392.  
  2393.    DISABLE;
  2394.  
  2395.    do
  2396.    {
  2397.       if (CB_FreeList != 0)             /* Allocate from free list */
  2398.       {
  2399.          npCWA = (NPCWA) CB_FreeList;
  2400.          (NPIORBH) CB_FreeList = ((NPIORBH) CB_FreeList)->pNxtIORB;
  2401.          Allocated = TRUE;
  2402.       }
  2403.       else                              /* else wait till control block free */
  2404.       {
  2405.          ENABLE;
  2406.          PoolSem = 1;                   /* Indicate at least 1 thread blocked */
  2407.          DevHelp_ProcBlock((ULONG) ppDataSeg, (ULONG)-1, 0);
  2408.       }
  2409.    } while (Allocated == FALSE);
  2410.  
  2411.    ENABLE;
  2412.  
  2413.    /* Zero fill the CWA */
  2414.  
  2415.    f_ZeroCB((PBYTE)npCWA, sizeof(CWA));
  2416.  
  2417.    *pCWA = npCWA;
  2418.  
  2419. }
  2420.  
  2421. /*------------------------------------------------------------------------
  2422. ;
  2423. ;** FreeCWA - Free a CWA
  2424. ;
  2425. ;   Return a CWA back to the control block pool.
  2426. ;
  2427. ;   VOID   FreeCWA  (NPCWA pCWA)
  2428. ;
  2429. ;   ENTRY:    pCWA              -  pointer to CWA
  2430. ;
  2431. ;   RETURN:
  2432. ;
  2433. ;   EFFECTS:
  2434. ;
  2435. ------------------------------------------------------------------------*/
  2436. VOID FreeCWA (pCWA)
  2437.  
  2438. NPCWA pCWA;
  2439.  
  2440. {
  2441.    USHORT AwakeCount;
  2442.  
  2443.    DISABLE;
  2444.  
  2445.    ((NPIORBH) pCWA)->pNxtIORB = (NPIORBH) CB_FreeList;
  2446.    CB_FreeList = (NPBYTE) pCWA;
  2447.  
  2448.    ENABLE;
  2449.  
  2450.    /* If any threads waiting for a CWA, then wake them up */
  2451.  
  2452.    if (PoolSem != 0)
  2453.    {
  2454.       PoolSem = 0;
  2455.       DevHelp_ProcRun((ULONG)ppDataSeg, &AwakeCount);
  2456.    }
  2457. }
  2458.  
  2459. /*------------------------------------------------------------------------
  2460. ;
  2461. ;** SectorSizeToSectorIndex - Convert Sector Size to Index
  2462. ;
  2463. ;   Converts a sector size from bytes to an index that can be used
  2464. ;   by the NEC disk controller.
  2465. ;
  2466. ;   (0=>128, 1=>256, 2=>512, 3=>1024)
  2467. ;
  2468. ;   UCHAR  NEAR SectorSizeToSectorIndex (USHORT BytesPerSector)
  2469. ;
  2470. ;   ENTRY:    BytesPerSector   - Number of bytes in the sector
  2471. ;
  2472. ;   RETURN:   UCHAR            - Sector size index
  2473. ;
  2474. ;   EFFECTS:
  2475. ;
  2476. ;   NOTES:
  2477. ------------------------------------------------------------------------*/
  2478. UCHAR NEAR SectorSizeToSectorIndex (BytesPerSector)
  2479.  
  2480. USHORT BytesPerSector;
  2481. {
  2482.    UCHAR SectorIndex;
  2483.  
  2484.    SectorIndex = 3;
  2485.    if (BytesPerSector <= 512)
  2486.       SectorIndex = BytesPerSector / 256;
  2487.  
  2488.    return(SectorIndex);
  2489. }
  2490.  
  2491.  
  2492. /*------------------------------------------------------------------------
  2493. ;
  2494. ;** SectorIndexToSectorSize - Convert Sector Index to Sector Size
  2495. ;
  2496. ;   Converts a sector index to a size in bytes.
  2497. ;
  2498. ;   (0=>128, 1=>256, 2=>512, 3=>1024)
  2499. ;
  2500. ;   USHORT  NEAR SectorIndexToSectorSize (UCHAR SectorIndex)
  2501. ;
  2502. ;   ENTRY:    SectorIndex      - Sector Size Index
  2503. ;
  2504. ;   RETURN:   USHORT           - Bytes per Sector
  2505. ;
  2506. ;   EFFECTS:
  2507. ;
  2508. ;   NOTES:
  2509. ------------------------------------------------------------------------*/
  2510. USHORT NEAR SectorIndexToSectorSize (SectorIndex)
  2511.  
  2512. UCHAR SectorIndex;
  2513. {
  2514.    USHORT BytesPerSector;
  2515.  
  2516.    BytesPerSector = 128;
  2517.    return (BytesPerSector << SectorIndex);
  2518.  
  2519. }
  2520.