/* SCCSID = "src/dev/usb/UHCI/UHCCTX.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:  UHCCTX.C                                              */
/*                                                                            */
/*   DESCRIPTIVE NAME:  Context thread support routines.                      */
/*                                                                            */
/*   FUNCTION: These routines handle Context Thread calls                     */
/*             for UHCI compliant device driver.                              */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*             UHCICtxHookRtn       IRQ processing CTX handler                */
/*             RHubCtxHookRtn       Root Hub CTX handler                      */
/*             IsoIRQHookRtn        Isohronous request CTX handler            */
/*                                                                            */
/*   EXTERNAL REFERENCES:													               */
/*				CheckTDQueue                                                      */
/*          UHCIRootHub                                                       */
/*          ProcessIsoIRQ                                                     */
/*                                                                            */
/* Change Log                                                                 */
/*                                                                            */
/*  Mark    yy/mm/dd  Programmer      Comment                                 */
/*  ----    --------  ----------      -------                                 */
/*          98/02/16  MB              Original developer.                     */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#include "uhci.h"

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  UHCICtxHookRtn                                   */
/*                                                                    */
/* DESCRIPTIVE NAME:  IRQ Context Thread Handler                      */
/*                                                                    */
/* FUNCTION:  This routine is called from context thread and meets    */
/*            all the kernel requirements on register saving. Calls   */
/*            CheckQHs to process completed requests.                 */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task Time                                                 */
/*                                                                    */
/* ENTRY POINT :  UHCICtxHookRtn                                      */
/*    LINKAGE  :  CALL FAR                                            */
/*                                                                    */
/* INPUT:  none                                                       */
/*                                                                    */
/* EXIT-NORMAL:  n/a                                                  */
/*                                                                    */
/* EXIT-ERROR:  n/s                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:          CheckQHs                                     */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/
#pragma optimize("eglt", off)
VOID FAR PASCAL UHCICtxHookRtn( VOID )
{
   //   save the registers
   _asm
   {
      _emit  66h
      push  si

      _emit  66h
      push  di

      _emit  66h
      push  bx
   }

#ifdef   DEBUG
   if (gInterruptFlags)
   {
      USHORT   tdIndex, wordIndex;
      LONG     *qData, phyAddress;
      USHORT   cmdReg, statusReg, portSc1Reg, portSc2Reg, frNumReg, sofModReg, intrReg;

      dsPrint1(DBG_CRITICAL, "UHCI: UHCICtxHookRtn gInterruptFlags %x\r\n",gInterruptFlags);

      inp16(gusbCmdReg,cmdReg);
      inp16(gusbStsReg,statusReg);
      inp16(gusbIntrReg,intrReg);
      inp16(gusbFrnumReg,frNumReg);
      inp16(gusbSofModReg,sofModReg);
      inp16(gusbPortSc1Reg,portSc1Reg);
      inp16(gusbPortSc2Reg,portSc2Reg);
      dsPrint4(DBG_CRITICAL, "UHCI: UHCICtxHookRtn cmdReg %0x, statusReg %0x, intrReg %0x, frNumReg %0x\r\n",
               cmdReg,statusReg,intrReg,frNumReg);
      dsPrint3(DBG_CRITICAL, "UHCI: UHCICtxHookRtn sofModReg %0x, portSc1Reg %0x, portSc2Reg %0x\r\n",
               sofModReg,portSc1Reg,portSc2Reg);
      frNumReg&=UHCI_FRNUM_MASK;
      dsPrint1(DBG_CRITICAL, "UHCI: UHCICtxHookRtn failed frame entry %0lx\r\n",
               gFrameListAddr[frNumReg]);

      for (tdIndex=0; tdIndex<gTDCount; tdIndex++)
      {
         if (gTDListStart[tdIndex].LP==UHCI_LP_UNUSED)
            continue;
         qData=(LONG *)(gTDListStart+tdIndex);
         phyAddress=gTDListStart[tdIndex].phyTDAddr;
         for (wordIndex=0; wordIndex<sizeof(TD)/sizeof(LONG); wordIndex+=4)
         {
            dsPrint1(DBG_CRITICAL, "UHCI: QH/TD %0lx ",phyAddress);
            dsPrint4(DBG_CRITICAL, " %0lx %0lx  %0lx %0lx\r\n",qData[0],qData[1], qData[2], qData[3]);
            qData+=4; phyAddress+=16;
         }
      }
   }
#endif

   CheckQHs();  // process completed requests

   if (gInterruptFlags)
   {
      if (gInterruptFlags&(UHCI_USBSTS_HCPE|UHCI_USBSTS_HSE))
      {  // serious hardware/software error detected - host stopped - proceed with host reset
         RPH      rp_reset;

         gInterruptFlags=0;   // reset interrupt flags
         gHostReset=FALSE; // reset requested

         UHCICancelAll();  // cancel all I/O requests

         setmem((PSZ)&rp_reset, 0, sizeof(rp_reset));
         UHCIInitComplete( (RPH FAR *)&rp_reset ); // reinitialize host
      }
      else
      {   //   resume detected - not yet procesed
         gInterruptFlags=0;   // reset interrupt flags
      }
   }

   // restore the registers
   _asm
   {
      _emit  66h
      pop   bx

      _emit  66h
      pop   di

      _emit  66h
      pop   si
   }
}
#pragma optimize("", on)

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  RHubCtxHookRtn                                   */
/*                                                                    */
/* DESCRIPTIVE NAME:  Root hub Context Thread Handler                 */
/*                                                                    */
/* FUNCTION:  This routine is called from context thread and meets    */
/*            all the kernel requirements on register saving. Calls   */
/*            UHCIRootHub to process Root Hub requests.               */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task Time                                                 */
/*                                                                    */
/* ENTRY POINT :  RHubCtxHookRtn                                      */
/*    LINKAGE  :  CALL FAR                                            */
/*                                                                    */
/* INPUT:  none                                                       */
/*                                                                    */
/* EXIT-NORMAL:  n/a                                                  */
/*                                                                    */
/* EXIT-ERROR:  n/s                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:          UHCIRootHub                                  */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/
#pragma optimize("eglt", off)
VOID FAR PASCAL RHubCtxHookRtn( VOID )
{
   //   save the registers
   _asm
   {
      ;mov   npACB, ax

      _emit  66h
      push  si

      _emit  66h
      push  di

      _emit  66h
      push  bx
   }

   if (gRootReqStatus==ROOT_HUB_REQ)
   {
      USHORT   rootReqIndex;
      BOOL     allRequestsFinished=TRUE;

      for (rootReqIndex=0; rootReqIndex<ROOT_MAX_REQ; rootReqIndex++)
      {
         if (gRootHubRP[rootReqIndex].rph.Status)
            UHCIRootHub( (RP_GENIOCTL FAR *)&gRootHubRP[rootReqIndex] );  // process root hub request
      }
      for (rootReqIndex=0; rootReqIndex<ROOT_MAX_REQ; rootReqIndex++)
      {
         if (gRootHubRP[rootReqIndex].rph.Status)
            allRequestsFinished=FALSE;
      }
      if (allRequestsFinished)
         gRootReqStatus=ROOT_HUB_NOREQ;
   }

   // restore the registers
   _asm
   {
      _emit  66h
      pop   bx

      _emit  66h
      pop   di

      _emit  66h
      pop   si
   }
}
#pragma optimize("", on)

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  AddIsoHookRtn                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Root hub Context Thread Handler                 */
/*                                                                    */
/* FUNCTION:  This routine is called from context thread and meets    */
/*            all the kernel requirements on register saving. Calls   */
/*            UHCIRootHub to process Root Hub requests.               */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task Time                                                 */
/*                                                                    */
/* ENTRY POINT :  AddIsoHookRtn                                       */
/*    LINKAGE  :  CALL FAR                                            */
/*                                                                    */
/* INPUT:  none                                                       */
/*                                                                    */
/* EXIT-NORMAL:  n/a                                                  */
/*                                                                    */
/* EXIT-ERROR:  n/s                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:          UHCIRootHub                                  */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/
#pragma optimize("eglt", off)
VOID FAR PASCAL AddIsoHookRtn( VOID )
{
   //   save the registers
   _asm
   {
      _emit  66h
      push  si

      _emit  66h
      push  di

      _emit  66h
      push  bx
   }

   AddIsoBuffsToSchedule();

   // restore the registers
   _asm
   {
      _emit  66h
      pop   bx

      _emit  66h
      pop   di

      _emit  66h
      pop   si
   }
}
#pragma optimize("", on)

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  IsoIRQHookRtn                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Isohronous Request proceesin Context            */
/*                    Thread Handler                                  */
/*                                                                    */
/* FUNCTION:  This routine is called from context thread and meets    */
/*            all the kernel requirements on register saving. Calls   */
/*            ProcessIsoIRQ to process finished isohronous requests.  */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task Time                                                 */
/*                                                                    */
/* ENTRY POINT :  IsoIRQHookRtn                                       */
/*    LINKAGE  :  CALL FAR                                            */
/*                                                                    */
/* INPUT:  none                                                       */
/*                                                                    */
/* EXIT-NORMAL:  n/a                                                  */
/*                                                                    */
/* EXIT-ERROR:  n/s                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:          ProcessIsoIRQ                                */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/
#pragma optimize("eglt", off)
VOID FAR PASCAL IsoIRQHookRtn( VOID )
{
   //   save the registers
   _asm
   {
      _emit  66h
      push  si

      _emit  66h
      push  di

      _emit  66h
      push  bx
   }

   ProcessIsoIRQ();

   // restore the registers
   _asm
   {
      _emit  66h
      pop   bx

      _emit  66h
      pop   di

      _emit  66h
      pop   si
   }
}
#pragma optimize("", on)

