/*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.                                */
/*                                                                           */
/*****************************************************************************/
/*static char *SCCSID = "src/dev/dasd/os2scsi/sccrttsb.c, scsy, ddk_subset, b_bdd.032 93/03/19";*/
/*************************************************************************
 *
 * SOURCE FILE NAME =   SCCRTTSB.C
 *
 * DESCRIPTIVE NAME = OS2SCSI.DMD - OS/2 SCSI.SYS Emulation
 *                    IORB error code to IBM TSB translation
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION     This routine creates Termination Status Block from IORB
 *                 Status, Error Code, Status Block, and Sense Data.
 *
 *
*/

#define INCL_NOBASEAPI
#define INCL_NOPMAPI
#include "os2.h"
#include "strat2.h"
#include "dhcalls.h"
#include "reqpkt.h"
#include "scb.h"
#include "iorb.h"
#include "scsi.h"
#include "scscsi.h"
#include "scgen.h"
#include "abios.h"
#include "scproto.h"

extern UNITCB     UnitCB[1];               /* First UnitCB allocated here    */

/********************** START OF SPECIFICATIONS *****************************
*                                                                           *
* SUBROUTINE NAME:  CreateTSB                                               *
*                                                                           *
* DESCRIPTIVE NAME: Create TSB                                              *
*                                                                           *
* FUNCTION:         This routine creates Termination Status Block from      *
*                   Status, Error Code, Status Block, and Sense Data.       *
*                                                                           *
* ENTRY POINT:      CreateTSB                                               *
*                                                                           *
* LINKAGE:          Call Near                                               *
*                                                                           *
* INPUT:                                                                    *
*                                                                           *
* EXIT-NORMAL:      Status                                                  *
*                                                                           *
* EXIT-ERROR:       Status                                                  *
*                                                                           *
*                                                                           *
* The following is the details of this routine.                             *
*                                                                           *
*  Status => IORB_DONE    SCB Status               SCB Ended                *
*                         Retry Count              0                        *
*                         Residual Byte Count      0                        *
*                         S/G List Element Addr    ?                        *
*                         Stauts Length            0                        *
*                                                                           *
*  Status => IORB_ERROR                                                     *
*                                                                           *
*      IOERR_CMD                                                            *
*                                                                           *
*                                                                           *
*                                                                           *
*                                                                           *
*                                                                           *
*********************** END OF SPECIFICATIONS *******************************/

#define IOERR_DETAIL_MASK     0xFF00


void near CreateTSB(npUCB, pTSB)

NPUCB            npUCB;
PTSB             pTSB;
{
  USHORT        errorcode;

  if (!(npUCB->LastStatus & IORB_ERROR))    /* No error */
  {
     pTSB->Retries     = 0;
     pTSB->ResidCnt    = 0;
     pTSB->ppResidBuf  = 0;
     pTSB->SCSIStatus  = SCSI_STAT_GOOD;
     pTSB->CmdError    = CE_NO_ERROR;
     pTSB->DevError    = DE_NO_ERROR;

     if (!npUCB->ppLastSCB)       /* Immediate command */
     {
        pTSB->Status      = TSBSfNOERR | TSBSfINTREQ;
        pTSB->CmdStatus   = CS_IMM_CMD_COMP;
        pTSB->StatusLen   = 0x04;
     }
     else                                       /* SCB command */
     {
        pTSB->Status      = TSBSfNOERR | TSBSfHALT | TSBSfINTREQ | TSBSfSTATF;
        pTSB->DiagMod     = 0;
        pTSB->CacheInfo   = 0;
        pTSB->CmdStatus   = CS_COMP_W_SUCCESS;

        pTSB->StatusLen   = 0x0C;
        pTSB->ppLastSCB   = npUCB->ppLastSCB;
     }
  }
  else                                          /* Error */
  {
     pTSB->Status = TSBSfHALT | TSBSfINTREQ | TSBSfSTATF | TSBSfEXCEPT;

     if (npUCB->LastErrCode & IOERR_RETRY)
        pTSB->Retries = RC_SYSTEN_CHECK_RETRY;
     else
        pTSB->Retries = 0;

     if ((npUCB->LastStatus & IORB_STATUSBLOCK_AVAIL) &&
         (npUCB->LastSSB.Flags & STATUS_RESIDUAL_VALID))
        pTSB->ResidCnt = npUCB->LastSSB.ResidualLength;
     else
        pTSB->ResidCnt = 0;

     pTSB->ppResidBuf = 0;

     if (npUCB->LastStatus & IORB_STATUSBLOCK_AVAIL)
        pTSB->SCSIStatus = npUCB->LastSSB.TargetStatus;
     else
        pTSB->SCSIStatus = SCSI_STAT_GOOD;

     pTSB->ppLastSCB = npUCB->ppLastSCB;


     errorcode = npUCB->LastErrCode;

     switch (errorcode & IORB_ERR_MASK)
     {
        case (IOERR_CMD):

           pTSB->CmdStatus = CS_COMMAND_ERROR;
           pTSB->DevError  = DE_NO_ERROR;

           switch (errorcode)
           {
              case (IOERR_CMD_NOT_SUPPORTED):
                 pTSB->CmdError = CE_CMD_NOT_SUPPORT;
                 break;

              case (IOERR_CMD_SYNTAX):
                 pTSB->CmdError = CE_INVALID_PARM;
                 break;

              case (IOERR_CMD_SGLIST_BAD):
                 pTSB->CmdError = CE_INVALID_PARM;
                 break;

              case (IOERR_CMD_SW_RESOURCE):
                 pTSB->CmdError = CE_NO_ERROR;
                 break;

              case (IOERR_CMD_ABORTED):
                 pTSB->CmdError = CE_CMD_ABORT;
                 break;
           }
           pTSB->DiagMod   = 0;
           pTSB->CacheInfo = 0;
           pTSB->StatusLen = 0x0C;

        break;

        case (IOERR_UNIT):

           pTSB->CmdStatus = CS_SW_SEQUENCE_ERROR;
           pTSB->DevError  = DE_NO_ERROR;
           pTSB->CmdError  = CE_NO_ERROR;
           pTSB->DiagMod   = 0;
           pTSB->CacheInfo = 0;
           pTSB->StatusLen = 0x0C;

        break;

        case (IOERR_RBA):

           pTSB->CmdStatus = CS_COMMAND_ERROR;
           pTSB->DevError  = DE_NO_ERROR;

           switch (errorcode)
           {
              case (IOERR_RBA_LIMIT):
                 pTSB->CmdError = CE_MAX_LBA_EXCEED;
                 break;

              default:
                 pTSB->CmdError = CE_INVALID_PARM;
                 break;
           }
           pTSB->DiagMod   = 0;
           pTSB->CacheInfo = 0;
           pTSB->StatusLen = 0x0C;

        break;

        case (IOERR_MEDIA):

           pTSB->CmdStatus = CS_COMP_W_FAILURE;
           pTSB->DevError  = DE_NO_ERROR;
           pTSB->CmdError  = CE_NO_ERROR;
           pTSB->DiagMod   = 0;
           pTSB->CacheInfo = 0;
           pTSB->StatusLen = 0x0C;

        break;

        case (IOERR_ADAPTER):

           pTSB->CmdStatus = CS_ADAPTER_HW_ERROR;
           pTSB->CmdError  = CE_ADAPTER_HW_ERR;
           pTSB->DevError  = DE_NO_ERROR;

           switch (errorcode)
           {
              case (IOERR_ADAPTER_TIMEOUT):
                 pTSB->CmdError = CE_GLOBAL_CMD_TIMEOUT;
                 break;

              case (IOERR_ADAPTER_DEVICE_TIMEOUT):
                 pTSB->DevError = DE_SCSI_SELCT_TIMEOUT;
                 break;

              case (IOERR_ADAPTER_REQ_NOT_SUPPORTED):
                 pTSB->CmdError = CE_CMD_NOT_SUPPORT;
                 break;

              case (IOERR_ADAPTER_REFER_TO_STATUS):
                                            /* default error TSB */
                 break;
           }
           pTSB->DiagMod   = 0;
           pTSB->CacheInfo = 0;
           pTSB->StatusLen = 0x0C;

        break;

        case (IOERR_DEVICE):

           pTSB->CmdStatus = CS_COMP_W_FAILURE;
           pTSB->CmdError  = CE_NO_ERROR;

           switch (errorcode)
           {
              case (IOERR_DEVICE_REQ_NOT_SUPPORTED):
                 pTSB->CmdError = CE_CMD_NOT_SUPPORT;
                 pTSB->DevError = DE_NO_ERROR;
                 break;

              case (IOERR_DEVICE_BUSY):
                 pTSB->DevError = DE_NO_ERROR;
                 break;

              default:
                 pTSB->DevError = DE_SCSI_INTF_FAULT;
                 break;
           }
           pTSB->DiagMod   = 0;
           pTSB->CacheInfo = 0;
           pTSB->StatusLen = 0x0C;

        break;

        default:
           pTSB->CmdStatus = CS_COMMAND_ERROR;
           pTSB->DevError  = DE_NO_ERROR;
           pTSB->CmdError  = CE_NO_ERROR;
           pTSB->DiagMod   = 0;
           pTSB->CacheInfo = 0;
           pTSB->StatusLen = 0x0C;
        break;
     }
                                       /* Imm. cmd or failed to get SCB addr */
     if (!pTSB->ppLastSCB)
        pTSB->StatusLen = 0x08;

  }
  return;


}

void far  f_CreateTSB(npUCB, pTSB)
NPUCB            npUCB;
PTSB             pTSB;
{
  CreateTSB(npUCB, pTSB);

}
