Example #1
0
/*
 * Find out media capacity.
 */
uint32_t
get_last_possible_lba(cd_device *dev)
{
	uchar_t *di;
	uint32_t cap;

	di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
	if (!read_disc_info(dev->d_fd, di)) {
		free(di);
		return (0);
	}

	/*
	 * If we have a DVD+R this field is an LBA. If the media is
	 * a CD-R/W the field is MSF formatted. Otherwise this field
	 * is not valid and will be zero.
	 */
	if (device_type == DVD_PLUS) {
		if (read_scsi32(&di[20]) != 0xffffffff) {
			cap = read_scsi32(&di[20]);
		} else {
			cap = 0;
		}
	} else {
		if ((di[21] != 0) && (di[21] != 0xff)) {
			cap = MSF2LBA(di[21], di[22], di[23]);
		} else {
			cap = 0;
		}
	}

	free(di);
	return (cap);
}
Example #2
0
/*
 * Determine the starting LBA of the the session leadout by parsing the Raw TOC
 * format of the READ TOC/PMA/ATIP command response data.
 */
static int
rtoc_get_sess_leadout_lba(uchar_t *rtoc, size_t rtoc_len, int sess_num,
    uint32_t *leadout_lba)
{
	rtoc_td_t *tdp = (rtoc_td_t *)(rtoc + sizeof (rtoc_hdr_t));
	rtoc_td_t *last_tdp = (rtoc_td_t *)(rtoc + rtoc_len -
	    sizeof (rtoc_td_t));

	while ((tdp = get_rtoc_td(tdp, last_tdp, Q_MODE_1,
	    POINT_LEADOUT_ADDR)) != NULL) {
		if (tdp->rt_session_num == sess_num) {
			*leadout_lba = MSF2LBA(tdp->rt_pmin, tdp->rt_psec,
			    tdp->rt_pframe);
			return (1);
		} else {
			++tdp;
		}
	}

	return (0);
}
Example #3
0
void DoCommand(cdrom_Device *cd)
{
   int i;

   /*for(i=0;i<=0x100000;i++)
     Data[i]=0;

     DataLen=0;*/
   cd->StatusLen=0;

   cd->Poll &= ~POLST;
   cd->Poll &= ~POLDT;
   cd->XbusStatus &= ~CDST_ERRO;
   cd->XbusStatus &= ~CDST_RDY;

   switch(cd->Command[0])
   {
      case 0x1:
         //seek
         //not used in opera
         //01 00 ll-bb-aa 00 00.
         //01 02 mm-ss-ff 00 00.
         //status 4 bytes
         //xx xx xx XS  (xs=xbus status)
         //		sprintf(str,"#CDROM 0x1 SEEK!!!\n");
         //		CDebug::DPrint(str);
         break;
      case 0x2:
         //spin up
         //opera status request = 0
         //status 4 bytes
         //xx xx xx XS  (xs=xbus status)
         if((cd->XbusStatus & CDST_TRAY) && (cd->XbusStatus & CDST_DISC))
         {
            cd->XbusStatus |= CDST_SPIN;
            cd->XbusStatus |= CDST_RDY;
            cd->MEIStatus = MEI_CDROM_no_error;
         }
         else
         {
            cd->XbusStatus |= CDST_ERRO;
            cd->XbusStatus &= ~CDST_RDY;
            cd->MEIStatus = MEI_CDROM_recv_ecc;

         }

         cd->Poll |= POLST; //status is valid

         cd->StatusLen=2;
         cd->Status[0]=0x2;
         //cd->Status[1]=0x0;
         //cd->Status[2]=0x0;
         cd->Status[1] = cd->XbusStatus;


         break;
      case 0x3:
         // spin down
         //opera status request = 0 // not used in opera
         //status 4 bytes
         //xx xx xx XS  (xs=xbus status)
         if((cd->XbusStatus & CDST_TRAY) && (cd->XbusStatus & CDST_DISC))
         {
            cd->XbusStatus &= ~CDST_SPIN;
            cd->XbusStatus |= CDST_RDY;
            cd->MEIStatus=MEI_CDROM_no_error;

         }
         else
         {
            cd->XbusStatus|=CDST_ERRO;
            cd->XbusStatus|=CDST_RDY;
            cd->MEIStatus=MEI_CDROM_recv_ecc;

         }

         cd->Poll|=POLST; //status is valid

         cd->StatusLen=2;
         cd->Status[0]=0x3;
         //cd->Status[1]=0x0;
         //cd->Status[2]=0x0;
         cd->Status[1] = cd->XbusStatus;

         break;
      case 0x4:
         //diagnostics
         // not used in opera
         //04 00 ll-bb-aa 00 00.
         //04 02 mm-ss-ff 00 00.
         //status 4 bytes
         //xx S1 S2 XS
         //		sprintf(str,"#CDROM 0x4 Diagnostic!!!\n");
         //		CDebug::DPrint(str);

         break;
      case 0x6:
         // eject disc
         //opera status request = 0
         //status 4 bytes
         //xx xx xx XS
         // 1b command of scsi
         //emulation ---
         // Execute EJECT command;
         // Check Sense, update PollRegister (if medium present)
         cd->XbusStatus&=~CDST_TRAY;
         cd->XbusStatus&=~CDST_DISC;
         cd->XbusStatus&=~CDST_SPIN;
         cd->XbusStatus&=~CDST_2X;
         cd->XbusStatus&=~CDST_ERRO;
         cd->XbusStatus|=CDST_RDY;
         cd->Poll|=POLST; //status is valid
         cd->Poll&=~POLMA;
         cd->MEIStatus=MEI_CDROM_no_error;

         cd->StatusLen=2;
         cd->Status[0]=0x6;
         //cd->Status[1]=0x0;
         //cd->Status[2]=0x0;
         cd->Status[1]=cd->XbusStatus;

         /*	ClearCDB();
            CDB[0]=0x1b;
            CDB[4]=0x2;
            CDBLen=12;
            */



         break;
      case 0x7:
         // inject disc
         //opera status request = 0
         //status 4 bytes
         //xx xx xx XS
         //1b command of scsi
         //		sprintf(str,"#CDROM 0x7 INJECT!!!\n");
         //		CDebug::DPrint(str);

         break;
      case 0x8:
         // abort !!!
         //opera status request = 31
         //status 4 bytes
         //xx xx xx XS
         //
         cd->StatusLen=33;
         cd->Status[0]=0x8;
         for(i=1;i<32;i++)
            cd->Status[i]=0;
         cd->Status[32]=cd->XbusStatus;

         cd->XbusStatus|=CDST_RDY;
         cd->MEIStatus=MEI_CDROM_no_error;


         break;
      case 0x9:
         // mode set
         //09 MM nn 00 00 00 00 // 2048 or 2340 transfer size
         // to be checked -- wasn't called even once
         // 2nd byte is type selector
         // MM = mode nn= value
         //opera status request = 0
         //status 4 bytes
         //xx xx xx XS
         // to check!!!

         //	if((XbusStatus&CDST_TRAY) && (XbusStatus&CDST_DISC))
         //	{
         cd->XbusStatus |= CDST_RDY;
         cd->MEIStatus = MEI_CDROM_no_error;

         //CDMode[Command[1]]=Command[2];
         //	}
         //	else
         //	{
         //		XbusStatus|=CDST_ERRO;
         //		XbusStatus&=~CDST_RDY;
         //	}

         cd->Poll |= POLST; //status is valid

         cd->StatusLen=2;
         cd->Status[0]=0x9;
         cd->Status[1] = cd->XbusStatus;
         break;
      case 0x0a:
         // reset
         //not used in opera
         //status 4 bytes
         //xx xx xx XS
         //		sprintf(str,"#CDROM 0xa RESET!!!\n");
         //		CDebug::DPrint(str);
         break;
      case 0x0b:
         // flush
         //opera status request = 31
         //status 4 bytes
         //xx xx xx XS
         //returns data
         //flush all internal buffer
         //1+31+1
         cd->XbusStatus|=CDST_RDY;
         cd->StatusLen=33;
         cd->Status[0]=0xb;
         for(i=1;i<32;i++)
            cd->Status[i]=0;
         cd->Status[32] = cd->XbusStatus;

         //cd->XbusStatus|=CDST_RDY;
         cd->MEIStatus=MEI_CDROM_no_error;

         break;
      case 0x10:
         //Read Data !!!
         //10 01 00 00 00 00 01 // read 0x0 blocks from MSF=1.0.0
         //10 xx-xx-xx nn-nn fl.
         //00 01 02 03 04 05 06
         //reads nn blocks from xx
         //fl=0 xx="lba"
         //fl=1 xx="msf"
         //block= 2048 bytes
         //opera status request = 0
         //status 4 bytes
         //xx xx xx XS
         //returns data
         // here we go


         //olddataptr=DataLen;
         if((cd->XbusStatus & CDST_TRAY) && (cd->XbusStatus & CDST_DISC) && (cd->XbusStatus & CDST_SPIN))
         {
            cd->XbusStatus |= CDST_RDY;
            //cd->CDMode[Command[1]] = cd->Command[2];
            cd->StatusLen = 2;
            cd->Status[0] = 0x10;
            //cd->Status[1]=0x0;
            //cd->Status[2]=0x0;
            cd->Status[1] = cd->XbusStatus;

            //if(cd->Command[6] == Address_Abs_MSF)
            {
               cd->DISC.curabsmsf[0] = (cd->Command[1]);
               cd->DISC.curabsmsf[1] = (cd->Command[2]);
               cd->DISC.curabsmsf[2] = (cd->Command[3]);
               cd->DISC.tempmsf[0] = cd->DISC.curabsmsf[0];
               cd->DISC.tempmsf[1] = cd->DISC.curabsmsf[1];
               cd->DISC.tempmsf[2] = cd->DISC.curabsmsf[2];
               MSF2LBA(cd);


               //if(fiso!=NULL)
               //	fseek(fiso,DISC.templba*2048+iso_off_from_begin,SEEK_SET);
               {
                  cd->curr_sector = cd->DISC.templba;
                  _3do_OnSector(cd->DISC.templba);
               }
               //fseek(fiso,DISC.templba*2048,SEEK_SET);
               //fseek(fiso,DISC.templba*2336,SEEK_SET);
            }





            cd->olddataptr = (cd->Command[5] << 8) + cd->Command[6];
            //cd->olddataptr = cd->olddataptr*2048; //!!!
            cd->Requested = cd->olddataptr;

            if (cd->Requested)
            {
               _3do_OnSector(cd->curr_sector++);
               _3do_Read2048(cd->Data);
               cd->DataLen = REQSIZE;
               cd->Requested--;
            }
            else
               cd->DataLen=0;

            cd->Poll |= POLDT;
            cd->Poll |= POLST;
            cd->MEIStatus = MEI_CDROM_no_error;
         }
         else
         {
            cd->XbusStatus|=CDST_ERRO;
            cd->XbusStatus&=~CDST_RDY;
            cd->Poll|=POLST; //status is valid
            cd->StatusLen=2;
            cd->Status[0]=0x10;
            //cd->Status[1]=0x0;
            //cd->Status[2]=0x0;
            cd->Status[1] = cd->XbusStatus;
            cd->MEIStatus = MEI_CDROM_recv_ecc;

         }


         break;
      case 0x80:
         // data path chech
         //opera status request = 2
         //MKE =2
         // status 4 bytes
         // 80 AA 55 XS
         cd->XbusStatus |= CDST_RDY;
         cd->StatusLen = 4;
         cd->Status[0]=0x80;
         cd->Status[1]=0xaa;
         cd->Status[2]=0x55;
         cd->Status[3] = cd->XbusStatus;
         cd->Poll|=POLST;
         cd->MEIStatus=MEI_CDROM_no_error;


         break;
      case 0x82:
         //read error (get last status???)
         //opera status request = 8 ---- tests status req=9?????
         //MKE = 8!!!
         //00
         //11
         //22   Current Status //MKE / Opera???
         //33
         //44
         //55
         //66
         //77
         //88   Current Status //TEST
         cd->Status[0]=0x82;
         cd->Status[1] = cd->MEIStatus;
         cd->Status[2] = cd->MEIStatus;
         cd->Status[3] = cd->MEIStatus;
         cd->Status[4] = cd->MEIStatus;
         cd->Status[5] = cd->MEIStatus;
         cd->Status[6] = cd->MEIStatus;
         cd->Status[7] = cd->MEIStatus;
         cd->Status[8] = cd->MEIStatus;
         cd->XbusStatus|=CDST_RDY;
         cd->Status[9] = cd->XbusStatus;
         //cd->Status[9] = cd->XbusStatus; // 1 == disc present
         cd->StatusLen=10;
         cd->Poll |= POLST;
         //Poll|=0x80; //MDACC



         break;
      case 0x83:
         //read id
         //opera status request = 10
         //status 12 bytes (3 words)
         //MEI text + XS
         //00 M E I 1 01 00 00 00 00 00 XS
         cd->XbusStatus|=CDST_RDY;
         cd->StatusLen=12;
         cd->Status[0]=0x83;
         cd->Status[1]=0x00;//manufacture id
         cd->Status[2]=0x10;//10
         cd->Status[3]=0x00;//MANUFACTURE NUM
         cd->Status[4]=0x01;//01
         cd->Status[5]=00;
         cd->Status[6]=00;
         cd->Status[7]=0;//REVISION NUMBER:
         cd->Status[8]=0;
         cd->Status[9]=0x00;//FLAG BYTES
         cd->Status[10]=0x00;
         cd->Status[11] = cd->XbusStatus;//DEV.DRIVER SIZE
         //cd->Status[11] = cd->XbusStatus;
         //cd->Status[12] = cd->XbusStatus;
         cd->Poll|=POLST;
         cd->MEIStatus=MEI_CDROM_no_error;

         break;
      case 0x84:
         //mode sense
         //not used in opera
         //84 mm 00 00 00 00 00.
         //status 4 bytes
         //xx S1 S2 XS
         //xx xx nn XS
         //
         cd->StatusLen = 4;
         cd->Status[0] = 0x0;
         cd->Status[1] = 0x0;
         cd->Status[2] = 0x0;

         if((cd->XbusStatus & CDST_TRAY) && (cd->XbusStatus & CDST_DISC))
         {
            cd->XbusStatus |= CDST_RDY;
            //CDMode[Command[1]]=Command[2];
            //cd->Status[2] = CDMode[Command[1]];
         }
         else
         {
            cd->XbusStatus |= CDST_ERRO;
            cd->XbusStatus &= ~CDST_RDY;
         }

         cd->Poll|=POLST; //status is valid

         cd->Status[3] = cd->XbusStatus;
         break;
      case 0x85:
         //read capacity
         //status 8 bytes
         //opera status request = 6
         //cc cc cc cc cc cc cc XS
         //data?
         //00 85
         //11 mm  total
         //22 ss  total
         //33 ff  total
         //44 ??
         //55 ??
         //66 ??
         if((cd->XbusStatus&CDST_TRAY) && (cd->XbusStatus&CDST_DISC)&&(cd->XbusStatus&CDST_SPIN))
         {
            cd->StatusLen=8;//CMD+status+DRVSTAT
            cd->Status[0]=0x85;
            cd->Status[1]=0;
            cd->Status[2]= cd->DISC.totalmsf[0]; //min
            cd->Status[3]= cd->DISC.totalmsf[1]; //sec
            cd->Status[4]= cd->DISC.totalmsf[2]; //fra
            cd->Status[5]=0x00;
            cd->Status[6]=0x00;
            cd->XbusStatus|=CDST_RDY;
            cd->Status[7]= cd->XbusStatus;
            cd->Poll|=POLST;
            cd->MEIStatus=MEI_CDROM_no_error;


         }
         else
         {
            cd->XbusStatus |= CDST_ERRO;
            cd->XbusStatus &= ~CDST_RDY;
            cd->StatusLen = 2;//CMD+status+DRVSTAT
            cd->Status[0] = 0x85;
            cd->Status[1] = cd->XbusStatus;
            cd->Poll |= POLST;
            cd->MEIStatus = MEI_CDROM_recv_ecc;

         }

         break;
      case 0x86:
         //read header
         // not used in opera
         // 86 00 ll-bb-aa 00 00.
         // 86 02 mm-ss-ff 00 00.
         // status 8 bytes
         // data?
         //		sprintf(str,"#CDROM 0x86 READ HEADER!!!\n");
         //		CDebug::DPrint(str);

         break;
      case 0x87:
         //read subq
         //opera status request = 10
         //87 fl 00 00 00 00 00
         //fl=0 "lba"
         //fl=1 "msf"
         //
         //11 00 (if !=00 then break)
         //22 Subq_ctl_adr=swapnibles(_11_)
         //33 Subq_trk = but2bcd(_22_)
         //44 Subq_pnt_idx=byt2bcd(_33_)
         //55 mm run tot
         //66 ss run tot
         //77 ff run tot
         //88 mm run trk
         //99 ss run trk
         //aa ff run trk

         if((cd->XbusStatus & CDST_TRAY) && (cd->XbusStatus & CDST_DISC) && (cd->XbusStatus & CDST_SPIN))
         {
            cd->StatusLen=12;//CMD+status+DRVSTAT
            cd->Status[0]=0x87;
            cd->Status[1]=0;//DISC.totalmsf[0]; //min
            cd->Status[2]=0; //sec
            cd->Status[3]=0; //fra
            cd->Status[4]=0;
            cd->Status[5]=0;
            cd->XbusStatus|=CDST_RDY;
            cd->Status[6]=0x0;
            cd->Status[7]=0x0;
            cd->Status[8]=0x0;
            cd->Status[9]=0x0;
            cd->Status[10]=0x0;
            cd->Status[11] = cd->XbusStatus;
            cd->Poll|=POLST;
            cd->MEIStatus=MEI_CDROM_no_error;
         }
         else
         {
            cd->XbusStatus|=CDST_ERRO;
            cd->XbusStatus&=~CDST_RDY;
            cd->StatusLen=2;//CMD+status+DRVSTAT
            cd->Status[0]=0x85;
            cd->Status[1] = cd->XbusStatus;
            cd->Poll |= POLST;
            cd->MEIStatus=MEI_CDROM_recv_ecc;

         }




         break;
      case 0x88:
         //read upc
         // not used in opera
         //88 00 ll-bb-aa 00 00
         //88 02 mm-ss-ff 00 00
         //status 20(16) bytes
         //data?
         //		sprintf(str,"#CDROM 0x88 READ UPC!!!\n");
         //		CDebug::DPrint(str);

         break;
      case 0x89:
         //read isrc
         // not used in opera
         //89 00 ll-bb-aa 00 00
         //89 02 mm-ss-ff 00 00
         //status 16(15) bytes
         //data?

         //		sprintf(str,"#CDROM 0x89 READ ISRC!!!\n");
         //		CDebug::DPrint(str);

         break;
      case 0x8a:
         //read disc code
         //ignore it yet...
         ////opera status request = 10
         // 8a 00 00 00 00 00 00
         //status 10 bytes
         //????? which code???
         if((cd->XbusStatus & CDST_TRAY) && (cd->XbusStatus & CDST_DISC) && (cd->XbusStatus & CDST_SPIN))
         {
            cd->StatusLen=12;//CMD+status+DRVSTAT
            cd->Status[0]=0x8a;
            cd->Status[1]=0;//DISC.totalmsf[0]; //min
            cd->Status[2]=0; //sec
            cd->Status[3]=0; //fra
            cd->Status[4]=0;
            cd->Status[5]=0;
            cd->XbusStatus|=CDST_RDY;
            cd->Status[6]=0x0;
            cd->Status[7]=0x0;
            cd->Status[8]=0x0;
            cd->Status[9]=0x0;
            cd->Status[10]=0x0;
            cd->Status[11] = cd->XbusStatus;
            cd->Poll|=POLST;
            cd->MEIStatus=MEI_CDROM_no_error;
         }
         else
         {
            cd->XbusStatus|=CDST_ERRO;
            cd->XbusStatus&=~CDST_RDY;
            cd->StatusLen=2;//CMD+status+DRVSTAT
            cd->Status[0] = 0x85;
            cd->Status[1] = cd->XbusStatus;
            cd->Poll |= POLST;
            cd->MEIStatus = MEI_CDROM_recv_ecc;

         }



         break;
      case 0x8b:
         //MKE !!!v the same
         //read disc information
         //opera status request = 6
         //8b 00 00 00 00 00 00
         //status 8(6) bytes
         //read the toc descritor
         //00 11 22 33 44 55 XS
         //00= 8b //command code
         //11= Disc ID /// XA_BYTE
         //22= 1st track#
         //33= last track#
         //44= minutes
         //55= seconds
         //66= frames


         cd->StatusLen = 8;//6+1 + 1 for what?
         cd->Status[0] = 0x8b;
         if(cd->XbusStatus&(CDST_TRAY|CDST_DISC|CDST_SPIN))
         {
            cd->Status[1] = cd->DISC.discid;
            cd->Status[2] = cd->DISC.firsttrk;
            cd->Status[3] = cd->DISC.lasttrk;
            cd->Status[4] = cd->DISC.totalmsf[0]; //minutes
            cd->Status[5] = cd->DISC.totalmsf[1]; //seconds
            cd->XbusStatus |= CDST_RDY;
            cd->Status[6] = cd->DISC.totalmsf[2]; //frames
            cd->MEIStatus = MEI_CDROM_no_error;
            cd->Status[7] = cd->XbusStatus;
         }
         else
         {
            cd->StatusLen=2;//6+1 + 1 for what?
            cd->XbusStatus|=CDST_ERRO;
            cd->MEIStatus=MEI_CDROM_recv_ecc;
            cd->Status[1] = cd->XbusStatus;
         }

         cd->Poll |= POLST; //status is valid

         break;
      case 0x8c:
         //read toc
         //MKE !!!v the same
         //opera status request = 8
         //8c fl nn 00 00 00 00 // reads nn entry
         //status 12(8) bytes
         //00 11 22 33 44 55 66 77 XS
         //00=8c
         //11=reserved0; // NIX BYTE
         //22=addressAndControl; //TOCENT_CTL_ADR=swapnibbles(11) ??? UPCCTLADR=_10_ | x02 (_11_ &F0 = _10_)
         //33=trackNumber;  //TOC_ENT NUMBER
         //44=reserved3;    //TOC_ENT FORMAT
         //55=minutes;     //TOCENT ADRESS == 0x00445566
         //66=seconds;
         //77=frames;
         //88=reserved7;
         cd->StatusLen = 10;//CMD+status+DRVSTAT
         cd->Status[0] = 0x8c;

         if(cd->XbusStatus & (CDST_TRAY|CDST_DISC|CDST_SPIN))
         {
            cd->Status[1] = cd->DISC.DiscTOC[cd->Command[2]].res0;
            cd->Status[2] = cd->DISC.DiscTOC[cd->Command[2]].CDCTL;
            cd->Status[3] = cd->DISC.DiscTOC[cd->Command[2]].TRKNUM;
            cd->Status[4] = cd->DISC.DiscTOC[cd->Command[2]].res1;
            cd->Status[5] = cd->DISC.DiscTOC[cd->Command[2]].mm; //min
            cd->XbusStatus |= CDST_RDY;
            cd->Status[6] = cd->DISC.DiscTOC[cd->Command[2]].ss; //sec
            cd->Status[7] = cd->DISC.DiscTOC[cd->Command[2]].ff; //frames
            cd->Status[8] = cd->DISC.DiscTOC[cd->Command[2]].res2;
            cd->MEIStatus = MEI_CDROM_no_error;
            cd->Status[9] = cd->XbusStatus;

         }
         else
         {
            cd->StatusLen = 2;
            cd->XbusStatus |= CDST_ERRO;
            cd->MEIStatus = MEI_CDROM_recv_ecc;
            cd->Status[1] = cd->XbusStatus;
         }

         cd->Poll |= POLST;
         break;
      case 0x8d:
         //read session information
         //MKE !!!v the same
         //opera status request = 6
         //status 8(6)
         //00 11 22 33 44 55 XS ==
         //00=8d
         //11=valid;  // 0x80 = MULTISESS
         //22=minutes;
         //33=seconds;
         //44=frames;
         //55=rfu1; //ignore
         //66=rfu2  //ignore

         cd->StatusLen = 8;//CMD+status+DRVSTAT
         cd->Status[0] = 0x8d;
         if((cd->XbusStatus & CDST_TRAY) && (cd->XbusStatus & CDST_DISC))
         {
            cd->Status[1] = 0x00;
            cd->Status[2] = 0x0;//DISC.sesmsf[0];//min
            cd->Status[3] = 0x2;//DISC.sesmsf[1];//sec
            cd->Status[4] = 0x0;//DISC.sesmsf[2];//fra
            cd->Status[5] = 0x00;
            cd->XbusStatus |= CDST_RDY;
            cd->Status[6] = 0x00;
            cd->Status[7] = cd->XbusStatus;
            cd->MEIStatus = MEI_CDROM_no_error;

         }
         else
         {
            cd->StatusLen = 2;//CMD+status+DRVSTAT
            cd->XbusStatus |= CDST_ERRO;
            cd->Status[1] = cd->XbusStatus;
            cd->MEIStatus = MEI_CDROM_recv_ecc;
         }

         cd->Poll|=POLST;
         break;
      case 0x8e:
         //read device driver
         break;
      case 0x93:
         //?????
         cd->StatusLen=4;
         cd->Status[0]=0x0;
         cd->Status[1]=0x0;
         cd->Status[2]=0x0;

         if((cd->XbusStatus&CDST_TRAY) && (cd->XbusStatus & CDST_DISC))
         {
            cd->XbusStatus|=CDST_RDY;
            //CDMode[Command[1]]=Command[2];
            //			Status[2]=CDMode[Command[1]];
         }
         else
         {
            cd->XbusStatus|=CDST_ERRO;
            cd->XbusStatus|=CDST_RDY;
         }

         cd->Poll |= POLST; //status is valid

         cd->Status[3] = cd->XbusStatus;

         break;
      default:
         // error!!!
         //sprintf(str,"#CDROM %x!!!\n",Command[0]);
         //CDebug::DPrint(str);
         break;
   }
}
Example #4
0
void matsucd_command_w( running_machine &machine, UINT8 data )
{
	UINT8	cmd;

	/* make sure we're enabled */
	if ( cd.enabled == 0 )
		return;

	/* make sure /CMD is asserted */
	if ( cd.cmd_signal == 0 )
		return;

	if ( cd.cdda_set == 0 )
	{
		// 2009-10, FP: for some reason, cdda_from_cdrom was not returning the correct
		// CDDA device. Hence, as a temp workaround, I added the cdda to the struct
		// and its tag is configured in matsucd_init
		if ( cd.cdrom )
			cdda_set_cdrom( cd.cdda, cd.cdrom);

		cd.cdda_set = 1;
	}

	cd.input[cd.input_pos++] = data;

	cmd = cd.input[0];

	switch( cmd )
	{
		case 0x01:	/* seek */
		{
			if ( cd.input_pos < 7 )
				return;

			/* stop CDDA audio if necessary */
			matsucd_cdda_stop(machine);

			cd.motor = 1;

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0x02:	/* read sectors */
		{
			if ( cd.input_pos < 7 )
				return;

			/* stop CDDA audio if necessary */
			matsucd_cdda_stop(machine);

			/* LBA */
			cd.lba = cd.input[1];
			cd.lba <<= 8;
			cd.lba |= cd.input[2];
			cd.lba <<= 8;
			cd.lba |= cd.input[3];

			/* Number of blocks */
			cd.num_blocks = cd.input[4];
			cd.num_blocks <<= 8;
			cd.num_blocks |= cd.input[5];

			/* Reset transfer count */
			cd.xfer_offset = 0;

			/* go ahead and cache the first block */
			if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type()))
			{
				logerror( "MATSUCD - Warning: Read error on CD!\n" );
				matsucd_command_error( machine );
				return;
			}

			cd.motor = 1;

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0x04:	/* motor on */
		{
			if ( cd.input_pos < 7 )
				return;

			cd.motor = 1;

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0x05:	/* motor off */
		{
			if ( cd.input_pos < 7 )
				return;

			/* stop CDDA audio if necessary */
			matsucd_cdda_stop(machine);

			cd.motor = 0;

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0x09:	/* play audio cd, LBA mode */
		{
			UINT32	lba, numblocks;

			if ( cd.input_pos < 7 )
				return;

			lba = cd.input[1];
			lba <<= 8;
			lba |= cd.input[2];
			lba <<= 8;
			lba |= cd.input[3];

			numblocks = cd.input[4];
			numblocks <<= 8;
			numblocks |= cd.input[5];
			numblocks <<= 8;
			numblocks |= cd.input[6];

			matsucd_cdda_play( machine, lba, numblocks );

			cd.motor = 1;

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0x0a:	/* play audio cd, MSF mode */
		{
			UINT32	start, end, lba_start, lba_end;

			if ( cd.input_pos < 7 )
				return;

			start = cd.input[1];
			start <<= 8;
			start |= cd.input[2];
			start <<= 8;
			start |= cd.input[3];

			end = cd.input[4];
			end <<= 8;
			end |= cd.input[5];
			end <<= 8;
			end |= cd.input[6];

			lba_start = MSF2LBA( start );
			lba_end = MSF2LBA( end );

			if ( end == 0xffffff )
			{
				lba_end = cdrom_get_track_start(cd.cdrom,cdrom_get_last_track(cd.cdrom)-1);
				lba_end += cdrom_get_toc(cd.cdrom)->tracks[cdrom_get_last_track(cd.cdrom)-1].frames;
			}

			if ( lba_end <= lba_start )
			{
				matsucd_cdda_stop(machine);
			}
			else
			{
				matsucd_cdda_play( machine, lba_start, lba_end - lba_start );
				cd.motor = 1;
			}

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0x0b:	/* play audio track and index */
		{
			UINT8	track_start = cd.input[1];
			UINT8	index_start = cd.input[2];
			UINT8	track_end = cd.input[3];
			UINT8	index_end = cd.input[4];
			UINT32	lba_start, lba_end;

			/* TODO: Add index support once the CDDA engine supports it */
			(void)index_start;
			(void)index_end;

			/* sanitize values */
			if ( track_start == 0 ) track_start++;
			if ( track_end == 0 ) track_end++;
			if ( track_end > cdrom_get_last_track(cd.cdrom) )
				track_end = cdrom_get_last_track(cd.cdrom);

			/* find the start and stop positions */
			lba_start = cdrom_get_track_start(cd.cdrom,track_start-1);
			lba_end = cdrom_get_track_start(cd.cdrom,track_end-1);

			lba_end += cdrom_get_toc(cd.cdrom)->tracks[track_end-1].frames;

			if ( lba_end <= lba_start )
			{
				matsucd_cdda_stop(machine);
			}
			else
			{
				matsucd_cdda_play( machine, lba_start, lba_end - lba_start );
				cd.motor = 1;
			}

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0x81:	/* status read */
		{
			UINT8	newstatus = cd.status;

			newstatus &= MATSU_STATUS_SUCCESS | MATSU_STATUS_ERROR | MATSU_STATUS_PLAYING;
			newstatus |= MATSU_STATUS_READY;

			if (cd.cdrom)
			{
				newstatus |= MATSU_STATUS_MEDIA;
			}

			if (cd.motor)
				newstatus |= MATSU_STATUS_MOTOR;

			cd.output[0] = newstatus;

			matsucd_set_status( machine, newstatus );

			matsucd_complete_cmd( machine, 1 );
		}
		break;

		case 0x82:	/* error read */
		{
			if ( cd.input_pos < 7 )
				return;

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 6 );
		}
		break;

		case 0x84:	/* set mode */
		{
			if ( cd.input_pos < 7 )
				return;

			cd.sector_size = cd.input[2];
			cd.sector_size <<= 8;
			cd.sector_size |= cd.input[3];

			memset( cd.output, 0, 6 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0x87:	/* read SUBQ */
		{
			int		msfmode;
			UINT32	lba;
			UINT8	track;

			if ( cd.input_pos < 7 )
				return;

			msfmode = (cd.input[1] & 0x02) ? 1 : 0;

			memset( cd.output, 0, 13 );

			cd.output[0] = matsucd_cdda_getstatus( machine, &lba );

			if ( lba > 0 )
			{
				UINT32	disk_pos;
				UINT32	track_pos;

				track = cdrom_get_track(cd.cdrom, lba);

				cd.output[1] = cdrom_get_adr_control(cd.cdrom, track);
				cd.output[2] = track+1;
				cd.output[3] = 0; /* index */

				disk_pos = lba;
				if ( msfmode ) disk_pos = LBA2MSF(disk_pos);

				cd.output[4] = (disk_pos >> 24) & 0xff;
				cd.output[5] = (disk_pos >> 16) & 0xff;
				cd.output[6] = (disk_pos >> 8) & 0xff;
				cd.output[7] = (disk_pos) & 0xff;

				track_pos = lba - cdrom_get_track_start(cd.cdrom, track);
				if ( msfmode ) track_pos = LBA2MSF(track_pos);

				cd.output[8] = (track_pos >> 24) & 0xff;
				cd.output[9] = (track_pos >> 16) & 0xff;
				cd.output[10] = (track_pos >> 8) & 0xff;
				cd.output[11] = (track_pos) & 0xff;

				/* TODO: UPC flag at offset 12 */
				cd.output[12] = 0;
			}

			matsucd_complete_cmd( machine, 13 );
		}
		break;

		case 0x89:	/* read disk info */
		{
			UINT32	end;

			if ( cd.input_pos < 7 )
				return;

			memset( cd.output, 0, 5 );

			cd.output[0] = cdrom_get_last_track(cd.cdrom) ? 1 : 0;
			cd.output[1] = cdrom_get_last_track(cd.cdrom);
			end = cdrom_get_track_start(cd.cdrom,cd.output[1]-1);
			end += cdrom_get_toc(cd.cdrom)->tracks[cd.output[1]-1].frames;
			end = LBA2MSF(end);
			cd.output[2] = (end >> 16) & 0xff;
			cd.output[3] = (end >> 8) & 0xff;
			cd.output[4] = (end) & 0xff;

			matsucd_complete_cmd( machine, 5 );
		}
		break;

		case 0x8a:	/* read toc */
		{
			UINT8	track;
			int		msfmode;
			UINT32	track_start;

			if ( cd.input_pos < 7 )
				return;

			/* stop CDDA audio if necessary */
			matsucd_cdda_stop(machine);

			track = cd.input[2];
			msfmode = (cd.input[1] & 0x02) ? 1 : 0;

			if ( cd.cdrom == NULL )
			{
				logerror( "MATSUCD - Warning: Reading TOC without a CD!\n" );
				matsucd_command_error( machine );
				return;
			}

			if ( track > cdrom_get_last_track(cd.cdrom) )
			{
				logerror( "MATSUCD - Warning: Reading invalid track entry from TOC!\n" );
				matsucd_command_error( machine );
				return;
			}

			memset( cd.output, 0, 7 );

			track_start = cdrom_get_track_start(cd.cdrom, track > 0 ? (track-1) : track );
			if ( msfmode ) track_start = LBA2MSF( track_start );

			cd.output[1] = cdrom_get_adr_control(cd.cdrom, track > 0 ? (track-1) : track);
			cd.output[2] = track;
			cd.output[3] = (track == 0 ) ? cdrom_get_last_track(cd.cdrom) : 0;
			cd.output[4] = (track_start >> 24) & 0xff;
			cd.output[5] = (track_start >> 16) & 0xff;
			cd.output[6] = (track_start >> 8) & 0xff;
			cd.output[7] = (track_start) & 0xff;

			cd.motor = 1;

			matsucd_complete_cmd( machine, 8 );
		}
		break;

		case 0x8b:	/* pause audio */
		{
			if ( cd.input_pos < 7 )
				return;

			matsucd_cdda_pause( machine, (cd.input[1] == 0) ? 1 : 0 );
			memset( cd.output, 0, 7 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		case 0xa3:	/* front panel */
		{
			if ( cd.input_pos < 7 )
				return;

			/* TODO: ??? */

			memset( cd.output, 0, 7 );
			matsucd_complete_cmd( machine, 0 );
		}
		break;

		default:
			logerror( "MATSUCD: Unknown/inimplemented command %08x\n", cmd );
		break;
	}