
/* vdp50_driver.c : routines for DEC_VDP-50 videodisc player */

#include "vdp50.h"
#include "rpd_driver.h"
#include <stdio.h>

#define MAXRETRYS 0		/* the number of times we try before giving up */

extern int ttyutil_debug;

int		vdp50_debug = 0;
static	UBYTE	inbytes[16];
static	UBYTE	outbytes[16];
static 	int	not_loaded = 0;

/* ------------------------------------------------------------------------ */

static int
  vdp50_IntToFrame(n,f)

int	n;
UBYTE *	f;
{	
  int 	i; 
  char 	s[6];
  
  f[0] = f[1] = f[2] = 0;
  sprintf(s,"%05d",(n));
  for( i=0; i<5; i++ )
    f[(i+1)/2] |= (s[i]-'0') << (i%2?4:0);
  f[0] |= 0xf0;
  return 0;
}

/* ------------------------------------------------------------------------ */

static int
  vdp50_FrameToInt(f)

UBYTE *	f;
{	
  int i; 
  char s[6];
  
  s[5] = 0;
  for( i=0; i<5; i++ )
    s[i] = ((f[(i+1)/2] >> (i%2?4:0)) & 0x0f) + '0';
  return atoi(s);
}

/* ------------------------------------------------------------------------ */

static int
  vdp50_IntToJumpArg(n,j)

int	n;
UBYTE *	j;
{
  int 	i; 
  char 	s[4];
  
  j[0] = j[1] = 0;
  sprintf(s,"%03d",(n));
  for( i=0; i<3; i++ )
    j[(i+1)/2] |= ((s[i]-'0') << (i%2?4:0));
  return 0;
}

/* ------------------------------------------------------------------------ */

static int
  vdp50_RevisionToInts(r,hn,fn)

UBYTE *	r;
int *	hn;
int *	fn;
{	
  int i;
  *hn = r[1] * 0xff + r[0];
  *fn = r[3] * 0xff + r[2];
  return 0;
}

/* ------------------------------------------------------------------------ */

static int
  vdp50_SetAudioState( rpd, b )

RPD_ptr	rpd;
UBYTE *	b;
{
  *b = 0;
  if( rpd->state.audio1_on )
    BITS_ON( *b, VDP50_CH1_ON );
  else
    BITS_OFF( *b, VDP50_CH1_ON );
  
  if( rpd->state.audio2_on )
    BITS_ON( *b, VDP50_CH2_ON );
  else
    BITS_OFF( *b, VDP50_CH2_ON );
  return 0;
}

/* ------------------------------------------------------------------------ */

vdp50_cmd(rpd,num)
     
     RPD_ptr	rpd;
     int 	num;
{
  static char *funcname = "vdp50_cmd";
  int	success = 0;
  UBYTE	args[10];	/* assumes these are all 0 */
  VDP50_Frame	bcdf;
  VDP50_DiscID	id;
  int	frame;
  
  /* note that with the audio, must set the bits corresponding
     to the current state of the software */
  
  switch(num)
    {
    case INDEX_ON:
      BITS_ON( args[0], VDP50_INDEX_ON );
      if( !vdp50_ttyio( rpd->fd, VDP50_INDEX_PKT, args, 1 ) )
	{
	  rpd->state.indexon = 1;
	  success = 1;
	}
      break;
    case INDEX_OFF:
      BITS_OFF( args[0], VDP50_INDEX_ON );
      if( !vdp50_ttyio( rpd->fd, VDP50_INDEX_PKT, args, 1 ) )
	{
	  rpd->state.indexon = 0;
	  success = 1;
	}
      break;
    case A1_ON:
      vdp50_SetAudioState( rpd, &args[0] );
      BITS_ON( args[0], VDP50_CH1_ON );
      if( !vdp50_ttyio( rpd->fd, VDP50_AUDIO_PKT, args, 1 ) )
	{
	  rpd->state.audio1_on = 1;
	  success = 1;
	}
      break;
    case A1_OFF:
      vdp50_SetAudioState( rpd, &args[0] );
      BITS_OFF( args[0], VDP50_CH1_ON );
      if( !vdp50_ttyio( rpd->fd, VDP50_AUDIO_PKT, args, 1 ) )
	{
	  rpd->state.audio1_on = 0;
	  success = 1;
	}
      break;
    case A2_ON:
      vdp50_SetAudioState( rpd, &args[0] );
      BITS_ON( args[0], VDP50_CH2_ON );
      if( !vdp50_ttyio( rpd->fd, VDP50_AUDIO_PKT, args, 1 ) )
	{
	  rpd->state.audio2_on = 1;
	  success = 1;
	}
      break;
    case A2_OFF:
      vdp50_SetAudioState( rpd, &args[0] );
      BITS_OFF( args[0], VDP50_CH2_ON );
      if( !vdp50_ttyio( rpd->fd, VDP50_AUDIO_PKT, args, 1 ) )
	{
	  rpd->state.audio2_on = 0;
	  success = 1;
	}
      break;
    case LOAD:
      if( !vdp50_ttyio( rpd->fd, VDP50_LOAD_PKT, args, 1 ) )
	{
	  rpd->state.volume_loaded = 1;
	  bcopy( &inbytes[1], bcdf, 3 );
	  if( !vdp50_LoadIsNormal(bcdf) )
	    {
	      frame = vdp50_FrameToInt( bcdf );
	      fprintf(stderr,"%s: abnormal load: at frame %d\n",
		      rpd->devname,frame );
	    }
	  if( !vdp50_ttyio( rpd->fd, VDP50_ID_PKT, args, 1 ) )
	    {
	      bcopy( &inbytes[1], id, 3 );
	      sprintf(rpd->volume,"#%02x%02x%02x",
		      id[0],id[1],id[2] );
	      fprintf(stderr,"%s: vdp50 loaded volume id '%s'\n",
		      rpd->devname,rpd->volume);
	    }
	  success = 1;
	}
      else
	{
	  fprintf(stderr,"%s: load failure\n",rpd->devname);
	  rpd->state.volume_loaded = 0;
	}
      break;
    case UNLOAD:
      if( !vdp50_ttyio( rpd->fd, VDP50_UNLOAD_PKT, args, 1 ) )
	{
	  if( inbytes[1] == VDP50_UNLOAD_OK )
	    {
	      rpd->state.volume_loaded = 0;
	      rpd->volume[0] = 0;
	      success = 1;
	    }
	  else
	    {
	      if( inbytes[1] & VDP50_LASER_ON )
		fprintf(stderr,"%s: laser still on after unload\n",
			rpd->devname);
	      if( inbytes[1] & VDP50_MOTOR_ON )
		fprintf(stderr,"%s: motor still on after unload\n",
			rpd->devname);
	    }
#ifdef notdef
	  if( vdp50_ttyio( rpd->fd, VDP50_EJECT_PKT, args, 1 ) )
	    {
	      fprintf(stderr,"%s: eject failure\n",rpd->devname);
	    }
#endif
	}
      else
	{
	  fprintf(stderr,"%s: unload failure\n",rpd->devname);
	}
      break;
    default:
      fprintf(stderr,"%s: %s: illegal request %d\n",
	      rpd->devname,funcname,num);
      break;
    }
  
  if( success )
    return(0);
  else
    return -1;
}

/* ------------------------------------------------------------------------ */

static int
  vdp50_SendSpeed( rpd, range, speed )

RPD_ptr	rpd;
int	range;
int	speed;
{
  VDP50_Speed	s;
  
  vdp50_IntToSpeedArg(speed,s);
  vdp50_SetSpeedRange(s,range);
  if( vdp50_ttyio( rpd->fd, VDP50_SPEED_PKT, s, 1 ) )
    return -1;
  return 0;
}

/* ------------------------------------------------------------------------ */

vdp50_varspeed(rpd,num)
     
     RPD_ptr	rpd;
     int	num;
{
  static char *funcname = "vdp50_varspeed";
  int	success = 0;
  UBYTE	args[10];
  int	range;
  int	speed;
  int	dir;
  
  switch(num)
    {
    case R_MAX:
      range = VDP50_FAST_PLAY;
      speed = VDP50_MAX_FAST_SPEED;
      dir = VDP50_REV;
      break;
    case R_VERY_FAST:
      range = VDP50_FAST_PLAY;
      speed = VDP50_MAX_FAST_SPEED/2;
      dir = VDP50_REV;
      break;
    case R_FAST:
      range = VDP50_FAST_PLAY;
      speed = VDP50_MAX_FAST_SPEED/4;
      dir = VDP50_REV;
      break;
    case R_PLAY:
      range = VDP50_NORMAL_PLAY;
      speed = 1;
      dir = VDP50_REV;
      break;
    case R_SLOW:
      range = VDP50_SLOW_PLAY;
      speed = 5;
      dir = VDP50_REV;
      break;
    case R_VERY_SLOW:
      range = VDP50_SLOW_PLAY;
      speed = 10;
      dir = VDP50_REV;
      break;
    case STOP:
      /* special case */
      if( vdp50_ttyio(rpd->fd,VDP50_HALT_PKT,args,1) )
	{
	  fprintf(stderr,"%s: %s: can't stop\n",
		  rpd->devname,funcname);
	  return -1;
	}
      else
	return 0;
      break;
    case F_VERY_SLOW:
      range = VDP50_SLOW_PLAY;
      speed = 10;
      dir = VDP50_FWD;
      break;
    case F_SLOW:
      range = VDP50_SLOW_PLAY;
      speed = 5;
      dir = VDP50_FWD;
      break;
    case F_PLAY:
      range = VDP50_NORMAL_PLAY;
      speed = 1;
      dir = VDP50_FWD;
      break;
    case F_FAST:
      range = VDP50_FAST_PLAY;
      speed = VDP50_MAX_FAST_SPEED/4;
      dir = VDP50_FWD;
      break;
    case F_VERY_FAST:
      range = VDP50_FAST_PLAY;
      speed = VDP50_MAX_FAST_SPEED/2;
      dir = VDP50_FWD;
      break;
    case F_MAX:
      range = VDP50_FAST_PLAY;
      speed = VDP50_MAX_FAST_SPEED;
      dir = VDP50_FWD;
      break;
    default:
      fprintf(stderr,"%s: %s: illegal cmd %d\n",
	      rpd->devname,funcname,num);
      return(-1);
      break;
    }
  
  if( vdp50_SendSpeed(rpd,range,speed) )
    {
      fprintf(stderr,"%s: %s: can't set speed\n",
	      rpd->devname,funcname);
    }
  else
    {
      vdp50_SetPlayDirection(args[0],dir);
      if( vdp50_ttyio(rpd->fd,VDP50_PLAY_PKT,args,1) )
	fprintf(stderr,"%s: %s: can't play\n",
		rpd->devname,funcname);
      else
	success = 1;
    }	
  
  if( success )
    return(0);
  else
    return -1;
}

/* ------------------------------------------------------------------- */

vdp50_jog(rpd,num)
     
     RPD_ptr	rpd;
     int	num;
{
  static char *funcname = "vdp50_jog";
  int	success = 0;
  UBYTE	args[10];
  int	i;
  int	dir;
  
  if( num<0 ) 
    {
      num = (-num);
      dir = VDP50_REV;
    }
  else
    dir = VDP50_FWD;
  
  vdp50_SetStepDirection( args[0], dir );
  
  for( i=0; i<abs(num); i++ )
    {
      if( !vdp50_ttyio(rpd->fd, VDP50_STEP_PKT, args, 1) )
	{
	  if( !(inbytes[1] && VDP50_FRAME_NOT_FOUND) )
	    success = 1;	
	}
    }
  
  if( success )
    return(0);
  else
    return -1;
}

/* ------------------------------------------------------------------------ */

vdp50_getframe(rpd)
     
     RPD_ptr	rpd;
{
  static char *funcname = "vdp50_getframe";
  int	success = 0;
  UBYTE	args[10];
  VDP50_Status	st;
  VDP50_Frame	bcdf;
  int		frame;
  
  if( vdp50_ttyio(rpd->fd, VDP50_STATUS_PKT, args, 1) )
    fprintf(stderr,"%s: %s: can't get player status\n",
	    rpd->devname,funcname);
  else
    {
      bcopy( &inbytes[1], st, 2 );
      bcopy( &inbytes[3], bcdf, 3 );
      frame = vdp50_FrameToInt( bcdf );
      success = 1;
    }
  
  if( success )
    return(frame);
  else
    return -1;
}

/* ------------------------------------------------------------------------ */

vdp50_getstatus(rpd)
     
     RPD_ptr	rpd;
{
  static char *funcname = "vdp50_getstatus";
  int	success = 0;
  UBYTE	args[10];
  VDP50_Status	st;
  VDP50_Frame	bcdf;
  int		frame;
  
  if( vdp50_ttyio(rpd->fd, VDP50_STATUS_PKT, args, 1) )
    fprintf(stderr,"%s: %s: can't get player status\n",
	    rpd->devname,funcname);
  else
    {
      bcopy( &inbytes[1], st, 2 );
      bcopy( &inbytes[3], bcdf, 3 );
      vdp50_FrameToInt( bcdf );
      success = 1;
      
      if( !(st[0] & VDP50_ST_LOADED) )
	not_loaded = 1;
      /*		
	printf("Status of rpd: <%s>\n",rpd->devname);
	printf("------------------\n");
	
	if( st[0] & VDP50_ST_LOADED );
	else
	printf("disc NOT loaded!!\n");
	
	if( st[0] & VDP50_ST_PLAYING )
	printf("disc playing\n");
	else
	printf("disc NOT playing\n");
	
	if( st[0] & VDP50_ST_SEARCHING )
	printf("disc is searching!!\n");
	
	if( st[0] & VDP50_ST_CH1_ON )
	printf("channel 1 on\n");
	else
	printf("channel 1 off\n");
	
	if( st[0] & VDP50_ST_INDEX_ON )
	printf("index is ON\n");
	
	if( st[0] & VDP50_ST_CH2_ON )
	printf("channel 2 on\n");
	else
	printf("channel 2 off\n");
	
	if( st[1] & VDP50_ST_GENLOCKED );
	else
	printf("player NOT GENLOCKED!\n");
	
	success = 1;
	*/
    }
  if( success )
    return(0);
  else
    return -1;
}	

/* ------------------------------------------------------------------------ */

vdp50_search(rpd,frame,wait)
     RPD_ptr	rpd;
     int	frame;
     int	wait;		/* if true, hangs until it gets there 
				   or times out */
{
  static char *funcname = "vdp50_search";
  int	success = 0;
  UBYTE	args[10];
  VDP50_Frame	bcdf;
  VDP50_JumpArg	jump;
  int	at, last;
  int	dir;
  int	nframes;
  int	readnum;
  int	res;
  
  /* to do the quick jump, see if we're within the
     legal limits */
  
  at = vdp50_getframe(rpd);
  nframes = frame-at;
  
  if( nframes > 0 )
    dir = VDP50_FWD;
  else if( nframes < 0 )
    dir = VDP50_REV;
  else
    return 0;	/* already there */
  
  /* RMS - 11/19/87 changed this to bypass any quick jumps;
     1% to 2% of quick jumps miss by one frame;
     this error rate is deemed not worth the speed gain */
  
  /*	
    nframes = abs(nframes);
    
    if( at > 0 && nframes <= VDP50_MAX_SINGLE_JUMP )
    {
    vdp50_IntToJumpArg( nframes, jump );
    vdp50_SetJumpDirection( jump, dir );
    bcopy( jump, args, 2 );
    if( !vdp50_ttyio( rpd->fd, VDP50_JUMP_PKT, args, 1) )
    success = 1;
    else
    fprintf(stderr,"%s: %s: failed quick jump\n",
    rpd->devname,funcname );
    }
    else
    */
  /* do a normal search */
  {
    vdp50_IntToFrame( frame, bcdf );
    bcopy( bcdf, args, 3 );
    if( !vdp50_ttyio(rpd->fd, VDP50_SEARCH_PKT, args, wait) )
      {
	if( !wait )
	  return 0;
	
	readnum = vdp50_table[VDP50_ACK_PKT].resp_bytes + 2 +
	  vdp50_table[VDP50_SEARCH_PKT].resp_bytes + 2;
	res = ttyutil_read( rpd->fd, inbytes, readnum,
			   VDP50_SEARCH_TIMEOUT+1000 );
	if( res == readnum )
	  {	
	    if( inbytes[0] != 
	       vdp50_table[VDP50_ACK_PKT].resp_code
	       ||
	       inbytes[1] != 
	       vdp50_table[VDP50_ACK_PKT].resp_end )
	      {
		fprintf(stderr,"%s: %s: ACK packet mis-match\n",
			rpd->devname,funcname);
		return -1;
	      }
	    if( inbytes[2] != 
	       vdp50_table[VDP50_SEARCH_PKT].resp_code
	       ||
	       inbytes[readnum-1] != 
	       vdp50_table[VDP50_SEARCH_PKT].resp_end )
	      {
		fprintf(stderr,"%s: %s: SEARCH packet mis-match\n",
			rpd->devname,funcname);
		return -1;
	      }
	    bcopy( &inbytes[4], bcdf, 3 );
	    last = vdp50_FrameToInt(bcdf);
	    if( inbytes[3] & VDP50_FRAME_NOT_FOUND )
	      {	/* must search back to last valid frame */
		if( !vdp50_search( rpd, last, 1 ) )
		  fprintf(stderr,
			  "%s: %s: frame not found: now at %d, not %d\n",
			  rpd->devname,funcname,at,frame);
		else
		  {
		    fprintf(stderr,"%s: %s: search failed, resetting rpd\n",
			    rpd->devname,funcname);
		    if( vdp50_reset(rpd) )
		      fprintf(stderr,"%s: %s: RESET FAILED!\n",
			      rpd->devname,funcname);
		  }
	      }
	    else
	      success = 1;
	  }
      }
    else
      fprintf(stderr,"%s: %s: search error\n",
	      rpd->devname,funcname);
  }
  
  if( success )
    return(0);
  else
    return -1;
}

/* ------------------------------------------------------------------------ */

vdp50_reset(rpd)
     
     RPD_ptr	rpd;
{
  static char *funcname = "vdp50_reset";
  int	ret = 0;
  
  if( vdp50_getstatus(rpd) )
    {
      rpd->state.volume_loaded = 0;
      rpd->state.not_responding = 1;
      return -1;
    }
  if( not_loaded )
    {
      if( vdp50_cmd(rpd,LOAD) )
	{
	  ret = -1;
	  rpd->state.volume_loaded = 0;
	}
      else
	rpd->state.volume_loaded = 1;
    }
  else
    {
      rpd->state.volume_loaded = 1;
    }
  
  if( vdp50_cmd(rpd,INDEX_OFF) )
    ret = -1;
  if( vdp50_varspeed(rpd,STOP) )
    ret = -1;
  if( vdp50_cmd(rpd,A1_ON) )
    ret = -1;
  if( vdp50_cmd(rpd,A2_ON) )
    ret = -1;
  
  if( ret < 0 )
    {
      rpd->state.not_responding = 1;
      fprintf(stderr,"rpd '%s' not responding\n",rpd->devname);
    }
  else
    rpd->state.not_responding = 0;
  return ret;
}

/* ------------------------------------------------------------------------ */

vdp50_segplay(rpd,f1,f2,wait)
     
     RPD_ptr	rpd;
     int	f1,f2;
     int	wait;		/* if true, hangs until done */
{
  static char *funcname = "vdp50_segplay";
  int	success = 0;
  UBYTE	args[10];
  VDP50_Frame	endf;
  int		timeout;
  int		res;
  int		len;
  int		readnum;
  int 		i;
  
  len = abs(f1-f2);
  
  /* could take this out for variable-speed play */
  if( vdp50_SendSpeed( rpd,VDP50_NORMAL_PLAY, 1 ) )
    {
      fprintf(stderr,"%s: %s: couldn't set speed\n",
	      rpd->devname,funcname);
      return -1;
    }
  
  if( vdp50_search(rpd,f1,1) )	/* must wait for now */
    {
      fprintf(stderr,"%s: %s: couldn't search to %d\n",
	      rpd->devname,funcname,f1);
      return -1;
    }
  
  vdp50_IntToFrame( f2, endf );
  bcopy( endf, args, 3 );
  for( i=0; i<16; i++ )
    inbytes[i] = 0;
  
  if( !vdp50_ttyio(rpd->fd,VDP50_PLAY_U_PKT,args,wait) )
    {
      if( !wait )
	return 0;
      else
	{	/* since it's a play pkt, we must read the input
		   (see vdp50_ttyio() below) */
	  
	  readnum = vdp50_table[VDP50_ACK_PKT].resp_bytes + 2 +
	    vdp50_table[VDP50_PLAY_U_PKT].resp_bytes + 2;
	  timeout = vdp50_TimeToPlay(len,VDP50_NORMAL_PLAY,1);
	  res = ttyutil_read(rpd->fd,inbytes,readnum,timeout+1000);
	  
	  /*	
	    printf("segplay response:\n");
	    for( i=0; i<readnum; i++ )
	    printf("[%02x] ",inbytes[i]);
	    printf("\n");
	    */
	  if( res == -2 )
	    {
	      fprintf(stderr,"%s: %s: timed out\n",
		      rpd->devname, funcname );
	    }
	  else if( res == -1 )
	    fprintf(stderr,"%s: %s: read error\n",
		    rpd->devname, funcname );
	  else if( res != readnum )
	    fprintf(stderr,"%s: %s: read %d chars, not %d\n",
		    rpd->devname, funcname,res,readnum );
	  else
	    {
	      if( inbytes[0] != 
		 vdp50_table[VDP50_ACK_PKT].resp_code
		 ||
		 inbytes[1] != 
		 vdp50_table[VDP50_ACK_PKT].resp_end )
		{
		  fprintf(stderr,"%s: %s: ACK packet mis-match\n",
			  rpd->devname,funcname);
		  return -1;
		}
	      if( inbytes[2] != 
		 vdp50_table[VDP50_PLAY_U_PKT].resp_code
		 ||
		 inbytes[readnum-1] != 
		 vdp50_table[VDP50_PLAY_U_PKT].resp_end )
		{
		  fprintf(stderr,"%s: %s: PLAY_U packet mis-match\n",
			  rpd->devname,funcname);
		  return -1;
		}
	      /* check for frame-found */
	      if( inbytes[3] & VDP50_FRAME_NOT_FOUND )
		fprintf(stderr,"%s: %s: frame not found\n",
			rpd->devname,funcname );
	      else
		success = 1;
	    }
	}
    }
  
  if( success )
    return(0);
  else
    return -1;
}

/* ------------------------------------------------------------------------ */

vdp50_ttyio( fd, pkt, args, wait )
     
     int	fd;
     int	pkt;
     UBYTE *	args;		/* the argument bytes for the packet */
     int	wait;		/* if true, wait for the reply */
{
  static char *funcname = "vdp50_ttyio";
  static int	retry = 0;
  int	writenum, readnum;
  int	timeout;
  int	num = 0;

  ttyutil_debug = vdp50_debug;
  
  if( vdp50_table[pkt].cmd_code != VDP50_NO_COMMAND )
    {
      
      outbytes[0] = vdp50_table[pkt].cmd_code;
      num = vdp50_table[pkt].arg_bytes;
      if( num )
	bcopy( args, &outbytes[1], num );
      outbytes[1+num] = vdp50_table[pkt].cmd_end;
      
      writenum = num+2;		/* cmd + args + end */
      
      ttyutil_clear(fd);		/* flush input; maybe a mistake ... */
      
      if( ttyutil_write( fd,outbytes,writenum,0 ) == -1 )
	return (-1);
    }
  
  readnum = vdp50_table[pkt].resp_bytes+2;	/* resp + args + end */
  if( readnum == 0 || !wait )
    return (0);
  
  /* caller must pick up the final input on these first four packets;
     this is due to uncertain length of
     timeout (too complicated to do here) */
  
  if( 	pkt == VDP50_SEARCH_PKT ||
     pkt == VDP50_PLAY_U_PKT ||
     pkt == VDP50_PLAY_US_PKT ||
     pkt == VDP50_SCAN_U_PKT )
    {
      return 0;		/* caller must pick up all data */
    }
  else if( pkt == VDP50_LOAD_PKT || pkt == VDP50_UNLOAD_PKT
	  || pkt == VDP50_EJECT_PKT )
    timeout = VDP50_LOAD_TIMEOUT;
  
  else				/* normal timeout (1/4 second) */
    timeout = 250;
  
  if( (num=ttyutil_read(fd,inbytes,readnum,timeout)) == -1 )
    return (-1);
  
  if( num==-2 )	/* timeout condition */
    {
      if( vdp50_debug )
	{
	  if( num == -2 )
	    printf("%s: NO RESPONSE, try %d\n",
		   funcname,retry+1);
	  else
	    printf("%s: ERROR RESPONSE, try %d\n",
		   funcname,retry+1);
	}
      
      if( retry++ < MAXRETRYS )
	{
	  int rv;
	  rv = vdp50_ttyio( fd, pkt, args, wait );
	  retry = 0;
	  return (rv);
	}
      else
	{
	  retry = 0;
	  fprintf(stderr,"%s: i/o timeout\n",funcname);
	  return (-1);
	}
    }
  
  if( num != readnum )
    {
      fprintf(stderr,"%s: expected %d bytes, got %d\n",
	      funcname,readnum,num);
      return -1;
    }
  
  if( inbytes[0] != vdp50_table[pkt].resp_code )
    {
      fprintf(stderr,"%s: response code does not match command\n",
	      funcname );
      return -1;
    }
  
  if( inbytes[num-1] != vdp50_table[pkt].resp_end )
    {
      fprintf(stderr,"%s: response end code does not match command\n",
	      funcname);
      return -1;
    }
  
  return 0;
}

/* ------------------------------------------------------------------------ */

vdp50_setfuncs( disc )
     
     RPD_ptr	disc;
{
  disc->reset = vdp50_reset;
  disc->cmd = vdp50_cmd;
  disc->search = vdp50_search;
  disc->segplay = vdp50_segplay;
  disc->getframe = vdp50_getframe;
  disc->varspeed = vdp50_varspeed;
  disc->jog = vdp50_jog;
  disc->record = NULL;
}
