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. */
- /* */
- /*****************************************************************************/
- /**************************************************************************
- *
- * SOURCE FILE NAME = ATAPIISM.C
- *
- * DESCRIPTIVE NAME = ATAPI Inner State Machine
- *
- *
- *
- * VERSION = 1.0
- *
- * DATE
- *
- * DESCRIPTION :
- *
- * Purpose:
- *
- *
- *
- *
- *
- */
-
- #define INCL_NOBASEAPI
- #define INCL_NOPMAPI
- #include "os2.h"
- #include "dos.h"
- #include "dskinit.h"
-
- #include "iorb.h"
- #include "addcalls.h"
- #include "dhcalls.h"
-
- #define INCL_INITRP_ONLY
- #include "reqpkt.h"
-
- #include "scsi.h"
- #include "cdbscsi.h"
-
- #include "atapicon.h"
- #include "atapireg.h"
- #include "atapityp.h"
- #include "atapiext.h"
- #include "atapipro.h"
-
- /*
- ╔═════════════════════════════════════════════════════════════════════════════╗
- ║ ║
- ║ StartOSMRequest ║
- ║ ║
- ║ Outer State Machine Interface: This routine initializes the inner state ║
- ║ machine and sets up the outer state machine to go into a WAITSTATE until ║
- ║ the inner state machine finishes the requested operation. ║
- ║ ║
- ╚═════════════════════════════════════════════════════════════════════════════╝
- */
- VOID FAR StartOSMRequest ( NPACB npACB )
- {
- npACB->ISMState = ACBIS_START_STATE;
- npACB->ISMDoneReturn = StartOSM;
- if (npACB->suspended)
- {
- _asm INT 3
- }
- StartISM ( npACB );
-
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ StartISM ║
- ║ ║
- ║ Inner State Machine Router ║
- ║ ║
- ╚════════════════════════════════════╝
- */
-
- VOID NEAR StartISM( NPACB npACB )
- {
- VOID (FAR *ISMDoneReturn)( NPACB );
-
- DISABLE
-
- npACB->ISMUseCount++;
-
- if ( npACB->ISMUseCount == 1 )
- {
- do
- {
- ENABLE
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- do
- {
- switch ( npACB->ISMState )
- {
- case ACBIS_START_STATE:
- ISMStartState ( npACB );
- break;
-
- case ACBIS_INTERRUPT_STATE:
- InterruptState( npACB );
- break;
-
- case ACBIS_WRITE_ATAPI_PACKET_STATE:
- WriteATAPIPkt( npACB );
- break;
-
- case ACBIS_COMPLETE_STATE:
- npACB->ISMFlags |= ACBIF_WAITSTATE;
- npACB->ISMUseCount = 1;
- npACB->OSMState = ACBOS_ISM_COMPLETE;
- break;
-
- default :
- /* unknown state */
- npACB->ISMUseCount = 1;
- npACB->ISMFlags |= ACBIF_WAITSTATE;
- break;
- }
- }
- while ( !(npACB->ISMFlags & ACBIF_WAITSTATE) );
-
- DISABLE
- }
- while ( --npACB->ISMUseCount );
- }
- ENABLE
-
- if ( npACB->ISMState == ACBIS_COMPLETE_STATE )
- {
- DISABLE
- if (npACB->ISMDoneReturn)
- {
- ISMDoneReturn = npACB->ISMDoneReturn;
- npACB->ISMDoneReturn = 0;
- ENABLE
- (*ISMDoneReturn)( npACB );
- }
- else
- ENABLE
-
- } /* endif */
- } /* StartISM */
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ ISMStartState ║
- ║ ║
- ║ Initializes the Inner State ║
- ║ Machine ║
- ║ ║
- ╚════════════════════════════════════╝
- */
-
- VOID NEAR ISMStartState ( NPACB npACB )
- {
- USHORT Status;
-
- DISABLE
-
- if (!( npACB->OSMReqFlags & ACBR_RESET ) && /*V@106915*/
- ( !DRQ_AND_BSY_CLEAR_WAIT( npACB ) ) ) /*V@93531*/
- /* Max Poll wait time exceeded */
- {
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- npACB->OSMReqFlags |= ACBR_RESET; /* Set OSM for reset */
- ENABLE
- }
- else
- {
- ENABLE
- InitializeISM( npACB );
- /*
- ┌────────────────────────────────────────┐
- │ Do not write packet if unknown command │
- └────────────────────────────────────────┘
- */
- if (npACB->IORBError & IOERR_CMD_NOT_SUPPORTED)
- {
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- npACB->ISMDoneReturn = 0;
- }
- else
-
- if ( !(npACB->ISMFlags & ACBIF_ATA_OPERATION) )
- StartATAPICmd ( npACB );
- else
- StartATACmd ( npACB );
-
- } /* endif */
-
- }
-
- /*
- ╔══════════════════════════════════════╗
- ║ ║
- ║ InterruptState ║
- ║ ║
- ║ Routes interrupt generated threads ║
- ║ to the selected interrupt function ║
- ║ ║
- ╚══════════════════════════════════════╝
- */
- VOID NEAR InterruptState( NPACB npACB )
- {
- USHORT Status;
- USHORT INTReason;
- USHORT cXferBytes;
- USHORT cShortBytes;
- USHORT ByteBucket;
- USHORT Port;
- USHORT OddWord;
- USHORT cExtraBytes = 0;
- USHORT Reason = 0;
- USHORT DEBUGONold;
-
- if ( !(npACB->TimerFlags & ACBT_INTERRUPT) )
- {
-
- Status = GetRegister ( npACB, FI_PSTATUS );
- while ( Status & FX_BUSY )
- {
- Status = GetRegister ( npACB, FI_PSTATUS );
- }
-
- INTReason = GetRegister ( npACB, FI_PINTREASON );
- npACB->IORegs[FI_PSTATUS] = Status;
- npACB->IORegs[FI_PINTREASON] = INTReason;
-
-
- /* ┌─────────────────────────────────────────┐ */
- /* │Interrupt Reason (Defined in ATAPIREG.H)│ */
- if (INTReason & IRR_IO) /* │ │ */
- Reason |= IRM_IO; /* │ IO DRQ COD #define value │ */
- if (Status & FX_DRQ) /* │ 0 1 1 IR_PKTREADY │ */
- Reason |= IRM_DRQ; /* │ 1 1 1 IR_MESSAGE │ */
- if (INTReason & IRR_COD)/* │ 1 1 0 IR_XFER_FROM_DEVICE │ */
- Reason |= IRM_COD; /* │ 0 1 0 IR_XFER_TO_DEVICE │ */
- /* │ 1 0 1 IR_COMPLETE │ */
- /* └─────────────────────────────────────────┘ */
-
- if ( npACB->ISMFlags & ACBIF_ATA_OPERATION )
- Reason = IRM_IO | IRM_DRQ;
-
- /*
- ┌───────────────────────────────────────────────────────────────────────┐
- │ The 1.7 spec indicates that the completion status only relies on the │
- │ DRQ bit being 0. If we are in 1.7B compatibility mode and the DRQ │
- │ bit is 0, set the reason variable to IR_COMPLETE. │
- └───────────────────────────────────────────────────────────────────────┘
- */
-
- else if (/*( npACB->npUCB->Capabilities & UCBC_SPEC_REV_17B) && */
- !(Status & FX_DRQ))
- Reason |= IRM_IO | IRM_COD;
-
- /*
- ┌─────────────────────────────────────────────────┐
- │ If there was an error, go to the complete phase │
- └─────────────────────────────────────────────────┘
- */
- if ( Status & FX_ERROR )
- Reason = IR_COMPLETE;
-
- switch (Reason)
- {
- case IR_PKTREADY :
- npACB->ISMState = ACBIS_WRITE_ATAPI_PACKET_STATE;
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- break;
-
- case IR_XFER_FROM_DEVICE :
-
- if (npACB->npCmdIO->IOSGPtrs.Mode == SGLIST_TO_PORT)
- {
- _asm { int 3 } /* Expecting to go the opposite direction */
- } /* endif */
-
- if ( npACB->ISMFlags & ACBIF_ATA_OPERATION )
- {
- cXferBytes = npACB->npCmdIO->cXferBytesRemain;
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- npACB->ISMState = ACBIS_COMPLETE_STATE;
-
- }
- else
- {
- npACB->IORegs[FI_PBYTECTH] = GetRegister( npACB, FI_PBYTECTH );
- npACB->IORegs[FI_PBYTECTL] = GetRegister( npACB, FI_PBYTECTL );
-
- cXferBytes = MAKEUSHORT( npACB->IORegs[FI_PBYTECTL],
- npACB->IORegs[FI_PBYTECTH]);
- }
-
- if (cXferBytes & 1)
- {
- cXferBytes++;
- }
- /*
- ┌──────────────────────────────────────────────────────────────────┐
- │ If overrun, determine amount of extra bytes to transfer, and set │
- │ IOSGPtrs count to get only the number of bytes we are expecting │
- └──────────────────────────────────────────────────────────────────┘
- */
-
- if ( cXferBytes > npACB->npCmdIO->cXferBytesRemain )
- {
- cExtraBytes = cXferBytes - npACB->npCmdIO->cXferBytesRemain;
- cXferBytes = npACB->npCmdIO->cXferBytesRemain;
- }
-
- npACB->npCmdIO->IOSGPtrs.numTotalBytes = cXferBytes;
-
- /*
- ┌────────────────────────────────────────────────────────┐
- │ Start the interrupt timer if this is an ATAPI transfer │
- └────────────────────────────────────────────────────────┘
- */
-
- if ( !(npACB->ISMFlags & ACBIF_ATA_OPERATION) )
- {
- DISABLE
- if ( npACB->ISMFlags & ACBIF_INTERRUPT )
- {
- INT3
- }
- npACB->ISMFlags |= (ACBIF_WAITSTATE | ACBIF_INTERRUPT);
-
- if ( ADD_StartTimerMS((PULONG) &npACB->IRQTimeOutHandle,
- (ULONG) npACB->IRQTimeOut,
- (PFN) IRQTimeOutHandler,
- (PVOID) npACB,
- (ULONG) 0 ) )
- {
- _asm { int 3 }
- } /* endif */
- }
-
- /*
- ┌─────────────────────────────────────────┐
- │ Device will prepare for next interrupt │
- │ after last byte is transfered to host │
- └─────────────────────────────────────────┘
- */
-
- ENABLE
- ADD_XferIOW( &npACB->npCmdIO->IOSGPtrs );
-
- /*
- ┌───────────────────────────────────────────────────┐
- │ if extra bytes remain, put them in the byte bucket│
- └───────────────────────────────────────────────────┘
- */
-
- while ( cExtraBytes )
- {
- inwp( Port , ByteBucket );
- cExtraBytes-=2;
- } /* endwhile */
-
-
- /*
- ┌─────────────────────────────────────┐
- │ Adjust counts to show last transfer │
- └─────────────────────────────────────┘
- */
- npACB->npCmdIO->cXferBytesComplete += cXferBytes;
- npACB->npCmdIO->cXferBytesRemain -= cXferBytes;
-
- /*
- ┌───────────────────────────────────────────────────────────────┐
- │ If an odd byte count was requested, and we have finished the │
- │ even portion of the transfer, get the last byte and put it in │
- │ the S/G list. │
- └───────────────────────────────────────────────────────────────┘
- */
- if ( !(npACB->npCmdIO->cXferBytesRemain) &&
- ( npACB->ISMFlags & ACBIF_ODD_BYTE_XFER) )
- {
- inwp(Port, OddWord);
- PutByteInSGList ( npACB, OddWord );
-
- npACB->npCmdIO->cXferBytesComplete++;
- } /* endif */
- break;
-
- case IR_XFER_TO_DEVICE :
- if (npACB->npCmdIO->IOSGPtrs.Mode == PORT_TO_SGLIST)
- {
- DISABLE
- _asm { int 3 } /* Expecting to go the opposite direction */
- ENABLE
- } /* endif */
-
- npACB->IORegs[FI_PBYTECTH] = GetRegister( npACB, FI_PBYTECTH );
- npACB->IORegs[FI_PBYTECTL] = GetRegister( npACB, FI_PBYTECTL );
-
- cXferBytes = MAKEUSHORT( npACB->IORegs[FI_PBYTECTL],
- npACB->IORegs[FI_PBYTECTH]);
-
- /*
- ┌──────────────────────────────────────────────────────────────────┐
- │ If underrun, set IOSGPtrs count to send only the number of bytes │
- │ the device is expecting. Set up cExtraBytes to fill remaining │
- │ bytes with 0's │
- └──────────────────────────────────────────────────────────────────┘
- */
-
- if ( cXferBytes > npACB->npCmdIO->cXferBytesRemain )
- {
- cExtraBytes = cXferBytes - npACB->npCmdIO->cXferBytesRemain;
- cXferBytes = npACB->npCmdIO->cXferBytesRemain;
- }
-
- npACB->npCmdIO->IOSGPtrs.numTotalBytes = cXferBytes;
-
- /*
- ┌───────────────────────────┐
- │ Start the interrupt timer │
- └───────────────────────────┘
- */
-
- DISABLE
- if ( npACB->ISMFlags & ACBIF_INTERRUPT )
- {
- INT3
- }
- npACB->ISMFlags |= (ACBIF_WAITSTATE | ACBIF_INTERRUPT);
- if ( ADD_StartTimerMS((PULONG) &npACB->IRQTimeOutHandle,
- (ULONG) npACB->IRQTimeOut,
- (PFN) IRQTimeOutHandler,
- (PVOID) npACB,
- (ULONG) 0 ) )
- {
- _asm { int 3 }
- } /* endif */
-
- /*
- ┌──────────────────────────────────────────┐
- │ Device will prepare for next interrupt │
- │ after last byte is transfered from host │
- └──────────────────────────────────────────┘
- */
-
- ENABLE
- ADD_XferIOW( &npACB->npCmdIO->IOSGPtrs );
-
- /*
- ┌───────────────────────────────────────────────────┐
- │ if device expected more, give it zeros │
- └───────────────────────────────────────────────────┘
- */
-
- Port = npACB->npCmdIO->IOSGPtrs.iPortAddress;
-
- while ( cExtraBytes )
- {
- outwp( Port , 0 );
- cExtraBytes-=2;
- } /* endwhile */
-
- npACB->npCmdIO->cXferBytesComplete += cXferBytes;
- npACB->npCmdIO->cXferBytesRemain -= cXferBytes;
-
- break;
-
- case IR_COMPLETE :
-
- /* if an error, get the error register */
-
- if (Status & FX_ERROR )
- {
- npACB->IORegs[FI_PERROR] = GetRegister( npACB, FI_PERROR );
- npACB->OSMReqFlags |= ACBR_SENSE_DATA;
- }
- else if ( !(npACB->ISMFlags & ACBIF_ATA_OPERATION) &&
- (npACB->npCmdIO->IOSGPtrs.Mode == PORT_TO_SGLIST))
- {
- /*
- ┌───────────────────────────────────────────────────────────┐
- │ if the device did not give us as many bytes as we asked │
- │ for fill the remaining portion of the SG List with 0's. │
- └───────────────────────────────────────────────────────────┘
- */
- while ( npACB->npCmdIO->cXferBytesRemain )
- {
- if (npACB->npCmdIO->IOSGPtrs.SGOffset ==
- npACB->npCmdIO->IOSGPtrs.pSGList
- [npACB->npCmdIO->IOSGPtrs.iSGList].XferBufLen)
- {
- npACB->npCmdIO->IOSGPtrs.SGOffset = 0;
- npACB->npCmdIO->IOSGPtrs.iSGList++;
- }
-
- PutByteinSGList ( npACB, 0 );
- npACB->npCmdIO->cXferBytesComplete++;
- npACB->npCmdIO->cXferBytesRemain--;
- } /* endwhile */
- } /* end else */
-
-
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- break;
-
- default :
-
- // INT3
-
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- break;
-
- } /* endswitch */
-
- }
- else
- {
- /*
- ┌────────────────────────┐
- │ An Interrupt Timed Out │
- └────────────────────────┘
- */
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- npACB->OSMReqFlags |= ACBR_RESET;
- } /* endif */
-
- } /* InterruptState */
-
- /*
- ╔═══════════════════════════════════════╗
- ║ ║
- ║ PutByteInSGList ║
- ║ ║
- ║ Puts the next byte from the port ║
- ║ address in the next SGList location ║
- ║ ║
- ╚═══════════════════════════════════════╝
- */
- VOID NEAR PutByteInSGList ( NPACB npACB, USHORT Data )
- {
- PSCATGATENTRY pSGE; /* Current S/G List Entry */
- ULONG ppDst; /* Physical Address of Destination */
- PBYTE pDst; /* Virtual Address of Destination */
- USHORT ModeFlag;
-
- pSGE = &npACB->npCmdIO->IOSGPtrs.pSGList[npACB->npCmdIO->IOSGPtrs.iSGList];
- /* Point to the current entry */
- ppDst = pSGE->ppXferBuf + npACB->npCmdIO->IOSGPtrs.SGOffset;
- /* Offset in current entry */
-
- if ( DevHelp_PhysToVirt( (ULONG) ppDst,
- (USHORT) 1,
- (PVOID) &pDst,
- (PUSHORT) &ModeFlag ) )
- {
- _asm { int 3 }
- }
-
- *pDst = (UCHAR) (Data >> 8); /* Store the Byte */
- }
-
- /*
- ╔═══════════════════════════════════════╗
- ║ ║
- ║ WriteATAPIPkt ║
- ║ ║
- ║ Write ATAPI command packet to data ║
- ║ register ║
- ║ ║
- ╚═══════════════════════════════════════╝
- */
- VOID NEAR WriteATAPIPkt ( NPACB npACB )
- {
- USHORT Port,i;
- USHORT Data;
-
- Port = npACB->IOPorts[FI_PDATA];
-
- if ( !BSY_CLR_DRQ_SET_WAIT( npACB ) ) /*V@93531*/
- /* Max Poll wait time exceeded */ /*V@93531*/
- { /*V@93531*/
- npACB->ISMState = ACBIS_COMPLETE_STATE; /*V@93531*/
- npACB->OSMReqFlags |= ACBR_RESET; /* Set OSM for reset */ /*V@93531*/
- } /*V@93531*/
- else
- {
- /*
- ┌───────────────────────────┐
- │ Start the interrupt timer │
- └───────────────────────────┘
- */
- DISABLE
- if ( npACB->ISMFlags & ACBIF_INTERRUPT )
- {
- INT3
- }
- npACB->ISMFlags |= (ACBIF_WAITSTATE | ACBIF_INTERRUPT);
- npACB->ISMState = ACBIS_INTERRUPT_STATE;
-
- if ( ADD_StartTimerMS((PULONG) &npACB->IRQTimeOutHandle,
- (ULONG) npACB->IRQTimeOut,
- (PFN) IRQTimeOutHandler,
- (PVOID) npACB,
- (ULONG) 0 ) )
- {
- _asm { int 3 }
- } /* endif */
-
- i=0;
- do
- {
- Data = MAKEUSHORT(npACB->npCmdIO->ATAPIPkt[i],
- npACB->npCmdIO->ATAPIPkt[i+1]); /* MAKEUSHORT (h,l) */
- i+=2;
- outwp( Port, Data );
- IODelay ();
- } while ( i < npACB->npUCB->CmdPacketLength);
-
- ENABLE
-
- }
-
- } /* WriteATAPIPkt */
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ StartATAPICmd ║
- ║ ║
- ║ Write an ATAPI CMD and Paramters ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- VOID NEAR StartATAPICmd ( NPACB npACB )
- {
- USHORT Port;
- USHORT Data;
- USHORT Status;
- USHORT i;
- USHORT IOMask;
- USHORT Flags;
- USHORT cBytes;
-
- /* Set Drive Select Register */
- npACB->IORegs[FI_PDRVSLCT] =
- DEFAULT_ATAPI_DRV_SLCT_REG | ((npACB->UnitId == 0) ? UNIT0 : UNIT1 );
-
- IOMask = FM_PATAPI_CMD; /* Registers mask for ATAPI Cmd pkt */
- Flags = npACB->ISMFlags;
-
- /* Set Feature Register Data ( DMA OFF ) */
- npACB->IORegs[FI_PFEATURE] = DEFAULT_ATAPI_FEATURE_REG & ~DMA_ON;
-
- cBytes = npACB->npCmdIO->cXferBytesRemain;
- if ( cBytes > MAX_XFER_BYTES_PER_INTERRUPT )
- cBytes = MAX_XFER_BYTES_PER_INTERRUPT;
-
- /* Set Byte Count registers (Low and High order) */
- npACB->IORegs[FI_PBYTECTH] = cBytes >> 8;
- npACB->IORegs[FI_PBYTECTL] = cBytes & LOW_BYTE_MASK;
-
- /*
- ┌───────────────────────────────────────────────────────────────────────────┐
- │ The LBA bit of the ATAPI Drive Select Register is a reserved bit starting │
- │ in revision 1.2, and therefore must be set to 0. However, in the earlier │
- │ specs, the LBA bit must be 1. │
- └───────────────────────────────────────────────────────────────────────────┘
- */
-
- if ( npACB->npUCB->Capabilities & UCBC_SPEC_REV_17B)
- {
- npACB->IORegs[FI_PDRVSLCT] |= REV_17B_SET_LBA;
- } /* endif */
-
- /* Set Command Register with ATAPI Command */
- npACB->IORegs[FI_PCMD] = FX_PKTCMD;
-
- if ( npACB->npUCB->Capabilities & UCBC_INTERRUPT_DRQ )
- {
- DISABLE
- if (npACB->ISMFlags & ACBIF_INTERRUPT)
- {
- INT3
- }
- npACB->ISMFlags |= (ACBIF_WAITSTATE | ACBIF_INTERRUPT);
- npACB->ISMState = ACBIS_INTERRUPT_STATE;
-
- /*
- ┌───────────────────────────┐
- │ Start the interrupt timer │
- └───────────────────────────┘
- */
-
- if ( ADD_StartTimerMS((PULONG) &npACB->IRQTimeOutHandle,
- (ULONG) npACB->IRQTimeOut,
- (PFN) IRQTimeOutHandler,
- (PVOID) npACB,
- (ULONG) 0 ) )
- {
- _asm { int 3 }
- } /* endif */
- ENABLE
- }
- else
- {
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- npACB->ISMState = ACBIS_WRITE_ATAPI_PACKET_STATE;
- }
-
- /*
- ┌──────────────────────────┐
- │ Write selected registers │
- └──────────────────────────┘
- */
- for ( i = FI_PFEATURE; IOMask; i++ )
- {
- IOMask >>= 1;
-
- if ( IOMask & 0x0001 )
- {
- Port = npACB->IOPorts[i];
- Data = npACB->IORegs[i];
- outp( Port, Data);
- IODelay();
- }
- }
-
- } /* StartATAPICmd */
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ StartATACmd ║
- ║ ║
- ║ Write an ATA CMD and Paramters ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- VOID NEAR StartATACmd ( NPACB npACB )
- {
-
- USHORT Port;
- USHORT Data;
- USHORT Status;
- USHORT i;
- USHORT IOMask;
- USHORT Flags;
-
- IOMask = FM_PATA_CMD; /* Registers mask for ATA Commands */
-
- Flags = npACB->ISMFlags;
-
- /* Set Drive Select Register */
- npACB->IORegs[FI_PDRVSLCT] =
- DEFAULT_ATAPI_DRV_SLCT_REG | ((npACB->UnitId == 0) ? UNIT0 : UNIT1 );
-
- /* Set Command Register with ATA Command */
- if ( npACB->npUCB->ReqFlags & UCBR_IDENTIFY )
- {
- npACB->IORegs[FI_PCMD] = FX_IDENTIFYDRIVE;
-
- DISABLE
- if (npACB->ISMFlags & ACBIF_INTERRUPT)
- {
- INT3
- }
- npACB->ISMFlags |= (ACBIF_INTERRUPT | ACBIF_WAITSTATE);
- npACB->ISMState = ACBIS_INTERRUPT_STATE;
-
- /*
- ┌───────────────────────────┐
- │ Start the interrupt timer │
- └───────────────────────────┘
- */
-
- if ( ADD_StartTimerMS((PULONG) &npACB->IRQTimeOutHandle,
- (ULONG) npACB->IRQTimeOut,
- (PFN) IRQTimeOutHandler,
- (PVOID) npACB,
- (ULONG) 0 ) )
- {
- _asm { int 3 }
- } /* endif */
- ENABLE
-
- }
-
- else if ( npACB->npUCB->ReqFlags & UCBR_RESET )
- {
- npACB->IORegs[FI_PCMD] = FX_SOFTRESET;
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- }
-
- else
- {
- INT3
- }
-
-
- /*
- ┌──────────────────────────┐
- │ Write selected registers │
- └──────────────────────────┘
- */
- for ( i = FI_PFEATURE; IOMask; i++ )
- {
- IOMask >>= 1;
-
- if ( IOMask & 0x0001 )
- {
- Port = npACB->IOPorts[i];
- Data = npACB->IORegs[i];
- outp( Port, Data);
- IODelay();
- }
- }
-
- }
-
- /*
- ╔═══════════════════════════════════════╗
- ║ ║
- ║ InitializeISM ║
- ║ ║
- ║ Initializes state and flag variables ║
- ║ ║
- ╚═══════════════════════════════════════╝
- */
- VOID NEAR InitializeISM ( NPACB npACB )
- {
- UCHAR Opcode;
- struct CDB_ModeSense_10 NEAR *pModeSenseCmd; /* in order to fix 1.7B drives */
- struct CDB_PlayAudio_MSF NEAR *pPlayAudioMSFCmd;
-
- if ( !( npACB->ISMFlags & ACBIF_ATA_OPERATION ) )
- {
- /*
- ┌────────────────────────────┐
- │ set opcode dependent flags │
- └────────────────────────────┘
- */
-
- Opcode = npACB->npCmdIO->ATAPIPkt[0];
-
- switch( Opcode )
- {
- /* Immediate Commands - complete after returning status */
-
- case ATAPI_AUDIO_SCAN :
- case SCSI_PLAY_AUDIO_10 :
- case SCSI_PLAY_AUDIO_12 :
- case SCSI_PLAY_MSF :
- case SCSI_PLAY_TRACK_REL :
- case SCSI_PLAY_TRACK_REL_12 :
- case SCSI_SEEK_10 :
-
- /* Completion Status Only */
-
- case SCSI_START_STOP_UNIT :
- case SCSI_PAUSE_RESUME :
- case SCSI_LOCK_UNLOCK :
- case SCSI_REZERO_UNIT :
- case ATAPI_SET_CDROM_SPEED :
- case ATAPI_STOP_PLAYSCAN :
- case SCSI_TEST_UNIT_READY :
-
- npACB->ISMFlags |= (ACBIF_COMPLETION_STATUS_ONLY | ACBIF_WAITSTATE);
- break;
-
- /* Single IO */
- case SCSI_INQUIRY :
- case SCSI_READ_CAPACITY :
- case SCSI_MODE_SENSE_10 :
- case SCSI_READ_HEADER :
- case SCSI_READ_SUB_CHAN :
- case SCSI_READ_TOC :
- case SCSI_REQUEST_SENSE :
-
- npACB->ISMFlags |= (ACBIF_SINGLEIO | ACBIF_WAITSTATE);
- break;
-
- /* Block IO */
- case SCSI_READ_10 :
- case SCSI_READ_12 :
- case ATAPI_READ_CD :
- case ATAPI_READ_CD_MSF :
-
- npACB->ISMFlags |= (ACBIF_MULTIPLEIO | ACBIF_WAITSTATE);
- break;
-
- case SCSI_MODE_SELECT_10 :
- npACB->ISMFlags |= (ACBIF_MULTIPLEIO | ACBIF_WAITSTATE);
- /*
- ┌───────────────────────────────────┐
- │ change default transfer direction │
- └───────────────────────────────────┘
- */
- npACB->npCmdIO->IOSGPtrs.Mode = SGLIST_TO_PORT;
-
- break;
-
- default :
- if ( !(npACB->ISMFlags & ACBIF_ATA_OPERATION) )
- {
- npACB->ISMFlags |= ACBIF_WAITSTATE;
- break;
- }
- } /* endswitch */
-
- /*
- ┌───────────────────────────────────────────────┐
- │ If drive is only revision 1.7B compatible, │
- │ change the opcodes to the 1.7B spec's opcodes │
- │ and fix the inconsistancies in the data │
- └───────────────────────────────────────────────┘
- */
- if ( npACB->npUCB->Capabilities & UCBC_SPEC_REV_17B)
- {
- switch (Opcode)
- {
- case ATAPI_AUDIO_SCAN :
- npACB->npCmdIO->ATAPIPkt[0] = REV_17B_ATAPI_AUDIO_SCAN;
- break;
-
- case ATAPI_SET_CDROM_SPEED :
- npACB->npCmdIO->ATAPIPkt[0] = REV_17B_ATAPI_SET_CDROM_SPEED;
- break;
-
- case ATAPI_READ_CD :
- npACB->npCmdIO->ATAPIPkt[0] = REV_17B_ATAPI_READ_CD;
- break;
-
- case ATAPI_READ_CD_MSF :
- npACB->npCmdIO->ATAPIPkt[0] = REV_17B_ATAPI_READ_CD_MSF;
- break;
-
- case SCSI_PLAY_MSF :
- pPlayAudioMSFCmd =
- (struct CDB_PlayAudio_MSF NEAR *)npACB->npCmdIO->ATAPIPkt;
- /* silly 1.7B drives want this data in BCD */
- pPlayAudioMSFCmd->starting_M = x2BCD(pPlayAudioMSFCmd->starting_M);
- pPlayAudioMSFCmd->starting_S = x2BCD(pPlayAudioMSFCmd->starting_S);
- pPlayAudioMSFCmd->starting_F = x2BCD(pPlayAudioMSFCmd->starting_F);
- pPlayAudioMSFCmd->ending_M = x2BCD(pPlayAudioMSFCmd->ending_M);
- pPlayAudioMSFCmd->ending_S = x2BCD(pPlayAudioMSFCmd->ending_S);
- pPlayAudioMSFCmd->ending_F = x2BCD(pPlayAudioMSFCmd->ending_F);
- break;
-
- case SCSI_MODE_SENSE_10 :
- pModeSenseCmd =
- (struct CDB_ModeSense_10 NEAR *)npACB->npCmdIO->ATAPIPkt;
- if (pModeSenseCmd->page_code == PAGE_CAPABILITIES)
- {
- pModeSenseCmd->page_code = REV_17B_PAGE_CAPABILITIES;
- }
-
- default :
- break;
- } /* endswitch */
- } /* endif */
- }
- /*
- ┌────────────────────┐
- │ Odd Byte Transfers │
- └────────────────────┘
- */
- if ( npACB->npCmdIO->IOSGPtrs.numTotalBytes & 1 ) /* Is this an odd byte transfer? */
- {
- if (npACB->npCmdIO->IOSGPtrs.Mode == PORT_TO_SGLIST)
- {
- npACB->npCmdIO->IOSGPtrs.numTotalBytes -= 1; /* Must be even transfer Amount */
- npACB->ISMFlags |= ACBIF_ODD_BYTE_XFER;
- }
- else
- {
- npACB->npCmdIO->IOSGPtrs.numTotalBytes += 1; /* Must be even transfer Amount */
- } /* endif */
- } /* endif */
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ IRQTimeOutHandler ║
- ║ ║
- ║ Times out the interrupt ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- VOID FAR IRQTimeOutHandler( ULONG TimerHandle, ULONG Parm1, ULONG Parm2 )
- {
- NPACB npACB;
-
- DISABLE
- ADD_CancelTimer( TimerHandle );
-
- npACB = (NPACB) Parm1;
-
- npACB->IRQTimeOutHandle = 0;
- npACB->ISMFlags &= ~ACBIF_INTERRUPT;
-
- npACB->TimerFlags |= ACBT_INTERRUPT; /* Tell interrupt state we timedout */
-
- if ( npACB->ISMState == ACBIS_INTERRUPT_STATE )
- {
- ENABLE
- StartISM( npACB );
- }
- else
- ENABLE
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ AdapterIRQ0 ║
- ║ ║
- ║ Routes received IRQs for Adapter ║
- ║ 0 to generic handler ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- USHORT FAR _loadds AdapterIRQ0()
- {
-
- if ( ACBPtrs[0].npACB->ResourceFlags & ACBRF_SHARED ) /*V@93531*/
- return( AdptInterrupt( ACBPtrs[0].npACB ) ); /*V@93531*/
- else /*V@93531*/
- return( AdptInterrupt( ACBPtrs[0].npACB ) >> 1 ); /*V@93531*/
- /* Set carry flag interrupt is unclaimed */ /*V@93531*/
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ AdapterIRQ1 ║
- ║ ║
- ║ Routes received IRQs for Adapter ║
- ║ 1 to generic handler ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- USHORT FAR _loadds AdapterIRQ1()
- {
-
- if ( ACBPtrs[1].npACB->ResourceFlags & ACBRF_SHARED ) /*V@93531*/
- return( AdptInterrupt( ACBPtrs[1].npACB ) ); /*V@93531*/
- else /*V@93531*/
- return( AdptInterrupt( ACBPtrs[1].npACB ) >> 1 ); /*V@93531*/
- /* Set carry flag if interrupt is unclaimed */ /*V@93531*/
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ AdapterIRQ2 ║
- ║ ║
- ║ Routes received IRQs for Adapter ║
- ║ 2 to generic handler ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- USHORT FAR _loadds AdapterIRQ2()
- {
- if ( ACBPtrs[2].npACB->ResourceFlags & ACBRF_SHARED ) /*V@93531*/
- return( AdptInterrupt( ACBPtrs[2].npACB ) ); /*V@93531*/
- else /*V@93531*/
- return( AdptInterrupt( ACBPtrs[2].npACB ) >> 1 ); /*V@93531*/
- /* Set carry flag interrupt is unclaimed */ /*V@93531*/
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ AdapterIRQ3 ║
- ║ ║
- ║ Routes received IRQs for Adapter ║
- ║ 3 to generic handler ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- USHORT FAR _loadds AdapterIRQ3()
- {
- if ( ACBPtrs[3].npACB->ResourceFlags & ACBRF_SHARED ) /*V@93531*/
- return( AdptInterrupt( ACBPtrs[3].npACB ) ); /*V@93531*/
- else /*V@93531*/
- return( AdptInterrupt( ACBPtrs[3].npACB ) >> 1 ); /*V@93531*/
- /* Set carry flag interrupt is unclaimed */ /*V@93531*/
- }
-
- /*
- ╔══════════════════════════════════════╗
- ║ ║
- ║ AdptInterrupt ║
- ║ ║
- ║ Determines if IRQ should be claimed ║
- ║ and sets state flags accordingly ║
- ║ ║
- ╚══════════════════════════════════════╝
- */
- USHORT NEAR AdptInterrupt( NPACB npACB )
- {
- USHORT Claimed = 0;
-
- if ( npACB )
- {
- DISABLE
-
- Claimed = 1;
-
- /*
- ┌─────────────────────────────────────────────────────────┐
- │ Read the controller status register to clear interrupt │
- │ in case hardware is setup for level triggered operation │
- └─────────────────────────────────────────────────────────┘
- */
- GetRegister( npACB, FI_PSTATUS );
-
- if ( npACB->ISMFlags & ACBIF_INTERRUPT )
- {
-
- npACB->ISMFlags &= ~ACBIF_INTERRUPT;
-
- if ( npACB->IRQTimeOutHandle )
- {
- ADD_CancelTimer( npACB->IRQTimeOutHandle );
- npACB->IRQTimeOutHandle = 0;
- }
- else
- {
- _asm { int 3 }
- }
-
- DevHelp_EOI( npACB->IRQLevel );
-
- ENABLE
- StartISM( npACB );
- }
- else
- {
- npACB->SpuriousIRQ++;
-
- DevHelp_EOI( npACB->IRQLevel );
- }
- }
-
- return( ~Claimed );
- } /* AdptInterrupt */
-
- /*
- ╔═════════════════════════════════════════════╗
- ║ ║
- ║ GetRegister ║
- ║ ║
- ║ Get the error data from the error register ║
- ║ ║
- ╚═════════════════════════════════════════════╝
- */
- USHORT NEAR GetRegister ( NPACB npACB, USHORT Register )
- {
- USHORT Port;
- USHORT Data;
-
- Port = npACB->IOPorts[Register];
- inp ( Port, Data );
- return ( Data );
-
- } /* GetRegister */
-