home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / IBM / IBM2FLPY / FL2IO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  22.2 KB  |  514 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 = "%w% %e%";*/
  13. /**************************************************************************
  14.  *
  15.  * SOURCE FILE NAME = FL2IO.C
  16.  *
  17.  * DESCRIPTIVE NAME = IBM2FLPY.ADD - Adapter Driver for ABIOS Diskette
  18.  *
  19.  *
  20.  *
  21.  * VERSION = V2.0
  22.  *
  23.  * DATE
  24.  *
  25.  * DESCRIPTION : Routines to implement read, write and verify.
  26.  *
  27.  *
  28.  *
  29. */
  30.  
  31. #define INCL_NOBASEAPI
  32. #define INCL_NOPMAPI
  33. #include <os2.h>
  34. #include <dhcalls.h>
  35. #include <strat2.h>     /* needed to keep reqpkt.h happy */
  36. #include <reqpkt.h>
  37. #include <scb.h>        /* needed to keey abios.h happy */
  38. #include <abios.h>
  39. #include <iorb.h>
  40. #include <addcalls.h>
  41. #include "fl2def.h"
  42. #include "fl2proto.h"
  43. #include "fl2data.h"
  44.  
  45.  
  46.  
  47. /*****************************************************************************/
  48. /*                                                                           */
  49. /*   Routine     : IO                                                        */
  50. /*                                                                           */
  51. /*   Description : This routine checks to see a non-standard sector          */
  52. /*                 size is being read. If so, this routine establishes       */
  53. /*                 the requested sector size.                                */
  54. /*                                                                           */
  55. /*                 IOPhase1 is called to continue processing the request.    */
  56. /*                                                                           */
  57. /*****************************************************************************/
  58.  
  59. VOID NEAR IO()
  60. {
  61.    NPABRB_DSKT_SETDEVPARMS pRB = (NPABRB_DSKT_SETDEVPARMS) RequestBlock;
  62.    USHORT                  SectorSizeCode;
  63.  
  64.    /*---------------------------------------------------*/           /*@V82589*/
  65.    /* Changes for Defect 82589                          */           /*@V82589*/
  66.    /*                                                   */           /*@V82589*/
  67.    /* 1.) Issue Set Device Parms if request sector      */           /*@V82589*/
  68.    /*     size differs from current device sector       */           /*@V82589*/
  69.    /*     size.                                         */           /*@V82589*/
  70.    /*---------------------------------------------------*/           /*@V82589*/
  71.  
  72.    SectorSizeCode = BlkSizeToN(((PIORB_EXECUTEIO)pHeadIORB)->BlockSize);
  73.  
  74.    if ( SectorSizeCode == -1 )
  75.       {
  76.          pHeadIORB->Status   |= IORB_ERROR;
  77.          pHeadIORB->ErrorCode = IOERR_MEDIA_NOT_SUPPORTED;
  78.          IORBDone();
  79.          return;
  80.       }
  81.  
  82.  
  83.    if ( Drive[pHeadIORB->UnitHandle].SectorSizeCode != SectorSizeCode )
  84.       {
  85.          Drive[pHeadIORB->UnitHandle].SectorSizeCode = SectorSizeCode;
  86.  
  87.          pRB->abrbh.Function = ABFC_SET_DEVICE_PARMS;
  88.          pRB->abrbh.Unit     = pHeadIORB->UnitHandle;
  89.          pRB->abrbh.RC       = ABRC_START;
  90.          pRB->BlockSize      = SectorSizeCode;
  91.          pRB->ReadGap        = Drive[pHeadIORB->UnitHandle].ReadGap;
  92.          pRB->DataLen        = Drive[pHeadIORB->UnitHandle].DataLen;
  93.  
  94.          CompletionRoutine   = IOPhase1;
  95.          Retry = 0;
  96.          Stage = ABIOS_EP_START;
  97.          NextStage();
  98.       }
  99.    else
  100.       {
  101.          pRB->abrbh.RC = ABRC_COMPLETEOK;
  102.          IOPhase1();
  103.       }
  104.  
  105. }
  106.  
  107. /*****************************************************************************/
  108. /*                                                                           */
  109. /*   Routine     : IOPhase1                                                  */
  110. /*                                                                           */
  111. /*   Description : This routine insures that the media has not been          */
  112. /*                 changed since the last access and that the media          */
  113. /*                 desity has been established.                              */
  114. /*                                                                           */
  115. /*                 DetermineMedia is called to establish the media type.     */
  116. /*                                                                           */
  117. /*                 RWV is called to continue processing the request.         */
  118. /*                                                                           */
  119. /*****************************************************************************/
  120.  
  121.  
  122. VOID FAR IOPhase1()
  123. {
  124.    NPABRBH pRB = (NPABRBH) RequestBlock;
  125.  
  126.    /*---------------------------------------------------*/           /*@V82589*/
  127.    /* Changes for Defect 82589                          */           /*@V82589*/
  128.    /*                                                   */           /*@V82589*/
  129.    /* 1.) Call common routine which does media          */           /*@V82589*/
  130.    /*     media determination.                          */           /*@V82589*/
  131.    /*                                                   */           /*@V82589*/
  132.    /* Note: DetermineMedia will 'remember' if           */           /*@V82589*/
  133.    /*       unformatted media is detected and will      */           /*@V82589*/
  134.    /*       immediately return an error indication      */           /*@V82589*/
  135.    /*       until the media is changed.                 */           /*@V82589*/
  136.    /*                                                   */           /*@V82589*/
  137.    /*       This helps speed-up formats on unformatted  */           /*@V82589*/
  138.    /*       media since the ifs mechanism insists on    */           /*@V82589*/
  139.    /*       reading the media several times before      */           /*@V82589*/
  140.    /*       formatting begins.                          */           /*@V82589*/
  141.    /*                                                   */           /*@V82589*/
  142.    /*---------------------------------------------------*/           /*@V82589*/
  143.  
  144.    if ( pRB->RC == ABRC_COMPLETEOK )
  145.       {
  146.          DetermineMedia( RWV );
  147.       }
  148.    else
  149.       {
  150.          pHeadIORB->Status   |= IORB_ERROR;
  151.          pHeadIORB->ErrorCode = TranslateErrorCode( pRB->RC );
  152.          IORBDone();
  153.          return;
  154.       }
  155. }
  156.  
  157.  
  158. /*****************************************************************************/
  159. /*                                                                           */
  160. /*   Routine     : RWV                                                       */
  161. /*                                                                           */
  162. /*   Description : This routine does the initial setup of the ABIOS          */
  163. /*                 request block and the XferData structure for the          */
  164. /*                 read, write or verify.                                    */
  165. /*                                                                           */
  166. /*****************************************************************************/
  167.  
  168. VOID FAR RWV()
  169. {
  170.    PIORB_EXECUTEIO pIORB = (PIORB_EXECUTEIO)pHeadIORB;
  171.    NPABRB_DSKT_RWV pRB   = (NPABRB_DSKT_RWV)RequestBlock;
  172.    union
  173.       {
  174.          CHS_ADDR CHS;
  175.          ULONG    RBA;
  176.       } Addr;
  177.  
  178.    if ( pHeadIORB->ErrorCode )
  179.       {
  180.          pHeadIORB->Status |= IORB_ERROR;
  181.  
  182.          StartTimer( pHeadIORB->UnitHandle,
  183.                      Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );
  184.  
  185.          IORBDone();
  186.          return;
  187.       }
  188.  
  189.    /* Calculate initial CHS */
  190.    if ( pHeadIORB->RequestControl & IORB_CHS_ADDRESSING )
  191.       Addr.RBA = pIORB->RBA;
  192.    else
  193.       {
  194.          if ( f_ADD_ConvRBAtoCHS( pIORB->RBA,
  195.               &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]), (PCHS_ADDR)&Addr ) )
  196.             {
  197.                pHeadIORB->Status   |= IORB_ERROR;
  198.                pHeadIORB->ErrorCode = IOERR_RBA_ADDRESSING_ERROR;
  199.                IORBDone();
  200.                return;
  201.             }
  202.       }
  203.  
  204.    pRB->Cylinder        = Addr.CHS.Cylinder;
  205.    pRB->Head            = Addr.CHS.Head;
  206.    pRB->Sector          = Addr.CHS.Sector;
  207.  
  208.    pRB->abrbh.Unit      = pHeadIORB->UnitHandle;
  209.    pRB->ppIObuffer      = ppDMABuffer;
  210.  
  211.    XferData.cSGList     = pIORB->cSGList;
  212.    XferData.pSGList     = pIORB->pSGList;
  213.    XferData.pBuffer     = pDMABuffer;
  214.    XferData.iSGList     = 0;
  215.    XferData.SGOffset    = 0;
  216.  
  217.    pIORB->BlocksXferred = 0;
  218.  
  219.    NextRWV();
  220. }
  221.  
  222.  
  223. /*****************************************************************************/
  224. /*                                                                           */
  225. /*   Routine     : NextRWV                                                   */
  226. /*                                                                           */
  227. /*   Description : This routine is called repeatively during a large         */
  228. /*                 IORB read, write or verify request to break the           */
  229. /*                 request up into smaller chunks.                           */
  230. /*                                                                           */
  231. /*                 An IORB request may need to be broken up into several     */
  232. /*                 ABIOS requests, because ABIOS can read at most one        */
  233. /*                 cylinder at a time.  A single ABIOS request can not       */
  234. /*                 cross a cylinder boundry.  If the media geometry is       */
  235. /*                 logical, then an ABIOS request can not cross a head       */
  236. /*                 boundry.  Also, if the DMA buffer is small, then we       */
  237. /*                 may have to break the request up into buffer size         */
  238. /*                 chunks.                                                   */
  239. /*                                                                           */
  240. /*                 If the request is a write request, then this routine      */
  241. /*                 transfers the write data from the scatter/gather list     */
  242. /*                 to the DMA buffer.                                        */
  243. /*                                                                           */
  244. /*   Input  : pRB->Cylinder  \                                               */
  245. /*            pRB->Head       > location of next sector to RWV               */
  246. /*            pRB->Sector    /                                               */
  247. /*                                                                           */
  248. /*            pIORB->BlockCount       > difference is sectors left to RWV    */
  249. /*            pIORB->BlocksXferred   /                                       */
  250. /*                                                                           */
  251. /*****************************************************************************/
  252.  
  253. VOID NEAR NextRWV()
  254. {
  255.    PIORB_EXECUTEIO pIORB = (PIORB_EXECUTEIO)pHeadIORB;
  256.    NPABRB_DSKT_RWV pRB   = (NPABRB_DSKT_RWV)RequestBlock;
  257.    USHORT SectorsLeft,SectorsPerBuffer;
  258.    NPGEOMETRY pGeometry;
  259.  
  260.    pGeometry = &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]);
  261.  
  262.    if ( pHeadIORB->RequestControl & IORB_CHS_ADDRESSING )
  263.       {
  264.          SectorCnt = pIORB->BlockCount;
  265.       }
  266.    else
  267.       {
  268.          if ( Drive[pHeadIORB->UnitHandle].Flags.LogicalMedia )
  269.             /* SectorCnt = max possible sectors so head boundry is not crossed */
  270.             SectorCnt = pGeometry->SectorsPerTrack + 1 - pRB->Sector;
  271.          else
  272.             /* SectorCnt = max possible sectors so cylinder boundry is not crossed */
  273.             SectorCnt = ((pGeometry->NumHeads - pRB->Head) * pGeometry->SectorsPerTrack) + 1 - pRB->Sector;
  274.       }
  275.  
  276.    /* Don't do more sectors than can fit into the DMA buffer */
  277.    SectorsPerBuffer = BuffSize / pIORB->BlockSize;
  278.    if ( SectorCnt > SectorsPerBuffer ) SectorCnt = SectorsPerBuffer;
  279.  
  280.    /* Don't do more sectors than requested */
  281.    SectorsLeft = pIORB->BlockCount - pIORB->BlocksXferred;
  282.    if ( SectorCnt > SectorsLeft ) SectorCnt = SectorsLeft;
  283.  
  284.    switch( pHeadIORB->CommandModifier )
  285.       {
  286.          case IOCM_WRITE:
  287.          case IOCM_WRITE_VERIFY:
  288.                {
  289.                   /* Transfer data from the S/G List to the DMA buffer */
  290.                   XferData.Mode = SGLIST_TO_BUFFER;
  291.                   XferData.numTotalBytes = ((ULONG)SectorCnt) * pIORB->BlockSize;
  292.                   if ( f_ADD_XferBuffData( &XferData ) )
  293.                      {
  294.                         pHeadIORB->Status   |= IORB_ERROR;
  295.                         pHeadIORB->ErrorCode = IOERR_CMD_SGLIST_BAD;
  296.                         StartTimer( pHeadIORB->UnitHandle,
  297.                            Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );
  298.                         IORBDone();
  299.                         return;
  300.                      }
  301.  
  302.                   pRB->abrbh.Function = ABFC_DSKT_WRITE;
  303.                }
  304.             break;
  305.  
  306.          case IOCM_READ:
  307.             pRB->abrbh.Function = ABFC_DSKT_READ;
  308.             break;
  309.  
  310.          case IOCM_READ_VERIFY:
  311.             pRB->abrbh.Function = ABFC_DSKT_VERIFY;
  312.             break;
  313.       }
  314.  
  315.    NextRWVStep();
  316. }
  317.  
  318.  
  319. /*****************************************************************************/
  320. /*                                                                           */
  321. /*   Routine     : NextRWVStep                                               */
  322. /*                                                                           */
  323. /*   Description : This routine does the final setup before calling          */
  324. /*                 NextStage to do the read, write or verify.  If the        */
  325. /*                 operation is a write/verify then this routine will        */
  326. /*                 be called a second time to do the verify (or read).       */
  327. /*                                                                           */
  328. /*****************************************************************************/
  329.  
  330. VOID NEAR NextRWVStep()
  331. {
  332.    NPABRB_DSKT_RWV pRB = (NPABRB_DSKT_RWV)RequestBlock;
  333.  
  334.    pRB->cSectors   = SectorCnt;
  335.    pRB->abrbh.RC   = ABRC_START;
  336.    pRB->Reserved_1 = 0;           /* +10H reserved field           */
  337.    pRB->Reserved_2 = 0L;          /* +16H and +18H reserved fields */
  338.    pRB->Reserved_3 = 0;           /* +1EH reserved field           */
  339.  
  340.    CompletionRoutine = RWVComplete;
  341.    Drive[pRB->abrbh.Unit].Flags.MotorOn = TRUE;
  342.    Retry = 0;
  343.    Stage = ABIOS_EP_START;
  344.    NextStage();
  345. }
  346.  
  347.  
  348. /*****************************************************************************/
  349. /*                                                                           */
  350. /*   Routine     : RWVComplete                                               */
  351. /*                                                                           */
  352. /*   Description : This routine is called when the ABIOS read, write or      */
  353. /*                 verify operation completes.                               */
  354. /*                                                                           */
  355. /*                 If the operation was a read then data is tranferred       */
  356. /*                 from the DMA buffer to the scatter/gather list.           */
  357. /*                                                                           */
  358. /*                 If the operation is a write/verify and the write step     */
  359. /*                 has just completed successfully, then this routine        */
  360. /*                 sets up the ABIOS request block for the verify step.      */
  361. /*                 If read back is required, then the verify is              */
  362. /*                 actually a read back.  When the read back completes,      */
  363. /*                 then the last byte of each sector read back is            */
  364. /*                 compared to what should have been written.  If it         */
  365. /*                 does not match then the write is done again.              */
  366. /*                                                                           */
  367. /*                 This routine updates the BlocksXferred field in the       */
  368. /*                 IORB.  If the IORB request is not finished, then          */
  369. /*                 the CHS for the next block of sectors is calculated       */
  370. /*                 and NextRWV is called to read, write or verify them.      */
  371. /*                                                                           */
  372. /*****************************************************************************/
  373.  
  374. VOID FAR RWVComplete()
  375. {
  376.    PIORB_EXECUTEIO pIORB = (PIORB_EXECUTEIO)pHeadIORB;
  377.    NPABRB_DSKT_RWV pRB   = (NPABRB_DSKT_RWV)RequestBlock;
  378.    NPGEOMETRY pGeometry;
  379.    USHORT cTracks,x;
  380.    PBYTE pDataWritten,pDataReadBack;
  381.  
  382.    pGeometry = &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]);
  383.  
  384.    if ( pHeadIORB->CommandModifier == IOCM_READ )
  385.       {
  386.          /* Transfer data from the DMA buffer to the S/G List */
  387.          XferData.Mode = BUFFER_TO_SGLIST;
  388.          XferData.numTotalBytes = ((ULONG)pRB->cSectors) * pIORB->BlockSize;
  389.          if ( f_ADD_XferBuffData( &XferData ) )
  390.             {
  391.                pHeadIORB->Status   |= IORB_ERROR;
  392.                pHeadIORB->ErrorCode = IOERR_CMD_SGLIST_BAD;
  393.                StartTimer( pHeadIORB->UnitHandle,
  394.                   Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );
  395.                IORBDone();
  396.                return;
  397.             }
  398.       }
  399.    else if ( pHeadIORB->CommandModifier == IOCM_WRITE_VERIFY )
  400.       {
  401.          if ( pRB->abrbh.RC == ABRC_COMPLETEOK )
  402.             {
  403.                if ( pRB->abrbh.Function == ABFC_DSKT_WRITE )
  404.                   {
  405.                      if ( Drive[pHeadIORB->UnitHandle].Flags.ReadBackReq )
  406.                         {
  407.                            pRB->ppIObuffer     = ppReadBackBuffer;
  408.                            pRB->abrbh.Function = ABFC_DSKT_READ;
  409.                         }
  410.                      else /* Read back not required; just do a verify */
  411.                         {
  412.                            pRB->abrbh.Function = ABFC_DSKT_VERIFY;
  413.                         }
  414.                      NextRWVStep();
  415.                      return;
  416.                   }
  417.                else if ( pRB->abrbh.Function == ABFC_DSKT_READ )
  418.                   {
  419.                      pRB->ppIObuffer     = ppDMABuffer;
  420.                      pRB->abrbh.Function = ABFC_DSKT_WRITE;
  421.  
  422.                      /* Check the last byte of each sector */
  423.                      pDataWritten   = pDMABuffer      + pIORB->BlockSize - 1;
  424.                      pDataReadBack  = pReadBackBuffer + pIORB->BlockSize - 1;
  425.                      for ( x=0; x<pRB->cSectors; x++ )
  426.                         {
  427.                            if ( *pDataReadBack != *pDataWritten )
  428.                               {
  429.                                  NextRWVStep();  /* Write it again */
  430.                                  return;
  431.                               }
  432.                            pDataWritten  += pIORB->BlockSize;
  433.                            pDataReadBack += pIORB->BlockSize;
  434.                         }
  435.                   }
  436.                else pRB->abrbh.Function = ABFC_DSKT_WRITE;  /* Verify done */
  437.             }
  438.       }
  439.  
  440.    pIORB->BlocksXferred += pRB->cSectors;
  441.  
  442.    if ( pRB->abrbh.RC == ABRC_COMPLETEOK )
  443.       {
  444.          if ( pIORB->BlocksXferred < pIORB->BlockCount ) /* if not yet done */
  445.             {
  446.                if ( pHeadIORB->RequestControl & IORB_CHS_ADDRESSING )
  447.                   {
  448.                      pRB->Sector += SectorCnt;
  449.                   }
  450.                else
  451.                   {
  452.                      /* Calculate new CHS */
  453.                      cTracks        =  (pRB->Sector-1+pRB->cSectors)/pGeometry->SectorsPerTrack;
  454.                      pRB->Sector    = ((pRB->Sector-1+pRB->cSectors)%pGeometry->SectorsPerTrack)+1;
  455.                      pRB->Cylinder +=  (pRB->Head + cTracks) / pGeometry->NumHeads;
  456.                      pRB->Head      =  (pRB->Head + cTracks) % pGeometry->NumHeads;
  457.                   }
  458.                NextRWV();  /* Do next RWV */
  459.                return;
  460.             }
  461.       }
  462.    else
  463.       {
  464.          pHeadIORB->Status   |= IORB_ERROR;
  465.          pHeadIORB->ErrorCode = TranslateErrorCode( pRB->abrbh.RC );
  466.       }
  467.  
  468.    if ( pHeadIORB->ErrorCode == IOERR_MEDIA_CHANGED )
  469.       Drive[pHeadIORB->UnitHandle].Flags.UnknownMedia = TRUE;
  470.  
  471.    StartTimer( pHeadIORB->UnitHandle,
  472.               Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );
  473.  
  474.    IORBDone();
  475. }
  476.  
  477.  
  478.  
  479. /*****************************************************************************/
  480. /*                                                                           */
  481. /*   Routine     : BlkSizeToN                                                */
  482. /*                                                                           */
  483. /*   Description : This routine converts a blocksize (bytes) to Sector       */
  484. /*                 Size Code (N).                                            */
  485. /*                                                                           */
  486. /*****************************************************************************/
  487.  
  488. USHORT FAR BlkSizeToN( USHORT BlkSize )
  489. {
  490.    USHORT     BlkTmp;
  491.    USHORT     n;
  492.  
  493.    /*-----------------------------------------------------*/
  494.    /* Scan bits 7->MAX_N for 1. Report bit position (-7), */
  495.    /* i.e. 0x0080 = (0), 0x0100 = (1), etc                */
  496.    /*-----------------------------------------------------*/
  497.    BlkTmp = BlkSize >> 7;
  498.    for ( n=0; n < 7; n++, BlkTmp >>= 1 )
  499.      {
  500.         if (BlkTmp & 1) break;
  501.      }
  502.  
  503.    /*---------------------------------------------------*/
  504.    /* BlkSize must be a power of 2. If any bit other    */
  505.    /* than the expected 2^(N+7) value is on, then the   */
  506.    /* original blocksize was invalid                    */
  507.    /*---------------------------------------------------*/
  508.  
  509.    if ( BlkSize & ~(0x0001 << (n+7))  ) n = -1;
  510.  
  511.    return ( n );
  512. }
  513.  
  514.