home *** CD-ROM | disk | FTP | other *** search
- /* SCCSID = %W% %E% */
- /**************************************************************************
- *
- * SOURCE FILE NAME = ATAPIISM.C
- *
- * DESCRIPTIVE NAME = ATAPI Inner State Machine
- *
- *
- * Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992
- * LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
- * REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
- * RESTRICTED MATERIALS OF IBM
- * IBM CONFIDENTIAL
- *
- * VERSION = 1.0
- *
- * DATE
- *
- * DESCRIPTION :
- *
- * Purpose:
- *
- *
- *
- *
- *
- * CHANGE ACTIVITY =
- * DATE FLAG APAR CHANGE DESCRIPTION
- * -------- ---------- ----- --------------------------------------
- * 08/22/94 V@93531 93531 1) Suspend/Resume logic passes IRQ handler
- * address. 2) DRQ polling is not valid while
- * BSY bit set.
- * 04/05/96 @V151168 Merged warm dock/swap code.
- * 05/24/96 @V155162 Thinkpad docking/swapping IDE update.
- * 05/25/96 @V155162 Deleted int 3s on potential write commands
- * 04/26/98 @V195083 Added Panasonic PD support.
- ****************************************************************************/
- /*
- * Edit History for Feature # 149178:
- *
- * Edit Date Comments
- * ----- -------- -------------------------------------------------------------
- * [001] 01-03-96 Added code to setup and complete Bus Master DMA transfers
- * when UCBF_BM_DMA flag is set in UCB flags. Code to setup
- * scatter/gather tables was copied from S506SM.C source. /jlh
- *
- * [002] 02-06-96 Remove BM IDE Active bit test from IR_COMPLETE case in
- * InterruptState. For ATAPI CD-ROM drives this shouldn't be
- * an error condition. The actual xfer may be shorter than
- * the programmed length. /mol
- */
-
- #define INCL_NOBASEAPI
- #define INCL_NOPMAPI
- #include "os2.h"
- #include "dos.h"
- #include "dskinit.h"
-
- #include "iorb.h"
- #include "addcalls.h"
- #include "dhcalls.h"
- #include "apmcalls.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
- SelectUnit( npACB, npACB->UnitId ); /*@V195083*/
-
- if (!( npACB->OSMReqFlags & ACBR_RESET ) && /*V@106915*/
- ( !DRQ_AND_BSY_CLEAR_WAIT( npACB ) ) ) /*V@93531*/
- /* Max Poll wait time exceeded */
- {
- if( npACB->npUCB->Flags & UCBF_FORCE ) /*@V151168*//*@V155162*/
- { /*@V151168*/
- npACB->npUCB->Flags |= UCBF_NOTPRESENT; //set fake flag /*@V151168*/
- npACB->IORBError = IOERR_UNIT_NOT_READY; /*@V155162*/
- npACB->ISMState = ACBIS_COMPLETE_STATE; /*@V155162*/
- } /*@V151168*/
- else /*@V151168*/
- { /*@V151168*/
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- npACB->OSMReqFlags |= ACBR_RESET; /* Set OSM for reset */
- ENABLE
- return; /*@V151168*/
- } /*@V151168*/
- }
- 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 = 0; /*@V151168*/
- USHORT cXferBytes;
- USHORT cShortBytes;
- USHORT ByteBucket;
- USHORT Port;
- USHORT OddWord;
- USHORT cExtraBytes = 0;
- USHORT Reason = 0;
- USHORT data,port; /* [001] */
- register int loop; /* [001] */
-
- 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 :
- /*@V155162*/
- if (npACB->npCmdIO->IOSGPtrs.Mode == SGLIST_TO_PORT)
- {
- // Wrong WAY, expecting to go the opposite direction,/*@V195083*/
- // fix it instead of trapping. /*@V195083*/
- npACB->npCmdIO->IOSGPtrs.Mode == PORT_TO_SGLIST; /*@V195083*/
- } /* endif */
- /*@V155162*/
-
- 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 :
- /*@V155162*/
- if (npACB->npCmdIO->IOSGPtrs.Mode == PORT_TO_SGLIST)
- {
- // Wrong WAY, expecting to go the opposite direction,/*@V195083*/
- // fix it instead of trapping. /*@V195083*/
- npACB->npCmdIO->IOSGPtrs.Mode == SGLIST_TO_PORT; /*@V195083*/
- } /* endif */
- /*@V155162*/
-
- 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 :
-
- /* Begin [001] */
-
- if( ( npACB->ISMFlags & ACBIF_BUSMASTERDMAIO ) )
- {
- npACB->ISMFlags &= ~ACBIF_BUSMASTERDMAIO;
- npACB->npCmdIO->cXferBytesComplete = npACB->npCmdIO->cXferBytesRemain;
- npACB->npCmdIO->cXferBytesRemain = 0;
-
- /* Wait for BM DMA active to go away for a while. */
-
- port = npACB->BMISTA;
- for( loop=256 ; loop ; --loop )
- {
- inp(port,data);
- if ( !(data & ACBX_BMISTA_ACTIVE) )
- {
- break;
- }
- }
-
- /* Begin [002]
- if ( data & ACBX_BMISTA_ACTIVE )
- {
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- npACB->OSMReqFlags |= ACBR_RESET;
- }
- End [002] */
-
- port = npACB->BMICOM;
- outp ( port, 0 ); /* shut down BM DMA controller */
- port = npACB->BMISTA;
- data &= ( ACBX_BMISTA_INTERRUPT |
- ACBX_BMISTA_D0DMA |
- ACBX_BMISTA_D1DMA );
- outp ( port, data ); /* clear BM interrupt flag */
-
- /* Fix so that Bus Master errors will definitely result in retries */
-
- inp ( port, data );
- if ( data & ACBX_BMISTA_ERROR )
- {
- data &= ( ACBX_BMISTA_ERROR |
- ACBX_BMISTA_D0DMA |
- ACBX_BMISTA_D1DMA );
- outp ( port, data );
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- npACB->OSMReqFlags |= ACBR_RESET;
- }
- }
-
- /* End [001] */
-
- /* 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
- //BMK if all is 0 then there was an unknown problem /*@V151168*/
- npACB->IORegs[FI_PSTATUS] = FX_ERROR; /*@V151168*/
- //Do a reset /*@V151168*/
- npACB->ISMFlags &= ~ACBIF_WAITSTATE; /*@V151168*/
- npACB->OSMReqFlags |= ACBR_RESET; /*@V151168*/
-
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- break;
-
- } /* endswitch */
-
- }
- else
- {
- /*
- ┌────────────────────────┐
- │ An Interrupt Timed Out │
- └────────────────────────┘
- */
-
- /* Begin [001] */
-
- if( ( npACB->ISMFlags & ACBIF_BUSMASTERDMAIO ) )
- {
- npACB->ISMFlags &= ~ACBIF_BUSMASTERDMAIO;
- port = npACB->BMICOM;
- outp ( port, 0 ); /* shut down BM DMA controller */
- port = npACB->BMISTA;
- inp( port, data );
- data &= ( ACBX_BMISTA_INTERRUPT |
- ACBX_BMISTA_D0DMA |
- ACBX_BMISTA_D1DMA );
- outp( port, data ); /* clear BM interrupt flag */
- }
-
- /* End [001] */
-
- npACB->ISMState = ACBIS_COMPLETE_STATE;
- npACB->ISMFlags &= ~ACBIF_WAITSTATE;
- npACB->OSMReqFlags |= ACBR_RESET;
- // Fake interrupt timeout to get an error /*@V151168*/
- npACB->TimerFlags |= ACBT_INTERRUPT; /*@V151168*/
- } /* 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;
-
- 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 */
-
- /* Begin [001] Start Bus Master DMA transfer after issuing Packet command */
-
- if( npACB->BM_CommandCode & ACBX_BMICOM_START )
- {
- Port = npACB->BMISTA; /* addr status reg */
- inp( Port, Data );
- Data &= ( ACBX_BMISTA_INTERRUPT |
- ACBX_BMISTA_D0DMA |
- ACBX_BMISTA_D1DMA );
- outp( Port, Data ); /* clear BM interrupt flag */
- Port = npACB->BMICOM; /* Set port address to BM Command reg */
- Data = npACB->BM_CommandCode; /* BM controller command */
- outp( Port, Data ); /* Start BM controller */
- }
-
- /* End [001] */
-
- Port = npACB->IOPorts[FI_PDATA]; /* [001] Moved */
-
- 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;
-
- SelectUnit( npACB, npACB->UnitId ); /*@V195083*/
-
- if (npACB->npUCB->Flags & UCBF_NOTPRESENT) /*@V151168*/
- { /*@V151168*/
- // This is a not-present forced drive, fake the request /*@V151168*/
- FakeATAPI(npACB); /*@V151168*/
- npACB->ISMFlags &= ~ACBIF_WAITSTATE; /*@V151168*/
- npACB->ISMState = ACBIS_COMPLETE_STATE; // force completion /*@V151168*/
- return; //done /*@V151168*/
- } /*@V151168*/
-
- /* 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;
-
- /* Begin [001] */
-
- if ( npACB->ISMFlags & ACBIF_BUSMASTERDMAIO )
- {
- npACB->IORegs[FI_PFEATURE] |= DMA_ON; /* enable DMA for this xfer */
- }
-
- /* End [001] */
-
- 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;
-
- SelectUnit( npACB, npACB->UnitId ); /*@V195083*/
- IOMask = FM_PATA_CMD; /* Registers mask for ATA Commands */
-
- Flags = npACB->ISMFlags;
-
- if (npACB->npUCB->Flags & UCBF_NOTPRESENT) /*@V151168*/
- { /*@V151168*/
- // This is a not-present forced drive, fake the request /*@V151168*/
- FakeATA(npACB); /*@V151168*/
- npACB->ISMFlags &= ~ACBIF_WAITSTATE; /*@V151168*/
- npACB->ISMState = ACBIS_COMPLETE_STATE; // force completion /*@V151168*/
- return; //done /*@V151168*/
- } /*@V151168*/
-
- /* 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;
- NPUCB npUCB = npACB->npUCB; /* [001] */
- SHORT Port,Data; /* [001] */
-
- if ( !( npACB->ISMFlags & ACBIF_ATA_OPERATION ) )
- {
- /*
- ┌────────────────────────────┐
- │ set opcode dependent flags │
- └────────────────────────────┘
- */
-
- Opcode = npACB->npCmdIO->ATAPIPkt[0];
-
- npACB->BM_CommandCode = 0; /* [001] */
-
- 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);
-
- /* Begin [001] Determine if DMA capable system/CD-ROM and even length transfer */
-
- if ( (!InitActive) &&
- !(npACB->ISMFlags & ACBIF_BUSMASTERDMA_FORCEPIO) &&
- (npUCB->Flags & UCBF_BM_DMA) &&
- !(npACB->npCmdIO->IOSGPtrs.numTotalBytes & 1) )
- {
-
- if( !CreateBMSGList( npACB ) ) /* try and create scatter/gather list */
- {
- /* change transfer setup to Bus Master DMA */
-
- npACB->ISMFlags &= ~ACBIF_MULTIPLEIO;
- npACB->ISMFlags |= ACBIF_BUSMASTERDMAIO;
-
- /* Shut down Bus Master DMA controller if active */
-
- Port = npACB->BMISTA; /* Set port address to BM Status reg */
- inp ( Port, Data );
- if ( Data & ACBX_BMISTA_ACTIVE )
- {
- Port = npACB->BMICOM; /* Set port address to BM Command reg */
- outp( Port, 0 ); /* stop Bus Master DMA if active */
- }
- Port = npACB->BMISTA; /* set to status reg again */
- Data &= ( ACBX_BMISTA_INTERRUPT |
- ACBX_BMISTA_D0DMA |
- ACBX_BMISTA_D1DMA );
- outp ( Port, Data ); /* write to port */
-
- npACB->BM_CommandCode = (ACBX_BMICOM_RW | ACBX_BMICOM_START);
-
- #ifdef ENABLE_COUNTERS
- // ++npUCB->DeviceCounters.TotalBMReadOperations;
- #endif
-
- Port = npACB->BMIDTP; /* address descriptor base register in PIIX */
- Data = (USHORT) npACB->BMDMA_SGList;
- outwp ( Port, Data );
- Port += 2;
- Data = (USHORT) (npACB->BMDMA_SGList >> 16);
- outwp ( Port, Data );
-
- /*
- * Bus Master DMA is now ready for the transfer. It must be started after the
- * command is issued to the drive, to avoid data corruption in case a spurious
- * interrupt occurred at the beginning of the xfer and the drive is in an unknown
- * state.
- */
-
- } /* if( !CreateBMSGList( npACB ) ) */
-
- npACB->ISMFlags &= ~ACBIF_BUSMASTERDMA_FORCEPIO;
- }
-
- /* End [001] */
-
- 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()
- {
- return( AdptInterrupt( ACBPtrs[0].npACB ) ); /*V@93531*/
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ AdapterIRQ1 ║
- ║ ║
- ║ Routes received IRQs for Adapter ║
- ║ 1 to generic handler ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- USHORT FAR _loadds AdapterIRQ1()
- {
- return( AdptInterrupt( ACBPtrs[1].npACB ) ); /*V@93531*/
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ AdapterIRQ2 ║
- ║ ║
- ║ Routes received IRQs for Adapter ║
- ║ 2 to generic handler ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- USHORT FAR _loadds AdapterIRQ2()
- {
- return( AdptInterrupt( ACBPtrs[2].npACB ) ); /*V@93531*/
- }
-
- /*
- ╔════════════════════════════════════╗
- ║ ║
- ║ AdapterIRQ3 ║
- ║ ║
- ║ Routes received IRQs for Adapter ║
- ║ 3 to generic handler ║
- ║ ║
- ╚════════════════════════════════════╝
- */
- USHORT FAR _loadds AdapterIRQ3()
- {
- return( AdptInterrupt( ACBPtrs[3].npACB ) ); /*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 */
-
- /* Begin [001] */
-
- /*--------------------------------------------*/
- /* CreateBMSGList */
- /* -------------- */
- /* */
- /* Arguments: */
- /* */
- /* */
- /* Actions: */
- /* Takes OS/2 scatter/gather list and */
- /* builds SFF-8038i compatible list for */
- /* DMA controller. */
- /* */
- /* */
- /* Returns: */
- /* 0 if successful */
- /* */
- /* */
- /*--------------------------------------------*/
-
- int CreateBMSGList( NPACB npACB )
- {
- USHORT i;
- PPRD pSGL;
- ULONG BytesLeft;
- ULONG PhysicalSgl;
- ULONG PhysicalAddress;
- ULONG Length;
- ULONG LengthLeftInBoundary;
- ULONG DescriptorCount = 0;
- ULONG TempLength;
- PSCATGATENTRY pSGList;
-
- /* get seg:off address of BM DMA scatter/gather table */
-
- if ( DevHelp_PhysToVirt( npACB->BMDMA_SGList, npACB->BMDMA_SGListSize,
- &pSGL, &i ) )
- {
- return ( 1 ); /* fail it */
- }
-
- // BytesLeft = npACB->BytesToTransfer;
- BytesLeft = npACB->npCmdIO->cXferBytesRemain;
-
- /* process each entry in OS/2 scatter/gather list */
-
- pSGList = npACB->npCmdIO->IOSGPtrs.pSGList;
- for (i=0; i < npACB->npCmdIO->IOSGPtrs.cSGList; i++,pSGList++)
- {
-
- Length = pSGList->XferBufLen; /* get length of memory region */
- PhysicalAddress = pSGList->ppXferBuf;
-
- if ( Length > BytesLeft )
- {
- #ifdef DEBUG_WDCIDEOS
- {
- _asm int 3;
- }
- #endif
- Length = BytesLeft; /* Don't set up entry bigger than total */
- } /* transfer length reported */
-
- if( (PhysicalAddress & 1) || /* if on odd byte boundary, do PIO */
- (Length & 1) ) /* if odd transfer length, do PIO */
- {
- #ifdef ENABLE_COUNTERS
- // ++npACB->npUCB->DeviceCounters.ByteMisalignedBuffers;
- #endif
- return ( 1 ); /* fail conversion */
- }
-
-
- while( Length )
- {
-
- pSGL->MR_PhysicalBaseAddress = PhysicalAddress;
- TempLength = Length; /* make copy of total length */
-
- /* Can't exceed 64KB size per entry in BM DMA SG List */
-
- if( TempLength > MR_64K_LIMIT )
- {
- #ifdef DEBUG_WDCIDEOS
- {
- _asm mov ax,1
- _asm int 3;
- }
- #endif
-
- TempLength = MR_64K_LIMIT; /* force to max size */
- }
-
- if ( TempLength > BytesLeft )
- {
- #ifdef DEBUG_WDCIDEOS
- {
- _asm mov ax,2
- _asm int 3;
- }
- #endif
-
- TempLength = BytesLeft; /* Don't exceed remaining transfer length */
- }
-
- /* Can't cross 64KB boundary so check for it and adjust */
-
- LengthLeftInBoundary = MR_64K_LIMIT - (PhysicalAddress & (MR_64K_LIMIT-1));
- if ( TempLength > LengthLeftInBoundary )
- {
- TempLength = LengthLeftInBoundary;
- #ifdef ENABLE_COUNTERS
- // ++npACB->npUCB->DeviceCounters.ByteMisalignedBuffers;
- #endif
- }
-
- /* Adjust counts */
-
- PhysicalAddress += TempLength;
- Length -= TempLength;
- BytesLeft -= TempLength;
-
- /* Create SGL descriptor entry */
-
- pSGL->ByteCountAndEOT = (ULONG) TempLength;
- ++DescriptorCount;
- if(BytesLeft == 0)
- {
- pSGL->ByteCountAndEOT |= PRD_EOT_FLAG;
- }
- else if ( DescriptorCount > npACB->BMDMA_SGListCount )
- {
- #ifdef DEBUG_WDCIDEOS
- {
- _asm mov ax,4
- _asm int 3;
- }
- #endif
- return( 1 ); /* ran out of descriptors */
-
- }
- pSGL++;
- } /* while( Length ) */
- } /* for (i=0; i < npACB->IOSGPtrs.cSGList; i++,pSGList++) */
-
- return( 0 ); /* finished building sg list */
- } /* End of CreateBMSGList */
-
- /* End [001] */
-