home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / OS2SCSI / SCSUBRS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  43.6 KB  |  1,018 lines

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  4. /*                                                                           */
  5. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  6. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  7. /*    drivers. You may use this code in accordance with the IBM License      */
  8. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  9. /*    Copyright statement may not be removed.                                */
  10. /*                                                                           */
  11. /*****************************************************************************/
  12. /*static char *SCCSID = "src/dev/dasd/os2scsi/scsubrs.c, scsy, ddk_subset, b_bdd.032 93/08/25";*/
  13. /**************************************************************************
  14.  *
  15.  * SOURCE FILE NAME = SCSUBRS.C
  16.  *
  17.  * DESCRIPTIVE NAME = OS2SCSI.DMD - OS/2 SCSI.SYS Emulation
  18.  *
  19.  *
  20.  *
  21.  * VERSION = V2.0
  22.  *
  23.  * DATE
  24.  *
  25.  * DESCRIPTION : IORB Management and miscellaneous functions.
  26.  *
  27.  *
  28.  *
  29. */
  30.  
  31. #define INCL_NOBASEAPI
  32. #define INCL_NOPMAPI
  33. #include "os2.h"
  34. #include "error.h"
  35. #include "strat2.h"
  36. #include "reqpkt.h"
  37. #include "dhcalls.h"
  38. #include "SCB.h"
  39. #include "iorb.h"
  40. #include "scsi.h"
  41. #include "scscsi.h"
  42. #include "scgen.h"
  43. #include "abios.h"
  44. #include "scproto.h"
  45.  
  46.  
  47. extern UNITCB      UnitCB[1];              /* First UnitCB allocated here    */
  48. extern USHORT      NumUnitCBs;             /* number of unit control blocks  */
  49. extern NPSELARRAY  npSelArray;             /* near ptr to GDT selector array */
  50. extern ULONG       plDataSeg;              /* near ptr to GDT selector array */
  51. extern USHORT      GDTSelStack[];
  52. extern USHORT      GDTSelStackPtr;
  53.  
  54.  
  55. /********************** START OF SPECIFICATIONS *****************************
  56. *                                                                           *
  57. * SUBROUTINE NAME:  SetAdditionalData                                       *
  58. *                                                                           *
  59. * DESCRIPTIVE NAME: Set Additional Data segment area                        *
  60. *                                                                           *
  61. * FUNCTION:         This routine allocates request queues for each unit, and*
  62. *                   allocates GDT selector array.                           *
  63. *                                                                           *
  64. * ENTRY POINT:      SetAdditionalData                                       *
  65. *                                                                           *
  66. * LINKAGE:          Call Near                                               *
  67. *                                                                           *
  68. * INPUT:            None                                                    *
  69. *                                                                           *
  70. * EXIT-NORMAL:      The final size of DATA segment                          *
  71. *                                                                           *
  72. * EXIT-ERROR:       0 => Devhelp function failed                            *
  73. *                                                                           *
  74. *********************** END OF SPECIFICATIONS *******************************/
  75.  
  76. USHORT near SetAdditionalData()
  77. {
  78.   USHORT   i;
  79.   NPBYTE   npEndData;
  80.  
  81.   npEndData  = (NPBYTE)UnitCB;
  82.   npEndData += (sizeof(UNITCB) * (BYTE)NumUnitCBs);
  83.  
  84.   npSelArray = (NPSELARRAY)npEndData;
  85.  
  86.   npEndData += (sizeof(SEL) * (BYTE)NumUnitCBs);
  87.  
  88.   DevHelp_AllocGDTSelector((PSEL)npSelArray, NumUnitCBs);
  89.  
  90.   DevHelp_AllocGDTSelector((PSEL) &GDTSelStack[1], MAX_GDT_SEL_STACK);
  91.  
  92.   return((USHORT)npEndData);
  93.  
  94. }
  95.  
  96. /********************** START OF SPECIFICATIONS *****************************
  97. *                                                                           *
  98. * SUBROUTINE NAME:  WaitIORB                                                *
  99. *                                                                           *
  100. * DESCRIPTIVE NAME: Wait for IORB until available                           *
  101. *                                                                           *
  102. * FUNCTION:         This routine check wether IORB is in use or not,        *
  103. *                   and wait for IORB until available.                      *
  104. *                                                                           *
  105. * ENTRY POINT:      WaitIORB                                                *
  106. *                                                                           *
  107. * LINKAGE:          Call Near                                               *
  108. *                                                                           *
  109. * INPUT:            pGenctl   Pointer to Generic I/O Control request packet *
  110. *                                                                           *
  111. * EXIT-NORMAL:      TRUE                                                    *
  112. *                                                                           *
  113. *                                                                           *
  114. * EXIT-ERROR:       FALSE       Devhelp error                               *
  115. *                   REQ_FLUSHED Request is flushed                          *
  116. *                                                                           *
  117. * Notes:            Called at TASK TIME                                     *
  118. *                                                                           *
  119. *********************** END OF SPECIFICATIONS *******************************/
  120.  
  121. BOOL near WaitIORB(pGenctl, EntryType)
  122. USHORT           EntryType;
  123. PRP_GENIOCTL     pGenctl;
  124. {
  125.   USHORT       bottom;
  126.   USHORT       rc;
  127.   USHORT       status    = 0;
  128.   USHORT       allocated = FALSE;
  129.   NPUCB        npUCB;
  130.   PSCSI_IN     pParm;
  131.  
  132.   pParm  = (PSCSI_IN)(pGenctl->ParmPacket);
  133.  
  134.   npUCB  = &UnitCB[pParm->hDev];
  135.  
  136.   /*--------------------------------------------------*/
  137.   /* Requesting threads are blocked here waiting for  */
  138.   /* the device. A thread may wakeup from the block   */
  139.   /* under the following conditions:                  */
  140.   /*                                                  */
  141.   /* 1.) The underlying process was aborted.          */
  142.   /* 2.) The driver is flushing the queues for this   */
  143.   /*     device.                                      */
  144.   /* 3.) The request has timed out.                   */
  145.   /* 4.) A spurious wakeup occurred.                  */
  146.   /*--------------------------------------------------*/
  147.  
  148.   npUCB->WaitReqCnt++;
  149.  
  150.   while ( npUCB->IntUnitFlags & IUF_IORB_BUSY )
  151.   {
  152.      rc = DevHelp_ProcBlock((ULONG) (PUSHORT)  &npUCB->WaitReqCnt,
  153.                                     (ULONG)    MAX_REQ_WAIT,
  154.                                     (USHORT)   WAIT_IS_INTERRUPTABLE  );
  155.  
  156.      /*------------------------------------------------*/
  157.      /* If the request has timed out, then put it on a */
  158.      /* FIFO queue of timed out requests. This queue   */
  159.      /* will be serviced before the general queue      */
  160.      /*------------------------------------------------*/
  161.  
  162.      if ( rc == WAIT_TIMED_OUT )
  163.      {
  164.         rc = HoldInTimeOutQ( npUCB, pGenctl );
  165.      }
  166.  
  167.  
  168.      if (npUCB->IntUnitFlags & IUF_REQ_FLUSH)
  169.      {
  170.         if (!(npUCB->WaitReqCnt--))
  171.            npUCB->IntUnitFlags &= ~IUF_REQ_FLUSH;
  172.  
  173.         status = REQ_FLUSHED;
  174.         break;
  175.      }
  176.  
  177.      /*------------------------------------------------*/
  178.      /* If the request was aborted. Then just return   */
  179.      /* it to the caller.                              */
  180.      /*------------------------------------------------*/
  181.  
  182.      if ( rc == WAIT_INTERRUPTED )
  183.      {
  184.         npUCB->WaitReqCnt--;
  185.  
  186.         /*--------------------------------------------------*/
  187.         /* The current drivers IBM drivers do not handle    */
  188.         /* INTERRUPTED requests. Return request as FLUSHED  */
  189.         /* instead.                                         */
  190.         /*--------------------------------------------------*/
  191.  
  192.         status = REQ_FLUSHED /* REQ_INTERRUPTED */;
  193.         break;
  194.      }
  195.  
  196.   }
  197.  
  198.   /*-----------------------------------------------*/
  199.   /* If this is a normal wakeup and the queues are */
  200.   /* not being flushed. Then start-up this request */
  201.   /*-----------------------------------------------*/
  202.  
  203.   if ( !status )
  204.   {
  205.      npUCB->IntUnitFlags |= IUF_IORB_BUSY;
  206.  
  207.      if (ValidateUserPacket(pGenctl, npUCB, EntryType))
  208.         status = TRUE;
  209.      else
  210.      {
  211.         ReleaseIORB(pGenctl);
  212.         status = FALSE;
  213.      }
  214.   }
  215.  
  216.   return ( status );
  217. }
  218.  
  219.  
  220. /********************** START OF SPECIFICATIONS *****************************
  221. *                                                                           *
  222. * SUBROUTINE NAME:  ReleaseIORB                                             *
  223. *                                                                           *
  224. * DESCRIPTIVE NAME: Release request from the queue.                         *
  225. *                                                                           *
  226. * FUNCTION:         This routine removes the request already done from the  *
  227. *                   queue.                                                  *
  228. *                                                                           *
  229. * ENTRY POINT:      ReleaseQueue                                            *
  230. *                                                                           *
  231. * LINKAGE:          Call Near                                               *
  232. *                                                                           *
  233. * INPUT:            pGenctl   Pointer to Generic I/O Control request packet *
  234. *                                                                           *
  235. * EXIT-NORMAL:                                                              *
  236. *                                                                           *
  237. * EXIT-ERROR:                                                               *
  238. *                                                                           *
  239. * Notes:            Called at TASK TIME                                     *
  240. *                                                                           *
  241. *********************** END OF SPECIFICATIONS *******************************/
  242.  
  243. void near ReleaseIORB(pGenctl)
  244. PRP_GENIOCTL     pGenctl;
  245. {
  246.   NPUCB         npUCB;
  247.   ULONG         BlockId;
  248.   USHORT        AwakeCount;
  249.   PSCSI_IN      pParm;
  250.  
  251.   pParm = (PSCSI_IN)(pGenctl->ParmPacket);
  252.   npUCB = &UnitCB[pParm->hDev];
  253.  
  254.   npUCB->WaitReqCnt--;
  255.  
  256.   UnlockUserPacket(npUCB);
  257.  
  258.   npUCB->IntUnitFlags &= ~IUF_IORB_BUSY;
  259.  
  260.   /*----------------------------------------*/
  261.   /* If there are requests waiting, then    */
  262.   /* run the request at the head of the     */
  263.   /* TimeOut Q first. Then run the normal   */
  264.   /* requests.                              */
  265.   /*----------------------------------------*/
  266.  
  267.   if ( npUCB->WaitReqCnt )
  268.   {
  269.     BlockId = ( npUCB->TimeOutQHead ) ? (ULONG)           npUCB->TimeOutQHead
  270.                                       : (ULONG) (PULONG) &npUCB->WaitReqCnt;
  271.  
  272.     DevHelp_ProcRun((ULONG) BlockId, &AwakeCount);
  273.   }
  274.  
  275.  
  276.   return;
  277.  
  278. }
  279.  
  280. /********************** START OF SPECIFICATIONS *****************************
  281. *                                                                           *
  282. * SUBROUTINE NAME:  WaitOtherIORB                                           *
  283. *                                                                           *
  284. * DESCRIPTIVE NAME: Wait for IORB until available                           *
  285. *                                                                           *
  286. * FUNCTION:         This routine check whether the Other IORB is in use     *
  287. *                   or not and waits for the IORB to become available.      *
  288. *                                                                           *
  289. * ENTRY POINT:      WaitOtherIORB                                           *
  290. *                                                                           *
  291. * LINKAGE:          Call Near                                               *
  292. *                                                                           *
  293. * INPUT:                                                                    *
  294. *                                                                           *
  295. * EXIT-NORMAL:                                                              *
  296. *                                                                           *
  297. *                                                                           *
  298. * EXIT-ERROR:                                                               *
  299. *                                                                           *
  300. * Notes:            Called at TASK TIME                                     *
  301. *                                                                           *
  302. *********************** END OF SPECIFICATIONS *******************************/
  303.  
  304. void near WaitOtherIORB( npUCB )
  305.  
  306. NPUCB           npUCB;
  307. {
  308.  
  309.   npUCB->OtherReqCnt++;
  310.  
  311.   while ( npUCB->IntUnitFlags & IUF_OTHERIORB_BUSY )
  312.   {
  313.      DevHelp_ProcBlock((ULONG)(PUSHORT)  &npUCB->OtherReqCnt,
  314.                               (ULONG)    -1,
  315.                               (USHORT)   WAIT_IS_NOT_INTERRUPTABLE  );
  316.   }
  317.   ENABLE
  318.  
  319.   npUCB->IntUnitFlags |= IUF_OTHERIORB_BUSY;
  320.  
  321.   return;
  322. }
  323.  
  324.  
  325. /********************** START OF SPECIFICATIONS *****************************
  326. *                                                                           *
  327. * SUBROUTINE NAME:  ReleaseOtherIORB                                        *
  328. *                                                                           *
  329. * DESCRIPTIVE NAME: Release the Other IORB.                                 *
  330. *                                                                           *
  331. * FUNCTION:         This routine indicates the OtherIORB is available       *
  332. *                                                                           *
  333. * ENTRY POINT:      ReleaseOtherIORB                                        *
  334. *                                                                           *
  335. * LINKAGE:          Call Near                                               *
  336. *                                                                           *
  337. * INPUT:                                                                    *
  338. *                                                                           *
  339. * EXIT-NORMAL:                                                              *
  340. *                                                                           *
  341. * EXIT-ERROR:                                                               *
  342. *                                                                           *
  343. * Notes:            Called at TASK TIME                                     *
  344. *                                                                           *
  345. *********************** END OF SPECIFICATIONS *******************************/
  346.  
  347. void near ReleaseOtherIORB( npUCB )
  348.  
  349. NPUCB           npUCB;
  350. {
  351.   USHORT        AwakeCount;
  352.  
  353.  
  354.   npUCB->OtherReqCnt--;
  355.  
  356.   if ( npUCB->OtherReqCnt )
  357.   {
  358.      DevHelp_ProcRun((ULONG) (PUSHORT) &npUCB->OtherReqCnt, &AwakeCount);
  359.   }
  360.  
  361.   npUCB->IntUnitFlags &= ~IUF_OTHERIORB_BUSY;
  362.  
  363.   return;
  364.  
  365. }
  366.  
  367.  
  368. /********************** START OF SPECIFICATIONS *****************************
  369. *                                                                           *
  370. * SUBROUTINE NAME:  FlushQueue                                              *
  371. *                                                                           *
  372. * DESCRIPTIVE NAME: Flush the requests from the queue                       *
  373. *                                                                           *
  374. * FUNCTION:         This routine flush the request from the queue           *
  375. *                                                                           *
  376. * ENTRY POINT:      FlushQueue                                              *
  377. *                                                                           *
  378. * LINKAGE:          Call Near                                               *
  379. *                                                                           *
  380. * INPUT:            npUCB     Unit Control Block                            *
  381. *                                                                           *
  382. * EXIT_NORMAL:      always                                                  *
  383. *                                                                           *
  384. * EXIT-ERROR:                                                               *
  385. *                                                                           *
  386. * Notes:            Called at TASK TIME                                     *
  387. *                                                                           *
  388. *********************** END OF SPECIFICATIONS *******************************/
  389.  
  390. void near FlushReqPkt(npUCB)
  391.  
  392. NPUCB            npUCB;
  393. {
  394.   USHORT     AwakeCount;
  395.   NPQELE     npQEle;
  396.  
  397.  
  398.   if (npUCB->WaitReqCnt > 1)
  399.   {
  400.      npUCB->IntUnitFlags |= IUF_REQ_FLUSH;
  401.  
  402.      /*---------------------------------*/
  403.      /* Flush requests on the TimeOut Q */
  404.      /*---------------------------------*/
  405.  
  406.      for (npQEle=npUCB->TimeOutQHead; npQEle; npQEle=npQEle->Next )  /*@V73138*/
  407.      {
  408.         DevHelp_ProcRun((ULONG)(PVOID) npQEle, &AwakeCount);
  409.      }
  410.      DevHelp_ProcRun((ULONG)((PIORB) &npUCB->XferSCB_IORB), &AwakeCount);
  411.   }
  412.   return;
  413. }
  414.  
  415.  
  416. /********************** START OF SPECIFICATIONS *****************************
  417. *                                                                           *
  418. * SUBROUTINE NAME:  HoldInTimeOutQueue                                      *
  419. *                                                                           *
  420. * DESCRIPTIVE NAME:                                                         *
  421. *                                                                           *
  422. * FUNCTION:                                                                 *
  423. *                                                                           *
  424. *                                                                           *
  425. * ENTRY POINT:                                                              *
  426. *                                                                           *
  427. * LINKAGE:          Call Near                                               *
  428. *                                                                           *
  429. * INPUT:            pGenctl   Pointer to Generic I/O Control request packet *
  430. *                                                                           *
  431. * EXIT-NORMAL:                                                              *
  432. *                                                                           *
  433. * EXIT-ERROR:                                                               *
  434. *                                                                           *
  435. * Notes:            Called at TASK TIME                                     *
  436. *                                                                           *
  437. *********************** END OF SPECIFICATIONS *******************************/
  438.  
  439. USHORT near HoldInTimeOutQ(npUCB, pGenctl)
  440.  
  441. NPUCB            npUCB;
  442. PRP_GENIOCTL     pGenctl;
  443. {
  444.   USHORT rc;
  445.   NPQELE npQEle;
  446.  
  447.   if ( !(npUCB->IntUnitFlags & IUF_IORB_BUSY) )
  448.   {
  449.     return ( 0 );
  450.   }
  451.  
  452.   if ( !( npQEle=AddToTimeOutQ( npUCB, pGenctl ) ) )
  453.   {
  454.      return( 1 );
  455.   }
  456.  
  457.   do
  458.   {
  459.      rc = DevHelp_ProcBlock((ULONG) (PVOID) npQEle,
  460.                             (ULONG) -1,
  461.                             (USHORT) WAIT_IS_INTERRUPTABLE );
  462.   }
  463.  
  464.   while (   !rc
  465.          && !(npUCB->IntUnitFlags & IUF_REQ_FLUSH)
  466.          &&  (npUCB->IntUnitFlags & IUF_IORB_BUSY     )  );
  467.  
  468.   if ( RemoveFromTimeOutQ( npUCB, npQEle ) )
  469.   {
  470.      _asm { int 3 }
  471.   }
  472.  
  473.   return ( rc );
  474. }
  475.  
  476. /********************** START OF SPECIFICATIONS *****************************
  477. *                                                                           *
  478. * SUBROUTINE NAME:  AddToTimeOutQ                                           *
  479. *                                                                           *
  480. * DESCRIPTIVE NAME:                                                         *
  481. *                                                                           *
  482. * FUNCTION:                                                                 *
  483. *                                                                           *
  484. *                                                                           *
  485. * ENTRY POINT:                                                              *
  486. *                                                                           *
  487. * LINKAGE:          Call Near                                               *
  488. *                                                                           *
  489. * INPUT:            pGenctl   Pointer to Generic I/O Control request packet *
  490. *                                                                           *
  491. * EXIT-NORMAL:                                                              *
  492. *                                                                           *
  493. * EXIT-ERROR:                                                               *
  494. *                                                                           *
  495. * Notes:            Called at TASK TIME                                     *
  496. *                                                                           *
  497. *********************** END OF SPECIFICATIONS *******************************/
  498.  
  499. NPQELE AddToTimeOutQ(npUCB, pGenctl)
  500.  
  501. NPUCB            npUCB;
  502. PRP_GENIOCTL     pGenctl;
  503. {
  504.   NPQELE npQEle;
  505.  
  506.  
  507.   /*---------------------------------------*/
  508.   /* Add element to TimeOut Q if available */
  509.   /*---------------------------------------*/
  510.  
  511.   if ( npQEle = npUCB->TimeOutQFree )
  512.   {
  513.      npUCB->TimeOutQFree = npQEle->Next;
  514.      npQEle->Next        = 0;
  515.  
  516.      npQEle->pRP = (ULONG) pGenctl;
  517.  
  518.      if ( !npUCB->TimeOutQFoot )
  519.      {
  520.         npUCB->TimeOutQHead = npQEle;
  521.      }
  522.      else
  523.      {
  524.        (npUCB->TimeOutQFoot)->Next  = npQEle;
  525.      }
  526.  
  527.      npUCB->TimeOutQFoot = npQEle;
  528.   }
  529.  
  530.   return ( npQEle );
  531. }
  532.  
  533. /********************** START OF SPECIFICATIONS *****************************
  534. *                                                                           *
  535. * SUBROUTINE NAME:  RemoveFromTimeOutQ                                      *
  536. *                                                                           *
  537. * DESCRIPTIVE NAME:                                                         *
  538. *                                                                           *
  539. * FUNCTION:                                                                 *
  540. *                                                                           *
  541. *                                                                           *
  542. * ENTRY POINT:                                                              *
  543. *                                                                           *
  544. * LINKAGE:          Call Near                                               *
  545. *                                                                           *
  546. * INPUT:            pGenctl   Pointer to Generic I/O Control request packet *
  547. *                                                                           *
  548. * EXIT-NORMAL:                                                              *
  549. *                                                                           *
  550. * EXIT-ERROR:                                                               *
  551. *                                                                           *
  552. * Notes:            Called at TASK TIME                                     *
  553. *                                                                           *
  554. *********************** END OF SPECIFICATIONS *******************************/
  555.  
  556. USHORT near RemoveFromTimeOutQ(npUCB, npQEleRemove)
  557.  
  558. NPUCB            npUCB;
  559. NPQELE           npQEleRemove;
  560. {
  561.   USHORT rc = 0;
  562.   NPQELE npQEle;
  563.   NPQELE npQElePrev;
  564.  
  565.   npQElePrev = 0;
  566.   npQEle     = npUCB->TimeOutQHead;
  567.  
  568.   /*-----------------------------------*/
  569.   /* Search TimeOut Q for match on pRP */
  570.   /*-----------------------------------*/
  571.  
  572.   while ( npQEle && npQEle != npQEleRemove )
  573.   {
  574.      npQElePrev = npQEle;
  575.      npQEle     = npQEle->Next;
  576.   }
  577.  
  578.   /*----------------------------------------*/
  579.   /* Delete element from TimeOut Q if found */
  580.   /*----------------------------------------*/
  581.  
  582.   if ( npQEle )
  583.   {
  584.      if ( npQElePrev )
  585.      {
  586.         npQElePrev->Next = npQEle->Next;
  587.      }
  588.      else
  589.      {
  590.         if ( !(npUCB->TimeOutQHead = npQEle->Next) )
  591.         {
  592.            npUCB->TimeOutQFoot = 0;
  593.         }
  594.      }
  595.  
  596.      npQEle->Next        = npUCB->TimeOutQFree;
  597.      npUCB->TimeOutQFree = npQEle;
  598.   }
  599.   else
  600.   {
  601.     rc = 1;
  602.   }
  603.  
  604.   return( rc );
  605. }
  606.  
  607. /********************** START OF SPECIFICATIONS *****************************
  608. *                                                                           *
  609. * SUBROUTINE NAME:  ValidateUserPacket                                      *
  610. *                                                                           *
  611. * DESCRIPTIVE NAME: Lock and Validate Device Class Driver Packets           *
  612. *                                                                           *
  613. * FUNCTION:         Normally requests packets received from device class    *
  614. *                   drivers are locked and are addressed by GDT selectors   *
  615. *                   which are not context sensitive.                        *
  616. *                                                                           *
  617. *                   For SenseData buffers on the R0 stack or passed from    *
  618. *                   an application we lock the area and alias it to a       *
  619. *                   GDT Selector.                                           *
  620. *                                                                           *
  621. *                   For SCB chains, we allow the device class driver to     *
  622. *                   use its stack only during its initialization phase.     *
  623. *                   Any other context-sensitive references to SCB chains    *
  624. *                   are rejected.                                           *
  625. *                                                                           *
  626. *                                                                           *
  627. * ENTRY POINT:      ValidateUserPacket                                      *
  628. *                                                                           *
  629. * LINKAGE:          Call Near                                               *
  630. *                                                                           *
  631. * INPUT:            npUCB     Unit Control Block                            *
  632. *                                                                           *
  633. * EXIT_NORMAL:      TRUE                                                    *
  634. *                                                                           *
  635. * EXIT-ERROR:       FALSE   Devhelp function error                          *
  636. *                                                                           *
  637. * Notes:            Called at TASK TIME                                     *
  638. *                                                                           *
  639. *********************** END OF SPECIFICATIONS *******************************/
  640.  
  641. BOOL near ValidateUserPacket (pGenctl, npUCB, EntryType)
  642.  
  643. PRP_GENIOCTL     pGenctl;
  644. NPUCB            npUCB;
  645. USHORT           EntryType;
  646. {
  647.    PSCSI_IN  pParm;
  648.    PSCSI_OUT pData;
  649.    USHORT    rc;
  650.    USHORT    Sel;
  651.    USHORT    Function;
  652.    ULONG     plPkt;              /* Linear address of Parm or Data Packet */
  653.    ULONG     plLockHandle;
  654.    ULONG     plPhysAddr;
  655.    ULONG     PageListCount;
  656.    ULONG     VMLockFlags;
  657.    ULONG     Length;
  658.  
  659.    pParm  = (PSCSI_IN)(pGenctl->ParmPacket);
  660.    pData  = (PSCSI_OUT)(pGenctl->DataPacket);
  661.  
  662.    npUCB->ppDataPkt  = 0;
  663.    npUCB->SenseSel   = 0;
  664.  
  665.    Function = pGenctl->Function - SCSI_PLUS_VALUE;
  666.  
  667.    /*--------------------------------------------------------*/
  668.    /* Validate XFER SCB Requests                             */
  669.    /* --------------------------                             */
  670.    /* If an SCB chain is pointed to by a Context-Sensitive   */
  671.    /* selector, we reject the request. The only exception    */
  672.    /* is a device class driver in its initialization         */
  673.    /* phase.                                                 */
  674.    /*--------------------------------------------------------*/
  675.  
  676.    if (Function == ABFC_SCSIP_TRANSFER_SCB)
  677.    {
  678.       Sel = SELECTOROF( ((PSCSI_IN_XFERSCB) pParm)->lpSCBH );
  679.  
  680.       /*--------------------------------------------------------------*/
  681.       /* We determine whether the device class driver is initializing */
  682.       /* by its use of the Strat 1 entry point rather than the IDC    */
  683.       /* entry point.                                                 */
  684.       /*--------------------------------------------------------------*/
  685.  
  686.       if ((Sel == R0_STACK_SEL) ||
  687.          ((Sel & LDT_SEL) && (EntryType != STRAT1_ENTRY)) )
  688.       {
  689.          return(FALSE);
  690.       }
  691.    }
  692.  
  693.    /*--------------------------------------------------------*/
  694.    /* Validate Sense Data Requests                           */
  695.    /* ----------------------------                           */
  696.    /* These requests can potentially return SCSI Sense Data. */
  697.    /* The request is examined further to determine whether   */
  698.    /* the buffer needs to be locked.                         */
  699.    /*--------------------------------------------------------*/
  700.  
  701.    if ( Function == ABFC_RESET_DEVICE ||
  702.         Function == ABFC_SCSIP_ABORT  ||
  703.         Function == ABFC_SCSIP_TRANSFER_SCB )
  704.    {
  705.       if (pParm && (Length = ((PSCSI_IN_XFERSCB)pParm)->lnSenseData))
  706.       {
  707.          npUCB->pSenseData = (PSCSI_REQSENSE_DATA) pData;
  708.  
  709.          Sel = SELECTOROF( pData );
  710.  
  711.          if ((Sel == R0_STACK_SEL) || (Sel & LDT_SEL) )
  712.          {
  713.             rc = DevHelp_VirtToLin(SELECTOROF(pData), (ULONG) OFFSETOF(pData),
  714.                                                       (PVOID) &plPkt);
  715.             if (!rc)
  716.             {
  717.                plLockHandle = plDataSeg + (ULONG) ((USHORT) &(npUCB->hLockDataP));
  718.                plPhysAddr   = plDataSeg + (ULONG) ((USHORT) &(npUCB->ppDataPkt));
  719.                VMLockFlags  = (VMDHL_LONG | VMDHL_WRITE | VMDHL_CONTIGUOUS | VMDHL_16M);
  720.  
  721.                if (DevHelp_VMLock(VMLockFlags, plPkt, Length, plPhysAddr,
  722.                               plLockHandle, (PULONG) &PageListCount) != 0)
  723.  
  724.                   return(FALSE);
  725.  
  726.                if ( (Sel = npUCB->SenseSel = AllocateGDTSel()) )
  727.                {
  728.                   if ( !DevHelp_PhysToGDTSelector( (ULONG)  npUCB->ppDataPkt,
  729.                                                    (USHORT) Length,
  730.                                                    (SEL)    Sel  )          )
  731.                   {                                                  /*@V53750*/
  732.                      npUCB->pSenseData = (PSCSI_REQSENSE_DATA) MAKEP(Sel, 0);
  733.                   }
  734.                   else
  735.                   {
  736.                      return(FALSE);
  737.                   }
  738.                }
  739.                else
  740.                   return(FALSE);
  741.             }
  742.             else
  743.                return(FALSE);
  744.          }
  745.       }
  746.    }
  747.  
  748.    return(TRUE);
  749. }
  750.  
  751.  
  752. /********************** START OF SPECIFICATIONS *****************************
  753. *                                                                           *
  754. * SUBROUTINE NAME:  UnlockUserPacket                                        *
  755. *                                                                           *
  756. * DESCRIPTIVE NAME: Unlock Parameter and Data Pakets                        *
  757. *                                                                           *
  758. * FUNCTION:         Unlock parameter and data packets from General control  *
  759. *                   request.                                                *
  760. *                                                                           *
  761. * ENTRY POINT:      UnlockUserPacket                                        *
  762. *                                                                           *
  763. * LINKAGE:          Call Near                                               *
  764. *                                                                           *
  765. * INPUT:            npUCB     Unit Control Block                            *
  766. *                                                                           *
  767. * EXIT_NORMAL:      TRUE                                                    *
  768. *                                                                           *
  769. * EXIT-ERROR:                                                               *
  770. *                                                                           *
  771. * Notes:            Called at TASK TIME                                     *
  772. *                                                                           *
  773. *********************** END OF SPECIFICATIONS *******************************/
  774.  
  775. void near UnlockUserPacket (npUCB)
  776.  
  777. NPUCB           npUCB;
  778.  
  779. {
  780.    if ( npUCB->ppDataPkt )
  781.    {
  782.       DevHelp_VMUnLock((LIN)(plDataSeg+(ULONG) ((USHORT) &(npUCB->hLockDataP))));
  783.       npUCB->ppDataPkt = 0;
  784.    }
  785.  
  786.    if ( npUCB->SenseSel )
  787.    {
  788.       DeallocateGDTSel( npUCB->SenseSel );
  789.       npUCB->SenseSel = 0;
  790.    }
  791. }
  792.  
  793.  
  794. /********************** START OF SPECIFICATIONS *****************************
  795. *                                                                           *
  796. * SUBROUTINE NAME:  f_CheckIORBError                                        *
  797. *                                                                           *
  798. * DESCRIPTIVE NAME: Far Check IORB Error Code                               *
  799. *                                                                           *
  800. * FUNCTION:         This routine just calls CheckIORBError                  *
  801. *                                                                           *
  802. * ENTRY POINT:      f_CheckIORBError                                        *
  803. *                                                                           *
  804. * LINKAGE:          Call Far                                                *
  805. *                                                                           *
  806. * INPUT:                                                                    *
  807. *                                                                           *
  808. * EXIT-NORMAL:                                                              *
  809. *                                                                           *
  810. * EXIT-ERROR:                                                               *
  811. *                                                                           *
  812. * Notes:            Called at TASK/INTERRUPT TIME                           *          *
  813. *                                                                           *
  814. *********************** END OF SPECIFICATIONS *******************************/
  815.  
  816. USHORT far f_CheckIORBError(npUCB, npIORB)
  817.  
  818. NPUCB            npUCB;
  819. NPIORBH          npIORB;
  820. {
  821.   return(CheckIORBError(npUCB, npIORB));
  822. }
  823.  
  824.  
  825. /********************** START OF SPECIFICATIONS *****************************
  826. *                                                                           *
  827. * SUBROUTINE NAME:  CheckIORBError                                          *
  828. *                                                                           *
  829. * DESCRIPTIVE NAME: Check IORB Error Code                                   *
  830. *                                                                           *
  831. * FUNCTION:         This routine convert SCSI error code from IORB and      *
  832. *                   sense key.  If sense key is UNIT ATTENTION, the rest    *
  833. *                   of the requests will be flushed.                        *
  834. *                                                                           *
  835. * ENTRY POINT:      CheckIORBError                                          *
  836. *                                                                           *
  837. * LINKAGE:          Call Near                                               *
  838. *                                                                           *
  839. * INPUT:                                                                    *
  840. *                                                                           *
  841. * EXIT-NORMAL:                                                              *
  842. *                                                                           *
  843. * EXIT-ERROR:                                                               *
  844. *                                                                           *
  845. * Notes:            Called at TASK/INTERRUPT TIME                           *
  846. *                                                                           *
  847. *********************** END OF SPECIFICATIONS *******************************/
  848.  
  849.  
  850. USHORT near CheckIORBError(npUCB, npIORB)
  851.  
  852. NPUCB             npUCB;
  853. NPIORBH           npIORB;
  854. {
  855.   NPSCSI_STATUS_BLOCK  npStatusBlk;
  856.   PSCSI_REQSENSE_DATA  pSense;
  857.  
  858.   USHORT               status = STDON | STERR;
  859.   USHORT               ErrorCode;
  860.  
  861.  
  862.   if ( !(npIORB->Status & IORB_ERROR) )
  863.   {
  864.     return( STDON );
  865.   }
  866.  
  867.   ErrorCode = npIORB->ErrorCode;
  868.  
  869.   if (npIORB->Status & IORB_STATUSBLOCK_AVAIL)
  870.   {
  871.      npStatusBlk = (NPSCSI_STATUS_BLOCK) npIORB->pStatusBlock;
  872.  
  873.      if (npStatusBlk->Flags & STATUS_SENSEDATA_VALID)
  874.      {
  875.         pSense = npStatusBlk->SenseData;
  876.  
  877.         if ((pSense->SenseKey & SCSI_SENSEKEY_MASK) == SCSI_SK_UNITATTN)
  878.         {
  879.            FlushReqPkt(npUCB);
  880.         }
  881.         return(status | SCSI_ERR_DEVICE);
  882.      }
  883.      else
  884.      {
  885.         if (npStatusBlk->AdapterErrorCode)
  886.         {
  887.            ErrorCode = npStatusBlk->AdapterErrorCode;
  888.         }
  889.      }
  890.   }
  891.  
  892.   /*--------------------------------------------------------*/
  893.   /* Normally an ADD will return SCSI Sense Data. However,  */
  894.   /* in cases where an error occurred on the adapter itself */
  895.   /* or in the ADD, sense data might not be available. In   */
  896.   /* these cases, the AdapterError code or IORBError code   */
  897.   /* is examined and the error is reported either as a      */
  898.   /* failed request sense or an I24_* device driver         */
  899.   /* error code as appropriate.                             */
  900.   /*--------------------------------------------------------*/
  901.  
  902.   switch (ErrorCode & IORB_ERR_MASK)
  903.   {
  904.      case (IOERR_CMD):
  905.         status |= ERROR_I24_BAD_COMMAND;
  906.         break;
  907.  
  908.  
  909.      case (IOERR_ADAPTER):
  910.  
  911.         switch (ErrorCode)
  912.         {
  913.            case (IOERR_ADAPTER_TIMEOUT):
  914.            case (IOERR_ADAPTER_DEVICE_TIMEOUT):
  915.               status |= SCSI_ERR_TIMEOUT;
  916.               break;
  917.  
  918.            case (IOERR_ADAPTER_REQ_NOT_SUPPORTED):
  919.               status |= ERROR_I24_BAD_COMMAND;
  920.               break;
  921.  
  922.            default:
  923.               status |= SCSI_ERR_REQ_SENSE_FAILED;
  924.               break;
  925.         }
  926.         break;
  927.  
  928.      case (IOERR_DEVICE):
  929.  
  930.         switch (ErrorCode)
  931.         {
  932.            case (IOERR_DEVICE_REQ_NOT_SUPPORTED):
  933.               status |= ERROR_I24_BAD_COMMAND;
  934.               break;
  935.  
  936.            case (IOERR_DEVICE_BUSY):
  937.               status |= SCSI_ERR_DEV_BUSY;
  938.               break;
  939.  
  940.            default:
  941.               status |= SCSI_ERR_REQ_SENSE_FAILED;
  942.         }
  943.         break;
  944.  
  945.      default:
  946.         status |= ERROR_I24_GEN_FAILURE;
  947.  
  948.   }
  949.   return (status);
  950.  
  951. }
  952.  
  953. /********************** START OF SPECIFICATIONS *****************************
  954. *                                                                           *
  955. * SUBROUTINE NAME:  AllocateGDTSel                                          *
  956. *                                                                           *
  957. * DESCRIPTIVE NAME: Allocate GDT Selector                                   *
  958. *                                                                           *
  959. * FUNCTION:         This routine manages a stack of GDT selectors which     *
  960. *                   are used to alias Sense Data buffers pointed to by      *
  961. *                   LDT or Ring 0 Stack selectors.                          *
  962. *                                                                           *
  963. * ENTRY POINT:      AllocateGDTSel                                          *
  964. *                                                                           *
  965. * LINKAGE:          Call Near                                               *
  966. *                                                                           *
  967. * INPUT:                                                                    *
  968. *                                                                           *
  969. * EXIT-NORMAL:                                                              *
  970. *                                                                           *
  971. * EXIT-ERROR:                                                               *
  972. *                                                                           *
  973. * Notes:            Called at TASK TIME                                     *
  974. *                                                                           *
  975. *********************** END OF SPECIFICATIONS *******************************/
  976.  
  977. USHORT near AllocateGDTSel(VOID)
  978. {
  979.   USHORT Sel = 0;
  980.   if ( GDTSelStackPtr )
  981.   {
  982.      Sel = GDTSelStack[GDTSelStackPtr];
  983.      GDTSelStack[GDTSelStackPtr--] = 0;
  984.   }
  985.   return( Sel );
  986. }
  987.  
  988. /********************** START OF SPECIFICATIONS *****************************
  989. *                                                                           *
  990. * SUBROUTINE NAME:  DeallocateGDTSel                                        *
  991. *                                                                           *
  992. * DESCRIPTIVE NAME: Deallocate GDT Selector                                 *
  993. *                                                                           *
  994. * FUNCTION:         This routine manages a stack of GDT selectors which     *
  995. *                   are used to alias Sense Data buffers pointed to by      *
  996. *                   LDT or Ring 0 Stack selectors.                          *
  997. *                                                                           *
  998. * ENTRY POINT:      DeallocateGDTSel                                        *
  999. *                                                                           *
  1000. * LINKAGE:          Call Near                                               *
  1001. *                                                                           *
  1002. * INPUT:                                                                    *
  1003. *                                                                           *
  1004. * EXIT-NORMAL:                                                              *
  1005. *                                                                           *
  1006. * EXIT-ERROR:                                                               *
  1007. *                                                                           *
  1008. * Notes:            Called at TASK TIME                                     *
  1009. *                                                                           *
  1010. *********************** END OF SPECIFICATIONS *******************************/
  1011.  
  1012. VOID near DeallocateGDTSel(Sel)
  1013.  
  1014. USHORT Sel;
  1015. {
  1016.   GDTSelStack[++GDTSelStackPtr] = Sel;
  1017. }
  1018.