/* SCCSID = "src/dev/usb/UHCI/UHCTIME.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:  UHCTIME.C                                             */
/*                                                                            */
/*   DESCRIPTIVE NAME:  UHCI Compliant USB Host Controller driver time        */
/*                      service routines.                                     */
/*                                                                            */
/*   FUNCTION: These routines handle the miscellaneous utility functions      */
/*             for the USB UHCI host device driver.                           */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*             IODelay                                                        */
/*             TimeExecutionStall                                             */
/*             USBExecutionStall                                              */
/*             UHCIRootHubTimer                                               */
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*                                                                            */
/* Change Log                                                                 */
/*                                                                            */
/*  Mark    yy/mm/dd  Programmer      Comment                                 */
/*  ----    --------  ----------      -------                                 */
/*          96/03/01  Frank Schroeder Original developer.                     */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#include "uhci.h"

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  IODelay                                          */
/*                                                                    */
/* DESCRIPTIVE NAME:  Delay execution for 500 ns.                     */
/*                                                                    */
/* FUNCTION:  The function of this routine is to delay execution      */
/*            for 500 ns.                                             */
/*                                                                    */
/* NOTES:  DOSIODELAYCNT is an absolute fixup.  See .DEF file.        */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT:  IODelay                                              */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: None                                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
#pragma optimize("eglt", off)
void  IODelay( void )
{
   extern   USHORT DOSIODELAYCNT;
   _asm
   {
      mov   ax, OFFSET DOSIODELAYCNT
      top:  dec   ax
      jnz   top
   }
}
#pragma optimize("", on)


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  TimeExecutionStall                               */
/*                                                                    */
/* DESCRIPTIVE NAME:  Delay execution for multiples of 500 ns.        */
/*                                                                    */
/* FUNCTION:  The function of this routine is to delay execution      */
/*            for a period of time equal to a multiple of 500 ns.     */
/*                                                                    */
/* NOTES:  DOSIODELAYCNT is an absolute fixup.  See .DEF file.        */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT:  TimeExecutionDelay                                   */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  USHORT    delay    - multiple of 500 ns                    */
/*                              1   = 500 ns                          */
/*                              2   = 1 ms                            */
/*                              20  = 10 ms                           */
/*                              200 = 100 ms                          */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: None                                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
#pragma optimize("eglt", off)
void  TimeExecutionStall( USHORT delay )
{
   extern   USHORT DOSIODELAYCNT;
   _asm
   {
      mov   ax, OFFSET DOSIODELAYCNT
      mul   delay
      top:  dec   ax
      jnz   top
   }
}
#pragma optimize("", on)

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  USBExecutionStall                                */
/*                                                                    */
/* DESCRIPTIVE NAME:  Delay execution for multiples of 1 ms.          */
/*                                                                    */
/* FUNCTION:  The function of this routine is to delay execution      */
/*            for a period of time equal to a multiple of 1 ms.       */
/*                                                                    */
/* NOTES:  implementation is based on USB host frame index register   */
/*         changes. In case host is not running (and frame index is   */
/*         not changing) routine exits immediately.                   */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT:  USBExecutionStall                                    */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  USHORT    delay    - multiple of 1 ms                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: None                                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
#pragma optimize("eglt", off)
void  USBExecutionStall( USHORT delay )
{
   USHORT   usbCMD, prevFrNum, frNum;

   inp16(gusbFrnumReg, prevFrNum);
   for (;delay;)
   {
      inp16(gusbCmdReg, usbCMD);
      if (!(usbCMD&UHCI_USBCMD_RS))  // exit if host not running
         break;
      inp16(gusbFrnumReg, frNum);
      if (prevFrNum!=frNum)
      {
         delay--; // decrease millisecond count when frame number has been changed
         prevFrNum=frNum;
      }
   }
}
#pragma optimize("", on)

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  UHCIRootHubTimer                                 */
/*                                                                    */
/* DESCRIPTIVE NAME:  Root hub request processing timer routine       */
/*                                                                    */
/* FUNCTION:  This routine                                            */
/*            1) checks root hub request block and calls              */
/*               worker routine to process uncompleted request.       */
/*            2) processes default address request timeouts.          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Timer Interrupt Time                                      */
/*                                                                    */
/* ENTRY POINT :  UHCIRootHubTimer                                    */
/*    LINKAGE  :  CALL FAR                                            */
/*                                                                    */
/* INPUT:  none                                                       */
/*                                                                    */
/* EXIT-NORMAL:  none                                                 */
/*                                                                    */
/* EXIT-ERROR:  none                                                  */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  UHCIRootHub                                  */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/
void FAR UHCIRootHubTimer()
{
   if (gHostReset)
   {
      if (gRootReqStatus==ROOT_HUB_REQ)
      {
         DevHelp_ArmCtxHook( 0, gRHubHookHandle );  // claim root hub request processing
      }

      if (!g0Time)
      {  // default address request timed out
         if (g0QH)
            DefAddrTimeOut(); // reset default address request
      }
      else
         g0Time--;   // decrease timeout value
   }
}
