📄 drv_mmc.c
字号:
/* @(#)drv_mmc.c 1.28 98/10/07 Copyright 1997 J. Schilling */#ifndef lintstatic char sccsid[] = "@(#)drv_mmc.c 1.28 98/10/07 Copyright 1997 J. Schilling";#endif/* * CDR device implementation for * SCSI-3/mmc conforming drives * e.g. Yamaha CDR-400, Ricoh MP6200 * * 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 DEBUG*/#define PRINT_ATIP#include <mconfig.h>#include <stdio.h>#include <standard.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <sys/time.h>#include <utypes.h>#include <btorder.h>#include <scgio.h>#include <scsidefs.h>#include <scsireg.h>#include <scsimmc.h>#include "cdrecord.h"#include "scsitransp.h"extern BOOL isgui;struct scg_cmd scmd;struct scsi_inquiry inq;extern int scsibus;extern int target;extern int lun;extern int silent;extern int verbose;extern int lverbose;LOCAL int curspeed = 1;LOCAL int mmc_load __PR((void));LOCAL int mmc_unload __PR((void));LOCAL cdr_t *identify_mmc __PR((cdr_t *, struct scsi_inquiry *));LOCAL int attach_mmc __PR((cdr_t *));LOCAL int get_diskinfo __PR((struct disk_info *dip));LOCAL void di_to_dstat __PR((struct disk_info *dip, dstat_t *dsp));#ifdef PRINT_ATIPLOCAL int get_pma __PR((void));#endifLOCAL int getdisktype_mmc __PR((cdr_t *dp, dstat_t *dsp));LOCAL int speed_select_mmc __PR((int speed, int dummy));LOCAL int next_wr_addr_mmc __PR((int track, track_t *trackp, long *ap));LOCAL int open_track_mmc __PR((cdr_t *dp, int track, track_t *trackp));LOCAL int close_track_mmc __PR((int track, track_t *trackp));LOCAL int open_session_mmc __PR((int tracks, track_t *trackp, int toctype, int multi));LOCAL int waitfix_mmc __PR((int secs));LOCAL int fixate_mmc __PR((int onp, int dummy, int toctype, int tracks, track_t *trackp));LOCAL int blank_mmc __PR((long addr, int blanktype));LOCAL int scsi_sony_write __PR((caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));LOCAL intmmc_load(){ return (scsi_load_unload(1));}LOCAL intmmc_unload(){ return (scsi_load_unload(0));}cdr_t cdr_mmc = { 0, CDR_TAO|CDR_DAO|CDR_PACKET|CDR_SWABAUDIO, "mmc_cdr", "generic SCSI-3/mmc CD-R driver", 0, identify_mmc, attach_mmc, getdisktype_mmc, scsi_load,/* mmc_load,*/ scsi_unload, recovery_needed, recover, speed_select_mmc, select_secsize, next_wr_addr_mmc, reserve_track, scsi_cdr_write, open_track_mmc, close_track_mmc, open_session_mmc, cmd_dummy, read_session_offset, fixate_mmc, blank_mmc,};cdr_t cdr_mmc_sony = { 0, CDR_TAO|CDR_DAO|CDR_PACKET|CDR_SWABAUDIO, "mmc_cdr_sony", "generic SCSI-3/mmc CD-R driver (Sony 928 variant)", 0, identify_mmc, attach_mmc, getdisktype_mmc, scsi_load,/* mmc_load,*/ scsi_unload, recovery_needed, recover, speed_select_mmc, select_secsize, next_wr_addr_mmc, reserve_track, scsi_sony_write, open_track_mmc, close_track_mmc, open_session_mmc, cmd_dummy, read_session_offset, fixate_mmc, blank_mmc,};/* * SCSI-3/mmc conformant CD drive */cdr_t cdr_cd = { 0, CDR_ISREADER|CDR_SWABAUDIO, "mmc_cd", "generic SCSI-3/mmc CD driver", 0, identify_mmc, attach_mmc, drive_getdisktype, scsi_load, scsi_unload, cmd_dummy, /* recovery_needed */ (int(*)__PR((int)))cmd_dummy, /* recover */ speed_select_mmc, select_secsize, (int(*)__PR((int, track_t *, long *)))cmd_dummy, /* next_wr_addr */ reserve_track, scsi_cdr_write, open_track_mmc, close_track_mmc, (int(*)__PR((int, track_t *, int, int)))cmd_dummy, cmd_dummy, read_session_offset, fixation, blank_dummy,};/* * Old pre SCSI-3/mmc CD drive */cdr_t cdr_oldcd = { 0, CDR_ISREADER, "scsi2_cd", "generic SCSI-2 CD driver", 0, identify_mmc, drive_attach, drive_getdisktype, scsi_load, scsi_unload, cmd_dummy, /* recovery_needed */ (int(*)__PR((int)))cmd_dummy, /* recover */ speed_select_mmc, select_secsize, (int(*)__PR((int, track_t *, long *)))cmd_dummy, /* next_wr_addr */ reserve_track, scsi_cdr_write, open_track_mmc, close_track_mmc, (int(*)__PR((int, track_t *, int, int)))cmd_dummy, cmd_dummy, read_session_offset_philips, fixation, blank_dummy,};LOCAL cdr_t *identify_mmc(dp, ip) cdr_t *dp; struct scsi_inquiry *ip;{ BOOL cdrr = FALSE; /* Read CD-R */ BOOL cdwr = FALSE; /* Write CD-R */ BOOL cdrrw = FALSE; /* Read CD-RW */ BOOL cdwrw = FALSE; /* Write CD-RW */ Uchar mode[0x100]; struct cd_mode_page_2A *mp; if (ip->type != INQ_WORM && ip->type != INQ_ROMD) return ((cdr_t *)0); allow_atapi(TRUE); /* Try to switch to 10 byte mode cmds */ silent++; mp = mmc_cap(mode); /* Get MMC capabilities */ silent--; if (mp == NULL) return (&cdr_oldcd); /* Pre SCSI-3/mmc drive */ mmc_getval(mp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL); /* * At this point we know that we have a SCSI-3/mmc compliant drive. * Unfortunately ATAPI drives violate the SCSI spec in returning * a response data format of '1' which from the SCSI spec would * tell us not to use the "PF" bit in mode select. As ATAPI drives * require the "PF" bit to be set, we 'correct' the inquiry data. * * XXX xxx_identify() should not have any side_effects ?? */ if (ip->data_format < 2) ip->data_format = 2; if (strncmp(ip->vendor_info, "SONY", 4) == 0 && strncmp(ip->prod_ident, "CD-R CDU928E", 14) == 0) { dp = &cdr_mmc_sony; } if (!cdwr) /* SCSI-3/mmc CD drive */ dp = &cdr_cd; return (dp);}LOCAL intattach_mmc(dp) cdr_t *dp;{ struct cd_mode_page_2A *mp; allow_atapi(TRUE); /* Try to switch to 10 byte mode cmds */ silent++; mp = mmc_cap(NULL); /* Get MMC capabilities in allocated mp */ silent--; if (mp == NULL) return (-1); /* Pre SCSI-3/mmc drive */ dp->cdr_cdcap = mp; /* Store MMC cap pointer */ if (mp->loading_type == LT_TRAY) dp->cdr_flags |= CDR_TRAYLOAD; else if (mp->loading_type == LT_CADDY) dp->cdr_flags |= CDR_CADDYLOAD; return (0);}#ifdef PRINT_ATIPLOCAL int get_atip __PR((struct atipinfo *atp)); void print_di __PR((struct disk_info *dip)); void print_atip __PR((struct atipinfo *atp));#endif /* PRINT_ATIP */LOCAL intget_diskinfo(dip) struct disk_info *dip;{ int len; int ret; fillbytes((caddr_t)dip, sizeof(*dip), '\0'); if (read_disk_info((caddr_t)dip, 2) < 0) return (-1); len = a_to_u_short(dip->data_len); len += 2; ret = read_disk_info((caddr_t)dip, len);#ifdef DEBUG scsiprbytes("Disk info:", (u_char *)dip, len-scsigetresid());#endif return (ret);}LOCAL voiddi_to_dstat(dip, dsp) struct disk_info *dip; dstat_t *dsp;{ dsp->ds_diskid = a_to_u_long(dip->disk_id); if (dip->did_v) dsp->ds_flags |= DSF_DID_V; dsp->ds_diskstat = dip->disk_status; dsp->ds_sessstat = dip->sess_status; dsp->ds_maxblocks = msf_to_lba(dip->last_lead_out[1], dip->last_lead_out[2], dip->last_lead_out[3]); /* * Check for 0xFF:0xFF/0xFF which is an indicator for a complete disk */ if (dsp->ds_maxblocks == 716730) dsp->ds_maxblocks = -1L; if (dsp->ds_first_leadin == 0) { dsp->ds_first_leadin = msf_to_lba(dip->last_lead_in[1], dip->last_lead_in[2], dip->last_lead_in[3]); if (dsp->ds_first_leadin > 0) dsp->ds_first_leadin = 0; } if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0) dsp->ds_last_leadout = dsp->ds_maxblocks;}#ifdef PRINT_ATIPLOCAL intget_atip(atp) struct atipinfo *atp;{ int len; int ret; fillbytes((caddr_t)atp, sizeof(*atp), '\0'); if (read_toc((caddr_t)atp, 0, 2, 0, FMT_ATIP) < 0) return (-1); len = a_to_u_short(atp->hd.len); len += 2; ret = read_toc((caddr_t)atp, 0, len, 0, FMT_ATIP);#ifdef DEBUG scsiprbytes("ATIP info:", (u_char *)atp, len-scsigetresid());#endif /* * Yamaha sometimes returns zeroed ATIP info for disks without ATIP */ if (atp->desc.lead_in[1] == 0 && atp->desc.lead_in[2] == 0 && atp->desc.lead_in[3] == 0 && atp->desc.lead_out[1] == 0 && atp->desc.lead_out[2] == 0 && atp->desc.lead_out[3] == 0) return (-1); return (ret);}LOCAL int/*get_pma(atp)*/get_pma()/* struct atipinfo *atp;*/{ int len; int ret;char atp[1024]; fillbytes((caddr_t)atp, sizeof(*atp), '\0');/* if (read_toc((caddr_t)atp, 0, 2, 1, FMT_PMA) < 0)*/ if (read_toc((caddr_t)atp, 0, 2, 0, FMT_PMA) < 0) return (-1);/* len = a_to_u_short(atp->hd.len);*/ len = a_to_u_short(atp); len += 2;/* ret = read_toc((caddr_t)atp, 0, len, 1, FMT_PMA);*/ ret = read_toc((caddr_t)atp, 0, len, 0, FMT_PMA);#ifdef DEBUG scsiprbytes("PMA:", (u_char *)atp, len-scsigetresid());#endif ret = read_toc((caddr_t)atp, 0, len, 1, FMT_PMA);#ifdef DEBUG scsiprbytes("PMA:", (u_char *)atp, len-scsigetresid());#endif return (ret);}#endif /* PRINT_ATIP */LOCAL intgetdisktype_mmc(dp, dsp) cdr_t *dp; dstat_t *dsp;{extern char *buf; struct disk_info *dip; u_char mode[0x100]; char ans[2]; msf_t msf; BOOL did_atip = FALSE; msf.msf_min = msf.msf_sec = msf.msf_frame = 0;#ifdef PRINT_ATIP /* * It seems that there are drives that do not support to * read ATIP (e.g. HP 7100) * Also if a NON CD-R media is inserted, this will never work. * For this reason, make a failure non-fatal. */ silent++; if (get_atip((struct atipinfo *)mode) >= 0) { msf.msf_min = mode[8]; msf.msf_sec = mode[9]; msf.msf_frame = mode[10]; did_atip = TRUE; if (lverbose) { print_atip((struct atipinfo *)mode); pr_manufacturer(&msf); } } silent--;#endif dip = (struct disk_info *)buf; if (get_diskinfo(dip) < 0) return (-1); /* * Check for non writable disk first. */ if (dip->disk_status == DS_COMPLETE) { errmsgno(EX_BAD, "Drive needs to reload the media to return to proper status.\n"); unload_media(dp, F_EJECT); if ((dp->cdr_flags & CDR_TRAYLOAD) == 0) { printf("Re-load disk and hit <CR>"); if (isgui) printf("\n"); flush(); getline(ans, 1); } load_media(dp); } if (get_diskinfo(dip) < 0) return (-1); di_to_dstat(dip, dsp); if (!did_atip && dsp->ds_first_leadin < 0) lba_to_msf(dsp->ds_first_leadin, &msf); if (lverbose && !did_atip) { print_min_atip(dsp->ds_first_leadin, dsp->ds_last_leadout); if (dsp->ds_first_leadin < 0) pr_manufacturer(&msf); } dsp->ds_maxrblocks = disk_rcap(&msf, dsp->ds_maxblocks);#ifdef PRINT_ATIP#ifdef DEBUG if (get_atip((struct atipinfo *)mode) < 0) return (-1); /* * Get pma gibt 膔ger mit CW-7502 * Wenn Die Disk leer ist, dann stuerzt alles ab. * Firmware 4.02 kann nicht get_pma */ if (dip->disk_status != DS_EMPTY) {/* get_pma();*/ } printf("ATIP lead in: %ld (%02d:%02d/%02d)\n", msf_to_lba(mode[8], mode[9], mode[10]), mode[8], mode[9], mode[10]); printf("ATIP lead out: %ld (%02d:%02d/%02d)\n", msf_to_lba(mode[12], mode[13], mode[14]), mode[12], mode[13], mode[14]); print_di(dip);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -