📄 drv_jvc.c
字号:
/** @(#)drv_jvc.c 1.31 98/09/15 Copyright 1997 J. Schilling */#ifndef lintstatic char sccsid[] = "@(#)drv_jvc.c 1.31 98/09/15 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. */#include <mconfig.h>#include <stdio.h>#include <standard.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <utypes.h>#include <btorder.h>#include <scgio.h>#include <scsidefs.h>#include <scsireg.h>#include "cdrecord.h"#include "scsitransp.h"struct scg_cmd scmd;struct scsi_inquiry inq;/* 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 scsibus;extern int target;extern int lun;extern int silent;extern int verbose;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((cdr_t *dp));LOCAL int teac_getdisktype __PR((cdr_t *dp, dstat_t *dsp));LOCAL int speed_select_teac __PR((int speed, int dummy));LOCAL int select_secsize_teac __PR((track_t *trackp));LOCAL int next_wr_addr_jvc __PR((int track, track_t *, long *ap));LOCAL int write_teac_xg1 __PR((caddr_t, long, long, int, BOOL));LOCAL int cdr_write_teac __PR((caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));LOCAL int open_track_jvc __PR((cdr_t *dp, int track, track_t *trackp));LOCAL int teac_fixation __PR((int onp, int dummy, int toctype, int tracks, track_t *trackp));LOCAL int close_track_teac __PR((int track, track_t *trackp));LOCAL int teac_open_session __PR((int tracks, track_t *trackp, int toctype, int multi));LOCAL int teac_calibrate __PR((int toctype, int multi));LOCAL int opt_power_judge __PR((int judge));LOCAL int clear_subcode __PR((void));LOCAL int set_limits __PR((long lba, long length));LOCAL int set_subcode __PR((u_char *subcode_data, int length));LOCAL int read_disk_info_teac __PR((u_char *data, int length, int type));LOCAL int teac_freeze __PR((int bp_flag));LOCAL int teac_wr_pma __PR((void));LOCAL int teac_rd_pma __PR((void));LOCAL int next_wr_addr_teac __PR((long start_lba, long last_lba));LOCAL int blank_jvc __PR((long addr, int blanktype));cdr_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, recovery_needed, recover, speed_select_teac, select_secsize, next_wr_addr_jvc, reserve_track, cdr_write_teac, open_track_jvc, close_track_teac, teac_open_session, cmd_dummy, read_session_offset_philips, teac_fixation,/* blank_dummy,*/ blank_jvc,};LOCAL intteac_getdisktype(dp, dsp) 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(); if (mode_sense((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_3_byte(md.blockdesc.nlblock); dsp->ds_maxblocks = l; return (0);}LOCAL intspeed_select_teac(speed, dummy) int speed; int dummy;{ struct cdd_52x_mode_data md; int count; int status; 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((u_char *)&md, count, 0, inq.data_format >= 2); if (status < 0) return (status); 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((u_char *)&md, count, 0, inq.data_format >= 2));}LOCAL intselect_secsize_teac(trackp) 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(); if (mode_sense((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((u_char *)&md, count, 0, inq.data_format >= 2));}LOCAL intnext_wr_addr_jvc(track, trackp, ap) int track; track_t *trackp; long *ap;{ if (track > 0) { *ap = lba_addr; } else { long nwa; if (read_B0(TRUE, &nwa, NULL) < 0) return (-1); *ap = nwa + 150; } return (0);}LOCAL intwrite_teac_xg1(bp, sectaddr, size, blocks, extwr) 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 */{ 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 = target; scmd.cdb.g1_cdb.cmd = SC_EWRITE; scmd.cdb.g1_cdb.lun = lun; g1_cdbaddr(&scmd.cdb.g1_cdb, sectaddr); g1_cdblen(&scmd.cdb.g1_cdb, blocks); scmd.cdb.g1_cdb.vu_97 = extwr; if (scsicmd("write_teac_g1") < 0) return (-1); return (size - scmd.resid);}LOCAL intcdr_write_teac(bp, sectaddr, size, blocks, islast) 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(bp, sectaddr, size, blocks, !islast); if (ret < 0) return (ret); lba_addr = sectaddr + blocks; return (ret);}LOCAL intopen_track_jvc(dp, track, trackp) 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(trackp) < 0) return (-1); status = clear_subcode();/*next_wr_addr_teac();*/ 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(lba_addr, trackp->pregapsize); if (status < 0) return (status); /* * Set pre-gap (pause - index 0) */ set_pgm_subcode(&sc, SC_P, st2mode[trackp->sectype&ST_MASK], ADR_POS, track, 0); if (lverbose > 1) scsiprbytes("Subcode:", (u_char *)&sc, sizeof(sc)); status = set_subcode((u_char *)&sc, sizeof(sc)); if (status < 0) return (status); pregapsize = trackp->pregapsize; if (!is_audio(trackp)) { lba_addr += 5; /* link & run in blocks */ pregapsize -= 5; } if (lverbose > 1) { printf("pad_track(%ld, %ld)-> %ld\n", lba_addr, pregapsize, lba_addr + pregapsize); } if (pad_track(dp, track, trackp, lba_addr, pregapsize*trackp->secsize, FALSE, (long *)0) < 0) return (-1);} blocks = trackp->tracksize/trackp->secsize + (trackp->tracksize%trackp->secsize?1:0); blocks += trackp->padsize/trackp->secsize + (trackp->padsize%trackp->secsize?1:0); if (blocks < 300) blocks = 300; if (!is_audio(trackp)) blocks += 2;if (!is_last(trackp) && trackp[1].pregapsize == 0) blocks -= 150; /* * set the limits for the new subcode - seems to apply to all * of the data track. * Unknown tracksize is handled in open_session. * We definitely need to know the tracksize in this driver. */ if (lverbose > 1) { printf("set_limits(%ld, %ld)-> %ld\n", lba_addr, blocks, lba_addr + blocks); } status = set_limits(lba_addr, blocks); if (status < 0) return (status); /* * Set track start (index 1) */ set_pgm_subcode(&sc, SC_TR, st2mode[trackp->sectype&ST_MASK], ADR_POS, track, 1); if (lverbose > 1) scsiprbytes("Subcode:", (u_char *)&sc, sizeof(sc)); status = set_subcode((u_char *)&sc, sizeof(sc)); if (status < 0) return (status);if (!is_last(trackp) && trackp[1].pregapsize == 0) { blocks += lba_addr; pregapsize = 150; if (lverbose > 1) { printf("set_limits(%ld, %ld)-> %ld\n", blocks, pregapsize, blocks + pregapsize); } status = set_limits(blocks, pregapsize); if (status < 0) return (status); /* * Set pre-gap (pause - index 0) */ track++; trackp++; set_pgm_subcode(&sc, SC_P, st2mode[trackp->sectype&ST_MASK], ADR_POS, track, 0); if (lverbose > 1) scsiprbytes("Subcode:", (u_char *)&sc, sizeof(sc));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -