home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 4 Drivers / 04-Drivers.zip / scsiopt2.zip / init1.c < prev    next >
C/C++ Source or Header  |  1998-03-04  |  54KB  |  2,090 lines

  1. /*
  2.  * $Source: d:/source/driver/perf/RCS/init1.c,v $
  3.  * $Revision: 1.9 $
  4.  * $Date: 1998/03/04 02:11:28 $
  5.  * $Locker:  $
  6.  *
  7.  * First step of initialisation, executed at ring 0 in protected
  8.  * mode as the only running process.
  9.  *
  10.  * History: see bottom of file
  11.  * --------------------------------------------
  12.  * Author: Vitus Jensen, 2:2474/424, 1997-98
  13.  */
  14. #pragma off (unreferenced)
  15. static char const id[]="$Id: init1.c,v 1.9 1998/03/04 02:11:28 vitus Exp $";
  16. #pragma on (unreferenced)
  17.  
  18.  
  19. #include <string.h>
  20.  
  21. #define INCL_DOSERRORS
  22. #define INCL_NOPMAPI
  23. #include <os2.h>
  24.  
  25. #include <devcmd.h>
  26. #include <devclass.h>
  27. #include <dskinit.h>
  28. #include <infoseg.h>
  29.  
  30. #define INCL_INITRP_ONLY
  31. #include <reqpkt.h>
  32.  
  33. #include <scsi.h>
  34. #include <iorb.h>
  35. #include <addcalls.h>
  36. #if defined(__WATCOMC__)
  37. # include <devhelp.h>
  38. typedef USHORT NEAR *    NPUSHORT;
  39. typedef VOID NEAR *    NPVOID;
  40. #else
  41. # include <dhcalls.h>
  42. #endif
  43. #include "cmdphdr.h"
  44.  
  45. #include "scsiopt.h"
  46. #include "proto.h"
  47. #include "extern.h"
  48.  
  49. #include "modepages.h"
  50.  
  51.  
  52.  
  53. /*
  54.  * Macro to allocate data from memory pool.
  55.  * OBS: to free this memory decrement 'npInitData' by the amount
  56.  * allocated.  Be sure to undo it inverse.
  57.  */
  58. #define GETINITRAM(p,type,size) (p=(type)npInitData,npInitData+=(size))
  59.  
  60.  
  61.  
  62. #define INITMSG        static char _ininit
  63.  
  64.  
  65. /*
  66.  * Messages used during initialization
  67.  *
  68.  * 1. error messages start with driver name as they are
  69.  * displayed even if '/V' isn't used.
  70.  */
  71. INITMSG    szErrorVAddr[]= "%s: error converting virtual to physical address";
  72. INITMSG    szNoDriverTab[]="%s: error retrieving driver table";
  73. INITMSG    szNoDevTab[]=    "%s: error retrieving device table from ADD %u";
  74. INITMSG    szAllocFailed[]="%s: adapter %u, unit %u allocation failed";
  75. INITMSG    szDeallocFailed[]="%s: adapter %u, unit %u, deallocation failed";
  76.  
  77. INITMSG    szSenseFailed[]= "%s: adapter %u, unit %u MODE SENSE(6) failed (%04x)";
  78. INITMSG    szSelectFailed[]= "%s: adapter %u, unit %u MODE SELECT(6) failed (%04x)";
  79. INITMSG    szUnknFormat[]=    "%s: adapter %u, unit %u, unknown format of page %u";
  80.  
  81. INITMSG    szStatusblock[]= "%s: StatusBlock, Flags %02x, Adapter Error %04x, Target Status %02x";
  82. INITMSG    szAdapterDiag[]= "%s: adapter specific info [%s]";
  83. INITMSG    szSensedata[]=    "%s: SenseData [%s]";
  84. INITMSG    szHex[]=    "%02x ";
  85.  
  86.  
  87. /*
  88.  * 2. Screen messages only displayed if '/V' or '/DEBUG' are used.
  89.  */
  90.  
  91. INITMSG    szNoDevices[]=    "No devices found";
  92. INITMSG    szNoSCSI[]=    "Adapter %u: no SCSI bus";
  93. INITMSG    szNo16M[]=    "Adapter %u: hardware doesn't support memory above 16MB";
  94. INITMSG    szNoScGa[]=    "Adapter %u: hardware doesn't support scatter/gather";
  95. INITMSG    szDiskette[]=    "Adapter %u, Unit %u: diskette drive";
  96. INITMSG    szDefective[]=    "Adapter %u, Unit %u: defect";
  97.  
  98. /* Related to device modifications */
  99.  
  100. INITMSG    szModifyStart[]=  "Adapter %u, Unit %u: modifications start...";
  101. INITMSG    szModifyOK[]=      "Adapter %u, Unit %u: modifications ended w/o errors";
  102.  
  103. INITMSG    szRCachePage[]=      "Adapter %u, Unit %u: reading cache page 8";
  104. INITMSG    szRControlPage[]= "Adapter %u, Unit %u: reading control page 10";
  105. INITMSG    szRConnectPage[]= "Adapter %u, Unit %u: reading connect/disconnect page 2";
  106. INITMSG    szRCDPage[]=    "Adapter %u, Unit %u: reading CD-ROM page 13";
  107. INITMSG    szWCachePage[]=      "Adapter %u, Unit %u: writing cache page 9";
  108. INITMSG    szWControlPage[]= "Adapter %u, Unit %u: writing control page 10";
  109. INITMSG    szWConnectPage[]= "Adapter %u, Unit %u: writing connect/disconnect page 2";
  110. INITMSG    szWCDPage[]=    "Adapter %u, Unit %u: writing CD-ROM page 13";
  111.  
  112. /* Display current settings */
  113.  
  114. INITMSG    szReadCache[]=    "Adapter %u, Unit %u: read cache %s";
  115. INITMSG    szWriteCache[]=    "Adapter %u, Unit %u: write cache %s";
  116. INITMSG    szPrefetchPrio[]= "Adapter %u, Unit %u: prefetch priority %s";
  117. INITMSG    szPrefetch[]=    "Adapter %u, Unit %u: prefetch %s";
  118.  
  119. INITMSG    szTaggedQueue[]="Adapter %u, Unit %u: tagged queuing %s";
  120. INITMSG    szReorder[]=    "Adapter %u, Unit %u: unrestricted reordering %s";
  121.  
  122. INITMSG    szFullReselect[]="Adapter %u, Unit %u: buffer fill disconnect/reconnect %s";
  123. INITMSG    szInactiveTO[]="Adapter %u, Unit %u: inactive bus disconnect %s";
  124. INITMSG    szDisconnectTO[]="Adapter %u, Unit %u: disconnect to reselect timeout %s";
  125. INITMSG    szConnectTO[]="Adapter %u, Unit %u: connection timeout %s";
  126.  
  127. INITMSG    szCDTimeout[]=    "Adapter %u, Unit %u: CD-ROM inactivity timeout %s";
  128.  
  129.  
  130. /* Related to command line parsing */
  131.  
  132. INITMSG    szCmdLineSyntax[]= "%s: syntax error in command line";
  133. INITMSG    szMissingOption[]= "%s: required option missing in command line";
  134. INITMSG    szUnknownOption[]= "%s: unknown command line option";
  135. INITMSG    szCmdLineError[]=  "%s: command line option error %d";
  136.  
  137.  
  138. INITMSG    szFoundDevice[]=   "Adapter %u, Unit %u: found";
  139.  
  140.  
  141.  
  142.  
  143. /*
  144.  * Very important :-)
  145.  */
  146. INITMSG szProduct[]=    "SCSI Optimizer                ";
  147. INITMSG szLogo[]=    "\r\n%s                               Version %u.%02u"
  148. "\r\nMade by Vitus Jensen (2:2474/424)                            " __DATE__ ;
  149.  
  150.  
  151.  
  152.  
  153. #pragma pack(1)
  154. typedef struct _UNIT_OPTION {
  155.     UCHAR    adpno;            /* MSB set if valid entry */
  156.     UCHAR    unitno;
  157.     struct {
  158.     UINT    access : 2;        /* forces reading of  this page */
  159.     UINT    buffer : 2;        /* empty/full ration */
  160.     UINT    inactive : 2;        /* enable inactive bus timeout */
  161.     UINT    disconnect : 2;        /* enable disconnect timeout */
  162.     UINT    connect : 2;        /* enable connect timeout */
  163.     } pg2;
  164.     struct {
  165.     UINT    access : 2;        /* forces reading of  this page */
  166.     UINT    wce : 2;        /* write cache enable */
  167.     UINT    rce : 2;        /* read cache enable */
  168.     UINT    pre : 2;        /* pre-fetch enable */
  169.     UINT    prio : 2;        /* higher pre-fetch priority */
  170.     } pg8;
  171.     struct {
  172.     UINT    access : 2;        /* forces reading of this page */
  173.     UINT    queue : 2;        /* enable tagged queuing */
  174.     UINT    reorder : 2;        /* unrestricted reordering */
  175.     } pg10;
  176.     struct {
  177.     UINT    access : 2;        /* forces reading of this page */
  178.     UINT    seconds : 12;        /* seconds until CD-ROM stop */
  179.     } pg13;
  180. } UNIT_OPTION, FAR * PUNIT_OPTION;
  181. #pragma pack(1)
  182. UNIT_OPTION _ininit    UnitOption[MAX_UNITS] = {0};
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189. /*
  190.  * Last element in code segments which remains resident
  191.  */
  192. PRIVATE void
  193. Code_End(void) {}
  194.  
  195.  
  196.  
  197.  
  198. /*#
  199.  * CALL
  200.  *    AddUTable(aidx,uidx,pgno,patch)
  201.  * PARAMETER
  202.  *    aidx        adapter index
  203.  *    uidx        unit index
  204.  *    pgno        mode page to change
  205.  *    enable        enable feature?  or disable?
  206.  *    patch        bitfield telling which patches to apply
  207.  * RETURNS
  208.  *    (nothing)
  209.  * GLOBAL
  210.  *    UnitTable
  211.  * DESPRIPTION
  212.  *    Adds entry to global table to save unit specific settings
  213.  *    or updates already allocated entry.
  214.  *
  215.  * REMARKS
  216.  *    Entries are allocated from low to higher indices and never freed.
  217.  */
  218. PRIVATE void
  219. AddUTable(USHORT aidx,USHORT uidx,USHORT pgno,int enable,USHORT patch)
  220. {
  221.     int i;
  222.  
  223.     DEBMSG4("\r\nAddUTable: %w %w %w = %w",aidx,uidx,pgno,patch);
  224.     if( aidx > 0x007F  ||  uidx > 0x00FF )
  225.     return;                    /* can't allocate that */
  226.  
  227.     for( i = 0; i < MAX_UNITS; ++i )
  228.     {
  229.     if( (UnitOption[i].adpno & 0x80) == 0
  230.         ||  ((UCHAR)(UnitOption[i].adpno & ~0x80) == aidx
  231.          &&  UnitOption[i].unitno == uidx) )
  232.     {
  233.         UnitOption[i].adpno = (UCHAR)(aidx | 0x80);
  234.         UnitOption[i].unitno = (UCHAR)uidx;
  235.         switch( pgno )
  236.         {
  237.           case 2:
  238.         UnitOption[i].pg2.access |= (patch == 0 ? 1 : 2);
  239.         if( (patch & 0x0001) )
  240.             UnitOption[i].pg2.buffer = (enable ? 2 : 1);
  241.         if( (patch & 0x0002) )
  242.             UnitOption[i].pg2.inactive = (enable ? 2 : 1);
  243.         if( (patch & 0x0004) )
  244.             UnitOption[i].pg2.disconnect = (enable ? 2 : 1);
  245.         if( (patch & 0x0008) )
  246.             UnitOption[i].pg2.connect = (enable ? 2 : 1);
  247.         break;
  248.  
  249.           case 8:
  250.         UnitOption[i].pg8.access |= (patch == 0 ? 1 : 2);
  251.         if( (patch & 0x0001) )
  252.             UnitOption[i].pg8.wce = (enable ? 2 : 1);
  253.         if( (patch & 0x0002) )
  254.             UnitOption[i].pg8.rce = (enable ? 2 : 1);
  255.         if( (patch & 0x0004) )
  256.             UnitOption[i].pg8.pre = (enable ? 2 : 1);
  257.         if( (patch & 0x0008) )
  258.             UnitOption[i].pg8.prio = (enable ? 2 : 1);
  259.         break;
  260.  
  261.           case 10:
  262.         UnitOption[i].pg10.access |= (patch == 0 ? 1 : 2);
  263.         if( (patch & 0x0001) )
  264.             UnitOption[i].pg10.queue = (enable ? 2 : 1);
  265.         if( (patch & 0x0002) )
  266.             UnitOption[i].pg10.reorder = (enable ? 2 : 1);
  267.         break;
  268.  
  269.           case 13:
  270.         UnitOption[i].pg13.access |= (patch == 0 ? 1 : 2);
  271.         UnitOption[i].pg13.seconds = (patch > 0x0FFF ? 0x0FFF : patch);
  272.         break;
  273.  
  274.           default:
  275.         break;            /* no error, empty entry */
  276.         }
  277.  
  278.         DEBMSG2("\r\nAddUTable: entry\r\n%z",(PVOID)&UnitOption[i],sizeof(UnitOption[i]));
  279.         return;
  280.     } /* end[if found of empty entry] */
  281.     } /* end[for every entry] */
  282.  
  283.     return;
  284. }
  285.  
  286.  
  287.  
  288.  
  289. /*#
  290.  * CALL
  291.  *    QueryUTable(aidx,uidx)
  292.  * PARAMETER
  293.  *    aidx        adapter index
  294.  *    uidx        unit index
  295.  * RETURNS
  296.  *    &UnitTable[]
  297.  * GLOBAL
  298.  *    UnitTable
  299.  * DESPRIPTION
  300.  *    Retrieve special settings for this device, if available.
  301.  *
  302.  * REMARKS
  303.  */
  304. PRIVATE UNIT_OPTION FAR *
  305. QueryUTable(USHORT aidx,USHORT uidx)
  306. {
  307.     int i;
  308.  
  309.     if( aidx > 0x007F  ||  uidx > 0xFF )
  310.     return 0;                /* quiet fail */
  311.  
  312.     for( i = 0; i < MAX_UNITS; ++i )
  313.     {
  314.     if( (UnitOption[i].adpno & 0x80)
  315.        &&  (UCHAR)(UnitOption[i].adpno & ~0x80) == aidx
  316.        &&  UnitOption[i].unitno == uidx )
  317.     {
  318.         return &UnitOption[i];
  319.     }
  320.     }
  321.  
  322.     return 0;                    /* let compiler expand... */
  323. }
  324.  
  325.  
  326.  
  327.  
  328. /*#
  329.  * CALL
  330.  *    DumpStatusblock(statusblock)
  331.  * PARAMETER
  332.  *    statusblock    SCSI_STATUS_BLOCK, see DDK
  333.  * RETURNS
  334.  *    (nothing)
  335.  * GLOBAL
  336.  *    (none)
  337.  * DESPRIPTION
  338.  *    Displays error values and dumps sense data to screen
  339.  *
  340.  * REMARKS
  341.  */
  342. char _ininit    achDump[200];
  343. PRIVATE void NEAR
  344. DumpStatusblock(NPSCSI_STATUS_BLOCK statusblock)
  345. {
  346.     /* Status block */
  347.  
  348.     sprintk(szMsgBuffer, szStatusblock, (PSZ)szDriverName,
  349.         statusblock->Flags, statusblock->AdapterErrorCode,
  350.         statusblock->TargetStatus);
  351.     SaveMessage();
  352.  
  353.     /* Adapter specific info, only if valid */
  354.  
  355.     if( (statusblock->Flags & STATUS_DIAGINFO_VALID) )
  356.     {
  357.     USHORT    i;
  358.  
  359.     achDump[0] = '\0';
  360.     for( i = 0; i < 8; ++i )
  361.         sprintk(&achDump[_fstrlen(achDump)],
  362.             szHex, statusblock->AdapterDiagInfo[i]);
  363.     sprintk(szMsgBuffer, szAdapterDiag, (PSZ)szDriverName, (PSZ)achDump);
  364.     SaveMessage();
  365.     }
  366.  
  367.     /* Sense data, only if valid */
  368.  
  369.     if( (statusblock->Flags & STATUS_SENSEDATA_VALID) )
  370.     {
  371.     USHORT    i;
  372.     PUCHAR    sensedata = (PUCHAR)statusblock->SenseData;
  373.  
  374.     achDump[0] = '\0';
  375.     for( i = 0; i < statusblock->ReqSenseLen; ++i )
  376.         sprintk(&achDump[_fstrlen(achDump)], szHex, sensedata[i]);
  377.     sprintk(szMsgBuffer, szSensedata, (PSZ)szDriverName, (PSZ)achDump);
  378.     SaveMessage();
  379.     }
  380.     return;
  381. }
  382.  
  383.  
  384.  
  385.  
  386. /*#
  387.  * CALL
  388.  *    SendIORBNotify(iorb)
  389.  * PARAMETER
  390.  *    iorb        completed request
  391.  * RETURNS
  392.  *    (nothing)
  393.  * GLOBAL
  394.  *    (none)
  395.  * DESPRIPTION
  396.  *    Awakens any process blocking on the passed IORB.  Used
  397.  *    by 'SendIORB'.
  398.  *
  399.  * REMARKS
  400.  */
  401. PRIVATE void FAR _loadds _Cdecl
  402. SendIORBNotify(PIORB iorb)
  403. {
  404.     USHORT awoken;
  405.  
  406.     DevHelp_ProcRun((ULONG)iorb, &awoken);
  407.     return;
  408. }
  409.  
  410.  
  411.  
  412.  
  413. /*#
  414.  * CALL
  415.  *    SendIORB(iorb,addentry)
  416.  * PARAMETER
  417.  *    iorb        request to execute
  418.  *    addentry    entry point of ADD to call
  419.  * RETURNS
  420.  *    0        OK
  421.  *    /0        error code returned from ADD
  422.  * GLOBAL
  423.  *    (none)
  424.  * DESPRIPTION
  425.  *    Uses 'SendIORBNotify' as notification routine.
  426.  *
  427.  * REMARKS
  428.  *    Need local variable to prevent restoring sp from bp
  429.  *    after ADD call.
  430.  */
  431. #pragma optimize("lge",off)
  432. PRIVATE USHORT NEAR
  433. SendIORB(PIORB iorb,void (FAR _Cdecl * addentry)(PIORB))
  434. {
  435. #if defined(_MSC_VER)
  436.     ULONG    dummy;                /* needed for SAVE_REGS() */
  437. #endif
  438.  
  439.     iorb->NotifyAddress = (PVOID)SendIORBNotify; /* kind of hack */
  440.     iorb->RequestControl |= IORB_ASYNC_POST;
  441.     iorb->ErrorCode =    0;
  442.     iorb->Status =    0;
  443.  
  444.     SAVE_REGS();
  445.     (addentry)(iorb);
  446.     RESTORE_REGS();
  447.  
  448.     DISABLE();
  449.     while( !(iorb->Status & IORB_DONE) )
  450.     {
  451.     DevHelp_ProcBlock( (ULONG)iorb, -1L, WAIT_IS_NOT_INTERRUPTABLE );
  452.     DISABLE();
  453.     }
  454.     ENABLE();
  455.  
  456.     return (iorb->Status & IORB_ERROR ? iorb->ErrorCode : 0);
  457. }
  458. #pragma optimize("",on)
  459.  
  460.  
  461.  
  462.  
  463. /*#
  464.  * CALL
  465.  *    CheckAdapterInfo(iAdapter,npAdapterInfo)
  466.  * PARAMETER
  467.  *    iAdapter        index of adapter in system
  468.  *,    npAdapterInfo        from GET_DEVICE_TABLE
  469.  * RETURNS
  470.  *    0            OK to process units from this adapter
  471.  *    /0            no SCSI, defect, ...
  472.  * GLOBAL
  473.  *    fDriverFlags
  474.  * DESPRIPTION
  475.  *    Checks adapter flags, additional service: displays some
  476.  *    performance related capabilities of adapter.
  477.  *
  478.  * REMARKS
  479.  */
  480. PRIVATE int
  481. CheckAdapterInfo(USHORT const iAdapter,NPADAPTERINFO const npAdapterInfo)
  482. {
  483.     if( !(npAdapterInfo->AdapterFlags & AF_16M) )
  484.     {
  485.     sprintk(szMsgBuffer, szNo16M, iAdapter);
  486.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  487.     if( (fDriverFlags & DF_DEBUG) )
  488.         SaveMessage();
  489.     }
  490.     if( !(npAdapterInfo->AdapterFlags & AF_HW_SCATGAT) )
  491.     {
  492.     sprintk(szMsgBuffer, szNoScGa, iAdapter);
  493.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  494.     if( (fDriverFlags & DF_DEBUG) )
  495.         SaveMessage();
  496.     }
  497.  
  498.     if( !((npAdapterInfo->AdapterDevBus & AI_DEVBUS_SCSI_1)
  499.       ||  (npAdapterInfo->AdapterDevBus & AI_DEVBUS_SCSI_2)
  500.       ||  (npAdapterInfo->AdapterDevBus & AI_DEVBUS_SCSI_3)) )
  501.     {
  502.     /* No SCSI devices to expect on non-SCSI bus,
  503.      * ignore adapter. */
  504.  
  505.     sprintk(szMsgBuffer, szNoSCSI, iAdapter);
  506.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  507.     if( (fDriverFlags & DF_DEBUG) )
  508.         SaveMessage();
  509.     return 1;
  510.     }
  511.  
  512.     return 0;
  513. }
  514.  
  515.  
  516.  
  517.  
  518. /*#
  519.  * CALL
  520.  *    CheckUnitInfo(iAdapter,npUnitInfo)
  521.  * PARAMETER
  522.  *    iAdapter        index of adapter in system
  523.  *    npUnitInfo        from GET_DEVICE_TABLE
  524.  * RETURNS
  525.  *    0    OK, try/use this unit
  526.  *    /0    bad type, defective, etc.
  527.  * GLOBAL
  528.  *    fDriverFlags
  529.  * DESPRIPTION
  530.  *    If this unit is defect then skip the unit.
  531.  *    Dito if it's diskette A or B.
  532.  *
  533.  * REMARKS
  534.  */
  535. PRIVATE int
  536. CheckUnitInfo(PDEVICE const device,NPUNITINFO const npUnitInfo)
  537. {
  538.     USHORT const uflags = npUnitInfo->UnitFlags;
  539.  
  540.     DEBMSG2("\r\nCheckUnitInfo: %w %w",device->iAdapter,device->iUnit);
  541.     if( (uflags & (UF_A_DRIVE | UF_B_DRIVE)) )
  542.     {
  543.     sprintk(szMsgBuffer, szDiskette, device->iAdapter, device->iUnit);
  544.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  545.     if( (fDriverFlags & DF_DEBUG) )
  546.         SaveMessage();
  547.     return 3;
  548.     }
  549.  
  550.     if( (uflags & UF_DEFECTIVE) )
  551.     {
  552.     sprintk(szMsgBuffer, szDefective, device->iAdapter, device->iUnit);
  553.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  554.     if( (fDriverFlags & DF_VERBOSE) )
  555.         SaveMessage();
  556.     return 4;
  557.     }
  558.  
  559.     return 0;
  560. }
  561.  
  562.  
  563.  
  564.  
  565. /*#
  566.  * CALL
  567.  *    ModeSense(pADDEntry,npUnit,pgno,buf,bufsiz)
  568.  * PARAMETER
  569.  *    pADDEntry    call ADD
  570.  *    npUnit        ADD's UNITINFO structure
  571.  *    pgno        which page?
  572.  *    buf
  573.  *    bufsiz
  574.  * RETURNS
  575.  *    0        OK
  576.  *    /0        error code from ADD
  577.  * GLOBAL
  578.  * DESPRIPTION
  579.  * REMARKS
  580.  */
  581. PRIVATE USHORT
  582. ModeSense(void (FAR _Cdecl * pADDEntry)(),NPUNITINFO const npUnit,
  583.       UCHAR pgno,PUCHAR buf,USHORT bufsiz)
  584. {
  585.     NPIORB_ADAPTER_PASSTHRU    iothru;
  586.     NPSCSI_STATUS_BLOCK        statusblock;
  587.     NPSCSI_REQSENSE_DATA    sensedata;
  588.  
  589.     BYTE        cdb[6];
  590.     USHORT        error;
  591.  
  592.     GETINITRAM(iothru, NPIORB_ADAPTER_PASSTHRU, sizeof(IORB_ADAPTER_PASSTHRU));
  593.     GETINITRAM(statusblock, NPSCSI_STATUS_BLOCK, sizeof(SCSI_STATUS_BLOCK));
  594.     GETINITRAM(sensedata, NPSCSI_REQSENSE_DATA, sizeof(SCSI_REQSENSE_DATA));
  595.  
  596.     cdb[0] = SCSI_MODE_SENSE;
  597.     cdb[1] = (UCHAR)((npUnit->UnitSCSILUN << 5) | 0);
  598.     cdb[2] = pgno;
  599.     cdb[3] = 0;
  600.     cdb[4] = (UCHAR)bufsiz;
  601.     cdb[5] = 0;
  602.  
  603.     memset(iothru, 0, sizeof(IORB_ADAPTER_PASSTHRU));
  604.     memset(statusblock, 0, sizeof(SCSI_STATUS_BLOCK));
  605.     memset(sensedata, 0, sizeof(SCSI_REQSENSE_DATA));
  606.     statusblock->ReqSenseLen = sizeof(SCSI_REQSENSE_DATA);
  607.     statusblock->SenseData = sensedata;
  608.  
  609.     iothru->iorbh.Length =    sizeof(IORB_ADAPTER_PASSTHRU);
  610.     iothru->iorbh.UnitHandle =    npUnit->UnitHandle;
  611.     iothru->iorbh.CommandCode =    IOCC_ADAPTER_PASSTHRU;
  612.     iothru->iorbh.CommandModifier =    IOCM_EXECUTE_CDB;
  613.  
  614.     iothru->iorbh.RequestControl =    IORB_REQ_STATUSBLOCK;
  615.     iothru->iorbh.StatusBlockLen =    sizeof(SCSI_STATUS_BLOCK);
  616.     iothru->iorbh.pStatusBlock =    (NPBYTE)statusblock;
  617.  
  618.     iothru->pControllerCmd =    cdb;
  619.     iothru->ControllerCmdLen =    6;
  620.  
  621.     /* Data buffer: have to supply a scatter/gather list
  622.      * (1 entry) and a direction. */
  623.  
  624.     ScGaEntry.ppXferBuf = (ULONG)((USHORT)buf + ppDiskDDHeader);
  625.     ScGaEntry.XferBufLen = bufsiz;
  626.     iothru->Flags = PT_DIRECTION_IN;
  627.     iothru->cSGList = 1;
  628.     iothru->pSGList = &ScGaEntry;
  629.     iothru->ppSGLIST = (ULONG)((USHORT)&ScGaEntry + ppDiskDDHeader);
  630.  
  631.     DEBMSG2("\r\nMODE SENSE(6) - iorb cdb sc/ga\r\n%z",(PIORB)iothru,iothru->iorbh.Length);
  632.     DEBMSG2("\r\n%z",(PVOID)cdb,6);
  633.     DEBMSG2("\r\n%z",(PVOID)&ScGaEntry,sizeof(ScGaEntry));
  634.  
  635.     if( (error=SendIORB((PIORB)iothru, pADDEntry)) )
  636.     {
  637.     sprintk(szMsgBuffer, szSenseFailed, (PSZ)szDriverName,
  638.         npUnit->AdapterIndex, npUnit->UnitIndex, error);
  639.     SaveMessage();
  640.     DumpStatusblock(statusblock);
  641.     }
  642.  
  643.     npInitData -= sizeof(SCSI_REQSENSE_DATA);
  644.     npInitData -= sizeof(SCSI_STATUS_BLOCK);
  645.     npInitData -= sizeof(IORB_ADAPTER_PASSTHRU);
  646.  
  647.     return error;
  648. }
  649.  
  650.  
  651.  
  652.  
  653. /*#
  654.  * CALL
  655.  *    ModeSelect(pADDEntry,npUnit,pgno,buf,bufsiz)
  656.  * PARAMETER
  657.  *    pADDEntry    call ADD
  658.  *    npUnit        ADD's UNITINFO structure
  659.  *    pgno        which page?
  660.  *    buf
  661.  *    bufsiz
  662.  * RETURNS
  663.  *    0        OK
  664.  *    /0        error code from ADD
  665.  * GLOBAL
  666.  * DESPRIPTION
  667.  * REMARKS
  668.  */
  669. PRIVATE USHORT
  670. ModeSelect(void (FAR _Cdecl * pADDEntry)(),NPUNITINFO const npUnit,
  671.        UCHAR pgno,PUCHAR buf,USHORT bufsiz)
  672. {
  673.     NPIORB_ADAPTER_PASSTHRU    iothru;
  674.     NPSCSI_STATUS_BLOCK        statusblock;
  675.     NPSCSI_REQSENSE_DATA    sensedata;
  676.  
  677.     BYTE        cdb[6];
  678.     USHORT        error;
  679.  
  680.  
  681.     GETINITRAM(iothru, NPIORB_ADAPTER_PASSTHRU, sizeof(IORB_ADAPTER_PASSTHRU));
  682.     GETINITRAM(statusblock, NPSCSI_STATUS_BLOCK, sizeof(SCSI_STATUS_BLOCK));
  683.     GETINITRAM(sensedata, NPSCSI_REQSENSE_DATA, sizeof(SCSI_REQSENSE_DATA));
  684.  
  685.     cdb[0] = SCSI_MODE_SELECT;
  686.     cdb[1] = (UCHAR)((npUnit->UnitSCSILUN << 5) | 0x10 | 0x00);
  687.     cdb[2] = 0x00;
  688.     cdb[3] = 0;
  689.     cdb[4] = (UCHAR)bufsiz;
  690.     cdb[5] = 0;
  691.  
  692.     memset(iothru, 0, sizeof(IORB_ADAPTER_PASSTHRU));
  693.     memset(statusblock, 0, sizeof(SCSI_STATUS_BLOCK));
  694.     memset(sensedata, 0, sizeof(SCSI_REQSENSE_DATA));
  695.     statusblock->ReqSenseLen = sizeof(SCSI_REQSENSE_DATA);
  696.     statusblock->SenseData = sensedata;
  697.  
  698.     iothru->iorbh.Length =        sizeof(IORB_ADAPTER_PASSTHRU);
  699.     iothru->iorbh.UnitHandle =        npUnit->UnitHandle;
  700.     iothru->iorbh.CommandCode =        IOCC_ADAPTER_PASSTHRU;
  701.     iothru->iorbh.CommandModifier =    IOCM_EXECUTE_CDB;
  702.  
  703.     iothru->iorbh.RequestControl =    IORB_REQ_STATUSBLOCK;
  704.     iothru->iorbh.StatusBlockLen =    sizeof(SCSI_STATUS_BLOCK);
  705.     iothru->iorbh.pStatusBlock =    (NPBYTE)statusblock;
  706.  
  707.     iothru->pControllerCmd =    cdb;
  708.     iothru->ControllerCmdLen =    6;
  709.  
  710.     /* Data buffer: have to supply a scatter/gather list
  711.      * (1 entry) and a direction. */
  712.  
  713.     ScGaEntry.ppXferBuf = (ULONG)((USHORT)buf + ppDiskDDHeader);
  714.     ScGaEntry.XferBufLen = MAX_MODE_DATA;
  715.     iothru->Flags = 0;
  716.     iothru->cSGList = 1;
  717.     iothru->pSGList = &ScGaEntry;
  718.     iothru->ppSGLIST = (ULONG)((USHORT)&ScGaEntry + ppDiskDDHeader);
  719.  
  720.     DEBMSG2("\r\nMODE SELECT(6) - iorb cdb sc/ga\r\n%z",(PIORB)iothru,iothru->iorbh.Length);
  721.     DEBMSG2("\r\n%z",(PVOID)cdb,6);
  722.     DEBMSG2("\r\n%z",(PVOID)&ScGaEntry,sizeof(ScGaEntry));
  723.  
  724.     if( (error=SendIORB((PIORB)iothru, pADDEntry)) )
  725.     {
  726.     sprintk(szMsgBuffer, szSelectFailed, (PSZ)szDriverName,
  727.         npUnit->AdapterIndex, npUnit->UnitIndex, error);
  728.     SaveMessage();
  729.     DumpStatusblock(statusblock);
  730.     }
  731.  
  732.     npInitData -= sizeof(SCSI_REQSENSE_DATA);
  733.     npInitData -= sizeof(SCSI_STATUS_BLOCK);
  734.     npInitData -= sizeof(IORB_ADAPTER_PASSTHRU);
  735.  
  736.     return error;
  737. }
  738.  
  739.  
  740.  
  741.  
  742. /*#
  743.  * CALL
  744.  *    ModifyCachePage(device,npUnit)
  745.  * PARAMETER
  746.  *    device        our own device structure
  747.  *    npUnit        from GET_DEVICE_TABLE
  748.  * RETURNS
  749.  *    0        OK
  750.  * GLOBAL
  751.  *    fDriverFlags
  752.  * DESPRIPTION
  753.  *    Reads caching mode page (MODE SENSE), modifies requested
  754.  *    settings and writes new page (MODE SELECT).
  755.  *    If device options exists for this page nothing is done at all.
  756.  *    If no change is requested MODE SELECT isn't executed.
  757.  *
  758.  * REMARKS
  759.  *    The device isn't requested to save these parameters permanent.  I
  760.  *    think it's safer this way: reset your machine and you get the default
  761.  *    state.
  762.  */
  763. PRIVATE int
  764. ModifyCachePage(PDEVICE const device,NPUNITINFO const npUnit)
  765. {
  766.     NPBYTE    data;
  767.     int        rc = 0;                /* error? */
  768.     PUNIT_OPTION pOption = QueryUTable(device->iAdapter, device->iUnit);
  769.  
  770.     if( pOption == NULL  ||  pOption->pg8.access == 0 )
  771.     {
  772.     DEBMSG2("\r\nModifyCachePage: nothing requested for %w,%w", device->iAdapter,device->iUnit);
  773.     return 0;                /* no change -> no error */
  774.     }
  775.  
  776.     GETINITRAM(data, NPBYTE, MAX_MODE_DATA);
  777.  
  778.     sprintk(szMsgBuffer, szRCachePage, device->iAdapter, device->iUnit);
  779.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  780.     if( (fDriverFlags & DF_VERBOSE) )
  781.     SaveMessage();
  782.  
  783.     do
  784.     {
  785.     UCHAR            pgno = 0x08;
  786.     NPSCSI_MODEPAGE_8    page;
  787.     UCHAR            mdlen;
  788.     int            modified = 0;    /* how many modifications? */
  789.  
  790.     /* First: read cache mode page via MODE SENSE(6),
  791.      * read current values. */
  792.  
  793.     if( ModeSense(device->pADDEntry, npUnit, pgno, data, MAX_MODE_DATA) )
  794.     {
  795.         rc = 1;
  796.         break;
  797.     }
  798.     DEBMSG3("\r\nOld page %w\r\n%z",pgno,(PVOID)data,sizeof(SCSI_MODEPAGE_HDR)
  799.         +sizeof(SCSI_MODEPAGE_DESCR)+sizeof(SCSI_MODEPAGE_8));
  800.  
  801.     /* Make some checks to detect non-standard page layout. */
  802.  
  803.     mdlen = (UCHAR)(data[0] + 1u);        /* 'does not include itself' */
  804.     page = (NPVOID)&data[sizeof(SCSI_MODEPAGE_HDR)
  805.                 +sizeof(SCSI_MODEPAGE_DESCR)];
  806.  
  807.     if( (UCHAR)(page->pcode & 0x7F) != pgno ) /* correct page read? */
  808.     {
  809.         sprintk(szMsgBuffer, szUnknFormat, (PSZ)szDriverName,
  810.             device->iAdapter, device->iUnit, pgno);
  811.         SaveMessage();
  812.         DEBMSG2("\r\nDumping complete buffer\r\n%z",(PVOID)data, mdlen);
  813.         rc = 2;
  814.         break;                /* skip this page */
  815.     }
  816.  
  817.  
  818.     /* If no change is requested: display current settings */
  819.  
  820.     if( pOption->pg8.access == 1  &&  (fDriverFlags & DF_VERBOSE) )
  821.     {
  822.         sprintk(szMsgBuffer, szReadCache,
  823.             device->iAdapter, device->iUnit,
  824.             (PSZ)((page->cache & 0x01) != 0 ? "disabled" : "enabled"));
  825.         SaveMessage();
  826.  
  827.         sprintk(szMsgBuffer, szWriteCache,
  828.             device->iAdapter, device->iUnit,
  829.             (PSZ)((page->cache & 0x04) == 0 ? "disabled" : "enabled"));
  830.         SaveMessage();
  831.  
  832.         sprintk(szMsgBuffer, szPrefetchPrio,
  833.             device->iAdapter, device->iUnit,
  834.             (PSZ)((page->priority == 0) ? "disabled" : "enabled"));
  835.         SaveMessage();
  836.  
  837.         sprintk(szMsgBuffer, szPrefetch,
  838.             device->iAdapter, device->iUnit,
  839.             (PSZ)((page->disprefetch[0] | page->disprefetch[1]) == 0
  840.               ? "disabled" : "enabled"));
  841.         SaveMessage();
  842.  
  843.         break;                /* nothing more to do, exit */
  844.     }
  845.  
  846.  
  847.     /* Modify page according to 'pOption'. */
  848.  
  849.     if( pOption->pg8.rce == 1  &&  (page->cache & 0x01) == 0 )
  850.     {
  851.         page->cache |= 0x01;        /* disable read cache */
  852.         ++modified;
  853.     }
  854.     else if( pOption->pg8.rce == 2  &&  (page->cache & 0x01) != 0 )
  855.     {
  856.         page->cache &= ~0x01;        /* don't disable read cache */
  857.         ++modified;
  858.     }
  859.  
  860.     if( pOption->pg8.wce == 1  &&  (page->cache & 0x04) != 0 )
  861.     {
  862.         page->cache &= ~0x04;        /* don't enable write cache */
  863.         ++modified;
  864.     }
  865.     else if( pOption->pg8.wce == 2  &&  (page->cache & 0x04) == 0 )
  866.     {
  867.         page->cache |= 0x04;        /* enable write cache */
  868.         ++modified;
  869.     }
  870.  
  871.     if( pOption->pg8.prio == 1  &&  page->priority != 0 )
  872.     {
  873.         page->priority = 0;            /* don't distinguish */
  874.         ++modified;
  875.     }
  876.     else if( pOption->pg8.prio == 2  &&  page->priority != 0x11 )
  877.     {
  878.         page->priority = 0x11;        /* keep prefetched data longer */
  879.         ++modified;
  880.     }
  881.  
  882.     if( pOption->pg8.pre == 1
  883.         &&  (page->disprefetch[0] | page->disprefetch[1]) != 0 )
  884.     {
  885.         /* Disable all pre-fetches */
  886.  
  887.         page->disprefetch[0] = 0;
  888.         page->disprefetch[1] = 0;        /* LSB */
  889.         page->minprefetch[0] = 0;
  890.         page->minprefetch[1] = 0;        /* LSB */
  891.         page->maxprefetch[0] = 0;
  892.         page->maxprefetch[1] = 0;        /* LSB */
  893.         page->prefetchceiling[0] = 0;
  894.         page->prefetchceiling[1] = 0;    /* LSB */
  895.         ++modified;
  896.     }
  897.     else if( pOption->pg8.pre == 2
  898.          &&  (page->disprefetch[0] | page->disprefetch[1]) == 0 )
  899.     {
  900.         /* Enable pre-fetch but disable it
  901.          * on reads with more than 8KB data. */
  902.  
  903.         page->cache &= ~0x02;        /* no multipliers, real counts */
  904.         page->disprefetch[0] = 0;
  905.         page->disprefetch[1] = 32;        /* LSB */
  906.         page->minprefetch[0] = 0;
  907.         page->minprefetch[1] = 1;        /* LSB */
  908.         page->maxprefetch[0] = 0;
  909.         page->maxprefetch[1] = 16;        /* LSB */
  910.         page->prefetchceiling[0] = 0;
  911.         page->prefetchceiling[1] = 16;    /* LSB */
  912.         ++modified;
  913.     }
  914.  
  915.     if( modified > 0 )
  916.     {
  917.         sprintk(szMsgBuffer, szWCachePage, device->iAdapter, device->iUnit);
  918.         DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  919.         if( (fDriverFlags & DF_VERBOSE) )
  920.         SaveMessage();
  921.  
  922.         /* Write this control mode page via MODE SELECT(6)
  923.          * but don't let target save this permanently. */
  924.  
  925.         page->pcode &= 0x3f;        /* mask reserved bits */
  926.         data[0] = 0;            /* reserved in MODE SELECT */
  927.         DEBMSG3("\r\nNew data for page %w\r\n%z",pgno,(PVOID)data,mdlen);
  928.         if( ModeSelect(device->pADDEntry, npUnit, pgno, data, mdlen) )
  929.         rc = 4;
  930.     }
  931.     }
  932.     while( 0 );
  933.  
  934.  
  935.     /* Release all memory in inverted order. */
  936.  
  937.     npInitData -= MAX_MODE_DATA;
  938.  
  939.     return 0;
  940. }
  941.  
  942.  
  943.  
  944.  
  945. /*#
  946.  * CALL
  947.  *    ModifyControlPage(device,npUnit)
  948.  * PARAMETER
  949.  *    device        our own device structure
  950.  *    npUnit        from GET_DEVICE_TABLE
  951.  * RETURNS
  952.  *    0        OK
  953.  * GLOBAL
  954.  *    fDriverFlags
  955.  * DESPRIPTION
  956.  *    Modifies Control Page (10).  Similar to ModifyCachePage().
  957.  *
  958.  * REMARKS
  959.  */
  960. PRIVATE int
  961. ModifyControlPage(PDEVICE const device,NPUNITINFO const npUnit)
  962. {
  963.     NPBYTE    data;
  964.     int        rc = 0;                /* error? */
  965.     PUNIT_OPTION pOption = QueryUTable(device->iAdapter, device->iUnit);
  966.  
  967.     if( pOption == NULL  ||  pOption->pg10.access == 0 )
  968.     {
  969.     DEBMSG2("\r\nModifyControlPage: nothing requested for %w,%w", device->iAdapter,device->iUnit);
  970.     return 0;                /* no change -> no error */
  971.     }
  972.  
  973.     GETINITRAM(data, NPBYTE, MAX_MODE_DATA);
  974.  
  975.     sprintk(szMsgBuffer, szRControlPage, device->iAdapter, device->iUnit);
  976.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  977.     if( (fDriverFlags & DF_VERBOSE) )
  978.     SaveMessage();
  979.  
  980.     do
  981.     {
  982.     UCHAR            pgno = 0x0A;
  983.     NPSCSI_MODEPAGE_A    page;
  984.     UCHAR            mdlen;
  985.     int            modified = 0;
  986.  
  987.     /* First: read mode page via MODE SENSE(6),
  988.      * read current values. */
  989.  
  990.     if( ModeSense(device->pADDEntry, npUnit, pgno, data, MAX_MODE_DATA) )
  991.     {
  992.         rc = 1;
  993.         break;
  994.     }
  995.     DEBMSG3("\r\nOld page %w\r\n%z",pgno,(PVOID)data,sizeof(SCSI_MODEPAGE_HDR)
  996.         +sizeof(SCSI_MODEPAGE_DESCR)+sizeof(SCSI_MODEPAGE_A));
  997.  
  998.  
  999.     mdlen = (UCHAR)(data[0] + 1u);        /* 'does not include itself' */
  1000.     page = (NPVOID)&data[sizeof(SCSI_MODEPAGE_HDR)
  1001.                 +sizeof(SCSI_MODEPAGE_DESCR)];
  1002.  
  1003.     if( (page->pcode & 0x7F) != pgno )
  1004.     {
  1005.         sprintk(szMsgBuffer, szUnknFormat, (PSZ)szDriverName,
  1006.             device->iAdapter, device->iUnit, pgno);
  1007.         SaveMessage();
  1008.         DEBMSG2("\r\nDumping complete buffer\r\n%z",(PVOID)data, mdlen);
  1009.         rc = 2;
  1010.         break;                /* skip this page */
  1011.     }
  1012.  
  1013.  
  1014.     /* If no change is requested: display current settings */
  1015.  
  1016.     if( pOption->pg10.access == 1  &&  (fDriverFlags & DF_VERBOSE) )
  1017.     {
  1018.         sprintk(szMsgBuffer, szTaggedQueue,
  1019.             device->iAdapter, device->iUnit,
  1020.             (PSZ)((page->queuing & 0x01) != 0
  1021.               ? "disabled" : "enabled"));
  1022.         SaveMessage();
  1023.  
  1024.         sprintk(szMsgBuffer, szReorder,
  1025.             device->iAdapter, device->iUnit,
  1026.             (PSZ)((page->queuing & 0xF0) != 0x10
  1027.               ? "disabled" : "enabled"));
  1028.         SaveMessage();
  1029.  
  1030.         break;                /* nothing more to do, exit */
  1031.     }
  1032.  
  1033.  
  1034.     /* Modify page according to 'pOption'. */
  1035.  
  1036.     if( pOption->pg10.queue == 1  &&  (page->queuing & 0x01) == 0 )
  1037.     {
  1038.         page->queuing |= 0x01;        /* disable tagged queuing */
  1039.         ++modified;
  1040.     }
  1041.     else if( pOption->pg10.queue == 2  &&  (page->queuing & 0x01) != 0 )
  1042.     {
  1043.         page->queuing &= ~0x01;        /* don't disable TQ */
  1044.         ++modified;
  1045.     }
  1046.  
  1047.     if( pOption->pg10.reorder == 1  &&  (page->queuing & 0xF0) == 0x10 )
  1048.     {
  1049.         page->queuing &= 0x0F;        /* 'restricted reordering */
  1050.         ++modified;
  1051.     }
  1052.     else if(pOption->pg10.reorder == 2 && (page->queuing & 0xF0) != 0x10)
  1053.     {
  1054.         page->queuing &= 0x0F;
  1055.         page->queuing |= 0x10;        /* 'unrestricted reordering' */
  1056.         ++modified;
  1057.     }
  1058.  
  1059.  
  1060.     if( modified > 0 )
  1061.     {
  1062.         sprintk(szMsgBuffer,szWControlPage, device->iAdapter, device->iUnit);
  1063.         DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1064.         if( (fDriverFlags & DF_VERBOSE) )
  1065.         SaveMessage();
  1066.  
  1067.         /* Write this control mode page via MODE SELECT(6)
  1068.          * but don't let target save this permanently. */
  1069.  
  1070.         page->pcode &= 0x3f;        /* mask reserved bits */
  1071.         data[0] = 0;            /* reserved in MODE SELECT */
  1072.         DEBMSG3("\r\nNew page %w\r\n%z",pgno,(PVOID)data,mdlen);
  1073.         if( ModeSelect(device->pADDEntry, npUnit, pgno, data, mdlen) )
  1074.         rc = 4;
  1075.     }
  1076.     }
  1077.     while( 0 );
  1078.  
  1079.  
  1080.     /* Release all memory in inverted order. */
  1081.  
  1082.     npInitData -= MAX_MODE_DATA;
  1083.  
  1084.     return 0;
  1085. }
  1086.  
  1087.  
  1088.  
  1089.  
  1090. /*#
  1091.  * CALL
  1092.  *    ModifyConnectPage(device,npUnit)
  1093.  * PARAMETER
  1094.  *    device        our own device structure
  1095.  *    npUnit        from GET_DEVICE_TABLE
  1096.  * RETURNS
  1097.  *    0        OK
  1098.  * GLOBAL
  1099.  *    fDriverFlags
  1100.  * DESPRIPTION
  1101.  *    See ModifiyCachePage()
  1102.  *
  1103.  * REMARKS
  1104.  */
  1105. PRIVATE int
  1106. ModifyConnectPage(PDEVICE const device,NPUNITINFO const npUnit)
  1107. {
  1108.     NPBYTE    data;
  1109.     int        rc = 0;                /* error? */
  1110.     PUNIT_OPTION pOption = QueryUTable(device->iAdapter, device->iUnit);
  1111.  
  1112.     if( pOption == NULL  ||  pOption->pg2.access == 0 )
  1113.     {
  1114.     DEBMSG2("\r\nModifyConnectPage: nothing requested for %w,%w", device->iAdapter,device->iUnit);
  1115.     return 0;                /* no change -> no error */
  1116.     }
  1117.  
  1118.     GETINITRAM(data, NPBYTE, MAX_MODE_DATA);
  1119.  
  1120.     sprintk(szMsgBuffer, szRConnectPage, device->iAdapter, device->iUnit);
  1121.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1122.     if( (fDriverFlags & DF_VERBOSE) )
  1123.     SaveMessage();
  1124.  
  1125.     do
  1126.     {
  1127.     UCHAR            pgno = 0x02;
  1128.     NPSCSI_MODEPAGE_2    page;
  1129.     UCHAR            mdlen;
  1130.     int            modified = 0;
  1131.  
  1132.     /* First: read mode page via MODE SENSE(6),
  1133.      * read current values. */
  1134.  
  1135.     if( ModeSense(device->pADDEntry, npUnit, pgno, data, MAX_MODE_DATA) )
  1136.     {
  1137.         rc = 1;
  1138.         break;
  1139.     }
  1140.     DEBMSG3("\r\nOld page %w\r\n%z",pgno,(PVOID)data,sizeof(SCSI_MODEPAGE_HDR)
  1141.         +sizeof(SCSI_MODEPAGE_DESCR)+sizeof(SCSI_MODEPAGE_2));
  1142.  
  1143.  
  1144.     mdlen = (UCHAR)(data[0] + 1u);        /* 'does not include itself' */
  1145.     page = (NPVOID)&data[sizeof(SCSI_MODEPAGE_HDR)
  1146.                 +sizeof(SCSI_MODEPAGE_DESCR)];
  1147.  
  1148.     if( (page->pcode & 0x7F) != pgno )
  1149.     {
  1150.         sprintk(szMsgBuffer, szUnknFormat, (PSZ)szDriverName,
  1151.             device->iAdapter, device->iUnit, pgno);
  1152.         SaveMessage();
  1153.         DEBMSG2("\r\nDumping complete buffer\r\n%z",(PVOID)data, mdlen);
  1154.         rc = 2;
  1155.         break;                /* skip this page */
  1156.     }
  1157.  
  1158.  
  1159.     /* If no change is requested: display current settings */
  1160.  
  1161.     if( pOption->pg2.access == 1  &&  (fDriverFlags & DF_VERBOSE) )
  1162.     {
  1163.         sprintk(szMsgBuffer, szFullReselect,
  1164.             device->iAdapter, device->iUnit,
  1165.             (PSZ)((page->bfull | page->bempty) == 0
  1166.               ? "disabled" : "enabled"));
  1167.         SaveMessage();
  1168.  
  1169.         sprintk(szMsgBuffer, szInactiveTO,
  1170.             device->iAdapter, device->iUnit,
  1171.             (PSZ)((page->businactive[0] |  page->businactive[1]) == 0
  1172.               ? "disabled" : "enabled"));
  1173.         SaveMessage();
  1174.  
  1175.         sprintk(szMsgBuffer, szDisconnectTO,
  1176.             device->iAdapter, device->iUnit,
  1177.             (PSZ)((page->disconnect[0] |  page->disconnect[1]) == 0
  1178.               ? "disabled" : "enabled"));
  1179.         SaveMessage();
  1180.  
  1181.         sprintk(szMsgBuffer, szConnectTO,
  1182.             device->iAdapter, device->iUnit,
  1183.             (PSZ)((page->connect[0] |  page->connect[1]) == 0
  1184.               ? "disabled" : "enabled"));
  1185.         SaveMessage();
  1186.  
  1187.         break;                /* nothing more to do, exit */
  1188.     }
  1189.  
  1190.  
  1191.     /* Modify page according to 'pOption'. */
  1192.  
  1193.     if( pOption->pg2.buffer == 1
  1194.         &&  (page->bfull | page->bempty) != 0 )
  1195.     {
  1196.         /* no disconnect because of full/empty buffers */
  1197.  
  1198.         page->bfull = 0;
  1199.         page->bempty = 0;
  1200.         ++modified;
  1201.     }
  1202.     else if( pOption->pg2.buffer == 2
  1203.          &&  (page->bfull | page->bempty) == 0 )
  1204.     {
  1205.         /* disconnect because of full/empty buffers */
  1206.  
  1207.         page->bfull = 40;            /* ~15% */
  1208.         page->bempty = 40;
  1209.         ++modified;
  1210.     }
  1211.  
  1212.  
  1213.     if( pOption->pg2.inactive == 1
  1214.         &&  (page->businactive[0] |  page->businactive[1]) != 0 )
  1215.     {
  1216.         /* no limit on bus busy time w/o connection */
  1217.  
  1218.         page->businactive[0] = page->businactive[1] = 0;
  1219.         ++modified;
  1220.     }
  1221.     else if(pOption->pg2.inactive == 2
  1222.         &&  (page->businactive[0] |  page->businactive[1]) == 0 )
  1223.     {
  1224.         /* don't keep bus busy w/o connection */
  1225.  
  1226.         page->businactive[0] = 0;
  1227.         page->businactive[1] = 200;        /* LSB */
  1228.         ++modified;
  1229.     }
  1230.  
  1231.     if( pOption->pg2.disconnect == 1
  1232.         &&  (page->disconnect[0] |  page->disconnect[1]) != 0 )
  1233.     {
  1234.         /* no limit on bus disconnect state */
  1235.  
  1236.         page->disconnect[0] = page->disconnect[1] = 0;
  1237.         ++modified;
  1238.     }
  1239.     else if( pOption->pg2.disconnect == 2
  1240.          &&  (page->disconnect[0] |  page->disconnect[1]) == 0 )
  1241.     {
  1242.         /* don't keep disconnect state forever */
  1243.  
  1244.         page->disconnect[0] = 0;
  1245.         page->disconnect[1] = 200;        /* LSB */
  1246.         ++modified;
  1247.     }
  1248.  
  1249.     if( pOption->pg2.connect == 1
  1250.         &&  (page->connect[0] |  page->connect[1]) != 0 )
  1251.     {
  1252.         /* no limit on bus connect state */
  1253.  
  1254.         page->connect[0] = page->connect[1] = 0;
  1255.         ++modified;
  1256.     }
  1257.     else if( pOption->pg2.connect == 2
  1258.         &&  (page->connect[0] |  page->connect[1]) == 0 )
  1259.     {
  1260.         /* don't keep connect state forever */
  1261.  
  1262.         page->connect[0] = 0;
  1263.         page->connect[1] = 200;        /* LSB */
  1264.         ++modified;
  1265.     }
  1266.  
  1267.  
  1268.     if( modified > 0 )
  1269.     {
  1270.         sprintk(szMsgBuffer,szWConnectPage, device->iAdapter, device->iUnit);
  1271.         DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1272.         if( (fDriverFlags & DF_VERBOSE) )
  1273.         SaveMessage();
  1274.  
  1275.         /* Write this control mode page via MODE SELECT(6)
  1276.          * but don't let target save this permanently. */
  1277.  
  1278.         page->pcode &= 0x3f;        /* mask reserved bits */
  1279.         data[0] = 0;            /* reserved in MODE SELECT */
  1280.         DEBMSG3("\r\nNew page %w\r\n%z",pgno,(PVOID)data,mdlen);
  1281.         if( ModeSelect(device->pADDEntry, npUnit, pgno, data, mdlen) )
  1282.         rc = 4;
  1283.     }
  1284.     }
  1285.     while( 0 );
  1286.  
  1287.  
  1288.     /* Release all memory in inverted order. */
  1289.  
  1290.     npInitData -= MAX_MODE_DATA;
  1291.  
  1292.     return 0;
  1293. }
  1294.  
  1295.  
  1296.  
  1297.  
  1298. /*#
  1299.  * CALL
  1300.  *    ModifyCdromPage(device,npUnit)
  1301.  * PARAMETER
  1302.  *    device        our own device structure
  1303.  *    npUnit        from GET_DEVICE_TABLE
  1304.  * RETURNS
  1305.  *    0        OK
  1306.  * GLOBAL
  1307.  *    fDriverFlags
  1308.  * DESPRIPTION
  1309.  *    Modifies CDROM Control Page (13).
  1310.  *
  1311.  * REMARKS
  1312.  */
  1313. PRIVATE int
  1314. ModifyCdromPage(PDEVICE const device,NPUNITINFO const npUnit)
  1315. {
  1316.     NPBYTE    data;
  1317.     int        rc = 0;                /* error? */
  1318.     PUNIT_OPTION pOption = QueryUTable(device->iAdapter, device->iUnit);
  1319.  
  1320.     if( pOption == NULL  ||  pOption->pg13.access == 0 )
  1321.     {
  1322.     DEBMSG2("\r\nModifyCdromPage: nothing requested for %w,%w", device->iAdapter,device->iUnit);
  1323.     return 0;                /* no change -> no error */
  1324.     }
  1325.  
  1326.     GETINITRAM(data, NPBYTE, MAX_MODE_DATA);
  1327.  
  1328.     sprintk(szMsgBuffer, szRCDPage, device->iAdapter, device->iUnit);
  1329.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1330.     if( (fDriverFlags & DF_VERBOSE) )
  1331.     SaveMessage();
  1332.  
  1333.     do
  1334.     {
  1335.     UCHAR            pgno = 0x0D;
  1336.     NPSCSI_MODEPAGE_D    page;
  1337.     UCHAR            mdlen;
  1338.     int            modified = 0;
  1339.  
  1340.     /* First: read mode page via MODE SENSE(6),
  1341.      * read current values. */
  1342.  
  1343.     if( ModeSense(device->pADDEntry, npUnit, pgno, data, MAX_MODE_DATA) )
  1344.     {
  1345.         rc = 1;
  1346.         break;
  1347.     }
  1348.     DEBMSG3("\r\nOld page %w\r\n%z",pgno,(PVOID)data,sizeof(SCSI_MODEPAGE_HDR)
  1349.         +sizeof(SCSI_MODEPAGE_DESCR)+sizeof(SCSI_MODEPAGE_D));
  1350.  
  1351.  
  1352.     mdlen = (UCHAR)(data[0] + 1u);        /* 'does not include itself' */
  1353.     page = (NPVOID)&data[sizeof(SCSI_MODEPAGE_HDR)
  1354.                 +sizeof(SCSI_MODEPAGE_DESCR)];
  1355.  
  1356.     if( (page->pcode & 0x7F) != pgno )
  1357.     {
  1358.         sprintk(szMsgBuffer, szUnknFormat, (PSZ)szDriverName,
  1359.             device->iAdapter, device->iUnit, pgno);
  1360.         SaveMessage();
  1361.         DEBMSG2("\r\nDumping complete buffer\r\n%z",(PVOID)data, mdlen);
  1362.         rc = 2;
  1363.         break;                /* skip this page */
  1364.     }
  1365.  
  1366.  
  1367.     /* If no change is requested: display current settings */
  1368.  
  1369.     if( pOption->pg13.access == 1  &&  (fDriverFlags & DF_VERBOSE) )
  1370.     {
  1371.         char * cp;
  1372.  
  1373.         switch( page->multiplier )
  1374.         {
  1375.           case 0x01:
  1376.         cp = "125 ms";
  1377.         break;
  1378.           case 0x02:
  1379.         cp = "250 ms";
  1380.         break;
  1381.           case 0x03:
  1382.         cp = "500 ms";
  1383.         break;
  1384.           case 0x04:
  1385.         cp = "1 s";
  1386.         break;
  1387.           case 0x05:
  1388.         cp = "2 s";
  1389.         break;
  1390.           case 0x06:
  1391.         cp = "4 s";
  1392.         break;
  1393.           case 0x07:
  1394.         cp = "8 s";
  1395.         break;
  1396.           case 0x08:
  1397.         cp = "16 s";
  1398.         break;
  1399.           case 0x09:
  1400.         cp = "32 s";
  1401.         break;
  1402.           case 0x0A:
  1403.         cp = "60 s";
  1404.         break;
  1405.           case 0x0B:
  1406.         cp = "120 s";
  1407.         break;
  1408.           case 0x0C:
  1409.         cp = "240 s";
  1410.         break;
  1411.           case 0x0D:
  1412.         cp = "480 s";
  1413.         break;
  1414.           case 0x0E:
  1415.         cp = "960 s";
  1416.         break;
  1417.           case 0x0F:
  1418.         cp = "1920 s";
  1419.         break;
  1420.  
  1421.           case 0:
  1422.           default:
  1423.         cp = "unknown";
  1424.         break;
  1425.         }
  1426.  
  1427.         sprintk(szMsgBuffer, szCDTimeout, device->iAdapter, device->iUnit, cp);
  1428.         SaveMessage();
  1429.         break;                /* nothing more to do, exit */
  1430.     }
  1431.  
  1432.  
  1433.     /* Modify page according to 'pOption'. */
  1434.  
  1435.     page->multiplier &= 0xF0;        /* clear low nibble */
  1436.     ++modified;                /* always modified if reached */
  1437.     if( pOption->pg13.seconds <= 1 )
  1438.         page->multiplier |= 0x04;
  1439.     else if( pOption->pg13.seconds <= 2 )
  1440.         page->multiplier |= 0x05;
  1441.     else if( pOption->pg13.seconds <= 4 )
  1442.         page->multiplier |= 0x06;
  1443.     else if( pOption->pg13.seconds <= 8 )
  1444.         page->multiplier |= 0x07;
  1445.     else if( pOption->pg13.seconds <= 16 )
  1446.         page->multiplier |= 0x08;
  1447.     else if( pOption->pg13.seconds <= 32 )
  1448.         page->multiplier |= 0x09;
  1449.     else if( pOption->pg13.seconds <= 60 )
  1450.         page->multiplier |= 0x0A;
  1451.     else if( pOption->pg13.seconds <= 120 )
  1452.         page->multiplier |= 0x0B;
  1453.     else if( pOption->pg13.seconds <= 240 )
  1454.         page->multiplier |= 0x0C;
  1455.     else if( pOption->pg13.seconds <= 480 )
  1456.         page->multiplier |= 0x0D;
  1457.     else if( pOption->pg13.seconds <= 960 )
  1458.         page->multiplier |= 0x0E;
  1459.     else
  1460.         page->multiplier |= 0x0F;        /* else maximum */
  1461.  
  1462.     if( modified > 0 )
  1463.     {
  1464.         sprintk(szMsgBuffer,szWCDPage, device->iAdapter, device->iUnit);
  1465.         DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1466.         if( (fDriverFlags & DF_VERBOSE) )
  1467.         SaveMessage();
  1468.  
  1469.         /* Write this mode page via MODE SELECT(6)
  1470.          * but don't let target save this permanently. */
  1471.  
  1472.         page->pcode &= 0x3f;        /* mask reserved bits */
  1473.         data[0] = 0;            /* reserved in MODE SELECT */
  1474.         DEBMSG3("\r\nNew page %w\r\n%z",pgno,(PVOID)data,mdlen);
  1475.         if( ModeSelect(device->pADDEntry, npUnit, pgno, data, mdlen) )
  1476.         rc = 4;
  1477.     }
  1478.     }
  1479.     while( 0 );
  1480.  
  1481.  
  1482.     /* Release all memory in inverted order. */
  1483.  
  1484.     npInitData -= MAX_MODE_DATA;
  1485.  
  1486.     return 0;
  1487. }
  1488.  
  1489.  
  1490.  
  1491.  
  1492. /*#
  1493.  * CALL
  1494.  *    ModifyDevice(device,npUnit)
  1495.  * PARAMETER
  1496.  *    device        DEVICE structure
  1497.  *    npUnit
  1498.  * RETURNS
  1499.  *    0        OK
  1500.  *    /0        error
  1501.  * GLOBAL
  1502.  * DESPRIPTION
  1503.  *    Modify performance-related mode pages.
  1504.  *
  1505.  * REMARKS
  1506.  */
  1507. PRIVATE int NEAR
  1508. ModifyDevice(PDEVICE const device,NPUNITINFO const npUnit)
  1509. {
  1510.     int rc = 0;
  1511.  
  1512.     sprintk(szMsgBuffer, szModifyStart, device->iAdapter, device->iUnit);
  1513.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1514.     if( (fDriverFlags & DF_DEBUG) )
  1515.     SaveMessage();
  1516.  
  1517.     /* We need access to a device before issuing commands
  1518.      * to it.  So send a request to ALLOCATE UNIT */
  1519.  
  1520.     {
  1521.     NPIORB_UNIT_CONTROL pIOUC = (NPVOID)npInitData;
  1522.  
  1523.     memset(pIOUC, 0, sizeof(IORB_UNIT_CONTROL));
  1524.     pIOUC->iorbh.Length =        sizeof(IORB_UNIT_CONTROL);
  1525.     pIOUC->iorbh.UnitHandle =    npUnit->UnitHandle;
  1526.     pIOUC->iorbh.CommandCode =    IOCC_UNIT_CONTROL;
  1527.     pIOUC->iorbh.CommandModifier =    IOCM_ALLOCATE_UNIT;
  1528.  
  1529.     if( SendIORB((PIORB)pIOUC, device->pADDEntry) )
  1530.     {
  1531.         sprintk(szMsgBuffer, szAllocFailed, (PSZ)szDriverName,
  1532.             device->iAdapter, device->iUnit);
  1533.         SaveMessage();
  1534.         return 1;
  1535.     }
  1536.     }
  1537.  
  1538.     /* Modify pages... */
  1539.  
  1540.     rc = ModifyCachePage(device, npUnit);
  1541.     rc |= ModifyControlPage(device, npUnit);
  1542.     rc |= ModifyConnectPage(device, npUnit);
  1543.     rc |= ModifyCdromPage(device, npUnit);
  1544.  
  1545.     /* All done, so release access to this unit. */
  1546.  
  1547.     {
  1548.     NPIORB_UNIT_CONTROL pIOUC = (NPVOID)npInitData;
  1549.  
  1550.     /* Send request to DEALLOCATE UNIT */
  1551.  
  1552.     memset( pIOUC, 0, sizeof(IORB_UNIT_CONTROL) );
  1553.     pIOUC->iorbh.Length =        sizeof(IORB_UNIT_CONTROL);
  1554.     pIOUC->iorbh.UnitHandle =    npUnit->UnitHandle;
  1555.     pIOUC->iorbh.CommandCode =    IOCC_UNIT_CONTROL;
  1556.     pIOUC->iorbh.CommandModifier =    IOCM_DEALLOCATE_UNIT;
  1557.  
  1558.     if( SendIORB((PIORB)pIOUC, device->pADDEntry) )
  1559.     {
  1560.         /* Couldn't deallocte unit.
  1561.          * Bad, display and ignore */
  1562.  
  1563.         sprintk(szMsgBuffer, szDeallocFailed, (PSZ)szDriverName,
  1564.             device->iAdapter, device->iUnit);
  1565.         SaveMessage();
  1566.     }
  1567.     }
  1568.  
  1569.     if( rc == 0 )
  1570.     {
  1571.     sprintk(szMsgBuffer, szModifyOK, device->iAdapter, device->iUnit);
  1572.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1573.     if( (fDriverFlags & DF_DEBUG) )
  1574.         SaveMessage();
  1575.     }
  1576.     return rc;
  1577. }
  1578.  
  1579.  
  1580.  
  1581.  
  1582.  
  1583. /*#
  1584.  * CALL
  1585.  *    ScanDevices(void)
  1586.  * PARAMETER
  1587.  *    none
  1588.  * RETURNS
  1589.  *    0        OK, install driver
  1590.  *    <0        fatal error, loud abort
  1591.  *    >0        no device found, be quiet
  1592.  * GLOBAL
  1593.  *    anpUnit
  1594.  *    npInitData
  1595.  *    fDriverFlags
  1596.  * DESPRIPTION
  1597.  *    Scans all adapters on all ADDs for SCSI devices and
  1598.  *    calls ModifyDevice() for each.
  1599.  *
  1600.  * REMARKS
  1601.  */
  1602. PRIVATE int
  1603. ScanDevices(void)
  1604. {
  1605.     USHORT    j, k;
  1606.     USHORT    changed = 0;
  1607.     int        fatal = 0;
  1608.  
  1609.     USHORT    add_count;
  1610.     USHORT    add_index;
  1611.     USHORT    adp = 0;
  1612.  
  1613.     void    (FAR _Cdecl * pADDBaseEP)();
  1614.  
  1615.     struct DevClassTableEntry FAR *pDCE;
  1616.     struct DevClassTableStruc FAR *pDCT;
  1617.  
  1618.  
  1619.     DEBMSG("\r\nScanDevices");
  1620.  
  1621.     /* Get address of Registered ADD Table */
  1622.  
  1623.     if( DevHelp_GetDOSVar(DHGETDOSV_DEVICECLASSTABLE, DRIVERCLASS_ADD, &pDCT) )
  1624.     {
  1625.     /* Should never happen.  What can we do? */
  1626.  
  1627.     sprintk(szMsgBuffer, szNoDriverTab, (PSZ)szDriverName);
  1628.     SaveMessage();
  1629.     return -1;
  1630.     }
  1631.  
  1632.     add_count = pDCT->DCCount;
  1633.  
  1634.  
  1635.     /* For each ADD registered  */
  1636.  
  1637.     DEBMSG("\r\nLooking for ADDs");
  1638.     for( pDCE = pDCT->DCTableEntries, add_index = 0;
  1639.      add_index < add_count;
  1640.      ++add_index, ++pDCE )
  1641.     {
  1642.     {
  1643.         NPIORB_CONFIGURATION pIOCF = (NPVOID)npInitData;
  1644.  
  1645.         /* Get ADD's Device Table */
  1646.  
  1647.         memset( pIOCF, 0, sizeof(IORB_CONFIGURATION) );
  1648.         pIOCF->iorbh.Length =        sizeof(IORB_CONFIGURATION);
  1649.         pIOCF->iorbh.UnitHandle =        0;
  1650.         pIOCF->iorbh.CommandCode =        IOCC_CONFIGURATION;
  1651.         pIOCF->iorbh.CommandModifier =    IOCM_GET_DEVICE_TABLE;
  1652.  
  1653.         pIOCF->pDeviceTable =    (PDEVICETABLE)DeviceTable;
  1654.         pIOCF->DeviceTableLen =    sizeof(DeviceTable);
  1655.  
  1656.         pADDBaseEP = (PVOID)MAKEP(pDCE->DCSelector, pDCE->DCOffset);
  1657.  
  1658.         if( SendIORB((PIORB)pIOCF, pADDBaseEP) )
  1659.         {
  1660.         /* Error (?), could not get device table of installed
  1661.          * ADD.  Just ignore that ADD (which probably hasn't
  1662.          * any adapters/devices, either). */
  1663.  
  1664.         sprintk(szMsgBuffer, szNoDevTab, (PSZ)szDriverName, add_index);
  1665.         SaveMessage();
  1666.         continue;
  1667.         }
  1668.     }
  1669.  
  1670.  
  1671.     /* For each Adapter in ADD's Device Table */
  1672.  
  1673.     for( j = 0; j < ((PDEVICETABLE)DeviceTable)->TotalAdapters; ++j, ++adp )
  1674.         {
  1675.         NPADAPTERINFO const npAdapterInfo
  1676.         = ((PDEVICETABLE)DeviceTable)->pAdapter[j];
  1677.         NPUNITINFO        npUnitInfo;
  1678.  
  1679.  
  1680.         if( CheckAdapterInfo(adp, npAdapterInfo) )
  1681.         continue;
  1682.  
  1683.         /* Access UNITINFO for each Device on adapter */
  1684.  
  1685.         DEBMSG("\r\nLooking for Units");
  1686.         for( npUnitInfo = npAdapterInfo->UnitInfo, k = 0;
  1687.          k < npAdapterInfo->AdapterUnits;
  1688.          ++k, ++npUnitInfo )
  1689.             {
  1690.         DEVICE    dev;            /* local structure, not
  1691.                            global table as we aren't
  1692.                            a real filter. */
  1693.  
  1694.         /* If a Filter ADD has registered for this unit
  1695.          * then send subsequent requests to the Filter ADD
  1696.          * and not to the ADD. */
  1697.  
  1698.         if( (dev.hdFilter=npUnitInfo->FilterADDHandle) != 0 )
  1699.                 {
  1700.             struct DevClassTableEntry FAR *pDCEFilter;
  1701.  
  1702.             DEBMSG("\r\nFound other filter for unit");
  1703.             pDCEFilter = &pDCT->DCTableEntries[dev.hdFilter-1];
  1704.  
  1705.             dev.pADDEntry = (PVOID)MAKEP(pDCEFilter->DCSelector,
  1706.                          pDCEFilter->DCOffset);
  1707.                 }
  1708.         else
  1709.                 {
  1710.             dev.pADDEntry = pADDBaseEP;
  1711.                 }
  1712.         dev.iAdapter = adp;
  1713.         dev.iUnit = npUnitInfo->UnitIndex;
  1714.  
  1715.         if( CheckUnitInfo(&dev, npUnitInfo) )
  1716.             continue;
  1717.  
  1718.         sprintk(szMsgBuffer, szFoundDevice, dev.iAdapter, dev.iUnit);
  1719.         DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1720.         if( (fDriverFlags & DF_VERBOSE) )
  1721.             SaveMessage();
  1722.  
  1723.         if( ModifyDevice(&dev, npUnitInfo) == 0 )
  1724.             ++changed;
  1725.  
  1726.         } /* for each unit */
  1727.     } /* for each adapter */
  1728.     } /* for each ADD */
  1729.  
  1730.     if( fatal )                    /* errors occurred? */
  1731.     {
  1732.     return -1;                /* than display and wait */
  1733.     }
  1734.     if( changed == 0 )
  1735.     {
  1736.     sprintk(szMsgBuffer, szNoDevices);
  1737.     DEBMSG1("\r\n%s",(PSZ)szMsgBuffer);
  1738.     if( (fDriverFlags & DF_VERBOSE) )
  1739.         SaveMessage();
  1740.     return 1;                /* non-fatal error,
  1741.                            don't install */
  1742.     }
  1743.     return 0;
  1744. }
  1745.  
  1746.  
  1747.  
  1748.  
  1749.  
  1750.  
  1751. #define ENTRY_STATE       0
  1752. #define MAX_STATES       2
  1753.  
  1754. /*
  1755.  *                    opt.state[] initialization definitions
  1756.  *
  1757.  *                        ____ entry state
  1758.  *                        |        previous
  1759.  *                        v          opt    |
  1760.  *  ----Command Line Option --------        ----- STATE TABLE ----- |
  1761.  *  token id        string    type        0   1    2        |
  1762.  *                                    |
  1763.  *                        *  /A:    /A:     <-------
  1764.  *                             plus
  1765.  */
  1766. #define TOK_ID_EF    100
  1767. #define TOK_ID_DF    101
  1768.  
  1769. OPT OPT_VERBOSE =
  1770.     {TOK_ID_VERBOSE,0,    "/V", TYPE_0,        {0,  E,  E}};
  1771.  
  1772. OPT OPT_DEBUG_NO =
  1773.     {TOK_ID_DEBUG,0,    "/DEBUG:", TYPE_D,    {0,  E,  E}};
  1774.  
  1775. OPT OPT_DEBUG_DEFAULT =
  1776.     {TOK_ID_DEBUG,0,    "/DEBUG", TYPE_0,    {0,  E,  E}};
  1777.  
  1778. OPT OPT_ADAPTER =
  1779.     {TOK_ID_ADAPTER,0,    "/A:", TYPE_D,        {1,  E,  1}};
  1780.  
  1781. OPT OPT_ENABLE =
  1782.     {TOK_ID_EF,0,    "/E:", TYPE_GEOMETRY,    {E,  2,  2}};
  1783.  
  1784. OPT OPT_DISABLE =
  1785.     {TOK_ID_DF,0,    "/!E:", TYPE_GEOMETRY,    {E,  2,  2}};
  1786.  
  1787. OPT OPT_END =
  1788.     {TOK_ID_END,0,    "\0", TYPE_0,        {O,  O,  O}};
  1789.  
  1790.  
  1791. /*
  1792.  *   Please note the importance of the ordering of entries in poption[]
  1793.  *   For example: the pointer to the option "/DM:" must come before the
  1794.  *   option "/DM"
  1795.  */
  1796. OPTIONTABLE  opttable = {
  1797.     ENTRY_STATE, MAX_STATES,
  1798.     {
  1799.     &OPT_VERBOSE,
  1800.     &OPT_DEBUG_NO,
  1801.     &OPT_DEBUG_DEFAULT,
  1802.     &OPT_ADAPTER,
  1803.     &OPT_ENABLE,
  1804.     &OPT_DISABLE,
  1805.     &OPT_END
  1806.     }
  1807. };
  1808.  
  1809.  
  1810.  
  1811.  
  1812. /*#
  1813.  * CALL
  1814.  *    AnalyseCmdLine(pszLine)
  1815.  * PARAMETER
  1816.  *    pszLine        pointer to command line
  1817.  * RETURNS
  1818.  *    0        OK
  1819.  * GLOBAL
  1820.  * DESPRIPTION
  1821.  *    Invoke parser and analyse token output.
  1822.  *
  1823.  * REMARKS
  1824.  */
  1825. PRIVATE int NEAR
  1826. AnalyseCmdLine(PSZ const pszLine)
  1827. {
  1828.     CC        parse_rc;
  1829.     PCHAR    tp;
  1830.     CHAR    TokenId;
  1831.     int        i;
  1832.     USHORT    adapter = 0xFFFF;
  1833.  
  1834.  
  1835.     /* Call IBM supplied parser with the above defined option
  1836.      * table. */
  1837.  
  1838.     parse_rc = Command_Parser(pszLine, &opttable,
  1839.                   DeviceTable, MAX_DEVICETABLE_SIZE);
  1840.  
  1841.     /* Process errors. Although errors were detected the
  1842.      * command line and 'DeviceTable' may contain valid tokens
  1843.      * which have to be processed later, so only use 'break'
  1844.      * in 'case' clauses. */
  1845.  
  1846.     switch( parse_rc.ret_code )
  1847.     {
  1848.     /* SYNTAX_ERR:
  1849.      *    General error in command line, no special handling
  1850.      */
  1851.       case SYNTAX_ERR:
  1852.     sprintk(szMsgBuffer, szCmdLineSyntax, (PSZ)szDriverName);
  1853.     SaveMessage();
  1854.     break;
  1855.  
  1856.     /* REQ_OPT_ERR:
  1857.      *    Required option is missing in command line (probably /A: )
  1858.      */
  1859.       case REQ_OPT_ERR:
  1860.     sprintk(szMsgBuffer, szMissingOption, (PSZ)szDriverName);
  1861.     SaveMessage();
  1862.     break;
  1863.  
  1864.     /* INVALID_OPT_ERR:
  1865.      *    Bad format?
  1866.      */
  1867.       case INVALID_OPT_ERR:
  1868.     sprintk(szMsgBuffer, szUnknownOption,
  1869.         (PSZ)szDriverName, (PBYTE)DeviceTable);
  1870.     SaveMessage();
  1871.     break;
  1872.  
  1873.       case UNDEFINED_TYPE_ERR:
  1874.       case UNDEFINED_STATE_ERR:
  1875.       case BUF_TOO_SMALL_ERR:
  1876.       default:
  1877.     sprintk(szMsgBuffer, szCmdLineError, 
  1878.         (PSZ)szDriverName, parse_rc.ret_code);
  1879.     SaveMessage();
  1880.       case NO_OPTIONS_FND_ERR:
  1881.       case NO_ERR:
  1882.     break;
  1883.     }
  1884.  
  1885.     /* Let 'tp' jump from token to token. */
  1886.  
  1887.     for( tp = DeviceTable; (TokenId=*(tp+TOKL_ID)) != TOK_ID_END;
  1888.      tp += *(tp+TOKL_LEN) )
  1889.     {
  1890.     switch( TokenId )
  1891.     {
  1892.       case TOK_ID_VERBOSE:
  1893.         DEBMSG("\r\n/VERBOSE");
  1894.         fDriverFlags |= DF_VERBOSE;
  1895.         break;
  1896.  
  1897.       case TOK_ID_DEBUG:
  1898.         DEBMSG("\r\n/DEBUG");
  1899.         fDriverFlags |= DF_VERBOSE;
  1900.         fDriverFlags |= DF_DEBUG;
  1901.  
  1902.         if( *(tp+TOKL_LEN) == TOK_MIN_LENGTH+1 )
  1903.         {
  1904.         UCHAR code = *(tp+TOKL_VALUE);
  1905.  
  1906.         switch( code )
  1907.         {
  1908.           default:
  1909.             sprintk(szMsgBuffer, szUnknownOption, 
  1910.                 (PSZ)szDriverName, (PBYTE)DeviceTable);
  1911.             SaveMessage();
  1912.             break;
  1913.         }
  1914.         }
  1915.         break;
  1916.  
  1917.       case TOK_ID_ADAPTER:
  1918.         adapter = *(tp+TOKL_VALUE);
  1919.         DEBMSG1("\r\n/A:%w",adapter);
  1920.         break;
  1921.  
  1922.       case TOK_ID_EF:
  1923.       case TOK_ID_DF:
  1924.         /* Loop through every coordinate.patch provided */
  1925.         for( i = 0; i < *(tp+TOKL_LEN)-2; i += 6 )
  1926.         {
  1927.         PCHAR    cp = tp + TOKL_VALUE + i;
  1928.  
  1929.         DEBMSG3("\r\n/[!]E:(%w,%w,%w)",*(PUSHORT)(cp),*(PUSHORT)(cp+2),*(PUSHORT)(cp+4));
  1930.  
  1931.         AddUTable(adapter,            /* adapter index */
  1932.               *(PUSHORT)(cp),        /* unit index */
  1933.               *(PUSHORT)(cp+2),        /* page number */
  1934.               (TokenId == TOK_ID_EF ? 1 : 0),
  1935.               *(PUSHORT)(cp+4));        /* mask */
  1936.         }
  1937.         break;
  1938.  
  1939.       case TOK_ID_END:
  1940.         break;
  1941.  
  1942.       default:
  1943.         break;
  1944.     }
  1945.     }
  1946.  
  1947.     return 0;
  1948. } /*end[AnalyseCmdLine]*/
  1949.  
  1950.  
  1951.  
  1952.  
  1953.  
  1954. /* **********************************************************************
  1955.  * **** Public Entries **************************************************
  1956.  * ******************************************************************* */
  1957.  
  1958.  
  1959. /*#
  1960.  * CALL
  1961.  *    InitBase(pRPI)
  1962.  * PARAMETER
  1963.  *    pRPI        init request
  1964.  * RETURNS
  1965.  *    error code as expected from the OS/2 device system
  1966.  * GLOBAL
  1967.  *    Device_Help
  1968.  *    pGlobalInfoSeg
  1969.  *    fDriverFlags
  1970.  *    szDriverName, error messages
  1971.  * DESPRIPTION
  1972.  *    Process Base Initialization Request Packet
  1973.  *
  1974.  * REMARKS
  1975.  *    Uses IBM supplied command line parser.
  1976.  */
  1977. PUBLIC USHORT NEAR
  1978. InitBase(PRPINITIN pRPI)
  1979. {
  1980.     PULONG        pInfoSegSel;
  1981.     int            rc;
  1982.     PRPINITOUT const    pRPO = (PRPINITOUT)pRPI;
  1983.  
  1984.     PDDD_PARM_LIST const pInitParms = (PDDD_PARM_LIST)pRPI->InitArgs;
  1985.     PSZ            pCmdLine;
  1986.  
  1987.     DEBMSG("\r\nInitBase");
  1988.     DBSTOP();
  1989.  
  1990.     /* Contains entry point to kernel functions */
  1991.  
  1992.     Device_Help = pRPI->DevHlpEP;
  1993.     pCmdLine    = MK_FP(FP_SEL(pInitParms),pInitParms->cmd_line_args);
  1994.  
  1995.     if( DevHelp_VirtToPhys(&DiskDDHeader, &ppDiskDDHeader) )
  1996.     {
  1997.     sprintk(szMsgBuffer, szErrorVAddr, (PSZ)szDriverName);
  1998.     SaveMessage();
  1999.     rc = -1;
  2000.     goto ERROR_EXIT;            /* !!! */
  2001.     }
  2002.  
  2003.     DevHelp_GetDOSVar(DHGETDOSV_SYSINFOSEG, 0, (PPVOID)&pInfoSegSel);
  2004.     pGlobalInfoSeg = MAKEP(*pInfoSegSel, 0);
  2005.  
  2006.  
  2007.     /* Parse Command Line Args */
  2008.  
  2009.     AnalyseCmdLine(pCmdLine);
  2010.  
  2011.     if( (fDriverFlags & DF_VERBOSE) )
  2012.     {
  2013.     sprintk(szMsgBuffer, szLogo, (PSZ)szProduct, VERSION, SUBVERSION);
  2014.     SaveMessage();
  2015.     }
  2016.  
  2017.     rc = ScanDevices();
  2018.  
  2019.  
  2020.     /* Processing complete.  Analyse situation, should we install,
  2021.      * quiet fail or even loudly stop Config.Sys processing? */
  2022.  
  2023.     if( rc == 0 )
  2024.     {
  2025.     /* We do not need to register any units, since this
  2026.      * filter does not generate any units on his own. */
  2027.  
  2028.     pRPO->Unit    = 0;
  2029.     pRPO->CodeEnd = ((USHORT)Code_End & ~0x0F) + 0x10;
  2030.     pRPO->DataEnd = ((USHORT)npInitData & ~0x0F) + 0x10;
  2031.  
  2032.     DEBMSG("\r\nDriver installed");
  2033.     fDriverFlags |= DF_INITDONE;
  2034.     return STATUS_DONE;
  2035.     }
  2036.     else
  2037.     {
  2038.       ERROR_EXIT:                /* goto destination */
  2039.     pRPO->Unit    = 0;
  2040.     pRPO->CodeEnd = 0;
  2041.     pRPO->DataEnd = 0;
  2042.  
  2043.     if( rc < 0 )
  2044.         return STERR | STDON | ERROR_I24_GEN_FAILURE;
  2045.     else
  2046.         return STERR | STDON | ERROR_I24_QUIET_INIT_FAIL;
  2047.     }
  2048. }
  2049.  
  2050.  
  2051.  
  2052. /* History:
  2053.  *
  2054.  * $Log: init1.c,v $
  2055.  * Revision 1.9  1998/03/04 02:11:28  vitus
  2056.  * - added option and code to modify mode page 13 (inact. timeout)
  2057.  *
  2058.  * Revision 1.8  1997/12/16 02:48:09  vitus
  2059.  * - renamed source files
  2060.  * - clarified messages
  2061.  *
  2062.  * Revision 1.7  1997/12/11 01:43:44  vitus
  2063.  * - displays current settings if no change requested
  2064.  * - uses external SaveMessages() - keep messages in swappable memory
  2065.  *
  2066.  * Revision 1.6  1997/12/08 23:10:24  vitus
  2067.  * - INITMSG define
  2068.  * - expected messages don't display driver name
  2069.  * - AddUTable/QueryUTable: adjusted for WatCom's type conversion
  2070.  * - added messages before writing the new page contents
  2071.  * - new OPT structure layout
  2072.  *
  2073.  * Revision 1.5  1997/12/06 00:37:13  vitus
  2074.  * - enabled support for WatCom C
  2075.  * - switched to internal _fxxxxx functions
  2076.  *
  2077.  * Revision 1.4  1997/11/12 00:40:30  vitus
  2078.  * - enable/disable options are saved per page
  2079.  *
  2080.  * Revision 1.3  1997/11/10 01:15:37  vitus
  2081.  * - ModifyXxxxx function does MODE SENSE if device in device table,
  2082.  *   but doesn't do a MODE SELECT if no changes requested
  2083.  *
  2084.  * Revision 1.2  1997/11/05 00:49:57  vitus
  2085.  * - seperate functions 'ModifyXxxxxPage(device, npUnit)'
  2086.  *
  2087.  * Revision 1.1  1997/10/28 02:06:59  vitus
  2088.  * Initial revision
  2089.  */
  2090.