home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / rmfiles.zip / mitsrc.zip / CDINIT.C < prev    next >
C/C++ Source or Header  |  1994-10-06  |  37KB  |  918 lines

  1.  
  2.  #define INCL_DOSINFOSEG
  3.  #define INCL_NO_SCB
  4.  #define INCL_INITRP_ONLY
  5.  #include "os2.h"                  // \DRV6\H
  6.  #include "dos.h"                  // \DRV6\H
  7.  #include "sas.h"                  // \DRV6\H
  8.  #include "devcmd.h"               // \DRV6\H
  9.  
  10.  #include "iorb.h"                 // \DRV6\SRC\DEV\DASD\DISKH
  11.  #include "reqpkt.h"               // \DRV6\SRC\DEV\DASD\DISKH
  12.  #include "addcalls.h"             // \DRV6\SRC\DEV\DASD\DISKH
  13.  #include "dskinit.h"
  14.  #include "devclass.h"
  15.  
  16.  #include <scsi.h>
  17.  #include <cdbscsi.h>
  18.  #include "cmd.h"
  19.  #include "devhelp.h"              // \DRV6\SRC\DEV\DASD\DISKH
  20.  #include "cdb.h"
  21.  #include "proto.h"
  22.  #include "rmbase.h"
  23.  #include "rmcalls.h"
  24.  #include <string.h>
  25.  #include <memory.h>
  26.  
  27.  
  28. #define BAD_PARMS        0x8113
  29. #define STATUS_QUIET_FAIL   0x8015 | STATUS_DONE
  30. static BOOL Allocated=FALSE;
  31. BYTE Adapter[16]="MITSUMI$";
  32. USHORT DeviceHandle=0;
  33. extern USHORT near AdapterBase, near StatusRegister,near DataStatusRegister, near IrqNum, near IrqMode;
  34. extern PUCHAR near YieldFlag;
  35. extern PGINFOSEG near PGinfo;
  36. extern void ScaleClock(UCHAR CpuType);
  37. extern UCHAR near traceflag;
  38. extern BOOL near ReadStatusLate;
  39. extern UCHAR near wDrvVer[4];
  40. extern BOOL near Lu002;
  41. static char devstring[]="CDROM_0 ";
  42.  
  43. static UCHAR ProductIDMsg[] =                                    \
  44. "\n\r"                                                           \
  45. "IBM OS/2 MITFX001.ADD 1.10\n\r"                                 \
  46. "?ITSUMI CD-ROM ?       ?    Port: 0?00  IRQ: 000?   ";
  47. //"012345678901234567890123456789012345678901234567890"
  48. //              15      23          35           48
  49.  
  50. MSGTABLE  ProductIDMsgParm = { MSG_REPLACEMENT_STRING,
  51.                                1,
  52.                                ProductIDMsg,
  53.                               };
  54. static USHORT ValidPorts[] = {
  55. //static USHORT ValidPorts[16*4];// = {
  56.                                0x300,
  57.                                0x320,  // Micron ships at 320 default (used to be 300)
  58. //                             0x360,
  59. //                             0x390,
  60.                                0x340,
  61.                              };
  62. #define PortChoices sizeof(ValidPorts)/sizeof(USHORT)
  63.  
  64. static UCHAR charstring[]="0123456789ABCDEF";
  65.  
  66.    int   Active_Counter = 0 ;
  67.    static PIORB Head=0L, Tail=0L ; // Pointers to request packets queue management
  68.  
  69. //ULONG DevHlp=0;
  70. ULONG Device_Help=0;
  71. PFN             RM_Help0               = 0L;  /*VPNP*/
  72. PFN             RM_Help3               = 0L;  /*VPNP*/
  73.  
  74. DRIVERSTRUCT DriverStruct =
  75. {
  76.    "MITFX001.ADD",                           /* DrvrName                */
  77.    "Mitsumi CDROM Driver",                   /* DrvrDescript            */
  78.    "IBM OS/2",                               /* VendorName              */
  79.    CMVERSION_MAJOR,                          /* MajorVer                */
  80.    CMVERSION_MINOR,                          /* MinorVer                */
  81.    1994,9,1,                                 /* Date                    */
  82.    0,                                        /* DrvrFlags               */
  83.    DRT_ADDDM,                                /* DrvrType                */
  84.    DRS_ADD,                                  /* DrvrSubType             */
  85.    NULL                                      /* DrvrCallback            */
  86. };
  87.  
  88.  
  89. /*----------------------------------------------*/
  90. /* Adapter Description                          */    /*VPNP*/
  91. /*----------------------------------------------*/
  92. ADAPTERSTRUCT AdapterStruct =
  93. {
  94.   "Proprietary CD Controller",       /* AdaptDescriptName; */
  95.   0,                                 /* AdaptFlags;        */
  96.   AS_BASE_MSD,                       /* BaseType;          */
  97.   AS_SUB_OTHER,                      /* SubType;           */
  98.   AS_INTF_GENERIC,                   /* InterfaceType;     */
  99.   AS_HOSTBUS_ISA,                    /* HostBusType;       */
  100.   AS_BUSWIDTH_16BIT,                 /* HostBusWidth;      */
  101.   NULL,                              /* pAdjunctList;      */
  102.   NULL                               /* reserved           */
  103. };
  104.  
  105. /*----------------------------------------------*/
  106. /* Device Description                          */    /*VPNP*/
  107. /*----------------------------------------------*/
  108.  
  109. DEVICESTRUCT DevStruct =
  110. {
  111.    "CDROM Drive",       /* DevDescriptName; */
  112.    DS_REMOVEABLE_MEDIA, /* DevFlags;     */
  113.    DS_TYPE_CDROM        /* DevFlags;        */
  114. };
  115. HDRIVER         hDriver               = 0L;  /*VPNP*/
  116. HADAPTER        hAdapter=0;
  117. HDEVICE         hDevice=0;
  118. USHORT          RMFlags               = 0;   /*VPNP*/
  119.  
  120.  
  121. UCHAR            ResourceBuf[sizeof(AHRESOURCE)+sizeof(HRESOURCE)*2];  /*VPNP*/
  122. PAHRESOURCE      pResourceList = (PAHRESOURCE) &ResourceBuf;         /*VPNP*/
  123. extern void EnableASIC(USHORT Port, USHORT IRQ,USHORT type,USHORT CardPort);
  124. extern BOOL near PortValid(void);
  125.  
  126. /************************ START OF SPECIFICATIONS *****************************
  127.  *                                                                            *
  128.  * SUBROUTINE NAME:  CDStrat1                                                 *
  129.  *                                                                            *
  130.  * DESCRIPTIVE NAME:  Strategy 1 entry point                                  *
  131.  *                                                                            *
  132.  * FUNCTION:  This routine processes request "Device Driver Request Packets". *
  133.  *            Only, Initialize Base Request is accepted.  All other requests  *
  134.  *            are rejected.                                                   *
  135.  *                                                                            *
  136.  * NOTES:  This routine runs in protect mode only as a single thread          *
  137.  *         at level 3 with IOPL.                                              *
  138.  *                                                                            *
  139.  * INPUT:  ES:BX contain pointer to request packet.                           *
  140.  *                                                                            *
  141.  ************************* END OF SPECIFICATIONS ******************************/
  142.  VOID FAR CDStrat1()
  143.  {
  144.  PRPH pRPH;                   // Pointer to RPH (Request Packet Header)
  145.  USHORT        Cmd;           // Local variable
  146.  
  147.  _asm { mov word ptr pRPH[0], bx       //  pRPH is initialize to
  148.         mov word ptr pRPH[2], es };    //  ES:BX passed from the kernel
  149.  Cmd = pRPH->Cmd;
  150.  if (Cmd == CMDInitBase)
  151.    DriveInit( (PRPINITIN) pRPH );
  152.  else
  153.    pRPH->Status = STATUS_ERR_UNKCMD;
  154.  }
  155.  
  156. /************************ START OF SPECIFICATIONS *****************************
  157.  *                                                                            *
  158.  * SUBROUTINE NAME:  ProcessReq                                               *
  159.  *                                                                            *
  160.  * DESCRIPTIVE NAME:  Process IORB Requests                                   *
  161.  *                                                                            *
  162.  * FUNCTION: This routine receives the I/O Request Blocks to process          *
  163.  *           from the Queing entrypoint                                       *
  164.  *                                                                            *
  165.  ************************* END OF SPECIFICATIONS ******************************/
  166. VOID ProcessReq( PIORBH pIORB )
  167.  {
  168.  PSCSI_STATUS_BLOCK pStatus;
  169.  BOOL    Status = TRUE;
  170.  USHORT  CmdCode;
  171.  USHORT  SubCmd;
  172.  
  173.         CmdCode=pIORB->CommandCode;
  174.         SubCmd =pIORB->CommandModifier;
  175.  
  176.         switch(CmdCode)
  177.           {
  178.           case  IOCC_CONFIGURATION     :
  179.             switch(SubCmd)
  180.               {
  181.               case  IOCM_GET_DEVICE_TABLE:
  182.                 Build_Device_Table((PIORB_CONFIGURATION) pIORB);
  183.                 break;
  184.               case  IOCM_COMPLETE_INIT:
  185.                 break;
  186.               default:
  187.                 // error
  188.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  189.                 break;
  190.               } /* end switch */
  191.             break;
  192.           case IOCC_UNIT_CONTROL      :
  193.             switch(SubCmd)
  194.               {
  195.               case IOCM_ALLOCATE_UNIT  :
  196.                 if(!Allocated)
  197.                   {
  198.                   Allocated=TRUE;
  199.                   } /* end if */
  200.                 else
  201.                   {
  202.                   IORB_CmdErr(IOERR_UNIT_ALLOCATED, pIORB,0,0);
  203.                   } /* end else */
  204.                 break;
  205.               case IOCM_DEALLOCATE_UNIT:
  206.                 if(Allocated)
  207.                   {
  208.                   Allocated=FALSE;
  209.                   } /* end if */
  210.                 else
  211.                   {
  212.                   IORB_CmdErr(IOERR_UNIT_NOT_ALLOCATED, pIORB,0,0);
  213.                   } /* end else */
  214.                 break;
  215.               case IOCM_CHANGE_UNITINFO:
  216.                 // not used
  217.                 if(!Allocated)
  218.                   {
  219.                   IORB_CmdErr(IOERR_UNIT_NOT_ALLOCATED, pIORB,0,0);
  220.                   } /* end if */
  221.                 break;
  222.               default:
  223.                 // error
  224.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  225.                 break;
  226.               } /* end switch */
  227.             break;
  228.           case IOCC_GEOMETRY          :
  229.             switch(SubCmd)
  230.               {
  231.               case IOCM_GET_MEDIA_GEOMETRY :
  232.               case IOCM_GET_DEVICE_GEOMETRY:
  233.                 if(Allocated)
  234.                   {
  235.                   if(!GetGeometry(SubCmd,(PIORB_GEOMETRY)pIORB))
  236.                     IORB_CmdErr(IOERR_UNIT_NOT_READY, pIORB,SCSI_SK_NOTRDY,0);
  237.                   } /* end if */
  238.                 else
  239.                   {
  240.                   IORB_CmdErr(IOERR_UNIT_NOT_ALLOCATED, pIORB,0,0);
  241.                   } /* end else */
  242.                 break;
  243.               case IOCM_SET_MEDIA_GEOMETRY :
  244.               case IOCM_SET_LOGICAL_GEOMETRY:
  245.                 // error
  246.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  247.                 break;
  248.               default:
  249.                 // error
  250.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  251.                 break;
  252.               } /* end switch */
  253.             break;
  254.           case IOCC_EXECUTE_IO        :
  255.             switch(SubCmd)
  256.               {
  257.               case IOCM_READ          :
  258.                 // currently not used
  259.               case IOCM_READ_VERIFY   :
  260.                 // currently not used
  261.               case IOCM_READ_PREFETCH :
  262.                 // currently not used
  263.               case IOCM_WRITE         :
  264.               case IOCM_WRITE_VERIFY  :
  265.                 // error
  266.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  267.                 break;
  268.               default:
  269.                 // error
  270.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  271.                 break;
  272.               } /* end switch */
  273.             break;
  274.           case IOCC_FORMAT            :
  275.             // error
  276.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  277.             break;
  278.           case IOCC_UNIT_STATUS       :
  279.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  280.             break;
  281.           case IOCC_DEVICE_CONTROL    :
  282.             if(SubCmd!=IOCM_ABORT)
  283.               {
  284.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  285.               } /* end else */
  286.             // error
  287.             break;
  288.           case IOCC_ADAPTER_PASSTHRU  :
  289.             switch(SubCmd)
  290.               {
  291.               case IOCM_EXECUTE_SCB :
  292.                 // error
  293.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  294.                 break;
  295.               case IOCM_EXECUTE_CDB:
  296.                 if(Allocated)
  297.                   {
  298.                   pIORB->Status &= (~IORB_STATUSBLOCK_AVAIL);
  299.                   if(pIORB->RequestControl & IORB_REQ_STATUSBLOCK)
  300.                     {
  301.                     pStatus=(PSCSI_STATUS_BLOCK)MAKEP(SELECTOROF(pIORB),pIORB->pStatusBlock);
  302.                     pStatus->Flags &= ~STATUS_SENSEDATA_VALID;
  303.                     pStatus->SenseData->ErrCode_Valid = 0;           // ?????
  304.                     pStatus->SenseData->SenseKey  = 0;
  305.                     pStatus->SenseData->AddSenseCode=0;
  306.                     } /* end if */
  307.                   ProcessCDB(pIORB);
  308.                   }
  309.                 else
  310.                   {
  311.                   IORB_CmdErr(IOERR_UNIT_NOT_ALLOCATED, pIORB,0,0);
  312.                   } /* end else */
  313.                 break;
  314.               default:
  315.                 // error
  316.                 IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  317.                 break;
  318.               } /* end switch */
  319.             break;
  320.           default:
  321.             IORB_CmdErr(IOERR_CMD_NOT_SUPPORTED, pIORB,SCSI_SK_ILLEGALREQ,ASC_INVALID_COMMAND_OPCODE);
  322.             // error
  323.             break;
  324.           } /* end switch */
  325.  
  326.         // set the IORB as Done processing
  327.  
  328.         pIORB->Status |= IORB_DONE;
  329.  
  330.         // if there is an Asyn post routine, call it now
  331.  
  332.         if (pIORB->RequestControl & IORB_ASYNC_POST)
  333.           pIORB->NotifyAddress(pIORB);
  334.  
  335.  }
  336. /************************ START OF SPECIFICATIONS *****************************
  337.  *                                                                            *
  338.  * SUBROUTINE NAME:  IORB_CmdErr                                              *
  339.  *                                                                            *
  340.  * DESCRIPTIVE NAME:  IORB error completion                                   *
  341.  *                                                                            *
  342.  * FUNCTION:  This routine sets the error code into the IORB header, then     *
  343.  *            calls ThisIORB_Complete with error completion status.           *
  344.  *                                                                            *
  345.  ************************* END OF SPECIFICATIONS ******************************/
  346.  VOID  IORB_CmdErr (USHORT ErrCode, PIORBH pIORB, USHORT Sense_key, USHORT AdditionalSense)
  347.  {
  348.  
  349.  PSCSI_STATUS_BLOCK pStatus;
  350.  
  351.   if(pIORB)
  352.     {
  353.     pIORB->ErrorCode = ErrCode;
  354.     pIORB->Status |= IORB_ERROR;
  355.     if(pIORB->RequestControl & IORB_REQ_STATUSBLOCK)
  356.       {
  357.       pIORB->Status |= IORB_STATUSBLOCK_AVAIL;
  358.       pStatus=(PSCSI_STATUS_BLOCK)MAKEP(SELECTOROF(pIORB),pIORB->pStatusBlock);
  359.  
  360.       pStatus->Flags |= STATUS_SENSEDATA_VALID;
  361.       pStatus->SenseData->ErrCode_Valid = 0x70;           // ?????
  362.       pStatus->SenseData->SenseKey  = Sense_key;
  363.       pStatus->SenseData->AddSenseCode=AdditionalSense;
  364.       } /* end if */
  365.     } /* end if */
  366.  return;
  367.  }
  368.  
  369. /************************ START OF SPECIFICATIONS *****************************
  370.  *                                                                            *
  371.  * SUBROUTINE NAME:  Build_Device_Table                                       *
  372.  *                                                                            *
  373.  * DESCRIPTIVE NAME:  Build Adapter information table                         *
  374.  *                                                                            *
  375.  * FUNCTION:  This routine fills the DEVICETABLE, ADAPTERINFO and UNITINFO    *
  376.  *            tables pointed to by the IORB.  All current data is compiled    *
  377.  *            data tables.                                                    *
  378.  *                                                                            *
  379.  ************************* END OF SPECIFICATIONS ******************************/
  380.  VOID Build_Device_Table(PIORB_CONFIGURATION pIORB)
  381.  {
  382.  DEVICETABLE far *pDEVT = pIORB->pDeviceTable;
  383.  PADAPTERINFO     pADAPT;
  384.  PUNITINFO        pUNIT;
  385.  INT              A;
  386.  USHORT           FlagMask = (UF_NOSCSI_SUPT + UF_CHANGELINE + UF_REMOVABLE | UF_NODASD_SUPT );
  387.  
  388.  pIORB->DeviceTableLen = (sizeof (UNITINFO) );
  389.  pIORB->DeviceTableLen += sizeof (ADAPTERINFO) + sizeof (DEVICETABLE);
  390.  pDEVT->ADDLevelMajor   = ADD_LEVEL_MAJOR;
  391.  pDEVT->ADDLevelMinor   = ADD_LEVEL_MINOR;
  392.  pDEVT->ADDHandle       = DeviceHandle;
  393.  pDEVT->TotalAdapters   = 1;
  394.  pDEVT->pAdapter[0] = (NPADAPTERINFO) (OFFSETOF (pIORB->pDeviceTable) +
  395.                                        sizeof (DEVICETABLE));
  396.  pADAPT = MAKEP (SELECTOROF (pIORB->pDeviceTable), pDEVT->pAdapter[0]);
  397.  pUNIT  = &(pADAPT->UnitInfo[0]);
  398.  for (A = 0; A < 15; A++)
  399.    {
  400.    pADAPT->AdapterName[A] = Adapter[A];
  401.    } ;
  402.  pADAPT->AdapterUnits   = 1;
  403.  pADAPT->AdapterDevBus  = AI_DEVBUS_NONSCSI_CDROM;
  404.  pADAPT->AdapterIOAccess = AI_IOACCESS_PIO;
  405.  pADAPT->AdapterHostBus  = AI_HOSTBUS_ISA | AI_BUSWIDTH_8BIT;
  406.  pADAPT->AdapterSCSITargetID = 0;
  407.  pADAPT->AdapterSCSILUN = 0;
  408.  pADAPT->AdapterFlags  = 0;
  409.  pADAPT->MaxHWSGList  = 0;
  410.  pADAPT->MaxCDBTransferLength = 0;
  411.  pUNIT->AdapterIndex = 0;
  412.  pUNIT->UnitIndex = 0;
  413.  pUNIT->UnitFlags = FlagMask;
  414.  pUNIT->UnitHandle = 0;
  415.  pUNIT->UnitType = UIB_TYPE_CDROM;
  416.  pUNIT->QueuingCount = 1;
  417.  pUNIT->FilterADDHandle = 0;
  418.  return;
  419.  }
  420.  
  421. /************************ START OF SPECIFICATIONS *****************************
  422.  *                                                                            *
  423.  * SUBROUTINE NAME:  GetGeometry                                              *
  424.  *                                                                            *
  425.  * DESCRIPTIVE NAME:  Return Geometry to IORB sender                          *
  426.  *                                                                            *
  427.  * FUNCTION:   This routine stores the geometry for either the physical       *
  428.  *             device or the current media as requested.                      *
  429.  *                                                                            *
  430.  ************************* END OF SPECIFICATIONS ******************************/
  431.  BOOL GetGeometry(USHORT SubCmd, PIORB_GEOMETRY pIORB)
  432.  {
  433.  CDROMSTAT Data;
  434.  BOOL rc=FALSE;
  435.  USHORT Status;
  436.  
  437.    pIORB->pGeometry->TotalSectors    = DefaultDiscSize; // set default
  438.    pIORB->pGeometry->BytesPerSector  = 2048;            // set default
  439.  
  440.    DevHelp_RAS( 175 ,0 , 0, NULL);
  441.    if(!ReadyHardware((PIORB)pIORB,SCSI_READ_CAPACITY))
  442.      {
  443.      Status=DriveCommand(ReadToc,NULL,NULL,&Data,sizeof(Data.TOC));
  444.      if( (!DOOROPEN(Status)) && (!COMMANDCHECK(Status)) )
  445.        {
  446.        pIORB->pGeometry->TotalSectors    = (((BCD2Bin(Data.TOC.LeadoutMin)*60)+BCD2Bin(Data.TOC.LeadoutSec))*75)+BCD2Bin(Data.TOC.LeadoutFrame);
  447.         // MAKEULONG(MAKEUSHORT(BCD2Bin(Data.TOC.LeadoutFrame),MAKEUSHORT(BCD2Bin(Data.TOC.LeadoutSec),BCD2Bin(Data.TOC.LeadoutMin)));
  448.  
  449.        pIORB->pGeometry->BytesPerSector  = 2048;
  450.  
  451.        pIORB->pGeometry->NumHeads        = 1;
  452.        pIORB->pGeometry->SectorsPerTrack = 0x1ff;
  453.        pIORB->pGeometry->TotalCylinders  = 0;
  454.        pIORB->GeometryLen = sizeof (GEOMETRY);
  455.        DevHelp_RAS( 176 ,0 , 0, NULL);
  456.        rc=TRUE;
  457.        } /* end if */
  458.      } /* end if */
  459.      DevHelp_RAS( 177 ,0 , 0, NULL);
  460.  return rc;
  461.  }
  462.  
  463. /************************ START OF SPECIFICATIONS *****************************
  464.  *                                                                            *
  465.  * SUBROUTINE NAME:  DriveInit                                                *
  466.  *                                                                            *
  467.  * DESCRIPTIVE NAME: Soundblaster Pro Driver Init                             *
  468.  *                                                                            *
  469.  * FUNCTION: This procedure initializes the device driver.                    *
  470.  *                                                                            *
  471.  *           Installation will fail if there are no SBPro detected            *
  472.  *                                                                            *
  473.  *           This routine runs in protect mode only as a single thread        *
  474.  *           at CPL = 0.                                                      *
  475.  *                                                                            *
  476.  ************************* END OF SPECIFICATIONS ******************************/
  477.  VOID DriveInit(PRPINITIN pRPH )
  478.  {
  479.  PRPINITOUT pRPO;
  480.  extern UCHAR  near last_data_byte;
  481.  extern VOID last_code_byte();
  482.  USHORT i,l,temp,state,PortScan,Attachment=0,AttachmentPort;
  483.  PDDD_PARM_LIST Parmlist=(PDDD_PARM_LIST)pRPH->InitArgs;
  484.  PSZ Parms=MAKEP(SELECTOROF(Parmlist),Parmlist->cmd_line_args);
  485.  PMACHINE_CONFIG_INFO pMch=MAKEP(SELECTOROF(Parmlist),Parmlist->machine_config_table);
  486.  BOOL Verbose=FALSE;
  487.  PUCHAR p;
  488.  UCHAR a1,a2,a3;
  489.  struct DevClassTableStruc far *pdevs;
  490.  RESOURCESTRUCT Resource;
  491.  ADJUNCT AdjunctData;
  492.  
  493.  PortScan=0;            // start at first array entry
  494.  
  495. // DevHlp = (ULONG)pRPH->DevHlpEP;
  496.  Device_Help = (ULONG)pRPH->DevHlpEP;
  497.  
  498.  pRPO = (PRPINITOUT) pRPH;
  499.  
  500. // for(i=0,l=0x300; i<PortChoices;i++,l+=4 )           // lets scan all the ports
  501. //   {
  502. //   ValidPorts[i]=l;
  503. //   } /* end for */
  504.  
  505.  i=strlen(Parms);
  506.  for(l=0; l<i; l++)     // lower case the entire string
  507.    {
  508.    Parms[l]|=0x20;
  509.    } /* end for */
  510.  
  511.  for(;Parms && *Parms ; )               // loop thru parms
  512.    {
  513.    if(*Parms=='/')                      // did we find a slash?
  514.      {
  515.      if(!memcmp(Parms,"/e",2))          // read status early?
  516.        {
  517.        Parms+=2;                        // skip over
  518.        ReadStatusLate=FALSE;            // set flag for pre-read status
  519.        } /* end if */
  520.      else if(!memcmp(Parms,"/v",2))     // verbose message request?
  521.        {
  522.        Parms+=2;                        // skip over
  523.        Verbose=TRUE;                    // set flag verbose mode
  524.        } /* end if */
  525. #if defined(TRACE) | defined(TRACE1)
  526.      else if(!memcmp(Parms,"/t",2))     // enable tracing?
  527.        {
  528.        Parms+=2;                        // skip over
  529.        traceflag=TRUE;                  // enable tracing
  530.        } /* end if */
  531. #endif
  532.      else if(!memcmp(Parms,"/i:",3))    // is it the one we want?
  533.        {
  534.        if((i=strlen(Parms))>=4)         // still enough chars to process?
  535.          {
  536.          Parms+=3;                      // skip over /I:
  537.          if(Parms[1]>='0' && Parms[1]<='9')     // two byte irq number?
  538.            {
  539.            temp= ((Parms[0] - '0') *10 ) + // get the irq specified
  540.                   (Parms[1] - '0')  ;
  541.            Parms+=2;                       // skip over xx irqnum
  542.            } /* end if */
  543.          else                              // single byte irq number
  544.            {
  545.            temp= (Parms[0] - '0');         // get the irq specified
  546.            Parms+=1;                       // skip over x irqnum
  547.            } /* end else */
  548.          switch(temp)                   // make sure its one of our choices
  549.            {
  550.            case 2:
  551.              IrqMode=Irq9;                  // set adapter pattern
  552.              IrqNum=temp;                   // valid IRQnumber
  553.              break;
  554.            case 3:
  555.              IrqMode=Irq3;                  // set adapter pattern
  556.              IrqNum=temp;                   // valid IRQnumber
  557.              break;
  558.            case 5:
  559.              IrqMode=Irq5;                  // set adapter pattern
  560.              IrqNum=temp;                   // valid IRQnumber
  561.              break;
  562.            case 9:
  563.              IrqMode=Irq9;                  // set adapter pattern
  564.              IrqNum=temp;                   // valid IRQnumber
  565.              break;
  566.            case 10:
  567.              IrqMode=Irq10;                 // set adapter pattern
  568.              IrqNum=temp;                   // valid IRQnumber
  569.              break;
  570.            case 11:
  571.              IrqMode=Irq11;                 // set adapter pattern
  572.              IrqNum=temp;                   // valid IRQnumber
  573.              break;
  574.            case 12:
  575.              IrqMode=Irq12;                 // set adapter pattern
  576.              IrqNum=temp;                   // valid IRQnumber
  577.              break;
  578.            case 15:
  579.              IrqMode=Irq15;                 // set adapter pattern
  580.              IrqNum=temp;                   // valid IRQnumber
  581.              break;
  582.            default: // bad irq number
  583.              IrqMode=0;
  584.              IrqNum=0;
  585.              break;
  586.            } /* end switch */
  587.          }
  588.        }
  589.      else if(!memcmp(Parms,"/p:",3))         // is it the one we want?
  590.        {
  591.        if(strlen(Parms)>=6)             // still enough chars to process?
  592.          {
  593.          Parms+=3;                      // skip over /p:
  594.          a1=Parms[0]-(((Parms[0] & 0x70) == 0x30)?48:87);
  595.          a2=Parms[1]-(((Parms[1] & 0x70) == 0x30)?48:87);
  596.          a3=Parms[2]-(((Parms[2] & 0x70) == 0x30)?48:87);
  597.          temp= (a1*256 ) + (a2*16) + (a3)  ;
  598.          Parms+=3;                      // skip over address
  599.  
  600. // Remove address range verification to allow the sound blaster with p:230
  601. //
  602. //       if(temp>=0x300 && temp<=0x3fc && ((temp & 3) ==0))
  603. //         {
  604.            ValidPorts[PortScan=(PortChoices-1)]=temp; // use only last entry
  605. //         } /* end if */
  606. //       else
  607. //         {
  608. //         PortScan=PortChoices;              // past maximum
  609. //         } /* end else */
  610.        } /* end if */
  611.        else                             // /P: specified, but not enough bytes left
  612.          {
  613.          PortScan=PortChoices;                // past maximum
  614.          }
  615.        } /* end if */
  616.      else if(!memcmp(Parms,"/at:",4))   // is it the one we want?
  617.        {
  618.        if(strlen(Parms)>=6)             // still enough chars to process?
  619.          {
  620.          Parms+=4;                      // skip over /p:
  621.          Attachment+=(Parms[0] -0x30)*10;
  622.          Attachment+=(Parms[1] -0x30);
  623.          Parms+=2;
  624.          switch(Attachment)
  625.            {
  626.            case 5:
  627.              break;
  628.            case 6:
  629.              if(Parms[0]==',')
  630.                {
  631.                Parms++;
  632.                a1=Parms[0]-(((Parms[0] & 0x70) == 0x30)?48:87);
  633.                a2=Parms[1]-(((Parms[1] & 0x70) == 0x30)?48:87);
  634.                a3=Parms[2]-(((Parms[2] & 0x70) == 0x30)?48:87);
  635.                AttachmentPort=(a1*256 ) + (a2*16) + (a3)  ;
  636.                Parms+=3;                      // skip over address
  637.                }
  638.              else
  639.                {
  640.                AttachmentPort=0x220;
  641.                }
  642.              break;
  643.            default:
  644.              Attachment=0;
  645.              break;
  646.            }
  647.          } /* end if */
  648.        else                             // /P: specified, but not enough bytes left
  649.          {
  650.          PortScan=PortChoices;                // past maximum
  651.          }
  652.        } /* end if */
  653.      else
  654.        Parms++;
  655.      } /* end if */
  656.    else
  657.      Parms++;
  658.    } /* end for */
  659.  
  660.  if(!(pMch->BusInfo & BUSINFO_MCA))             // only if not MCA
  661.    {
  662.    RMCreateDriver(&DriverStruct,
  663.                   &hDriver);
  664.    PGinfo  = (PGINFOSEG)DevHelp_GetDosVar(1);   // pointer to global info segment
  665.    ScaleClock((UCHAR)(PGinfo->uchMinorVersion?pMch->CpuInfo:I386)); // say 386 if not 2.1 or above
  666.    DevHelp_RAS( 170 ,0 , sizeof(PGinfo->msecs),&PGinfo->msecs);
  667.  
  668. #if 0                                           // resource manager is supposed to handle this
  669.    if(PortScan==0)                              // nothing selected, scan all
  670.      {
  671.      if(pdevs = (struct DevClassTableStruc far *)DevHelp_GetDosVar(DHGETDOSV_DEVICECLASSTABLE))
  672.        {
  673.                                                 // pointer to add device table
  674.                                                 // make sure we don't collide
  675.                                                 // with Adaptec 152x adapter
  676.        for(i=0;i<pdevs->DCCount ;i++ )          // spin thru all adapters
  677.          {
  678.          if(!memcmp(pdevs->DCTableEntries[i].DCName,"AHA1520.ADD",11))
  679.            {
  680.            ValidPorts[PortChoices-1]=ValidPorts[0];
  681.            break;
  682.            } /* end if */
  683.          } /* end for */
  684.        } /* end if */
  685.      } /* end if */
  686. #endif
  687.  
  688.    for(; PortScan<PortChoices; PortScan++)      // loop thru array of addresses
  689.      {
  690.      Resource.ResourceType           = RS_TYPE_IO;
  691.      Resource.IOResource.BaseIOPort = ValidPorts[PortScan];
  692.      Resource.IOResource.NumIOPorts = 3;                        // what is this???
  693.      Resource.IOResource.IOFlags    = RS_IO_EXCLUSIVE;
  694.      Resource.IOResource.IOAddressLines = 10;
  695.  
  696.      pResourceList->NumResource = 1;
  697.      pResourceList->hResource[0] = 0L;                          /*VPNP*/
  698.      pResourceList->hResource[1] = 0L;                          /*VPNP*/
  699.      if(!RMAllocResource( hDriver, &pResourceList->hResource[0], &Resource ))
  700.        {
  701.        if(Attachment)
  702.          EnableASIC(ValidPorts[PortScan],IrqNum,Attachment,AttachmentPort);  // enable Orchid or Cardinal ASIC
  703.        AdapterBase=ValidPorts[PortScan];          // get base address
  704.        StatusRegister=AdapterBase+1,              // status register address
  705.        DataStatusRegister=AdapterBase+2;          // data status register address
  706.        if(PortValid() && ChkBaseAddx())           // check for adapter presence
  707.          {                                        // found adapter
  708.          DevHelp_RAS( 170 ,AdapterBase , sizeof(PGinfo->msecs),&PGinfo->msecs);
  709.          break;
  710.          }
  711.        else                                       // no adapter found at this address
  712.          {
  713.          RMDeallocResource( hDriver, pResourceList->hResource[0]);
  714.          DevHelp_RAS( 171 ,AdapterBase , sizeof(PGinfo->msecs),&PGinfo->msecs);
  715.          }
  716.        }
  717.      } /* end for */
  718.    } /* end if */
  719.  else
  720.    {
  721.    PortScan=PortChoices;                // force no loading on MCA machines
  722.    } /* end else */
  723.  
  724.  if(PortScan==PortChoices)              // if over max entries to search thru
  725.    {                                    // adapter wasn't found
  726.    pRPO->CodeEnd = 0;
  727.    pRPO->DataEnd = 0;
  728.    pRPO->rph.Status = STATUS_QUIET_FAIL;
  729.    DevHelp_RAS( 174 ,0, 0, NULL);
  730.    RMDestroyDriver(hDriver);            // remove Resource manager definition
  731.    for(i=0; i<sizeof(ProductIDMsg);i++ )
  732.      {
  733.      if(ProductIDMsg[i]=='?')
  734.        {
  735.        strcpy(&ProductIDMsg[i],"No units detected.");
  736.        break;
  737.        } /* end if */
  738.      } /* end for */
  739.    if(Verbose)
  740.      {
  741.      DevHelp_DisplayMsg(&ProductIDMsgParm);
  742.      } /* end if */
  743.    }
  744.  else
  745.    {
  746.    if(ChkDrive())
  747.      {
  748.      DevHelp_RAS( 172 ,0 , 0, NULL);
  749.      }
  750.    else
  751.       DevHelp_RAS( 173 ,0, 0,NULL);
  752.    RMCreateAdapter( hDriver, &hAdapter, &AdapterStruct, (HDEVICE)NULL, (PAHRESOURCE)pResourceList );
  753.    pRPO->CodeEnd = (USHORT)last_code_byte;      // set our code end
  754.    pRPO->DataEnd = (USHORT)&last_data_byte;     // and data
  755.  
  756.    YieldFlag=DevHelp_GetDosVar(7);              // get address of yield flag
  757.                                                 // register our ADD
  758.    DeviceHandle=DevHelp_RegisterDeviceClass(Adapter, (PVOID)IORBEntry, 0, 1);
  759.    pRPO->rph.Status = 0x100;
  760.    for(i=0,state=0; i<sizeof(ProductIDMsg);i++ )
  761.      {
  762.      if(ProductIDMsg[i]=='?')
  763.        {
  764.        switch(state)
  765.          {
  766.          case 0:
  767.            ProductIDMsg[i]='M';
  768.            DevStruct.DevDescriptName=&ProductIDMsg[i];
  769.            state=1;
  770.            break;
  771.          case 1:
  772.            switch(wDrvVer[0])
  773.              {
  774.              case 'M':
  775.                if(Lu002)
  776.                  {
  777.                  p="LU002S";
  778.                  } /* end if */
  779.                else
  780.                  {
  781.                  p="LU005S";
  782.                  } /* end else */
  783.                break;
  784.              case 'F':
  785.                p="FX001";
  786.                break;
  787.              case 'D':
  788.                p="FX001D";
  789.                break;
  790.              default:
  791.                p="unkown";
  792.                break;
  793.              } /* end switch */
  794.            memcpy(&ProductIDMsg[i],p,strlen(p));
  795.            state=2;
  796.            break;
  797.          case 2:
  798.            memcpy(&ProductIDMsg[i],wDrvVer,strlen(wDrvVer));
  799.            p=&ProductIDMsg[i]+strlen(wDrvVer);
  800.            state=3;
  801.            break;
  802.          case 3:
  803.            ProductIDMsg[i++]=charstring[(AdapterBase / 256)];
  804.            ProductIDMsg[i++]=charstring[((AdapterBase & 250)/16)];
  805.            ProductIDMsg[i]=charstring[(AdapterBase & 15)];
  806.            state=4;
  807.            break;
  808.          case 4:
  809.            if(IrqNum)
  810.              {
  811.              ProductIDMsg[i]=charstring[IrqNum];
  812.              } /* end if */
  813.            else
  814.              {
  815.              strcpy(&ProductIDMsg[i-3],"Polled");
  816.              } /* end else */
  817.            break;
  818.          default:
  819.            break;
  820.          } /* end switch */
  821.        } /* end if */
  822.      } /* end for */
  823.    if(Verbose)
  824.      {
  825.      DevHelp_DisplayMsg(&ProductIDMsgParm);
  826.      } /* end if */
  827.    *p='\0';
  828.    memset(&AdjunctData,0,sizeof(AdjunctData));
  829.    AdjunctData.AdjType=ADJ_ADD_UNIT;
  830.    AdjunctData.AdjLength=sizeof(AdjunctData);
  831.    AdjunctData.Add_Unit.ADDHandle=DeviceHandle;
  832.    AdjunctData.Add_Unit.UnitHandle=0;
  833.    DevStruct.pAdjunctList=&AdjunctData;
  834.  
  835.    // nasty code here. the text we were already using for the device string
  836.    // is a static variable, modified with parms we found during install
  837.    // so to save space, we are going to backup and PVERLAY a portion of the
  838.    // existing message..
  839.    // backup length of new text
  840.    DevStruct.DevDescriptName-=strlen(devstring);
  841.    // copy in this new stupid prefix...
  842.    memcpy(DevStruct.DevDescriptName,devstring,strlen(devstring));
  843.    // now create the device with this new modified title..
  844.    RMCreateDevice( hDriver, &hDevice, &DevStruct, hAdapter, NULL);
  845.    }
  846.  return;
  847.  }
  848. // =========================================== //
  849. //                                             //
  850. // This routine will queue the request packet  //
  851. //                                             //
  852. // input : rp - request packet pointer to be   //
  853. //              queued                         //
  854. //                                             //
  855. // ------------------------------------------- //
  856.  
  857. void QIORB( PIORBH pIORB )
  858. {
  859.    pIORB->pNxtIORB = 0L ;            // Clear forward link pointer
  860.  
  861.    if( Head==Tail && Head==0L )      // if nothing queued
  862.       Head = Tail = pIORB ;          // make this one both head and tail
  863.  
  864.    else
  865.    {
  866.       Tail->pNxtIORB = pIORB ;       // else link this one to last
  867.       Tail           = pIORB ;       // and make this one last in list
  868.    }
  869. }
  870.  
  871. // ================================================= //
  872. //                                                   //
  873. // This routine will dequeue the last request packet //
  874. //                                                   //
  875. // input : none                                      //
  876. //                                                   //
  877. // output : last request packet in list              //
  878. //                                                   //
  879. // ------------------------------------------------- //
  880.  
  881. PIORBH DeQIORB( void )
  882. {
  883.       PIORBH pIORB ;
  884.  
  885.    if( pIORB=Head )           // if there is an entry on queue
  886.    {
  887.       Head = pIORB->pNxtIORB ; // unlink it
  888.  
  889.       if( Head == 0L )     // if only entry
  890.          Tail = 0L ;       // clear tail pointer too
  891.    }
  892.  
  893.    return pIORB ;             // return pointer to dequeued packet
  894. }
  895. /************************ START OF SPECIFICATIONS *****************************
  896.  *                                                                            *
  897.  * SUBROUTINE NAME:  IORBEntry                                                *
  898.  *                                                                            *
  899.  * DESCRIPTIVE NAME:  IORB Entry point                                        *
  900.  *                                                                            *
  901.  * FUNCTION: This routine receives the I/O Request Blocks from the device     *
  902.  *           and filter managers.                                             *
  903.  *                                                                            *
  904.  ************************* END OF SPECIFICATIONS ******************************/
  905. VOID _loadds FAR IORBEntry( PIORBH pIORB )
  906. {
  907.    ++Active_Counter;
  908.    QIORB(pIORB);
  909.    if( Active_Counter==1 )
  910.    {
  911.       while(Head)
  912.         {
  913.         ProcessReq(DeQIORB());
  914.         } /* end while */
  915.    }
  916.    --Active_Counter;
  917. }
  918.