Logo Search packages:      
Sourcecode: cdrkit version File versions  Download package

drv_philips.c

/*
 * This file has been modified for the cdrkit suite.
 *
 * The behaviour and appearence of the program code below can differ to a major
 * extent from the version distributed by the original author(s).
 *
 * For details, see Changelog file distributed with the cdrkit package. If you
 * received this file from another source then ask the distributing person for
 * a log of modifications.
 *
 */

/* @(#)drv_philips.c    1.69 05/05/16 Copyright 1997-2005 J. Schilling */
/*
 *    CDR device implementation for
 *    Philips/Yamaha/Ricoh/Plasmon
 *
 *    Copyright (c) 1997-2005 J. Schilling
 */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; see the file COPYING.  If not, write to the Free Software
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <mconfig.h>

#include <stdio.h>
#include <unixstd.h>    /* Include sys/types.h to make off_t available */
#include <standard.h>
#include <intcvt.h>
#include <schily.h>

#include <usal/scsireg.h>
#include <usal/scsitransp.h>
#include <usal/usalcmd.h>
#include <usal/scsidefs.h>    /* XXX Only for DEV_RICOH_RO_1060C */

#include "wodim.h"

extern      int   debug;
extern      int   lverbose;

static      int   load_unload_philips(SCSI *usalp, int);
static      int   philips_load(SCSI *usalp, cdr_t *dp);
static      int   philips_unload(SCSI *usalp, cdr_t *dp);
static      int   philips_dumbload(SCSI *usalp, cdr_t *dp);
static      int   philips_dumbunload(SCSI *usalp, cdr_t *dp);
static      int   plasmon_buf(SCSI *, long *, long *);
static      int   recover_philips(SCSI *usalp, cdr_t *dp, int);
static      int   speed_select_yamaha(SCSI *usalp, cdr_t *dp, int *speedp);
static      int   speed_select_philips(SCSI *usalp, cdr_t *dp, int *speedp);
static      int   speed_select_oldphilips(SCSI *usalp, cdr_t *dp, int *speedp);
static      int   speed_select_dumbphilips(SCSI *usalp, cdr_t *dp, int *speedp);
static      int   speed_select_pioneer(SCSI *usalp, cdr_t *dp, int *speedp);
static      int   philips_init(SCSI *usalp, cdr_t *dp);
static      int   philips_getdisktype(SCSI *usalp, cdr_t *dp);
static      BOOL  capacity_philips(SCSI *usalp, long *lp);
static      int   first_writable_addr_philips(SCSI *usalp, long *, int, int, int, 
                                                                                     int);
static      int   next_wr_addr_philips(SCSI *usalp, track_t *trackp, long *ap);
static      int   reserve_track_philips(SCSI *usalp, unsigned long);
static      int   scsi_cdr_write_philips(SCSI *usalp, caddr_t bp, long sectaddr, 
                                                                          long size, int blocks, BOOL islast);
static      int   write_track_info_philips(SCSI *usalp, int);
static      int   write_track_philips(SCSI *usalp, long, int);
static      int   open_track_philips(SCSI *usalp, cdr_t *dp, track_t *trackp);
static      int   open_track_plasmon(SCSI *usalp, cdr_t *dp, track_t *trackp);
static      int   open_track_oldphilips(SCSI *usalp, cdr_t *dp, track_t *trackp);
static      int   open_track_yamaha(SCSI *usalp, cdr_t *dp, track_t *trackp);
static      int   close_track_philips(SCSI *usalp, cdr_t *dp, track_t *trackp);
static      int   fixation_philips(SCSI *usalp, cdr_t *dp, track_t *trackp);

static      int   philips_attach(SCSI *usalp, cdr_t *);
static      int   plasmon_attach(SCSI *usalp, cdr_t *);
static      int   ricoh_attach(SCSI *usalp, cdr_t *);
static      int   philips_getlilo(SCSI *usalp, long *lilenp, long *lolenp);


struct cdd_52x_mode_page_21 { /* write track information */
            MP_P_CODE;        /* parsave & pagecode */
      Uchar p_len;                  /* 0x0E = 14 Bytes */
      Uchar res_2;
      Uchar sectype;
      Uchar track;
      Uchar ISRC[9];
      Uchar res[2];
};

struct cdd_52x_mode_page_23 { /* speed selection */
            MP_P_CODE;        /* parsave & pagecode */
      Uchar p_len;                  /* 0x06 = 6 Bytes */
      Uchar speed;
      Uchar dummy;
      Uchar res[4];

};

#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */

struct yamaha_mode_page_31 {  /* drive configuration */
            MP_P_CODE;        /* parsave & pagecode */
      Uchar p_len;                  /* 0x02 = 2 Bytes */
      Uchar res;
      Ucbit dummy       : 4;
      Ucbit speed       : 4;
};

#else                   /* Motorola byteorder */

struct yamaha_mode_page_31 {  /* drive configuration */
            MP_P_CODE;        /* parsave & pagecode */
      Uchar p_len;                  /* 0x02 = 2 Bytes */
      Uchar res;
      Ucbit speed       : 4;
      Ucbit dummy       : 4;
};
#endif

struct cdd_52x_mode_data {
      struct scsi_mode_header header;
      union cdd_pagex   {
            struct cdd_52x_mode_page_21   page21;
            struct cdd_52x_mode_page_23   page23;
            struct yamaha_mode_page_31    page31;
      } pagex;
};


cdr_t cdr_philips_cdd521O = {
      0, 0,
      CDR_TAO|CDR_TRAYLOAD,
      CDR_CDRW_NONE,
      2, 2,
      "philips_cdd521_old",
      "driver for Philips old CDD-521",
      0,
      (dstat_t *)0,
      drive_identify,
      philips_attach,
      philips_init,
      philips_getdisktype,
      philips_load,
      philips_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_oldphilips,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_oldphilips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_philips_dumb = {
      0, 0,
      CDR_TAO|CDR_TRAYLOAD,
      CDR_CDRW_NONE,
      2, 2,
      "philips_dumb",
      "driver for Philips CDD-521 with pessimistic assumptions",
      0,
      (dstat_t *)0,
      drive_identify,
      philips_attach,
      philips_init,
      philips_getdisktype,
      philips_dumbload,
      philips_dumbunload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_dumbphilips,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_oldphilips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_philips_cdd521 = {
      0, 0,
      CDR_TAO|CDR_TRAYLOAD,
      CDR_CDRW_NONE,
      2, 2,
      "philips_cdd521",
      "driver for Philips CDD-521",
      0,
      (dstat_t *)0,
      drive_identify,
      philips_attach,
      philips_init,
      philips_getdisktype,
      philips_load,
      philips_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_philips,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_philips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_philips_cdd522 = {
      0, 0,
/*    CDR_TAO|CDR_SAO|CDR_TRAYLOAD,*/
      CDR_TAO|CDR_TRAYLOAD,
      CDR_CDRW_NONE,
      2, 2,
      "philips_cdd522",
      "driver for Philips CDD-522",
      0,
      (dstat_t *)0,
      drive_identify,
      philips_attach,
      philips_init,
      philips_getdisktype,
      philips_load,
      philips_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_philips,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_philips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_tyuden_ew50 = {
      0, 0,
      CDR_TAO|CDR_TRAYLOAD|CDR_SWABAUDIO,
      CDR_CDRW_NONE,
      2, 2,
      "tyuden_ew50",
      "driver for Taiyo Yuden EW-50",
      0,
      (dstat_t *)0,
      drive_identify,
      philips_attach,
      philips_init,
      philips_getdisktype,
      philips_load,
      philips_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_philips,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_philips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_kodak_pcd600 = {
      0, 0,
      CDR_TAO|CDR_TRAYLOAD,
      CDR_CDRW_NONE,
      6, 6,
      "kodak_pcd_600",
      "driver for Kodak PCD-600",
      0,
      (dstat_t *)0,
      drive_identify,
      philips_attach,
      philips_init,
      philips_getdisktype,
      philips_load,
      philips_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_philips,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_oldphilips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_plasmon_rf4100 = {
      0, 0,
      CDR_TAO|CDR_TRAYLOAD,
      CDR_CDRW_NONE,
      2, 4,
      "plasmon_rf4100",
      "driver for Plasmon RF 4100",
      0,
      (dstat_t *)0,
      drive_identify,
      plasmon_attach,
      philips_init,
      philips_getdisktype,
      philips_load,
      philips_unload,
      plasmon_buf,
      recovery_needed,
      recover_philips,
      speed_select_philips,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_plasmon,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_pioneer_dw_s114x = {
      0, 0,
      CDR_TAO|CDR_TRAYLOAD|CDR_SWABAUDIO,
      CDR_CDRW_NONE,
      2, 4,
      "pioneer_dws114x",
      "driver for Pioneer DW-S114X",
      0,
      (dstat_t *)0,
      drive_identify,
      philips_attach,
      philips_init,
      philips_getdisktype,
      scsi_load,
      scsi_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_pioneer,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
/*    open_track_yamaha,*/
/*???*/     open_track_oldphilips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_yamaha_cdr100 = {
      0, 0,
/*    CDR_TAO|CDR_SAO|CDR_CADDYLOAD|CDR_SWABAUDIO,*/
      CDR_TAO|CDR_CADDYLOAD|CDR_SWABAUDIO,
      CDR_CDRW_NONE,
      2, 4,
      "yamaha_cdr100",
      "driver for Yamaha CDR-100 / CDR-102",
      0,
      (dstat_t *)0,
      drive_identify,
      philips_attach,
      philips_init,
      drive_getdisktype,
      scsi_load,
      philips_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_yamaha,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_yamaha,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_ricoh_ro1060 = {
      0, 0,
/*    CDR_TAO|CDR_SAO|CDR_CADDYLOAD,*/
      CDR_TAO|CDR_CADDYLOAD,
      CDR_CDRW_NONE,
      2, 2,
      "ricoh_ro1060c",
      "driver for Ricoh RO-1060C",
      0,
      (dstat_t *)0,
      drive_identify,
      ricoh_attach,
      philips_init,
      philips_getdisktype,
      scsi_load,
      scsi_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_yamaha,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_philips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};

cdr_t cdr_ricoh_ro1420 = {
      0, 0,
/*    CDR_TAO|CDR_SAO|CDR_CADDYLOAD,*/
      CDR_TAO|CDR_CADDYLOAD,
      CDR_CDRW_NONE,
      2, 2,
      "ricoh_ro1420c",
      "driver for Ricoh RO-1420C",
      0,
      (dstat_t *)0,
      drive_identify,
      ricoh_attach,
      philips_init,
      philips_getdisktype,
      scsi_load,
      scsi_unload,
      buf_dummy,
      recovery_needed,
      recover_philips,
      speed_select_yamaha,
      select_secsize,
      next_wr_addr_philips,
      reserve_track_philips,
      scsi_cdr_write_philips,
      (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
      no_sendcue,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
      open_track_philips,
      close_track_philips,
      (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
      cmd_dummy,
      cmd_dummy,                          /* abort    */
      read_session_offset_philips,
      fixation_philips,
      cmd_dummy,                          /* stats    */
      blank_dummy,
      format_dummy,
      (int(*)(SCSI *, caddr_t, int, int))NULL,  /* no OPC   */
      cmd_dummy,                          /* opt1           */
      cmd_dummy,                          /* opt2           */
};


static int load_unload_philips(SCSI *usalp, int load)
{
      register struct   usal_cmd    *scmd = usalp->scmd;

      fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
      scmd->flags = SCG_DISRE_ENA;
      scmd->cdb_len = SC_G1_CDBLEN;
      scmd->sense_len = CCS_SENSE_LEN;
      scmd->cdb.g1_cdb.cmd = 0xE7;
      scmd->cdb.g1_cdb.lun = usal_lun(usalp);
      scmd->cdb.g1_cdb.count[1] = !load;

      usalp->cmdname = "philips medium load/unload";

      if (usal_cmd(usalp) < 0)
            return (-1);
      return (0);
}

static int 
philips_load(SCSI *usalp, cdr_t *dp)
{
      return (load_unload_philips(usalp, 1));
}

static int 
philips_unload(SCSI *usalp, cdr_t *dp)
{
      return (load_unload_philips(usalp, 0));
}

static int 
philips_dumbload(SCSI *usalp, cdr_t *dp)
{
      int   ret;

      usalp->silent++;
      ret = load_unload_philips(usalp, 1);
      usalp->silent--;
      if (ret < 0)
            return (scsi_load(usalp, dp));
      return (0);
}

static int 
philips_dumbunload(SCSI *usalp, cdr_t *dp)
{
      int   ret;

      usalp->silent++;
      ret = load_unload_philips(usalp, 0);
      usalp->silent--;
      if (ret < 0)
            return (scsi_unload(usalp, dp));
      return (0);
}

static int 
plasmon_buf(SCSI *usalp, 
            long *sp /* Size pointer */, 
            long *fp /* Free space pointer */)
{
      /*
       * There's no way to obtain these values from the
       * Plasmon RF41xx devices.  This function stub is only
       * present to prevent cdrecord.c from calling the READ BUFFER
       * SCSI cmd which is implemented non standard compliant in
       * the Plasmon drive. Calling READ BUFFER would only jam the Plasmon
       * as the non standard implementation in the Plasmon firmware
       * expects different parameters.
       */

      if (sp)
            *sp = 0L;
      if (fp)
            *fp = 0L;

      return (100);     /* 100 % */
}

static int 
recover_philips(SCSI *usalp, cdr_t *dp, int track)
{
      register struct   usal_cmd    *scmd = usalp->scmd;

      fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
      scmd->flags = SCG_DISRE_ENA;
      scmd->cdb_len = SC_G1_CDBLEN;
      scmd->sense_len = CCS_SENSE_LEN;
      scmd->cdb.g1_cdb.cmd = 0xEC;
      scmd->cdb.g1_cdb.lun = usal_lun(usalp);

      usalp->cmdname = "philips recover";

      if (usal_cmd(usalp) < 0)
            return (-1);
      return (0);
}

static int 
speed_select_yamaha(SCSI *usalp, cdr_t *dp, int *speedp)
{
      struct      scsi_mode_page_header   *mp;
      char                    mode[256];
      int                     len = 16;
      int                     page = 0x31;
      struct yamaha_mode_page_31    *xp;
      struct cdd_52x_mode_data md;
      int   count;
      int   speed = 1;
      BOOL  dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;

      if (speedp) {
            speed = *speedp;
      } else {
            fillbytes((caddr_t)mode, sizeof (mode), '\0');

            if (!get_mode_params(usalp, page, "Speed/Dummy information",
                  (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
                  return (-1);
            }
            if (len == 0)
                  return (-1);

            mp = (struct scsi_mode_page_header *)
                  (mode + sizeof (struct scsi_mode_header) +
                  ((struct scsi_mode_header *)mode)->blockdesc_len);

            xp = (struct yamaha_mode_page_31 *)mp;
            speed = xp->speed;
      }

      fillbytes((caddr_t)&md, sizeof (md), '\0');

      count  = sizeof (struct scsi_mode_header) +
            sizeof (struct yamaha_mode_page_31);

      speed >>= 1;
      md.pagex.page31.p_code = 0x31;
      md.pagex.page31.p_len =  0x02;
      md.pagex.page31.speed = speed;
      md.pagex.page31.dummy = dummy?1:0;

      return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
}

static int 
speed_select_philips(SCSI *usalp, cdr_t *dp, int *speedp)
{
      struct      scsi_mode_page_header   *mp;
      char                    mode[256];
      int                     len = 20;
      int                     page = 0x23;
      struct cdd_52x_mode_page_23   *xp;
      struct cdd_52x_mode_data      md;
      int                     count;
      int                     speed = 1;
      BOOL                    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;

      if (speedp) {
            speed = *speedp;
      } else {
            fillbytes((caddr_t)mode, sizeof (mode), '\0');

            if (!get_mode_params(usalp, page, "Speed/Dummy information",
                  (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
                  return (-1);
            }
            if (len == 0)
                  return (-1);

            mp = (struct scsi_mode_page_header *)
                  (mode + sizeof (struct scsi_mode_header) +
                  ((struct scsi_mode_header *)mode)->blockdesc_len);

            xp = (struct cdd_52x_mode_page_23 *)mp;
            speed = xp->speed;
      }

      fillbytes((caddr_t)&md, sizeof (md), '\0');

      count  = sizeof (struct scsi_mode_header) +
            sizeof (struct cdd_52x_mode_page_23);

      md.pagex.page23.p_code = 0x23;
      md.pagex.page23.p_len =  0x06;
      md.pagex.page23.speed = speed;
      md.pagex.page23.dummy = dummy?1:0;

      return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
}

static int 
speed_select_pioneer(SCSI *usalp, cdr_t *dp, int *speedp)
{
      if (speedp != 0 && *speedp < 2) {
            *speedp = 2;
            if (lverbose)
                  printf("WARNING: setting to minimum speed (2).\n");
      }
      return (speed_select_philips(usalp, dp, speedp));
}

static int 
speed_select_oldphilips(SCSI *usalp, cdr_t *dp, int *speedp)
{
      BOOL  dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;

      if (lverbose)
            printf("WARNING: ignoring selected speed.\n");
      if (dummy) {
            errmsgno(EX_BAD, "Cannot set dummy writing for this device.\n");
            return (-1);
      }
      return (0);
}

static int 
speed_select_dumbphilips(SCSI *usalp, cdr_t *dp, int *speedp)
{
      if (speed_select_philips(usalp, dp, speedp) < 0)
            return (speed_select_oldphilips(usalp, dp, speedp));
      return (0);
}

static int 
philips_init(SCSI *usalp, cdr_t *dp)
{
      return ((*dp->cdr_set_speed_dummy)(usalp, dp, NULL));
}


#define     IS(what, flag)    printf("  Is %s%s\n", flag?"":"not ", what);

static int 
philips_getdisktype(SCSI *usalp, cdr_t *dp)
{
      dstat_t     *dsp = dp->cdr_dstat;
      char  sbuf[16];
      long  dummy;
      long  lilen;
      long  lolen;
      msf_t msf;
      int   audio = -1;

      usalp->silent++;
      dummy = (*dp->cdr_next_wr_address)(usalp, (track_t *)0, &lilen);
      usalp->silent--;

      /*
       * Check for "Command sequence error" first.
       */
      if ((dsp->ds_cdrflags & RF_WRITE) != 0 &&
          dummy < 0 &&
          (usal_sense_key(usalp) != SC_ILLEGAL_REQUEST ||
                                    usal_sense_code(usalp) != 0x2C)) {
            reload_media(usalp, dp);
      }

      usalp->silent++;
      if (read_subchannel(usalp, sbuf, 0, 12, 0, 1, 0xf0) >= 0) {
            if (sbuf[2] == 0 && sbuf[3] == 8)
                  audio = (sbuf[7] & 0x40) != 0;
      }
      usalp->silent--;

      if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 &&
                                    dummy >= 0 && lilen == 0) {
            usalp->silent++;
            dummy = philips_getlilo(usalp, &lilen, &lolen);
            usalp->silent--;

            if (dummy >= 0) {
/*                printf("lead-in len: %d lead-out len: %d\n", lilen, lolen);*/
                  lba_to_msf(-150 - lilen, &msf);

                  printf("ATIP info from disk:\n");
                  if (audio >= 0)
                        IS("unrestricted", audio);
                  if (audio == 1 || (audio == 0 && (sbuf[7] & 0x3F) != 0x3F))
                        printf("  Disk application code: %d\n", sbuf[7] & 0x3F);
                  printf("  ATIP start of lead in:  %ld (%02d:%02d/%02d)\n",
                        -150 - lilen, msf.msf_min, msf.msf_sec, msf.msf_frame);

                  if (capacity_philips(usalp, &lolen)) {
                        lba_to_msf(lolen, &msf);
                        printf(
                        "  ATIP start of lead out: %ld (%02d:%02d/%02d)\n",
                        lolen, msf.msf_min, msf.msf_sec, msf.msf_frame);
                  }
                  lba_to_msf(-150 - lilen, &msf);
                  pr_manufacturer(&msf,
                              FALSE,            /* Always not erasable */
                              audio > 0); /* Audio from read subcode */
            }
      }

      if (capacity_philips(usalp, &lolen)) {
            dsp->ds_maxblocks = lolen;
            dsp->ds_maxrblocks = disk_rcap(&msf, dsp->ds_maxblocks,
                              FALSE,            /* Always not erasable */
                              audio > 0); /* Audio from read subcode */
      }
      usalp->silent++;
      /*read_subchannel(usalp, bp, track, cnt, msf, subq, fmt); */

      if (read_subchannel(usalp, sbuf, 0, 14, 0, 0, 0xf1) >= 0)
            usal_prbytes("Disk bar code:", (Uchar *)sbuf, 14 - usal_getresid(usalp));
      usalp->silent--;

      return (drive_getdisktype(usalp, dp));
}

static BOOL 
capacity_philips(SCSI *usalp, long *lp)
{
      long  l = 0L;
      BOOL  succeed = TRUE;

      usalp->silent++;
      if (read_B0(usalp, FALSE, NULL, &l) >= 0) {
            if (debug)
                  printf("lead out B0: %ld\n", l);
            *lp = l;
      } else if (read_trackinfo(usalp, 0xAA, &l, NULL, NULL, NULL, NULL) >= 0) {
            if (debug)
                  printf("lead out AA: %ld\n", l);
            *lp = l;
      } if (read_capacity(usalp) >= 0) {
            l = usalp->cap->c_baddr + 1;
            if (debug)
                  printf("lead out capacity: %ld\n", l);
      } else {
            succeed = FALSE;
      }
      *lp = l;
      usalp->silent--;
      return (succeed);
}

struct      fwa {
      char  len;
      char  addr[4];
      char  res;
};

static int 
first_writable_addr_philips(SCSI *usalp, long *ap, int track, int isaudio, 
                                                            int preemp, int npa)
{
      struct      fwa   fwa;
      register struct   usal_cmd    *scmd = usalp->scmd;

      fillbytes((caddr_t)&fwa, sizeof (fwa), '\0');
      fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
      scmd->addr = (caddr_t)&fwa;
      scmd->size = sizeof (fwa);
      scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
      scmd->cdb_len = SC_G1_CDBLEN;
      scmd->sense_len = CCS_SENSE_LEN;
      scmd->cdb.g1_cdb.cmd = 0xE2;
      scmd->cdb.g1_cdb.lun = usal_lun(usalp);
      scmd->cdb.g1_cdb.addr[0] = track;
      scmd->cdb.g1_cdb.addr[1] = isaudio ? (preemp ? 5 : 4) : 1;

      scmd->cdb.g1_cdb.count[0] = npa?1:0;
      scmd->cdb.g1_cdb.count[1] = sizeof (fwa);

      usalp->cmdname = "first writeable address philips";

      if (usal_cmd(usalp) < 0)
            return (-1);

      if (ap)
            *ap = a_to_4_byte(fwa.addr);
      return (0);
}

static int 
next_wr_addr_philips(SCSI *usalp, track_t *trackp, long *ap)
{

/*    if (first_writable_addr_philips(usalp, ap, 0, 0, 0, 1) < 0)*/
      if (first_writable_addr_philips(usalp, ap, 0, 0, 0, 0) < 0)
            return (-1);
      return (0);
}

static int 
reserve_track_philips(SCSI *usalp, unsigned long len)
{
      register struct   usal_cmd    *scmd = usalp->scmd;

      fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
      scmd->flags = SCG_DISRE_ENA;
      scmd->cdb_len = SC_G1_CDBLEN;
      scmd->sense_len = CCS_SENSE_LEN;
      scmd->cdb.g1_cdb.cmd = 0xE4;
      scmd->cdb.g1_cdb.lun = usal_lun(usalp);
      i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], len);

      usalp->cmdname = "philips reserve_track";

      if (usal_cmd(usalp) < 0)
            return (-1);
      return (0);
}

static int 
scsi_cdr_write_philips(SCSI *usalp, 
                       caddr_t bp       /* address of buffer */,
                       long sectaddr    /* disk address (sector) to put */,
                       long size        /* number of bytes to transfer */, 
                       int blocks       /* sector count */, 
                       BOOL islast      /* last write for track */)
{
      return (write_xg0(usalp, bp, 0, size, blocks));
}

static int 
write_track_info_philips(SCSI *usalp, int sectype)
{
      struct cdd_52x_mode_data md;
      int   count = sizeof (struct scsi_mode_header) +
                  sizeof (struct cdd_52x_mode_page_21);

      fillbytes((caddr_t)&md, sizeof (md), '\0');
      md.pagex.page21.p_code = 0x21;
      md.pagex.page21.p_len =  0x0E;
                        /* is sectype ok ??? */
      md.pagex.page21.sectype = sectype & ST_MASK;
      md.pagex.page21.track = 0;    /* 0 : create new track */

      return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
}

static int 
write_track_philips(SCSI *usalp, 
                                          long track /* track number 0 == new track */, 
                        int sectype)
{
      register struct   usal_cmd    *scmd = usalp->scmd;

      fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
      scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
/*    scmd->flags = SCG_DISRE_ENA;*/
      scmd->cdb_len = SC_G1_CDBLEN;
      scmd->sense_len = CCS_SENSE_LEN;
      scmd->cdb.g1_cdb.cmd = 0xE6;
      scmd->cdb.g1_cdb.lun = usal_lun(usalp);
      g1_cdbaddr(&scmd->cdb.g1_cdb, track);
      scmd->cdb.g1_cdb.res6 = sectype & ST_MASK;

      usalp->cmdname = "philips write_track";

      if (usal_cmd(usalp) < 0)
            return (-1);
      return (0);
}

static int 
open_track_philips(SCSI *usalp, cdr_t *dp, track_t *trackp)
{
      if (select_secsize(usalp, trackp->secsize) < 0)
            return (-1);

      if (write_track_info_philips(usalp, trackp->sectype) < 0)
            return (-1);

      if (write_track_philips(usalp, 0, trackp->sectype) < 0)
            return (-1);

      return (0);
}

static int 
open_track_plasmon(SCSI *usalp, cdr_t *dp, track_t *trackp)
{
      if (select_secsize(usalp, trackp->secsize) < 0)
            return (-1);

      if (write_track_info_philips(usalp, trackp->sectype) < 0)
            return (-1);

      return (0);
}

static int 
open_track_oldphilips(SCSI *usalp, cdr_t *dp, track_t *trackp)
{
      if (write_track_philips(usalp, 0, trackp->sectype) < 0)
            return (-1);

      return (0);
}

static int 
open_track_yamaha(SCSI *usalp, cdr_t *dp, track_t *trackp)
{
      if (select_secsize(usalp, trackp->secsize) < 0)
            return (-1);

      if (write_track_philips(usalp, 0, trackp->sectype) < 0)
            return (-1);

      return (0);
}

static int 
close_track_philips(SCSI *usalp, cdr_t *dp, track_t *trackp)
{
      return (scsi_flush_cache(usalp, FALSE));
}

static int fixation_philips(SCSI *usalp, cdr_t *dp, track_t *trackp)
{
      register struct   usal_cmd    *scmd = usalp->scmd;

      fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
      scmd->flags = SCG_DISRE_ENA;
      scmd->cdb_len = SC_G1_CDBLEN;
      scmd->sense_len = CCS_SENSE_LEN;
      scmd->timeout = 8 * 60;       /* Needs up to 4 minutes */
      scmd->cdb.g1_cdb.cmd = 0xE9;
      scmd->cdb.g1_cdb.lun = usal_lun(usalp);
      scmd->cdb.g1_cdb.count[1] =
                  ((track_base(trackp)->tracktype & TOCF_MULTI) ? 8 : 0) |
                  (track_base(trackp)->tracktype & TOC_MASK);

      usalp->cmdname = "philips fixation";

      if (usal_cmd(usalp) < 0)
            return (-1);
      return (0);
}

static const char *sd_cdd_521_error_str[] = {
      "\003\000tray out",                       /* 0x03 */
      "\062\000write data error with CU",       /* 0x32 */  /* Yamaha */
      "\063\000monitor atip error",             /* 0x33 */
      "\064\000absorbtion control error",       /* 0x34 */
#ifdef      YAMAHA_CDR_100
      /* Is this the same ??? */
      "\120\000write operation in progress",          /* 0x50 */
#endif
      "\127\000unable to read TOC/PMA/Subcode/ATIP",  /* 0x57 */
      "\132\000operator medium removal request",      /* 0x5a */
      "\145\000verify failed",                  /* 0x65 */
      "\201\000illegal track number",                 /* 0x81 */
      "\202\000command now not valid",          /* 0x82 */
      "\203\000medium removal is prevented",          /* 0x83 */
      "\204\000tray out",                       /* 0x84 */
      "\205\000track at one not in PMA",        /* 0x85 */
      "\240\000stopped on non data block",            /* 0xa0 */
      "\241\000invalid start adress",                 /* 0xa1 */
      "\242\000attampt to cross track-boundary",      /* 0xa2 */
      "\243\000illegal medium",                 /* 0xa3 */
      "\244\000disk write protected",                 /* 0xa4 */
      "\245\000application code conflict",            /* 0xa5 */
      "\246\000illegal blocksize for command",  /* 0xa6 */
      "\247\000blocksize conflict",             /* 0xa7 */
      "\250\000illegal transfer length",        /* 0xa8 */
      "\251\000request for fixation failed",          /* 0xa9 */
      "\252\000end of medium reached",          /* 0xaa */
#ifdef      REAL_CDD_521
      "\253\000non reserved reserved track",          /* 0xab */
#else
      "\253\000illegal track number",                 /* 0xab */
#endif
      "\254\000data track length error",        /* 0xac */
      "\255\000buffer under run",               /* 0xad */
      "\256\000illegal track mode",             /* 0xae */
      "\257\000optical power calibration error",      /* 0xaf */
      "\260\000calibration area almost full",         /* 0xb0 */
      "\261\000current program area empty",           /* 0xb1 */
      "\262\000no efm at search address",       /* 0xb2 */
      "\263\000link area encountered",          /* 0xb3 */
      "\264\000calibration area full",          /* 0xb4 */
      "\265\000dummy data blocks added",        /* 0xb5 */
      "\266\000block size format conflict",           /* 0xb6 */
      "\267\000current command aborted",        /* 0xb7 */
      "\270\000program area not empty",         /* 0xb8 */
#ifdef      YAMAHA_CDR_100
      /* Used while writing lead in in DAO */
      "\270\000write leadin in progress",       /* 0xb8 */
#endif
      "\271\000parameter list too large",       /* 0xb9 */
      "\277\000buffer overflow",                /* 0xbf */  /* Yamaha */
      "\300\000no barcode available",                 /* 0xc0 */
      "\301\000barcode reading error",          /* 0xc1 */
      "\320\000recovery needed",                /* 0xd0 */
      "\321\000cannot recover track",                 /* 0xd1 */
      "\322\000cannot recover pma",             /* 0xd2 */
      "\323\000cannot recover leadin",          /* 0xd3 */
      "\324\000cannot recover leadout",         /* 0xd4 */
      "\325\000cannot recover opc",             /* 0xd5 */
      "\326\000eeprom failure",                 /* 0xd6 */
      "\340\000laser current over",             /* 0xe0 */  /* Yamaha */
      "\341\000servo adjustment over",          /* 0xe0 */  /* Yamaha */
      NULL
};

static const char *sd_ro1420_error_str[] = {
      "\004\000logical unit is in process of becoming ready", /* 04 00 */
      "\011\200radial skating error",                       /* 09 80 */
      "\011\201sledge servo failure",                       /* 09 81 */
      "\011\202pll no lock",                          /* 09 82 */
      "\011\203servo off track",                      /* 09 83 */
      "\011\204atip sync error",                      /* 09 84 */
      "\011\205atip/subcode jumped error",                  /* 09 85 */
      "\127\300subcode not found",                    /* 57 C0 */
      "\127\301atip not found",                       /* 57 C1 */
      "\127\302no atip or subcode",                   /* 57 C2 */
      "\127\303pma error",                            /* 57 C3 */
      "\127\304toc read error",                       /* 57 C4 */
      "\127\305disk informatoion error",              /* 57 C5 */
      "\144\200read in leadin",                       /* 64 80 */
      "\144\201read in leadout",                      /* 64 81 */
      "\201\000illegal track",                        /* 81 00 */
      "\202\000command not now valid",                /* 82 00 */
      "\220\000reserve track check error",                  /* 90 00 */
      "\220\001verify blank error",                   /* 90 01 */
      "\221\001mode of last track error",             /* 91 01 */
      "\222\000header search error",                        /* 92 00 */
      "\230\001header monitor error",                       /* 98 01 */
      "\230\002edc error",                            /* 98 02 */
      "\230\003read link, run-in run-out",                  /* 98 03 */
      "\230\004last one block error",                       /* 98 04 */
      "\230\005illegal blocksize",                    /* 98 05 */
      "\230\006not all data transferred",             /* 98 06 */
      "\230\007cdbd over run error",                        /* 98 07 */
      "\240\000stopped on non_data block",                  /* A0 00 */
      "\241\000invalid start address",                /* A1 00 */
      "\243\000illegal medium",                       /* A3 00 */
      "\246\000illegal blocksize for command",        /* A6 00 */
      "\251\000request for fixation failed",                /* A9 00 */
      "\252\000end of medium reached",                /* AA 00 */
      "\253\000illegal track number",                       /* AB 00 */
      "\255\000buffer underrun",                      /* AD 00 */
      "\256\000illegal track mode",                   /* AE 00 */
      "\257\200power range error",                    /* AF 80 */
      "\257\201moderation error",                     /* AF 81 */
      "\257\202beta upper range error",               /* AF 82 */
      "\257\203beta lower range error",               /* AF 83 */
      "\257\204alpha upper range error",              /* AF 84 */
      "\257\205alpha lower range error",              /* AF 85 */
      "\257\206alpha and power range error",                /* AF 86 */
      "\260\000calibration area almost full",               /* B0 00 */
      "\261\000current program area empty",                 /* B1 00 */
      "\262\000no efm at search address",             /* B2 00 */
      "\264\000calibration area full",                /* B4 00 */
      "\265\000dummy blocks added",                   /* B5 00 */
      "\272\000write audio on reserved track",        /* BA 00 */
      "\302\200syscon rom error",                     /* C2 80 */
      "\302\201syscon ram error",                     /* C2 81 */
      "\302\220efm encoder error",                    /* C2 90 */
      "\302\221efm decoder error",                    /* C2 91 */
      "\302\222servo ic error",                       /* C2 92 */
      "\302\223motor controller error",               /* C2 93 */
      "\302\224dac error",                            /* C2 94 */
      "\302\225syscon eeprom error",                        /* C2 95 */
      "\302\240block decoder communication error",          /* C2 A0 */
      "\302\241block encoder communication error",          /* C2 A1 */
      "\302\242block encoder/decoder path error",           /* C2 A2 */
      "\303\000CD-R engine selftest error",                 /* C3 xx */
      "\304\000buffer parity error",                        /* C4 00 */
      "\305\000data transfer error",                        /* C5 00 */
      "\340\00012V failure",                          /* E0 00 */
      "\341\000undefined syscon error",               /* E1 00 */
      "\341\001syscon communication error",                 /* E1 01 */
      "\341\002unknown syscon error",                       /* E1 02 */
      "\342\000syscon not ready",                     /* E2 00 */
      "\343\000command rejected",                     /* E3 00 */
      "\344\000command not accepted",                       /* E4 00 */
      "\345\000verify error at beginning of track",         /* E5 00 */
      "\345\001verify error at ending of track",            /* E5 01 */
      "\345\002verify error at beginning of lead-in",       /* E5 02 */
      "\345\003verify error at ending of lead-in",          /* E5 03 */
      "\345\004verify error at beginning of lead-out",      /* E5 04 */
      "\345\005verify error at ending of lead-out",         /* E5 05 */
      "\377\000command phase timeout error",                /* FF 00 */
      "\377\001data in phase timeout error",                /* FF 01 */
      "\377\002data out phase timeout error",               /* FF 02 */
      "\377\003status phase timeout error",                 /* FF 03 */
      "\377\004message in phase timeout error",       /* FF 04 */
      "\377\005message out phase timeout error",            /* FF 05 */
      NULL
};

static int 
philips_attach(SCSI *usalp, cdr_t *dp)
{
      usal_setnonstderrs(usalp, sd_cdd_521_error_str);
      return (0);
}

static int 
plasmon_attach(SCSI *usalp, cdr_t *dp)
{
      usalp->inq->data_format = 1;  /* Correct the ly */

      usal_setnonstderrs(usalp, sd_cdd_521_error_str);
      return (0);
}

static int 
ricoh_attach(SCSI *usalp, cdr_t *dp)
{
      if (dp == &cdr_ricoh_ro1060) {
            errmsgno(EX_BAD, "No support for Ricoh RO-1060C\n");
            return (-1);
      }
      usal_setnonstderrs(usalp, sd_ro1420_error_str);
      return (0);
}

static int 
philips_getlilo(SCSI *usalp, long *lilenp, long *lolenp)
{
      char  buf[4];
      long  li, lo;
      register struct   usal_cmd    *scmd = usalp->scmd;

      fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
      scmd->addr = buf;
      scmd->size = sizeof (buf);
      scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
      scmd->cdb_len = SC_G1_CDBLEN;
      scmd->sense_len = CCS_SENSE_LEN;
      scmd->cdb.g1_cdb.cmd = 0xEE;  /* Read session info */
      scmd->cdb.g1_cdb.lun = usal_lun(usalp);
      g1_cdblen(&scmd->cdb.g1_cdb, sizeof (buf));

      usalp->cmdname = "philips read session info";

      if (usal_cmd(usalp) < 0)
            return (-1);

      if (usalp->verbose)
            usal_prbytes("Session info data: ", (Uchar *)buf, sizeof (buf) - usal_getresid(usalp));

      li = a_to_u_2_byte(buf);
      lo = a_to_u_2_byte(&buf[2]);

      if (lilenp)
            *lilenp = li;
      if (lolenp)
            *lolenp = lo;

      return (0);
}

Generated by  Doxygen 1.6.0   Back to index