home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cdrom.zip / DDK / BASE / SRC / DEV / DASD / CDROM / NEC / neiorb2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-18  |  27.8 KB  |  1,062 lines

  1. /**************************************************************************
  2.  *
  3.  * SOURCE FILE NAME = NEIORB2.C
  4.  *
  5.  * DESCRIPTIVE NAME = IORB handling for NEC Filter
  6.  *
  7.  * Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992
  8.  *             LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
  9.  *             REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
  10.  *             RESTRICTED MATERIALS OF IBM
  11.  *             IBM CONFIDENTIAL
  12.  *
  13.  * VERSION = V2.0
  14.  *
  15.  * DATE
  16.  *
  17.  * DESCRIPTION
  18.  *
  19.  *
  20.  * FUNCTIONS   Filters SCSI-2 Command Descriptor Blocks and conters
  21.  *             them to the vendor unique NEC Command Descriptor Blocks.
  22.  *
  23.  * ENTRY POINTS:
  24.  *
  25.  * DEPENDENCIES:
  26.  *
  27.  * NOTES
  28.  *
  29.  *
  30.  * STRUCTURES
  31.  *
  32.  * EXTERNAL REFERENCES
  33.  *
  34.  * EXTERNAL FUNCTIONS
  35.  *
  36.  * CHANGE ACTIVITY =
  37.  *  DATE      FLAG        APAR   CHANGE DESCRIPTION
  38.  *  --------  ----------  -----  --------------------------------------
  39.  *  mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
  40.  ****************************************************************************/
  41.  
  42. #include <flthdr.h>
  43.  
  44. /*
  45. ** FUNCTION PROTOTYPES
  46. */
  47.  
  48. USHORT NotifyReadSubChannel (PIORB_CDB pIORB);
  49. USHORT NotifyReadTrack (PIORB_CDB pIORB);
  50. USHORT NotifyReadMinMax (PIORB_CDB pIORB);
  51. USHORT NotifyAudioSearch (PIORB_CDB pIORB);
  52. USHORT NotifyResume (PIORB_CDB pIORB);
  53. USHORT NotifySeek6 (PIORB_CDB pIORB);
  54. USHORT NotifyTestUnitReady (PIORB_CDB pIORB);
  55.  
  56.  
  57. /*
  58. ** CODE STARTS HERE
  59. */
  60.  
  61.  
  62. /****************************************************************************
  63.  *
  64.  * FUNCTION NAME = Filter_TestUnitReady
  65.  *
  66.  * DESCRIPTION   = This routine filters Test Unit Ready. The CDR-35, 77 and 80
  67.  *                 does not generate a media changes check condition for this
  68.  *                 command.  We must issue a Request Sense prior to the
  69.  *                 Test Unit Ready to make sure the check condition is reported.
  70.  *
  71.  * INPUT         = pIORB - pointer to IORB
  72.  *
  73.  * OUTPUT        =
  74.  *
  75.  * RETURN-NORMAL =
  76.  * RETURN-ERROR  =
  77.  *
  78.  ****************************************************************************/
  79.  
  80. USHORT Filter_TestUnitReady (PIORB_CDB pIORB)
  81. {
  82.  
  83.    NPUNITCB pUnitCB;
  84.  
  85.    struct CDB_RequestSense    FAR *pCDB1;
  86.    PIORB_FLTWORK pFilter_workspace;
  87.  
  88.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  89.    pUnitCB = pFilter_workspace->pUnitCB;
  90.  
  91.    if ( ( pUnitCB->product_id[12] != ' ' ) &&
  92.         ( pUnitCB->product_id[6] != '2' ) )
  93.    {
  94.       return(CALL_ADD_AND_RET);
  95.    }
  96.  
  97.    pCDB1 = (struct CDB_RequestSense FAR *) pIORB->apt.pControllerCmd;
  98.  
  99.    pCDB1->OpCode = SCSI_REQUEST_SENSE;
  100.  
  101.    pCDB1->reserved_1 = 0;
  102.    pCDB1->reserved_2 = 0;
  103.    pCDB1->reserved_3 = 0;
  104.    pCDB1->alloc_length = sizeof(struct Sense_Data);
  105.    pCDB1->control = 0;
  106.  
  107.    pIORB->apt.cSGList = 1;
  108.    pIORB->apt.pSGList->XferBufLen = sizeof(struct Sense_Data);
  109.    pIORB->apt.Flags |= PT_DIRECTION_IN;
  110.  
  111.    /*
  112.    ** Replace callback address with ours.
  113.    */
  114.    pFilter_workspace->completion_address = NotifyTestUnitReady;
  115.  
  116.    return (CALL_ADD_AND_NOTIFY_FILTER);
  117. }
  118.  
  119.  
  120. /****************************************************************************
  121.  *
  122.  * FUNCTION NAME = NotifyTestUnitReady
  123.  *
  124.  * DESCRIPTION   =
  125.  *
  126.  * INPUT         = pIORB - pointer to IORB
  127.  *
  128.  * OUTPUT        =
  129.  *
  130.  * RETURN-NORMAL =
  131.  * RETURN-ERROR  =
  132.  *
  133.  ****************************************************************************/
  134.  
  135. USHORT NotifyTestUnitReady (PIORB_CDB pIORB)
  136. {
  137.  
  138.    struct Sense_Data FAR *pSense_Data;
  139.    pSense_Data = (struct Sense_Data FAR *) pIORB->CDB_data;
  140.  
  141.    if ( pSense_Data->sense_key != SK_NO_SENSE )
  142.    {
  143.        pIORB->sense_data = *pSense_Data;
  144.        pIORB->apt.iorbh.Status = IORB_DONE | IORB_ERROR |
  145.                                  IORB_STATUSBLOCK_AVAIL;
  146.  
  147.        pIORB->status_block.Flags = STATUS_SENSEDATA_VALID;
  148.        NEC_Sense_Fix (pIORB);
  149.    }
  150.  
  151.    return(NOTIFY_CDM);
  152. }
  153.  
  154.  
  155. /****************************************************************************
  156.  *
  157.  * FUNCTION NAME = Filter_Seek_6
  158.  *
  159.  * DESCRIPTION   =
  160.  *
  161.  * INPUT         = pIORB - pointer to IORB
  162.  *
  163.  * OUTPUT        =
  164.  *
  165.  * RETURN-NORMAL =
  166.  * RETURN-ERROR  =
  167.  *
  168.  ****************************************************************************/
  169.  
  170. USHORT Filter_Seek_6 (PIORB_CDB pIORB)
  171. {
  172.    PIORB_FLTWORK pFilter_workspace;
  173.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  174.  
  175.  
  176.    /*
  177.    ** Replace callback address with ours.
  178.    */
  179.  
  180.    pFilter_workspace->completion_address = NotifySeek6;
  181.    pFilter_workspace->flags |= FWF_SKIP_ERROR_CHECK;
  182.  
  183.    return CALL_ADD_AND_NOTIFY_FILTER;
  184. }
  185.  
  186.  
  187. /****************************************************************************
  188.  *
  189.  * FUNCTION NAME = NotifySeek6
  190.  *
  191.  * DESCRIPTION   =
  192.  *
  193.  * INPUT         = pIORB - pointer to IORB
  194.  *
  195.  * OUTPUT        =
  196.  *
  197.  * RETURN-NORMAL =
  198.  * RETURN-ERROR  =
  199.  *
  200.  ****************************************************************************/
  201.  
  202. USHORT NotifySeek6 (PIORB_CDB pIORB)
  203. {
  204.    pNEC_CDB_AudioTrackSearch  pCDB1;
  205.    struct CDB_Seek_6          FAR *pCDB2;
  206.  
  207.    if ( (pIORB->apt.iorbh.Status & IORB_ERROR) &&
  208.         ( !(pIORB->apt.iorbh.Status & IORB_RECOV_ERROR) ) &&
  209.         (pIORB->sense_data.sense_key == 3) &&
  210.         pIORB->sense_data.command_specific_info[1] == 0x1D)
  211.    {
  212.  
  213.       pCDB1 = (pNEC_CDB_AudioTrackSearch) pIORB->apt.pControllerCmd;
  214.       pCDB2 = (struct CDB_Seek_6 FAR *) pCDB1;
  215.  
  216.       pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_AudioTrackSearch);
  217.  
  218.       pCDB1->OpCode = NEC_AUDIO_TRACK_SEARCH;
  219.  
  220.       pCDB1->play = 0;                  /* pause after search */
  221.  
  222.       pCDB1->search_zero  = pCDB2->LBA.usbytes.byte_1;
  223.       pCDB1->search_frame = pCDB2->LBA.usbytes.byte_0;
  224.       pCDB1->search_sec   = pCDB2->LBA_msb;
  225.       pCDB1->search_min   = 0;
  226.  
  227.       pCDB1->addr_type = NEC_ADDR_HSG;
  228.  
  229.       pCDB1->reserved_1 = 0;
  230.       pCDB1->reserved_2 = 0;
  231.       pCDB1->reserved_3 = 0;
  232.       pCDB1->reserved_4 = 0;
  233.       pCDB1->reserved_5 = 0;
  234.       return CALL_ADD_AND_NOTIFY_CDM;
  235.    }
  236.    else
  237.       return NOTIFY_CDM;
  238. }
  239.  
  240.  
  241. /****************************************************************************
  242.  *
  243.  * FUNCTION NAME = Filter_ModeSelect
  244.  *
  245.  * DESCRIPTION   = This routine converts the Audio Control Mode Page to an NEC
  246.  *                 Play Audio command.  (audio channel control is changed by
  247.  *                 setting the play mode bits in the NEC Play Audio command).
  248.  *
  249.  * INPUT         = pIORB - pointer to IORB
  250.  *
  251.  * OUTPUT        =
  252.  *
  253.  * RETURN-NORMAL =
  254.  * RETURN-ERROR  =
  255.  *
  256.  ****************************************************************************/
  257.  
  258. USHORT Filter_ModeSelect (PIORB_CDB pIORB)
  259. {
  260.    UCHAR    play_mode, out_chan0, out_chan1, out_vol0, out_vol1;
  261.    UCHAR    left_off, right_off, transfer_length;
  262.    UCHAR    block_length_lsb, block_length_msb;
  263.    USHORT   i, rc;
  264.  
  265.    pNEC_CDB_PlayAudio         pCDB1;
  266.    struct CDB_ModeSelect      FAR *pCDB2;
  267.    struct ModeSelectParmList  FAR *pCDBData2;
  268.    PIORB_FLTWORK              pFilter_workspace;
  269.    NPUNITCB                   pUnitCB;
  270.  
  271.    pCDB1 = (pNEC_CDB_PlayAudio) pIORB->apt.pControllerCmd;
  272.    pCDB2 = (struct CDB_ModeSelect FAR *) pCDB1;
  273.    pCDBData2 = (struct ModeSelectParmList FAR *) pIORB->CDB_data;
  274.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  275.    pUnitCB = pFilter_workspace->pUnitCB;
  276.  
  277.    *((PBYTE) pCDB2+1) = 0;    /* Byte 1 of the command block must be zero */
  278.  
  279.    rc = NOTIFY_CDM;
  280.  
  281.    /*
  282.    ** Check for Block Descriptor Header.
  283.    */
  284.    if ( pCDBData2->ModeSelectHdr.block_descriptor_len == 8 )
  285.    {
  286.       /*
  287.       ** The NEC CDR-35 drive expects 11 bytes of information.  The last
  288.       ** byte must be zero.
  289.       */
  290.       if ( pUnitCB->product_id[6] == '2' )
  291.          transfer_length = 11;
  292.       else
  293.          transfer_length = 10;
  294.  
  295.       pCDB2->parm_length = transfer_length;
  296.       pIORB->apt.pSGList->XferBufLen = transfer_length;
  297.  
  298.       pCDBData2->ModeSelectHdr.block_descriptor_len = 0;
  299.  
  300.       block_length_lsb = pCDBData2->Descriptors.BlockDescriptor.block_length_2;
  301.       block_length_msb = pCDBData2->Descriptors.BlockDescriptor.block_length_1;
  302.  
  303.       /*
  304.       ** Test for block size of 2048 or 2340 bytes.  Return an error for
  305.       ** any other block size.
  306.       **
  307.       ** NOTE: The NEC CDR-35 drive only supports a block size of 2048 bytes.
  308.       */
  309.       if ( block_length_msb == 0x08 && block_length_lsb == 0x00 )
  310.       {
  311.          if ( pCDBData2->Descriptors.BlockDescriptor.density_code != 0x81 )
  312.             pCDBData2->Descriptors.BlockDescriptor.density_code = 0;
  313.       }
  314.       else if ( (block_length_msb == 0x09 && block_length_lsb == 0x24) &&
  315.                 (pUnitCB->product_id[6] != '2') )
  316.       {
  317.          pCDBData2->Descriptors.BlockDescriptor.density_code = 3;
  318.       }
  319.       else
  320.       {
  321.          return NOTIFY_CDM_WITH_ERROR;
  322.       }
  323.  
  324.       /*
  325.       ** Remaining 4 bytes should be zero and the last byte should be
  326.       ** set to 5 for the retry count.
  327.       */
  328.       pCDBData2->Descriptors.BlockDescriptor.block_count_0  = 0;
  329.       pCDBData2->Descriptors.BlockDescriptor.block_count_1  = 0;
  330.       pCDBData2->Descriptors.BlockDescriptor.block_count_2  = 0;
  331.       pCDBData2->Descriptors.BlockDescriptor.reserved_1     = 0;
  332.  
  333.       if ( pUnitCB->product_id[6] != '2' )
  334.          pCDBData2->Descriptors.BlockDescriptor.block_length_0 = 5;
  335.       else
  336.          pCDBData2->Descriptors.BlockDescriptor.block_length_0 = 0;
  337.  
  338.       pCDBData2->Descriptors.BlockDescriptor.block_length_1 = 0;
  339.  
  340.       rc = CALL_ADD_AND_RET;
  341.    }
  342.  
  343.  
  344.    /*
  345.    ** Check for Audio Channel Control page.
  346.    */
  347.  
  348.  
  349.    if ( (pCDBData2->ModeSelectHdr.block_descriptor_len == 0) &&
  350.         (pCDBData2->Descriptors.audio_control.page_code == PAGE_AUDIO_CONTROL) )
  351.    {
  352.       pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_PlayAudio);
  353.       pIORB->apt.cSGList = 0;
  354.       pIORB->apt.pSGList = 0;
  355.       pIORB->apt.ppSGLIST = 0;
  356.  
  357.       out_chan0 = pCDBData2->Descriptors.audio_control.output0_select;
  358.       out_vol0  = pCDBData2->Descriptors.audio_control.output0_volume;
  359.       out_chan1 = pCDBData2->Descriptors.audio_control.output1_select;
  360.       out_vol1  = pCDBData2->Descriptors.audio_control.output1_volume;
  361.  
  362.       left_off = right_off = FALSE;
  363.  
  364.       /*
  365.       ** Check for volume control of zero and output channel of zero.
  366.       */
  367.       if ( out_chan0 != 1 || out_vol0 == PCS_MUTED )
  368.          left_off = TRUE;
  369.  
  370.       if ( out_chan1 != 2 || out_vol1 == PCS_MUTED )
  371.          right_off = TRUE;
  372.  
  373.       /*
  374.       ** If audio channels are switched, continue to play in stereo.
  375.       */
  376.       if ( out_chan0 == 2 && out_chan1 == 1 )
  377.          left_off = right_off = FALSE;
  378.  
  379.       /*
  380.       ** The NEC CDR-35 drive only supports Stereo & Mute mode.  If only
  381.       ** one channel is muted, we must set the audio mode to Stereo for
  382.       ** this drive.
  383.       */
  384.       if ( pUnitCB->product_id[6] == '2' && !(left_off & right_off) )
  385.          left_off = right_off = FALSE;
  386.  
  387.       if ( left_off & right_off )
  388.          play_mode = NEC_PLAY_MUTE;
  389.       else if ( left_off )
  390.          play_mode = NEC_PLAY_RIGHT;
  391.       else if ( right_off )
  392.          play_mode = NEC_PLAY_LEFT;
  393.       else
  394.          play_mode = NEC_PLAY_STEREO;
  395.  
  396.       pUnitCB->play_mode = play_mode;
  397.  
  398.       /*
  399.       ** issue a play command if drive is in play mode
  400.       */
  401.       if ( pFilter_workspace->input_parm_0 == 1 )
  402.       {
  403.          pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_PlayAudio);
  404.  
  405.          pCDB1->OpCode = NEC_PLAY_AUDIO;
  406.  
  407.          pCDB1->play_mode = play_mode;
  408.  
  409.          for (i=2;i<9;i++)
  410.             *((PBYTE) pCDB1+i) = 0;
  411.  
  412.          pCDB1->reserved_5 = 0;
  413.  
  414.          pCDB1->addr_type = NEC_ADDR_PRV;
  415.  
  416.          rc = CALL_ADD_AND_RET;
  417.       }
  418.    }
  419.  
  420.    return rc;
  421. }
  422.  
  423.  
  424. /****************************************************************************
  425.  *
  426.  * FUNCTION NAME = Filter_StartStopUnit
  427.  *
  428.  * DESCRIPTION   = This routine checks the SCSI-2 Start/Stop command block for
  429.  *                 for eject bit and if set, sends down an NEC eject command.
  430.  *
  431.  * INPUT         = pIORB - pointer to IORB
  432.  *
  433.  * OUTPUT        =
  434.  *
  435.  * RETURN-NORMAL =
  436.  * RETURN-ERROR  =
  437.  *
  438.  ****************************************************************************/
  439.  
  440. USHORT Filter_StartStopUnit (PIORB_CDB pIORB)
  441.  
  442. {
  443.    USHORT   i;
  444.  
  445.    pNEC_CDB_Eject           pCDB1;
  446.    struct CDB_StartStopUnit FAR *pCDB2;
  447.  
  448.    pCDB1 = (pNEC_CDB_Eject) pIORB->apt.pControllerCmd;
  449.    pCDB2 = (struct CDB_StartStopUnit FAR *) pCDB1;
  450.  
  451.    /*
  452.    ** If eject reqested, build an NEC eject command.
  453.    */
  454.    if ( (pCDB2->LoEj) && !(pCDB2->start) )
  455.    {
  456.       pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_Eject);
  457.  
  458.       pCDB1->OpCode = NEC_EJECT;
  459.  
  460.       for (i=2;i<10;i++)
  461.          *((PBYTE) pCDB1+i) = 0;
  462.    }
  463.  
  464.    return CALL_ADD_AND_RET;
  465. }
  466.  
  467.  
  468. /****************************************************************************
  469.  *
  470.  * FUNCTION NAME = Filter_PreventAllowRemoval
  471.  *
  472.  * DESCRIPTION   =
  473.  *
  474.  * INPUT         = pIORB - pointer to IORB
  475.  *
  476.  * OUTPUT        =
  477.  *
  478.  * RETURN-NORMAL =
  479.  * RETURN-ERROR  =
  480.  *
  481.  ****************************************************************************/
  482.  
  483. USHORT Filter_PreventAllowRemoval (PIORB_CDB pIORB)
  484. {
  485.    /*
  486.    ** No conversion needed, pass along to ADD.
  487.    */
  488.  
  489.    return CALL_ADD_AND_RET;
  490. }
  491.  
  492.  
  493. /****************************************************************************
  494.  *
  495.  * FUNCTION NAME = Filter_ReadCapacity
  496.  *
  497.  * DESCRIPTION   = For the NEC-CDR 35, we have to hard code the Read Capcity
  498.  *                 Data since this device does not support this command.
  499.  *
  500.  * INPUT         = pIORB - pointer to IORB
  501.  *
  502.  * OUTPUT        =
  503.  *
  504.  * RETURN-NORMAL =
  505.  * RETURN-ERROR  =
  506.  *
  507.  ****************************************************************************/
  508.  
  509. USHORT Filter_ReadCapacity (PIORB_CDB pIORB)
  510. {
  511.    struct ReadCapacity_Data FAR *pCDBData1;
  512.    PIORB_FLTWORK pFilter_workspace;
  513.    NPUNITCB pUnitCB;
  514.  
  515.    pCDBData1 = (struct ReadCapacity_Data FAR *) pIORB->CDB_data;
  516.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  517.    pUnitCB = pFilter_workspace->pUnitCB;
  518.  
  519.    if ( pUnitCB->product_id[6] != '2' )
  520.       return CALL_ADD_AND_RET;
  521.  
  522.    /*
  523.    ** Set Total Blocks to 276,480.
  524.    */
  525.    pCDBData1->capacity_LBA.ulbytes.byte_0 = 0x00;
  526.    pCDBData1->capacity_LBA.ulbytes.byte_1 = 0x04;
  527.    pCDBData1->capacity_LBA.ulbytes.byte_2 = 0x38;
  528.    pCDBData1->capacity_LBA.ulbytes.byte_3 = 0x00;
  529.  
  530.    /*
  531.    ** Set Block Length to 2048.
  532.    */
  533.    pCDBData1->capacity_block_length.ulbytes.byte_0 = 0x00;
  534.    pCDBData1->capacity_block_length.ulbytes.byte_1 = 0x00;
  535.    pCDBData1->capacity_block_length.ulbytes.byte_2 = 0x08;
  536.    pCDBData1->capacity_block_length.ulbytes.byte_3 = 0x00;
  537.  
  538.    return NOTIFY_CDM;
  539. }
  540.  
  541.  
  542. /****************************************************************************
  543.  *
  544.  * FUNCTION NAME = Filter_Seek_10
  545.  *
  546.  * DESCRIPTION   =
  547.  *
  548.  * INPUT         = pIORB - pointer to IORB
  549.  *
  550.  * OUTPUT        =
  551.  *
  552.  * RETURN-NORMAL =
  553.  * RETURN-ERROR  =
  554.  *
  555.  ****************************************************************************/
  556.  
  557. USHORT Filter_Seek_10 (PIORB_CDB pIORB)
  558. {
  559.    /*
  560.    ** No conversion needed, pass along to ADD.
  561.    */
  562.  
  563.    return CALL_ADD_AND_RET;
  564. }
  565.  
  566.  
  567. /****************************************************************************
  568.  *
  569.  * FUNCTION NAME = Filter_ReadSubChannel
  570.  *
  571.  * DESCRIPTION   = This routine converts the SCSI-2 Read Sub Channel command to
  572.  *                 an NEC Read Subcode Q command.
  573.  *
  574.  * INPUT         = pIORB - pointer to IORB
  575.  *
  576.  * OUTPUT        =
  577.  *
  578.  * RETURN-NORMAL =
  579.  * RETURN-ERROR  =
  580.  *
  581.  ****************************************************************************/
  582.  
  583. USHORT Filter_ReadSubChannel (PIORB_CDB pIORB)
  584. {
  585.    USHORT   i, rc;
  586.  
  587.    pNEC_CDB_ReadSubQ         pCDB1;
  588.    struct CDB_ReadSubChannel FAR *pCDB2;
  589.    PIORB_FLTWORK             pFilter_workspace;
  590.  
  591.    pCDB1 = (pNEC_CDB_ReadSubQ) pIORB->apt.pControllerCmd;
  592.    pCDB2 = (struct CDB_ReadSubChannel FAR *) pCDB1;
  593.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  594.  
  595.    if ( pCDB2->data_format == RSC_CURRENT_POSITION )
  596.    {
  597.       pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_ReadSubQ);
  598.       pIORB->apt.pSGList->XferBufLen = sizeof (NEC_DATA_SubQChannel);
  599.  
  600.       pCDB1->OpCode = NEC_READ_SUB_Q;
  601.  
  602.       pCDB1->alloc_length = sizeof (NEC_DATA_SubQChannel);
  603.  
  604.       for (i=2;i<10;i++)
  605.          *((PBYTE) pCDB1+i) = 0;
  606.  
  607.       /*
  608.       ** Replace callback address with ours.
  609.       */
  610.       pFilter_workspace->completion_address = NotifyReadSubChannel;
  611.  
  612.       rc = CALL_ADD_AND_NOTIFY_FILTER;
  613.    }
  614.    else
  615.    {
  616.       rc = NOTIFY_CDM_WITH_ERROR;
  617.    }
  618.  
  619.    return rc;
  620. }
  621.  
  622.  
  623. /****************************************************************************
  624.  *
  625.  * FUNCTION NAME = NotifyReadSubChannel
  626.  *
  627.  * DESCRIPTION   =
  628.  *
  629.  * INPUT         = pIORB - pointer to IORB
  630.  *
  631.  * OUTPUT        =
  632.  *
  633.  * RETURN-NORMAL =
  634.  * RETURN-ERROR  =
  635.  *
  636.  ****************************************************************************/
  637.  
  638. USHORT NotifyReadSubChannel (PIORB_CDB pIORB)
  639. {
  640.    UCHAR    audio_status, control, track_number, index;
  641.  
  642.    pNEC_DATA_SubQChannel      pCDBData1;
  643.    struct SubChannel_Position FAR *pCDBData2;
  644.  
  645.    pCDBData1 = (pNEC_DATA_SubQChannel) pIORB->CDB_data;
  646.    pCDBData2 = (struct SubChannel_Position FAR *) pIORB->CDB_data;
  647.  
  648.    /*
  649.    ** convert NEC play status byte to SCSI-2
  650.    */
  651.    switch (pCDBData1->playback_status )
  652.    {
  653.       case NEC_PLAY_IN_PROGRESS:
  654.          audio_status = AS_PLAY_IN_PROGRESS;
  655.          break;
  656.  
  657.       case NEC_PLAY_STILL:
  658.          audio_status = AS_PLAY_PAUSED;
  659.          break;
  660.  
  661.       case NEC_PLAY_PAUSED:
  662.          audio_status = AS_PLAY_PAUSED;
  663.          break;
  664.  
  665.       case NEC_PLAY_COMPLETE:
  666.          audio_status = AS_PLAY_COMPLETE;
  667.          break;
  668.  
  669.       default:
  670.          audio_status = AS_NO_STATUS;
  671.          break;
  672.    }
  673.  
  674.    control = pCDBData1->control;
  675.    track_number = BCDtoBinary(pCDBData1->tno);
  676.    index = BCDtoBinary(pCDBData1->point);
  677.  
  678.    /*
  679.    ** fill in Current Position data block
  680.    */
  681.    pCDBData2->rel_address.redbook.zero  = 0;
  682.    pCDBData2->rel_address.redbook.min   = BCDtoBinary(pCDBData1->min);
  683.    pCDBData2->rel_address.redbook.sec   = BCDtoBinary(pCDBData1->sec);
  684.    pCDBData2->rel_address.redbook.frame = BCDtoBinary(pCDBData1->frame);
  685.  
  686.    pCDBData2->abs_address.redbook.frame = BCDtoBinary(pCDBData1->aframe);
  687.    pCDBData2->abs_address.redbook.sec   = BCDtoBinary(pCDBData1->asec);
  688.    pCDBData2->abs_address.redbook.min   = BCDtoBinary(pCDBData1->amin);
  689.    pCDBData2->abs_address.redbook.zero  = 0;
  690.  
  691.    pCDBData2->data_format_code = 1;
  692.    pCDBData2->control = control;
  693.    pCDBData2->ADR = ADR_CURRENT_POSITION;
  694.    pCDBData2->track_number = track_number;
  695.    pCDBData2->index_number = index;
  696.  
  697.    /*
  698.    ** fill in sub-channel header
  699.    */
  700.    pCDBData2->sub_channel_hdr.reserved_1 = 0;
  701.    pCDBData2->sub_channel_hdr.audio_status = audio_status;
  702.    pCDBData2->sub_channel_hdr.data_length.usbytes.byte_0 = 0;
  703.    pCDBData2->sub_channel_hdr.data_length.usbytes.byte_1 =
  704.                                        sizeof(struct SubChannel_Position) -
  705.                                        sizeof(struct SubChannel_Hdr);
  706.  
  707.    return NOTIFY_CDM;
  708. }
  709.  
  710.  
  711. /****************************************************************************
  712.  *
  713.  * FUNCTION NAME = Filter_ReadTOC
  714.  *
  715.  * DESCRIPTION   = This routine converts the SCSI-2 Read TOC command to an NEC
  716.  *                 Read TOC.
  717.  *
  718.  * INPUT         = pIORB - pointer to IORB
  719.  *
  720.  * OUTPUT        =
  721.  *
  722.  * RETURN-NORMAL =
  723.  * RETURN-ERROR  =
  724.  *
  725.  ****************************************************************************/
  726.  
  727. USHORT Filter_ReadTOC (PIORB_CDB pIORB)
  728. {
  729.    USHORT   i;
  730.  
  731.    pNEC_CDB_ReadTOC     pCDB1;
  732.    struct CDB_ReadTOC   FAR *pCDB2;
  733.    PIORB_FLTWORK        pFilter_workspace;
  734.  
  735.    pCDB1 = (pNEC_CDB_ReadTOC) pIORB->apt.pControllerCmd;
  736.    pCDB2 = (struct CDB_ReadTOC FAR *) pCDB1;
  737.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  738.  
  739.    pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_ReadTOC);
  740.    pIORB->apt.pSGList->XferBufLen = sizeof (NEC_DATA_TrackInfo);
  741.  
  742.    pCDB1->OpCode = NEC_READ_TOC;
  743.  
  744.    /*
  745.    ** we first want to get the track information
  746.    */
  747.    if ( pCDB2->starting_track == 0xAA )
  748.       pCDB1->data_type = NEC_LEADOUT_INFO;
  749.    else
  750.       pCDB1->data_type = NEC_TRACK_INFO;
  751.  
  752.    pCDB1->TNO = BinarytoBCD (pCDB2->starting_track);
  753.    pCDB1->control = 0;
  754.  
  755.    for (i=3;i<9;i++)
  756.       *((PBYTE) pCDB1+i) = 0;
  757.  
  758.    /*
  759.    ** Replace callback address with ours.
  760.    */
  761.    pFilter_workspace->completion_address = NotifyReadTrack;
  762.  
  763.    return CALL_ADD_AND_NOTIFY_FILTER;
  764. }
  765.  
  766.  
  767. /****************************************************************************
  768.  *
  769.  * FUNCTION NAME = NotifyReadTrack
  770.  *
  771.  * DESCRIPTION   =
  772.  *
  773.  * INPUT         = pIORB - pointer to IORB
  774.  *
  775.  * OUTPUT        =
  776.  *
  777.  * RETURN-NORMAL =
  778.  * RETURN-ERROR  =
  779.  *
  780.  ****************************************************************************/
  781.  
  782. USHORT NotifyReadTrack (PIORB_CDB pIORB)
  783. {
  784.    USHORT   i;
  785.  
  786.    pNEC_CDB_ReadTOC     pCDB1;
  787.    pNEC_DATA_TrackInfo  pCDBData1;
  788.    struct CDB_ReadTOC   FAR *pCDB2;
  789.    struct ReadTOC_Data  FAR *pCDBData2;
  790.    PIORB_FLTWORK        pFilter_workspace;
  791.  
  792.    pCDB1 = (pNEC_CDB_ReadTOC) pIORB->apt.pControllerCmd;
  793.    pCDBData1 = (pNEC_DATA_TrackInfo) pIORB->CDB_data;
  794.    pCDB2 = (struct CDB_ReadTOC FAR *) pCDB1;
  795.    pCDBData2 = (struct ReadTOC_Data FAR *) pIORB->CDB_data;
  796.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  797.  
  798.    pCDBData2->toc_descriptor[0].control = pCDBData1->control;
  799.    pCDBData2->toc_descriptor[0].ADR = ADR_CURRENT_POSITION;
  800.  
  801.    pCDBData2->toc_descriptor[0].track_num = pCDB1->TNO;
  802.  
  803.    pCDBData2->toc_descriptor[0].abs_address.redbook.zero  = 0;
  804.    pCDBData2->toc_descriptor[0].abs_address.redbook.min   =
  805.                                           BCDtoBinary(pCDBData1->amin);
  806.    pCDBData2->toc_descriptor[0].abs_address.redbook.sec   =
  807.                                           BCDtoBinary(pCDBData1->asec);
  808.    pCDBData2->toc_descriptor[0].abs_address.redbook.frame =
  809.                                           BCDtoBinary(pCDBData1->aframe);
  810.  
  811.    pCDB1->data_type = NEC_MINMAX_INFO;
  812.  
  813.    pFilter_workspace->completion_address = NotifyReadMinMax;
  814.  
  815.    return CALL_ADD_AND_NOTIFY_FILTER;
  816. }
  817.  
  818.  
  819. /****************************************************************************
  820.  *
  821.  * FUNCTION NAME = NotifyReadMinMax
  822.  *
  823.  * DESCRIPTION   =
  824.  *
  825.  * INPUT         = pIORB - pointer to IORB
  826.  *
  827.  * OUTPUT        =
  828.  *
  829.  * RETURN-NORMAL =
  830.  * RETURN-ERROR  =
  831.  *
  832.  ****************************************************************************/
  833.  
  834. USHORT NotifyReadMinMax (PIORB_CDB pIORB)
  835. {
  836.    pNEC_DATA_MinMax     pCDBData1;
  837.    struct ReadTOC_Data  FAR *pCDBData2;
  838.  
  839.    pCDBData1 = (pNEC_DATA_MinMax) pIORB->CDB_data;
  840.    pCDBData2 = (struct ReadTOC_Data FAR *) pIORB->CDB_data;
  841.  
  842.    pCDBData2->toc_hdr.first_track = BCDtoBinary(pCDBData1->min_tno);
  843.    pCDBData2->toc_hdr.last_track  = BCDtoBinary(pCDBData1->max_tno);
  844.  
  845.    pCDBData2->toc_hdr.toc_datalength.usbytes.byte_0 = 0;
  846.    pCDBData2->toc_hdr.toc_datalength.usbytes.byte_1 =
  847.                                     sizeof (struct ReadTOC_Data) - 2;
  848.  
  849.    pCDBData2->toc_descriptor[0].reserved_1 = 0;
  850.    pCDBData2->toc_descriptor[0].reserved_3 = 0;
  851.  
  852.    return NOTIFY_CDM;
  853. }
  854.  
  855.  
  856. /****************************************************************************
  857.  *
  858.  * FUNCTION NAME = Filter_ReadHeader
  859.  *
  860.  * DESCRIPTION   = Because the NEC drive does not support the Read Header
  861.  *                 command or equevalent, we always return a density code of 1.
  862.  *
  863.  * INPUT         = pIORB - pointer to IORB
  864.  *
  865.  * OUTPUT        =
  866.  *
  867.  * RETURN-NORMAL =
  868.  * RETURN-ERROR  =
  869.  *
  870.  ****************************************************************************/
  871.  
  872. USHORT Filter_ReadHeader (PIORB_CDB pIORB)
  873. {
  874.    USHORT   i;
  875.  
  876.    struct CDB_ReadHeader   FAR *pCDB1;
  877.    struct ReadHeader_Data  FAR *pCDBData1;
  878.  
  879.    pCDB1 = (struct CDB_ReadHeader FAR *) pIORB->apt.pControllerCmd;
  880.    pCDBData1 = (struct ReadHeader_Data FAR *) pIORB->CDB_data;
  881.  
  882.    pCDBData1->cdrom_data_mode = 1;
  883.  
  884.    for (i=1;i<8;i++)
  885.       *((PBYTE) pCDB1+i) = 0;
  886.  
  887.    return NOTIFY_CDM;
  888. }
  889.  
  890.  
  891. /****************************************************************************
  892.  *
  893.  * FUNCTION NAME = Filter_PlayAudio_MSF
  894.  *
  895.  * DESCRIPTION   = This routine converts the SCSI-2 Play MSF command to an NEC
  896.  *                 Audio Search command and then a Audio Play command.
  897.  *
  898.  * INPUT         = pIORB - pointer to IORB
  899.  *
  900.  * OUTPUT        =
  901.  *
  902.  * RETURN-NORMAL =
  903.  * RETURN-ERROR  =
  904.  *
  905.  ****************************************************************************/
  906.  
  907. USHORT Filter_PlayAudio_MSF (PIORB_CDB pIORB)
  908. {
  909.    pNEC_CDB_AudioTrackSearch  pCDB1;
  910.    struct CDB_PlayAudio_MSF   FAR *pCDB2;
  911.    PIORB_FLTWORK              pFilter_workspace;
  912.  
  913.    pCDB1 = (pNEC_CDB_AudioTrackSearch) pIORB->apt.pControllerCmd;
  914.    pCDB2 = (struct CDB_PlayAudio_MSF FAR *) pCDB1;
  915.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  916.  
  917.    pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_AudioTrackSearch);
  918.  
  919.    pCDB1->OpCode = NEC_AUDIO_TRACK_SEARCH;
  920.  
  921.    pCDB1->play = 0;                     /* pause after search */
  922.  
  923.    pCDB1->search_min   = BinarytoBCD (pCDB2->starting_M);
  924.    pCDB1->search_sec   = BinarytoBCD (pCDB2->starting_S);
  925.    pCDB1->search_frame = BinarytoBCD (pCDB2->starting_F);
  926.    pCDB1->search_zero  = 0;
  927.  
  928.    pFilter_workspace->end_play_address.redbook.min   =
  929.                                         BinarytoBCD (pCDB2->ending_M);
  930.    pFilter_workspace->end_play_address.redbook.sec   =
  931.                                         BinarytoBCD (pCDB2->ending_S);
  932.    pFilter_workspace->end_play_address.redbook.frame =
  933.                                         BinarytoBCD (pCDB2->ending_F);
  934.  
  935.    pCDB1->addr_type = NEC_ADDR_MSF;
  936.  
  937.    pCDB1->reserved_1 = 0;
  938.    pCDB1->reserved_2 = 0;
  939.    pCDB1->reserved_3 = 0;
  940.    pCDB1->reserved_4 = 0;
  941.    pCDB1->reserved_5 = 0;
  942.  
  943.    /*
  944.    ** Replace callback address with ours.
  945.    */
  946.    pFilter_workspace->completion_address = NotifyAudioSearch;
  947.  
  948.    return CALL_ADD_AND_NOTIFY_FILTER;
  949. }
  950.  
  951.  
  952. /****************************************************************************
  953.  *
  954.  * FUNCTION NAME = NotifyAudioSearch
  955.  *
  956.  * DESCRIPTION   =
  957.  *
  958.  * INPUT         = pIORB - pointer to IORB
  959.  *
  960.  * OUTPUT        =
  961.  *
  962.  * RETURN-NORMAL =
  963.  * RETURN-ERROR  =
  964.  *
  965.  ****************************************************************************/
  966.  
  967. USHORT NotifyAudioSearch (PIORB_CDB pIORB)
  968. {
  969.    pNEC_CDB_PlayAudio   pCDB1;
  970.    PIORB_FLTWORK        pFilter_workspace;
  971.    NPUNITCB             pUnitCB;
  972.  
  973.    pCDB1 = (pNEC_CDB_PlayAudio) pIORB->apt.pControllerCmd;
  974.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  975.    pUnitCB = pFilter_workspace->pUnitCB;
  976.  
  977.    pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_PlayAudio);
  978.  
  979.    pCDB1->OpCode = NEC_PLAY_AUDIO;
  980.  
  981.    pCDB1->play_mode = pUnitCB->play_mode;
  982.  
  983.    pCDB1->completion_min   = pFilter_workspace->end_play_address.redbook.min;
  984.    pCDB1->completion_sec   = pFilter_workspace->end_play_address.redbook.sec;
  985.    pCDB1->completion_frame = pFilter_workspace->end_play_address.redbook.frame;
  986.    pCDB1->completion_zero  = 0;
  987.  
  988.    pCDB1->addr_type = NEC_ADDR_MSF;
  989.  
  990.    return CALL_ADD_AND_NOTIFY_CDM;
  991. }
  992.  
  993.  
  994. /****************************************************************************
  995.  *
  996.  * FUNCTION NAME = Filter_Pause_Resume
  997.  *
  998.  * DESCRIPTION   = This routine converts the SCSI-2 Pause/Resume CDB to a NEC
  999.  *                 Still or Play CDB.
  1000.  *
  1001.  * INPUT         = pIORB - pointer to IORB
  1002.  *
  1003.  * OUTPUT        =
  1004.  *
  1005.  * RETURN-NORMAL =
  1006.  * RETURN-ERROR  =
  1007.  *
  1008.  ****************************************************************************/
  1009.  
  1010. USHORT Filter_Pause_Resume (PIORB_CDB pIORB)
  1011. {
  1012.    UCHAR    i, rc;
  1013.  
  1014.    pNEC_CDB_Still             pCDB1;
  1015.    pNEC_CDB_PlayAudio         pCDB1a;
  1016.    struct CDB_PauseResume FAR *pCDB2;
  1017.    PIORB_FLTWORK              pFilter_workspace;
  1018.  
  1019.    pCDB1  = (pNEC_CDB_Still) pIORB->apt.pControllerCmd;
  1020.    pCDB1a = (pNEC_CDB_PlayAudio) pIORB->apt.pControllerCmd;
  1021.    pCDB2  = (struct CDB_PauseResume FAR *) pCDB1;
  1022.    pFilter_workspace = (PIORB_FLTWORK) pIORB->filter_workspace;
  1023.  
  1024.    /*
  1025.    ** If SCSI-2 resume request, issue Audio Search followed by Play command.
  1026.    */
  1027.  
  1028.    if ( pCDB2->resume )
  1029.    {
  1030.       pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_PlayAudio);
  1031.  
  1032.       pCDB1a->OpCode = NEC_PLAY_AUDIO;
  1033.  
  1034.       pCDB1a->play_mode = NEC_PLAY_PREVIOUS_MODE;
  1035.  
  1036.       pCDB1a->completion_min   = 0;
  1037.       pCDB1a->completion_sec   = 0;
  1038.       pCDB1a->completion_frame = 0;
  1039.       pCDB1a->completion_zero  = 0;
  1040.  
  1041.       pCDB1a->addr_type = NEC_ADDR_PRV;
  1042.  
  1043.       rc = CALL_ADD_AND_NOTIFY_CDM;
  1044.    }
  1045.    else
  1046.    {
  1047.       /*
  1048.       ** Convert SCSI-2 Pause to NEC Still command.
  1049.       */
  1050.       pIORB->apt.ControllerCmdLen = sizeof (NEC_CDB_Still);
  1051.  
  1052.       pCDB1->OpCode = NEC_STILL;
  1053.  
  1054.       for (i=2;i<10;i++)
  1055.          *((PBYTE) pCDB1+i) = 0;
  1056.  
  1057.       rc = CALL_ADD_AND_RET;
  1058.    }
  1059.    return rc;
  1060. }
  1061.  
  1062.