📄 drv_jvc.c
字号:
/** @(#)drv_jvc.c 1.46 99/10/17 Copyright 1997 J. Schilling */#ifndef lintstatic char sccsid[] = "@(#)drv_jvc.c 1.46 99/10/17 Copyright 1997 J. Schilling";#endif/* * CDR device implementation for * JVC/TEAC * * Copyright (c) 1997 J. Schilling *//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * 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, 675 Mass Ave, Cambridge, MA 02139, USA. *//*#define XXDEBUG*//*#define XXBUFFER*/#include <mconfig.h>#include <stdio.h>#include <standard.h>#include <fctldefs.h>#include <errno.h>#include <strdefs.h>#include <unixstd.h>#ifdef XXDEBUG#include <stdxlib.h>#endif#include <utypes.h>#include <btorder.h>#include <intcvt.h>#include <scg/scgcmd.h>#include <scg/scsidefs.h>#include <scg/scsireg.h>#include <scg/scsitransp.h>#include "cdrecord.h"/* just a hack */long lba_addr;BOOL last_done;/* * macros for building MSF values from LBA */#define LBA_MIN(x) ((x)/(60*75))#define LBA_SEC(x) (((x)%(60*75))/75)#define LBA_FRM(x) ((x)%75)#define MSF_CONV(a) ((((a)%100)/10)*16 + ((a)%10))extern int lverbose;#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */struct teac_mode_page_21 { /* teac dummy selection */ MP_P_CODE; /* parsave & pagecode */ u_char p_len; /* 0x01 = 1 Byte */ Ucbit dummy : 2; Ucbit res : 6;};#elsestruct teac_mode_page_21 { /* teac dummy selection */ MP_P_CODE; /* parsave & pagecode */ u_char p_len; /* 0x01 = 1 Byte */ Ucbit res : 6; Ucbit dummy : 2;};#endifstruct teac_mode_page_31 { /* teac speed selection */ MP_P_CODE; /* parsave & pagecode */ u_char p_len; /* 0x02 = 2 Byte */ u_char speed; u_char res;};struct cdd_52x_mode_data { struct scsi_mode_header header; union cdd_pagex { struct teac_mode_page_21 teac_page21; struct teac_mode_page_31 teac_page31; } pagex;};#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */struct pgm_subcode { /* subcode for progam area */ u_char subcode; Ucbit addr : 4; Ucbit control : 4; u_char track; u_char index;};#elsestruct pgm_subcode { /* subcode for progam area */ u_char subcode; Ucbit control : 4; Ucbit addr : 4; u_char track; u_char index;};#endif#define set_pgm_subcode(sp, t, c, a, tr, idx) (\ (sp)->subcode = (t), \ (sp)->control = (c), \ (sp)->addr = (a), \ (sp)->track = MSF_CONV(tr), \ (sp)->index = (idx))#define SC_P 1 /* Subcode defines pre-gap (Pause) */#define SC_TR 0 /* Subcode defines track data */#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */typedef struct lin_subcode { /* subcode for lead in area */ Ucbit addr : 4; Ucbit control : 4; u_char track; u_char msf[3];} lsc_t;#elsetypedef struct lin_subcode { /* subcode for lead in area */ Ucbit control : 4; Ucbit addr : 4; u_char track; u_char msf[3];} lsc_t;#endif#define set_toc_subcode(sp, c, a, tr, bno) (\ ((lsc_t *)sp)->control = (c), \ ((lsc_t *)sp)->addr = (a), \ ((lsc_t *)sp)->track = MSF_CONV(tr), \ ((lsc_t *)sp)->msf[0] = MSF_CONV(LBA_MIN(bno)), \ ((lsc_t *)sp)->msf[1] = MSF_CONV(LBA_SEC(bno)), \ ((lsc_t *)sp)->msf[2] = MSF_CONV(LBA_FRM(bno)), \ &((lsc_t *)sp)->msf[3])#define set_lin_subcode(sp, c, a, pt, min, sec, frm) (\ ((lsc_t *)sp)->control = (c), \ ((lsc_t *)sp)->addr = (a), \ ((lsc_t *)sp)->track = (pt), \ ((lsc_t *)sp)->msf[0] = (min), \ ((lsc_t *)sp)->msf[1] = (sec), \ ((lsc_t *)sp)->msf[2] = (frm), \ &((lsc_t *)sp)->msf[3])#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */struct upc_subcode { /* subcode for upc/bar code */ u_char res; Ucbit addr : 4; Ucbit control : 4; u_char upc[13];};#elsestruct upc_subcode { /* subcode for upc/bar code */ u_char res; Ucbit control : 4; Ucbit addr : 4; u_char upc[13];};#endif#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */struct isrc_subcode { /* subcode for ISRC code */ u_char res; Ucbit addr : 4; Ucbit control : 4; u_char isrc[12]; u_char res14;};#elsestruct isrc_subcode { /* subcode for ISRC code */ u_char res; Ucbit control : 4; Ucbit addr : 4; u_char isrc[12]; u_char res14;};#endifLOCAL int teac_attach __PR((SCSI *scgp, cdr_t *dp));LOCAL int teac_getdisktype __PR((SCSI *scgp, cdr_t *dp, dstat_t *dsp));LOCAL int speed_select_teac __PR((SCSI *scgp, int *speedp, int dummy));LOCAL int select_secsize_teac __PR((SCSI *scgp, track_t *trackp));LOCAL int next_wr_addr_jvc __PR((SCSI *scgp, int track, track_t *, long *ap));LOCAL int write_teac_xg1 __PR((SCSI *scgp, caddr_t, long, long, int, BOOL));LOCAL int cdr_write_teac __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));LOCAL int open_track_jvc __PR((SCSI *scgp, cdr_t *dp, int track, track_t *trackp));LOCAL int teac_fixation __PR((SCSI *scgp, int onp, int dummy, int toctype, int tracks, track_t *trackp));LOCAL int close_track_teac __PR((SCSI *scgp, int track, track_t *trackp));LOCAL int teac_open_session __PR((SCSI *scgp, int tracks, track_t *trackp, int toctype, int multi));LOCAL int teac_calibrate __PR((SCSI *scgp, int toctype, int multi));LOCAL int opt_power_judge __PR((SCSI *scgp, int judge));LOCAL int clear_subcode __PR((SCSI *scgp));LOCAL int set_limits __PR((SCSI *scgp, long lba, long length));LOCAL int set_subcode __PR((SCSI *scgp, u_char *subcode_data, int length));LOCAL int read_disk_info_teac __PR((SCSI *scgp, u_char *data, int length, int type));LOCAL int teac_freeze __PR((SCSI *scgp, int bp_flag));LOCAL int teac_wr_pma __PR((SCSI *scgp));LOCAL int teac_rd_pma __PR((SCSI *scgp));LOCAL int next_wr_addr_teac __PR((SCSI *scgp, long start_lba, long last_lba));LOCAL int blank_jvc __PR((SCSI *scgp, long addr, int blanktype));LOCAL int buf_cap_teac __PR((SCSI *scgp, long *sp, long *fp));LOCAL long read_peak_buffer_cap_teac __PR((SCSI *scgp));LOCAL int buffer_inquiry_teac __PR((SCSI *scgp, int fmt));#ifdef XXBUFFERLOCAL void check_buffer_teac __PR((SCSI *scgp));#endif#ifdef XXDEBUGLOCAL void xxtest_teac __PR((SCSI *scgp));#endifcdr_t cdr_teac_cdr50 = { 0, CDR_TAO|CDR_DAO|CDR_SWABAUDIO|CDR_NO_LOLIMIT, "teac_cdr50", "driver for Teac CD-R50S, Teac CD-R55S, JVC XR-W2010, Pinnacle RCD-5020", 0, drive_identify, teac_attach, teac_getdisktype, scsi_load, scsi_unload, buf_cap_teac, (int(*)__PR((SCSI *)))cmd_dummy, /* recovery_needed */ (int(*)__PR((SCSI *, int)))cmd_dummy, /* recover */ speed_select_teac, select_secsize, next_wr_addr_jvc, (int(*)__PR((SCSI *, Ulong)))cmd_ill, /* reserve_track */ cdr_write_teac, no_sendcue, open_track_jvc, close_track_teac, teac_open_session, cmd_dummy, read_session_offset_philips, teac_fixation,/* blank_dummy,*/ blank_jvc,};LOCAL intteac_getdisktype(scgp, dp, dsp) SCSI *scgp; cdr_t *dp; dstat_t *dsp;{ struct scsi_mode_data md; int count = sizeof(struct scsi_mode_header) + sizeof(struct scsi_mode_blockdesc); int len; int page = 0; long l; fillbytes((caddr_t)&md, sizeof(md), '\0'); (void)test_unit_ready(scgp); if (mode_sense(scgp, (u_char *)&md, count, page, 0) < 0) { /* Page n current */ return (-1); } else { len = ((struct scsi_mode_header *)&md)->sense_data_len + 1; } if (((struct scsi_mode_header *)&md)->blockdesc_len < 8) return (-1); l = a_to_u_3_byte(md.blockdesc.nlblock); dsp->ds_maxblocks = l; return (0);}LOCAL intspeed_select_teac(scgp, speedp, dummy) SCSI *scgp; int *speedp; int dummy;{ struct cdd_52x_mode_data md; int count; int status; int speed = 1; if (speedp) speed = *speedp; fillbytes((caddr_t)&md, sizeof(md), '\0'); count = sizeof(struct scsi_mode_header) + sizeof(struct teac_mode_page_21); md.pagex.teac_page21.p_code = 0x21; md.pagex.teac_page21.p_len = 0x01; md.pagex.teac_page21.dummy = dummy?3:0; status = mode_select(scgp, (u_char *)&md, count, 0, scgp->inq->data_format >= 2); if (status < 0) return (status); if (speedp == 0) return (0); fillbytes((caddr_t)&md, sizeof(md), '\0'); count = sizeof(struct scsi_mode_header) + sizeof(struct teac_mode_page_31); speed >>= 1; md.pagex.teac_page31.p_code = 0x31; md.pagex.teac_page31.p_len = 0x02; md.pagex.teac_page31.speed = speed; return (mode_select(scgp, (u_char *)&md, count, 0, scgp->inq->data_format >= 2));}LOCAL intselect_secsize_teac(scgp, trackp) SCSI *scgp; track_t *trackp;{ struct scsi_mode_data md; int count = sizeof(struct scsi_mode_header) + sizeof(struct scsi_mode_blockdesc); int len; int page = 0; fillbytes((caddr_t)&md, sizeof(md), '\0'); (void)test_unit_ready(scgp); if (mode_sense(scgp, (u_char *)&md, count, page, 0) < 0) { /* Page n current */ return (-1); } else { len = ((struct scsi_mode_header *)&md)->sense_data_len + 1; } if (((struct scsi_mode_header *)&md)->blockdesc_len < 8) return (-1); md.header.sense_data_len = 0; md.header.blockdesc_len = 8; md.blockdesc.density = 1; if (trackp->secsize == 2352) md.blockdesc.density = 4; i_to_3_byte(md.blockdesc.lblen, trackp->secsize); return (mode_select(scgp, (u_char *)&md, count, 0, scgp->inq->data_format >= 2));}LOCAL intnext_wr_addr_jvc(scgp, track, trackp, ap) SCSI *scgp; int track; track_t *trackp; long *ap;{ if (track > 0) { *ap = lba_addr; } else { long nwa; if (read_B0(scgp, TRUE, &nwa, NULL) < 0) return (-1); *ap = nwa + 150; } return (0);}LOCAL intwrite_teac_xg1(scgp, bp, sectaddr, size, blocks, extwr) SCSI *scgp; 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 extwr; /* is an extended write */{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = bp; scmd->size = size; 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->target = scgp->target; scmd->cdb.g1_cdb.cmd = SC_EWRITE; scmd->cdb.g1_cdb.lun = scgp->lun; g1_cdbaddr(&scmd->cdb.g1_cdb, sectaddr); g1_cdblen(&scmd->cdb.g1_cdb, blocks); scmd->cdb.g1_cdb.vu_97 = extwr; scgp->cmdname = "write_teac_g1"; if (scsicmd(scgp) < 0) return (-1); return (size - scsigetresid(scgp));}LOCAL intcdr_write_teac(scgp, bp, sectaddr, size, blocks, islast) SCSI *scgp; 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 */{ int ret; if (islast) last_done = TRUE; ret = write_teac_xg1(scgp, bp, sectaddr, size, blocks, !islast); if (ret < 0) return (ret); lba_addr = sectaddr + blocks;#ifdef XXBUFFER check_buffer_teac(scgp);#endif return (ret);}LOCAL intopen_track_jvc(scgp, dp, track, trackp) SCSI *scgp; cdr_t *dp; int track; track_t *trackp;{ int status; long blocks; long pregapsize; struct pgm_subcode sc; last_done = FALSE; if (select_secsize_teac(scgp, trackp) < 0) return (-1); status = clear_subcode(scgp);/*next_wr_addr_teac(scgp);*/ if (status < 0) return (status);if (trackp->pregapsize != 0) { if (lverbose > 1) { printf("set_limits(%ld, %ld)-> %ld\n", lba_addr, trackp->pregapsize, lba_addr + trackp->pregapsize); } status = set_limits(scgp, lba_addr, trackp->pregapsize); if (status < 0) return (status);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -