/* SCCSID = "src/dev/usb/UHCI/UHCCANIO.C, usb, c.basedd 98/07/10" */
/*
*   Licensed Material -- Property of IBM
*
*   (c) Copyright IBM Corp. 1997, 1998  All Rights Reserved
*/
/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME:  UHCCANIO.C                                            */
/*                                                                            */
/*   DESCRIPTIVE NAME:  I/O cancel routines.                                  */
/*                                                                            */
/*   FUNCTION: This routine handles cancel I/O requests                       */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*             UHCICancelIO                                                   */
/*             UHCICancelAll                                                  */
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*                                                                            */
/* Change Log                                                                 */
/*                                                                            */
/*  Mark    yy/mm/dd  Programmer      Comment                                 */
/*  ----    --------  ----------      -------                                 */
/*          98/01/31  MB                                                      */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#include        "uhci.h"

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  UHCICancelIO                                     */
/*                                                                    */
/* DESCRIPTIVE NAME:  Cancel I/O request worker routine               */
/*                                                                    */
/* FUNCTION:  This routine ends all I/O requests to specified         */
/*            device address - searches for request QH, detaches      */
/*            QH from schedule, processes request as finished.        */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task Time                                                 */
/*                                                                    */
/* ENTRY POINT :  UHCICancelIO                                        */
/*    LINKAGE  :  CALL NEAR                                           */
/*                                                                    */
/* INPUT:  RP_GENIOCTL FAR *pRP_GENIOCTL                              */
/*                                                                    */
/* EXIT-NORMAL:  n/a                                                  */
/*                                                                    */
/* EXIT-ERROR:  n/a                                                   */
/*                                                                    */
/* EFFECTS: gNextForIRQ is adjusted if corresponding request canceled */
/*                                                                    */
/* INTERNAL REFERENCES:  none                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  CancelIsoRequests                            */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/
void UHCICancelIO( RP_GENIOCTL FAR *pRP_GENIOCTL )
{
   QH             *qh, *nextQH;
   register TD    *td;
   USBCancel FAR  *cancelData;
   UCHAR          deviceAddress;
#ifdef   DEBUG
   BOOL           noCanceled=TRUE;
#endif

   cancelData=(USBCancel FAR *)pRP_GENIOCTL->ParmPacket;

   // Cancel root hub request(s)
   if (cancelData->deviceAddress==gRootHubAddress)
   {
      USHORT         rootReqIndex;
      BOOL           allRequestsFinished=TRUE;

      for (rootReqIndex=0; rootReqIndex<ROOT_MAX_REQ; rootReqIndex++)
      {
         if (cancelData->endPointId==USBCANCEL_CANCEL_ALL ||
             gRootHubRB[rootReqIndex].endPointId==cancelData->endPointId)
         {
            gRootHubRP[rootReqIndex].rph.Status=0;   //  mark as processed to free request buffer
         }
         if (gRootHubRP[rootReqIndex].rph.Status)
            allRequestsFinished=FALSE;
      }
      if (allRequestsFinished)
         gRootReqStatus=ROOT_HUB_NOREQ;
   }

   // cancel isohronous requests for specified device
   CancelIsoRequests(cancelData->deviceAddress, cancelData->endPointId);

   // check all queued requests
   for (qh=gFirstBottomQH; qh; qh=nextQH)
   {
      nextQH=qh->nextBotQH;
      td=(TD *)qh->qeLinkVirt;
      deviceAddress=td->deviceAddress;

      // cancel request if request address and enpoint is equal to required
      if (deviceAddress==cancelData->deviceAddress &&
          (cancelData->endPointId==USBCANCEL_CANCEL_ALL || td->endPointId==cancelData->endPointId))
      {
         if (gNextForIRQ==qh)  // advance next QH pointer for IRQ processor
            gNextForIRQ=nextQH;
         DetachQH(qh);   // detach current QH from schedule
         FinshIO(td,TRUE); // process request
#ifdef   DEBUG
         noCanceled=FALSE;
#endif
      }
   }
#ifdef   DEBUG
   if (noCanceled)
      dsPrint(DBG_DETAILED,"UHCI: UHCICancelIO - no cancelled requests\r\n");
#endif
}

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  UHCICancelAll                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Cancel I/O requests worker routine              */
/*                                                                    */
/* FUNCTION:  This routine ends all I/O requests  - searches for      */
/*            request QH, detaches QH from schedule, processes        */
/*            request as finished.                                    */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task Time                                                 */
/*                                                                    */
/* ENTRY POINT :  UHCICancelAll                                       */
/*    LINKAGE  :  CALL NEAR                                           */
/*                                                                    */
/* INPUT:  none                                                       */
/*                                                                    */
/* EXIT-NORMAL:  n/a                                                  */
/*                                                                    */
/* EXIT-ERROR:  n/a                                                   */
/*                                                                    */
/* EFFECTS: gNextForIRQ is adjusted if corresponding request canceled */
/*                                                                    */
/* INTERNAL REFERENCES:  none                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/
void UHCICancelAll( void )
{
   QH       *qh, *nextQH;
   TD       *td;
   USHORT   rootReqIndex;
#ifdef   DEBUG
   BOOL     noCanceled=TRUE;
#endif

   // Cancel all root hub request(s)
   for (rootReqIndex=0; rootReqIndex<ROOT_MAX_REQ; rootReqIndex++)
   {
      gRootHubRP[rootReqIndex].rph.Status=0;   //  mark as processed to free request buffer
   }
   gRootReqStatus=ROOT_HUB_NOREQ;

   // cancel all isohronous requests for all devices
   CancelIsoRequests(USB_DEFAULT_DEV_ADDR, USBCANCEL_CANCEL_ALL);

   // process all queued requests
   for (qh=gFirstBottomQH; qh; qh=nextQH)
   {
      nextQH=qh->nextBotQH;
      td=(TD *)qh->qeLinkVirt;
      if (gNextForIRQ==qh)  // advance next QH pointer for IRQ processor
         gNextForIRQ=nextQH;
      DetachQH(qh);
      FinshIO(td,TRUE);
#ifdef   DEBUG
      noCanceled=FALSE;
#endif
   }
#ifdef   DEBUG
   if (noCanceled)
      dsPrint(DBG_DETAILED,"UHCI: UHCICancelAll - no cancelled requests\r\n");
#endif
}

#ifdef   DEBUG
/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  UHCIFinIO                                        */
/*                                                                    */
/* DESCRIPTIVE NAME:  Finish I/O reqest worker routine                */
/*                                                                    */
/* FUNCTION:  This routine is used to end specific I/O request        */
/*            as it was processed by HCD - it searches for request    */
/*            on device and pipe address, detaches request from       */
/*            schedule, fills in request buffer data (if required),   */
/*            processes request.                                      */
/*                                                                    */
/* NOTES: This routine is used only for debug purposes                */
/*                                                                    */
/* CONTEXT: Task Time                                                 */
/*                                                                    */
/* ENTRY POINT :  UHCIFinIO                                           */
/*    LINKAGE  :  CALL NEAR                                           */
/*                                                                    */
/* INPUT:  RP_GENIOCTL FAR *pRP_GENIOCTL                              */
/*                                                                    */
/* EXIT-NORMAL:  n/a                                                  */
/*                                                                    */
/* EXIT-ERROR:  n/a                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  none                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/
void UHCIFinIO( RP_GENIOCTL FAR *pRP_GENIOCTL )
{
   QH             *qh, *nextQH;
   TD             *td, *currTD;
   BOOL           noFinished=TRUE;      
   USBFinIO FAR   *finishData;
   UCHAR          deviceAddress, endPointId;
   USHORT         packetSize, bufferLength, bytesToMove;
   PUCHAR         buffer;

   finishData=(USBFinIO FAR *)pRP_GENIOCTL->ParmPacket;

   dsPrint3(DBG_DETAILED,"UHCI: UHCIFinIO devAddr=%d,endpt=%d,bufflen=%d\r\n",
            finishData->deviceAddress, finishData->endPointId, finishData->bufferLength);

   for (qh=gFirstBottomQH; qh; qh=nextQH)
   {
      nextQH=qh->nextBotQH;
      td=(TD *)qh->qeLinkVirt;
      deviceAddress=td->deviceAddress;
      endPointId=td->endPointId;
      if (deviceAddress==finishData->deviceAddress && endPointId==finishData->endPointId)
      {
         if (gNextForIRQ==qh)  // advance next QH pointer for IRQ processor
            gNextForIRQ=nextQH;
         DetachQH(qh);
         if ((buffer=finishData->buffer) && (bufferLength=finishData->bufferLength))
         {   //   move specified data to I/O request data buffer
            for (currTD=td; currTD && bufferLength; currTD=currTD->virtLP)
            {
               currTD->ctrlStat&=~TD_CTRLSTAT_STATUS_ERRMASK;  // mark TD finished without errors
               if ((currTD->token&TD_TOKEN_PID_MASK)!=TD_TOKEN_PID_IN)
                  continue;
               packetSize=(USHORT)(currTD->token>>21);
               if (packetSize==USB_ZERO_PACKET)
                  continue;
               packetSize++;
               bytesToMove=bufferLength;
               if (!bytesToMove)
                  continue;
               if (bytesToMove>packetSize)
                  bytesToMove=packetSize;
               movmem((PSZ)currTD->virtBufferPointer, (PSZ)buffer, bytesToMove );
               buffer+=bytesToMove;
               bufferLength-=bytesToMove;
            }
         }
         FinshIO(td,FALSE);
         noFinished=FALSE;
      }
   }
   if (noFinished)
      dsPrint(DBG_DETAILED,"UHCI: UHCIFinIO - no requests to finish\r\n");
}
#endif

