home *** CD-ROM | disk | FTP | other *** search
- /*DDK*************************************************************************/
- /* */
- /* COPYRIGHT Copyright (C) 1995 IBM Corporation */
- /* */
- /* The following IBM OS/2 WARP source code is provided to you solely for */
- /* the purpose of assisting you in your development of OS/2 WARP device */
- /* drivers. You may use this code in accordance with the IBM License */
- /* Agreement provided in the IBM Device Driver Source Kit for OS/2. This */
- /* Copyright statement may not be removed. */
- /* */
- /*****************************************************************************/
- /*static char *SCCSID = "%w% %e%";*/
- /**************************************************************************
- *
- * SOURCE FILE NAME = FL2IO.C
- *
- * DESCRIPTIVE NAME = IBM2FLPY.ADD - Adapter Driver for ABIOS Diskette
- *
- *
- *
- * VERSION = V2.0
- *
- * DATE
- *
- * DESCRIPTION : Routines to implement read, write and verify.
- *
- *
- *
- */
-
- #define INCL_NOBASEAPI
- #define INCL_NOPMAPI
- #include <os2.h>
- #include <dhcalls.h>
- #include <strat2.h> /* needed to keep reqpkt.h happy */
- #include <reqpkt.h>
- #include <scb.h> /* needed to keey abios.h happy */
- #include <abios.h>
- #include <iorb.h>
- #include <addcalls.h>
- #include "fl2def.h"
- #include "fl2proto.h"
- #include "fl2data.h"
-
-
-
- /*****************************************************************************/
- /* */
- /* Routine : IO */
- /* */
- /* Description : This routine checks to see a non-standard sector */
- /* size is being read. If so, this routine establishes */
- /* the requested sector size. */
- /* */
- /* IOPhase1 is called to continue processing the request. */
- /* */
- /*****************************************************************************/
-
- VOID NEAR IO()
- {
- NPABRB_DSKT_SETDEVPARMS pRB = (NPABRB_DSKT_SETDEVPARMS) RequestBlock;
- USHORT SectorSizeCode;
-
- /*---------------------------------------------------*/ /*@V82589*/
- /* Changes for Defect 82589 */ /*@V82589*/
- /* */ /*@V82589*/
- /* 1.) Issue Set Device Parms if request sector */ /*@V82589*/
- /* size differs from current device sector */ /*@V82589*/
- /* size. */ /*@V82589*/
- /*---------------------------------------------------*/ /*@V82589*/
-
- SectorSizeCode = BlkSizeToN(((PIORB_EXECUTEIO)pHeadIORB)->BlockSize);
-
- if ( SectorSizeCode == -1 )
- {
- pHeadIORB->Status |= IORB_ERROR;
- pHeadIORB->ErrorCode = IOERR_MEDIA_NOT_SUPPORTED;
- IORBDone();
- return;
- }
-
-
- if ( Drive[pHeadIORB->UnitHandle].SectorSizeCode != SectorSizeCode )
- {
- Drive[pHeadIORB->UnitHandle].SectorSizeCode = SectorSizeCode;
-
- pRB->abrbh.Function = ABFC_SET_DEVICE_PARMS;
- pRB->abrbh.Unit = pHeadIORB->UnitHandle;
- pRB->abrbh.RC = ABRC_START;
- pRB->BlockSize = SectorSizeCode;
- pRB->ReadGap = Drive[pHeadIORB->UnitHandle].ReadGap;
- pRB->DataLen = Drive[pHeadIORB->UnitHandle].DataLen;
-
- CompletionRoutine = IOPhase1;
- Retry = 0;
- Stage = ABIOS_EP_START;
- NextStage();
- }
- else
- {
- pRB->abrbh.RC = ABRC_COMPLETEOK;
- IOPhase1();
- }
-
- }
-
- /*****************************************************************************/
- /* */
- /* Routine : IOPhase1 */
- /* */
- /* Description : This routine insures that the media has not been */
- /* changed since the last access and that the media */
- /* desity has been established. */
- /* */
- /* DetermineMedia is called to establish the media type. */
- /* */
- /* RWV is called to continue processing the request. */
- /* */
- /*****************************************************************************/
-
-
- VOID FAR IOPhase1()
- {
- NPABRBH pRB = (NPABRBH) RequestBlock;
-
- /*---------------------------------------------------*/ /*@V82589*/
- /* Changes for Defect 82589 */ /*@V82589*/
- /* */ /*@V82589*/
- /* 1.) Call common routine which does media */ /*@V82589*/
- /* media determination. */ /*@V82589*/
- /* */ /*@V82589*/
- /* Note: DetermineMedia will 'remember' if */ /*@V82589*/
- /* unformatted media is detected and will */ /*@V82589*/
- /* immediately return an error indication */ /*@V82589*/
- /* until the media is changed. */ /*@V82589*/
- /* */ /*@V82589*/
- /* This helps speed-up formats on unformatted */ /*@V82589*/
- /* media since the ifs mechanism insists on */ /*@V82589*/
- /* reading the media several times before */ /*@V82589*/
- /* formatting begins. */ /*@V82589*/
- /* */ /*@V82589*/
- /*---------------------------------------------------*/ /*@V82589*/
-
- if ( pRB->RC == ABRC_COMPLETEOK )
- {
- DetermineMedia( RWV );
- }
- else
- {
- pHeadIORB->Status |= IORB_ERROR;
- pHeadIORB->ErrorCode = TranslateErrorCode( pRB->RC );
- IORBDone();
- return;
- }
- }
-
-
- /*****************************************************************************/
- /* */
- /* Routine : RWV */
- /* */
- /* Description : This routine does the initial setup of the ABIOS */
- /* request block and the XferData structure for the */
- /* read, write or verify. */
- /* */
- /*****************************************************************************/
-
- VOID FAR RWV()
- {
- PIORB_EXECUTEIO pIORB = (PIORB_EXECUTEIO)pHeadIORB;
- NPABRB_DSKT_RWV pRB = (NPABRB_DSKT_RWV)RequestBlock;
- union
- {
- CHS_ADDR CHS;
- ULONG RBA;
- } Addr;
-
- if ( pHeadIORB->ErrorCode )
- {
- pHeadIORB->Status |= IORB_ERROR;
-
- StartTimer( pHeadIORB->UnitHandle,
- Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );
-
- IORBDone();
- return;
- }
-
- /* Calculate initial CHS */
- if ( pHeadIORB->RequestControl & IORB_CHS_ADDRESSING )
- Addr.RBA = pIORB->RBA;
- else
- {
- if ( f_ADD_ConvRBAtoCHS( pIORB->RBA,
- &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]), (PCHS_ADDR)&Addr ) )
- {
- pHeadIORB->Status |= IORB_ERROR;
- pHeadIORB->ErrorCode = IOERR_RBA_ADDRESSING_ERROR;
- IORBDone();
- return;
- }
- }
-
- pRB->Cylinder = Addr.CHS.Cylinder;
- pRB->Head = Addr.CHS.Head;
- pRB->Sector = Addr.CHS.Sector;
-
- pRB->abrbh.Unit = pHeadIORB->UnitHandle;
- pRB->ppIObuffer = ppDMABuffer;
-
- XferData.cSGList = pIORB->cSGList;
- XferData.pSGList = pIORB->pSGList;
- XferData.pBuffer = pDMABuffer;
- XferData.iSGList = 0;
- XferData.SGOffset = 0;
-
- pIORB->BlocksXferred = 0;
-
- NextRWV();
- }
-
-
- /*****************************************************************************/
- /* */
- /* Routine : NextRWV */
- /* */
- /* Description : This routine is called repeatively during a large */
- /* IORB read, write or verify request to break the */
- /* request up into smaller chunks. */
- /* */
- /* An IORB request may need to be broken up into several */
- /* ABIOS requests, because ABIOS can read at most one */
- /* cylinder at a time. A single ABIOS request can not */
- /* cross a cylinder boundry. If the media geometry is */
- /* logical, then an ABIOS request can not cross a head */
- /* boundry. Also, if the DMA buffer is small, then we */
- /* may have to break the request up into buffer size */
- /* chunks. */
- /* */
- /* If the request is a write request, then this routine */
- /* transfers the write data from the scatter/gather list */
- /* to the DMA buffer. */
- /* */
- /* Input : pRB->Cylinder \ */
- /* pRB->Head > location of next sector to RWV */
- /* pRB->Sector / */
- /* */
- /* pIORB->BlockCount > difference is sectors left to RWV */
- /* pIORB->BlocksXferred / */
- /* */
- /*****************************************************************************/
-
- VOID NEAR NextRWV()
- {
- PIORB_EXECUTEIO pIORB = (PIORB_EXECUTEIO)pHeadIORB;
- NPABRB_DSKT_RWV pRB = (NPABRB_DSKT_RWV)RequestBlock;
- USHORT SectorsLeft,SectorsPerBuffer;
- NPGEOMETRY pGeometry;
-
- pGeometry = &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]);
-
- if ( pHeadIORB->RequestControl & IORB_CHS_ADDRESSING )
- {
- SectorCnt = pIORB->BlockCount;
- }
- else
- {
- if ( Drive[pHeadIORB->UnitHandle].Flags.LogicalMedia )
- /* SectorCnt = max possible sectors so head boundry is not crossed */
- SectorCnt = pGeometry->SectorsPerTrack + 1 - pRB->Sector;
- else
- /* SectorCnt = max possible sectors so cylinder boundry is not crossed */
- SectorCnt = ((pGeometry->NumHeads - pRB->Head) * pGeometry->SectorsPerTrack) + 1 - pRB->Sector;
- }
-
- /* Don't do more sectors than can fit into the DMA buffer */
- SectorsPerBuffer = BuffSize / pIORB->BlockSize;
- if ( SectorCnt > SectorsPerBuffer ) SectorCnt = SectorsPerBuffer;
-
- /* Don't do more sectors than requested */
- SectorsLeft = pIORB->BlockCount - pIORB->BlocksXferred;
- if ( SectorCnt > SectorsLeft ) SectorCnt = SectorsLeft;
-
- switch( pHeadIORB->CommandModifier )
- {
- case IOCM_WRITE:
- case IOCM_WRITE_VERIFY:
- {
- /* Transfer data from the S/G List to the DMA buffer */
- XferData.Mode = SGLIST_TO_BUFFER;
- XferData.numTotalBytes = ((ULONG)SectorCnt) * pIORB->BlockSize;
- if ( f_ADD_XferBuffData( &XferData ) )
- {
- pHeadIORB->Status |= IORB_ERROR;
- pHeadIORB->ErrorCode = IOERR_CMD_SGLIST_BAD;
- StartTimer( pHeadIORB->UnitHandle,
- Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );
- IORBDone();
- return;
- }
-
- pRB->abrbh.Function = ABFC_DSKT_WRITE;
- }
- break;
-
- case IOCM_READ:
- pRB->abrbh.Function = ABFC_DSKT_READ;
- break;
-
- case IOCM_READ_VERIFY:
- pRB->abrbh.Function = ABFC_DSKT_VERIFY;
- break;
- }
-
- NextRWVStep();
- }
-
-
- /*****************************************************************************/
- /* */
- /* Routine : NextRWVStep */
- /* */
- /* Description : This routine does the final setup before calling */
- /* NextStage to do the read, write or verify. If the */
- /* operation is a write/verify then this routine will */
- /* be called a second time to do the verify (or read). */
- /* */
- /*****************************************************************************/
-
- VOID NEAR NextRWVStep()
- {
- NPABRB_DSKT_RWV pRB = (NPABRB_DSKT_RWV)RequestBlock;
-
- pRB->cSectors = SectorCnt;
- pRB->abrbh.RC = ABRC_START;
- pRB->Reserved_1 = 0; /* +10H reserved field */
- pRB->Reserved_2 = 0L; /* +16H and +18H reserved fields */
- pRB->Reserved_3 = 0; /* +1EH reserved field */
-
- CompletionRoutine = RWVComplete;
- Drive[pRB->abrbh.Unit].Flags.MotorOn = TRUE;
- Retry = 0;
- Stage = ABIOS_EP_START;
- NextStage();
- }
-
-
- /*****************************************************************************/
- /* */
- /* Routine : RWVComplete */
- /* */
- /* Description : This routine is called when the ABIOS read, write or */
- /* verify operation completes. */
- /* */
- /* If the operation was a read then data is tranferred */
- /* from the DMA buffer to the scatter/gather list. */
- /* */
- /* If the operation is a write/verify and the write step */
- /* has just completed successfully, then this routine */
- /* sets up the ABIOS request block for the verify step. */
- /* If read back is required, then the verify is */
- /* actually a read back. When the read back completes, */
- /* then the last byte of each sector read back is */
- /* compared to what should have been written. If it */
- /* does not match then the write is done again. */
- /* */
- /* This routine updates the BlocksXferred field in the */
- /* IORB. If the IORB request is not finished, then */
- /* the CHS for the next block of sectors is calculated */
- /* and NextRWV is called to read, write or verify them. */
- /* */
- /*****************************************************************************/
-
- VOID FAR RWVComplete()
- {
- PIORB_EXECUTEIO pIORB = (PIORB_EXECUTEIO)pHeadIORB;
- NPABRB_DSKT_RWV pRB = (NPABRB_DSKT_RWV)RequestBlock;
- NPGEOMETRY pGeometry;
- USHORT cTracks,x;
- PBYTE pDataWritten,pDataReadBack;
-
- pGeometry = &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]);
-
- if ( pHeadIORB->CommandModifier == IOCM_READ )
- {
- /* Transfer data from the DMA buffer to the S/G List */
- XferData.Mode = BUFFER_TO_SGLIST;
- XferData.numTotalBytes = ((ULONG)pRB->cSectors) * pIORB->BlockSize;
- if ( f_ADD_XferBuffData( &XferData ) )
- {
- pHeadIORB->Status |= IORB_ERROR;
- pHeadIORB->ErrorCode = IOERR_CMD_SGLIST_BAD;
- StartTimer( pHeadIORB->UnitHandle,
- Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );
- IORBDone();
- return;
- }
- }
- else if ( pHeadIORB->CommandModifier == IOCM_WRITE_VERIFY )
- {
- if ( pRB->abrbh.RC == ABRC_COMPLETEOK )
- {
- if ( pRB->abrbh.Function == ABFC_DSKT_WRITE )
- {
- if ( Drive[pHeadIORB->UnitHandle].Flags.ReadBackReq )
- {
- pRB->ppIObuffer = ppReadBackBuffer;
- pRB->abrbh.Function = ABFC_DSKT_READ;
- }
- else /* Read back not required; just do a verify */
- {
- pRB->abrbh.Function = ABFC_DSKT_VERIFY;
- }
- NextRWVStep();
- return;
- }
- else if ( pRB->abrbh.Function == ABFC_DSKT_READ )
- {
- pRB->ppIObuffer = ppDMABuffer;
- pRB->abrbh.Function = ABFC_DSKT_WRITE;
-
- /* Check the last byte of each sector */
- pDataWritten = pDMABuffer + pIORB->BlockSize - 1;
- pDataReadBack = pReadBackBuffer + pIORB->BlockSize - 1;
- for ( x=0; x<pRB->cSectors; x++ )
- {
- if ( *pDataReadBack != *pDataWritten )
- {
- NextRWVStep(); /* Write it again */
- return;
- }
- pDataWritten += pIORB->BlockSize;
- pDataReadBack += pIORB->BlockSize;
- }
- }
- else pRB->abrbh.Function = ABFC_DSKT_WRITE; /* Verify done */
- }
- }
-
- pIORB->BlocksXferred += pRB->cSectors;
-
- if ( pRB->abrbh.RC == ABRC_COMPLETEOK )
- {
- if ( pIORB->BlocksXferred < pIORB->BlockCount ) /* if not yet done */
- {
- if ( pHeadIORB->RequestControl & IORB_CHS_ADDRESSING )
- {
- pRB->Sector += SectorCnt;
- }
- else
- {
- /* Calculate new CHS */
- cTracks = (pRB->Sector-1+pRB->cSectors)/pGeometry->SectorsPerTrack;
- pRB->Sector = ((pRB->Sector-1+pRB->cSectors)%pGeometry->SectorsPerTrack)+1;
- pRB->Cylinder += (pRB->Head + cTracks) / pGeometry->NumHeads;
- pRB->Head = (pRB->Head + cTracks) % pGeometry->NumHeads;
- }
- NextRWV(); /* Do next RWV */
- return;
- }
- }
- else
- {
- pHeadIORB->Status |= IORB_ERROR;
- pHeadIORB->ErrorCode = TranslateErrorCode( pRB->abrbh.RC );
- }
-
- if ( pHeadIORB->ErrorCode == IOERR_MEDIA_CHANGED )
- Drive[pHeadIORB->UnitHandle].Flags.UnknownMedia = TRUE;
-
- StartTimer( pHeadIORB->UnitHandle,
- Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );
-
- IORBDone();
- }
-
-
-
- /*****************************************************************************/
- /* */
- /* Routine : BlkSizeToN */
- /* */
- /* Description : This routine converts a blocksize (bytes) to Sector */
- /* Size Code (N). */
- /* */
- /*****************************************************************************/
-
- USHORT FAR BlkSizeToN( USHORT BlkSize )
- {
- USHORT BlkTmp;
- USHORT n;
-
- /*-----------------------------------------------------*/
- /* Scan bits 7->MAX_N for 1. Report bit position (-7), */
- /* i.e. 0x0080 = (0), 0x0100 = (1), etc */
- /*-----------------------------------------------------*/
- BlkTmp = BlkSize >> 7;
- for ( n=0; n < 7; n++, BlkTmp >>= 1 )
- {
- if (BlkTmp & 1) break;
- }
-
- /*---------------------------------------------------*/
- /* BlkSize must be a power of 2. If any bit other */
- /* than the expected 2^(N+7) value is on, then the */
- /* original blocksize was invalid */
- /*---------------------------------------------------*/
-
- if ( BlkSize & ~(0x0001 << (n+7)) ) n = -1;
-
- return ( n );
- }
-
-