📄 scsi_cdr.c
字号:
/*XXXSIZEOF testen !!!*//* @(#)scsi_cdr.c 1.93 00/07/02 Copyright 1995 J. Schilling */#ifndef lintstatic char sccsid[] = "@(#)scsi_cdr.c 1.93 00/07/02 Copyright 1995 J. Schilling";#endif/* * SCSI command functions for cdrecord * * Copyright (c) 1995 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. *//* * NOTICE: The Philips CDD 521 has several firmware bugs. * One of them is not to respond to a SCSI selection * within 200ms if the general load on the * SCSI bus is high. To deal with this problem * most of the SCSI commands are send with the * SCG_CMD_RETRY flag enabled. */#include <mconfig.h>#include <stdio.h>#include <standard.h>#include <stdxlib.h>#include <unixstd.h>#include <fctldefs.h>#include <errno.h>#include <strdefs.h>#include <utypes.h>#include <btorder.h>#include <intcvt.h>#include <schily.h>#include <scg/scgcmd.h>#include <scg/scsidefs.h>#include <scg/scsireg.h>#include <scg/scsitransp.h>#include "cdrecord.h"#define strbeg(s1,s2) (strstr((s2), (s1)) == (s2))EXPORT BOOL unit_ready __PR((SCSI *scgp));EXPORT BOOL wait_unit_ready __PR((SCSI *scgp, int secs));EXPORT BOOL scsi_in_progress __PR((SCSI *scgp));EXPORT int test_unit_ready __PR((SCSI *scgp));EXPORT int rezero_unit __PR((SCSI *scgp));EXPORT int request_sense __PR((SCSI *scgp));EXPORT int inquiry __PR((SCSI *scgp, caddr_t, int));EXPORT int read_capacity __PR((SCSI *scgp));EXPORT int scsi_load_unload __PR((SCSI *scgp, int));EXPORT int scsi_prevent_removal __PR((SCSI *scgp, int));EXPORT int scsi_start_stop_unit __PR((SCSI *scgp, int, int));EXPORT int scsi_set_speed __PR((SCSI *scgp, int readspeed, int writespeed));EXPORT int scsi_get_speed __PR((SCSI *scgp, int *readspeedp, int *writespeedp));EXPORT int qic02 __PR((SCSI *scgp, int));EXPORT int write_xg0 __PR((SCSI *scgp, caddr_t, long, long, int));EXPORT int write_xg1 __PR((SCSI *scgp, caddr_t, long, long, int));EXPORT int write_xg5 __PR((SCSI *scgp, caddr_t, long, long, int));EXPORT int scsi_flush_cache __PR((SCSI *scgp));EXPORT int read_buffer __PR((SCSI *scgp, caddr_t bp, int cnt, int mode));EXPORT int read_subchannel __PR((SCSI *scgp, caddr_t bp, int track, int cnt,int msf, int subq, int fmt));EXPORT int read_toc __PR((SCSI *scgp, caddr_t, int, int, int, int));EXPORT int read_toc_philips __PR((SCSI *scgp, caddr_t, int, int, int, int));EXPORT int read_header __PR((SCSI *scgp, caddr_t, long, int, int));EXPORT int read_disk_info __PR((SCSI *scgp, caddr_t, int));EXPORT int read_track_info __PR((SCSI *scgp, caddr_t, int, int));EXPORT int send_opc __PR((SCSI *scgp, caddr_t, int cnt, int doopc));EXPORT int read_track_info_philips __PR((SCSI *scgp, caddr_t, int, int));EXPORT int scsi_close_tr_session __PR((SCSI *scgp, int type, int track, BOOL immed));EXPORT int read_master_cue __PR((SCSI *scgp, caddr_t bp, int sheet, int cnt));EXPORT int send_cue_sheet __PR((SCSI *scgp, caddr_t bp, long size));EXPORT int read_buff_cap __PR((SCSI *scgp, long *, long *));EXPORT int scsi_blank __PR((SCSI *scgp, long addr, int blanktype, BOOL immed));EXPORT BOOL allow_atapi __PR((SCSI *scgp, BOOL new));EXPORT int mode_select __PR((SCSI *scgp, Uchar *, int, int, int));EXPORT int mode_sense __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));EXPORT int mode_select_sg0 __PR((SCSI *scgp, Uchar *, int, int, int));EXPORT int mode_sense_sg0 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));EXPORT int mode_select_g0 __PR((SCSI *scgp, Uchar *, int, int, int));EXPORT int mode_select_g1 __PR((SCSI *scgp, Uchar *, int, int, int));EXPORT int mode_sense_g0 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));EXPORT int mode_sense_g1 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));EXPORT int read_tochdr __PR((SCSI *scgp, cdr_t *, int *, int *));EXPORT int read_cdtext __PR((SCSI *scgp));EXPORT int read_trackinfo __PR((SCSI *scgp, int, long *, struct msf *, int *, int *, int *));EXPORT int read_B0 __PR((SCSI *scgp, BOOL isbcd, long *b0p, long *lop));EXPORT int read_session_offset __PR((SCSI *scgp, long *));EXPORT int read_session_offset_philips __PR((SCSI *scgp, long *));EXPORT int sense_secsize __PR((SCSI *scgp, int current));EXPORT int select_secsize __PR((SCSI *scgp, int));EXPORT BOOL is_cddrive __PR((SCSI *scgp));EXPORT BOOL is_unknown_dev __PR((SCSI *scgp));EXPORT int read_scsi __PR((SCSI *scgp, caddr_t, long, int));EXPORT int read_g0 __PR((SCSI *scgp, caddr_t, long, int));EXPORT int read_g1 __PR((SCSI *scgp, caddr_t, long, int));EXPORT BOOL getdev __PR((SCSI *scgp, BOOL));EXPORT void printdev __PR((SCSI *scgp));EXPORT BOOL do_inquiry __PR((SCSI *scgp, BOOL));EXPORT BOOL recovery_needed __PR((SCSI *scgp));EXPORT int scsi_load __PR((SCSI *scgp));EXPORT int scsi_unload __PR((SCSI *scgp));EXPORT int scsi_cdr_write __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));EXPORT struct cd_mode_page_2A * mmc_cap __PR((SCSI *scgp, Uchar *modep));EXPORT void mmc_getval __PR((struct cd_mode_page_2A *mp, BOOL *cdrrp, BOOL *cdwrp, BOOL *cdrrwp, BOOL *cdwrwp, BOOL *dvdp));EXPORT BOOL is_mmc __PR((SCSI *scgp, BOOL *dvdp));EXPORT BOOL mmc_check __PR((SCSI *scgp, BOOL *cdrrp, BOOL *cdwrp, BOOL *cdrrwp, BOOL *cdwrwp, BOOL *dvdp));EXPORT void print_capabilities __PR((SCSI *scgp));EXPORT BOOLunit_ready(scgp) SCSI *scgp;{ register struct scg_cmd *scmd = scgp->scmd; if (test_unit_ready(scgp) >= 0) /* alles OK */ return (TRUE); else if (scmd->error >= SCG_FATAL) /* nicht selektierbar */ return (FALSE); if (scmd->sense.code < 0x70) { /* non extended Sense */ if (scmd->sense.code == 0x04) /* NOT_READY */ return (FALSE); return (TRUE); } if (((struct scsi_ext_sense *)&scmd->sense)->key == SC_UNIT_ATTENTION) { if (test_unit_ready(scgp) >= 0) /* alles OK */ return (TRUE); } /* FALSE wenn NOT_READY */ return (((struct scsi_ext_sense *)&scmd->sense)->key != SC_NOT_READY);}EXPORT BOOLwait_unit_ready(scgp, secs) SCSI *scgp; int secs;{ int i; int c; int k; int ret; scgp->silent++; ret = test_unit_ready(scgp); /* eat up unit attention */ if (ret < 0) ret = test_unit_ready(scgp); /* got power on condition? */ scgp->silent--; if (ret >= 0) /* success that's enough */ return (TRUE); scgp->silent++; for (i=0; i < secs && (ret = test_unit_ready(scgp)) < 0; i++) { if (scgp->scmd->scb.busy != 0) { sleep(1); continue; } c = scsi_sense_code(scgp); k = scsi_sense_key(scgp); if (k == SC_NOT_READY && (c == 0x3A || c == 0x30)) { if (scgp->silent <= 1) scsiprinterr(scgp); scgp->silent--; return (FALSE); } sleep(1); } scgp->silent--; if (ret < 0) return (FALSE); return (TRUE);}EXPORT BOOLscsi_in_progress(scgp) SCSI *scgp;{ if (scsi_sense_key(scgp) == SC_NOT_READY && /* * Logigal unit not ready operation/long_write in progress */ scsi_sense_code(scgp) == 0x04 && (scsi_sense_qual(scgp) == 0x07 || scsi_sense_qual(scgp) == 0x08)) { return (TRUE); } else { if (scgp->silent <= 1) scsiprinterr(scgp); } return (FALSE);}EXPORT inttest_unit_ready(scgp) SCSI *scgp;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = (caddr_t)0; scmd->size = 0; scmd->flags = SCG_DISRE_ENA | (scgp->silent ? SCG_SILENT:0); scmd->cdb_len = SC_G0_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY; scmd->cdb.g0_cdb.lun = scgp->lun; scgp->cmdname = "test unit ready"; return (scsicmd(scgp));}EXPORT intrezero_unit(scgp) SCSI *scgp;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = (caddr_t)0; scmd->size = 0; scmd->flags = SCG_DISRE_ENA; scmd->cdb_len = SC_G0_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT; scmd->cdb.g0_cdb.lun = scgp->lun; scgp->cmdname = "rezero unit"; return (scsicmd(scgp));}EXPORT intrequest_sense(scgp) SCSI *scgp;{ char sensebuf[CCS_SENSE_LEN]; register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = sensebuf; scmd->size = sizeof(sensebuf);; scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA; scmd->cdb_len = SC_G0_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = SC_REQUEST_SENSE; scmd->cdb.g0_cdb.lun = scgp->lun; scmd->cdb.g0_cdb.count = CCS_SENSE_LEN; scgp->cmdname = "request_sense"; if (scsicmd(scgp) < 0) return (-1); scsiprsense((Uchar *)sensebuf, CCS_SENSE_LEN - scsigetresid(scgp)); return (0);}EXPORT intinquiry(scgp, bp, cnt) SCSI *scgp; caddr_t bp; int cnt;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes(bp, cnt, '\0'); fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = bp; scmd->size = cnt; scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA; scmd->cdb_len = SC_G0_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = SC_INQUIRY; scmd->cdb.g0_cdb.lun = scgp->lun; scmd->cdb.g0_cdb.count = cnt; scgp->cmdname = "inquiry"; if (scsicmd(scgp) < 0) return (-1); if (scgp->verbose) scsiprbytes("Inquiry Data :", (Uchar *)bp, cnt - scsigetresid(scgp)); return (0);}EXPORT intread_capacity(scgp) SCSI *scgp;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = (caddr_t)scgp->cap; scmd->size = sizeof(struct scsi_capacity); scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA; scmd->cdb_len = SC_G1_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g1_cdb.cmd = 0x25; /* Read Capacity */ scmd->cdb.g1_cdb.lun = scgp->lun; g1_cdblen(&scmd->cdb.g1_cdb, 0); /* Full Media */ scgp->cmdname = "read capacity"; if (scsicmd(scgp) < 0) { return (-1); } else { long kb; long mb; long prmb; double dkb; long cbsize; long cbaddr; /* * c_bsize & c_baddr are signed Int32_t * so we use signed int conversion here. */ cbsize = a_to_4_byte(&scgp->cap->c_bsize); cbaddr = a_to_4_byte(&scgp->cap->c_baddr); scgp->cap->c_bsize = cbsize; scgp->cap->c_baddr = cbaddr; if (scgp->silent) return (0); dkb = (scgp->cap->c_baddr+1.0) * (scgp->cap->c_bsize/1024.0); kb = dkb; mb = dkb / 1024.0; prmb = dkb / 1000.0 * 1.024; printf("Capacity: %ld Blocks = %ld kBytes = %ld MBytes = %ld prMB\n", (long)scgp->cap->c_baddr+1, kb, mb, prmb); printf("Sectorsize: %ld Bytes\n", (long)scgp->cap->c_bsize); } return (0);}EXPORT intscsi_load_unload(scgp, load) SCSI *scgp; int load;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->flags = SCG_DISRE_ENA; scmd->cdb_len = SC_G5_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g5_cdb.cmd = 0xA6; scmd->cdb.g5_cdb.lun = scgp->lun; scmd->cdb.g5_cdb.addr[1] = load?3:2; scmd->cdb.g5_cdb.count[2] = 0; /* slot # */ scgp->cmdname = "medium load/unload"; if (scsicmd(scgp) < 0) return (-1); return (0);}EXPORT intscsi_prevent_removal(scgp, prevent) SCSI *scgp; int prevent;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->flags = SCG_DISRE_ENA; scmd->cdb_len = SC_G0_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = 0x1E; scmd->cdb.g0_cdb.lun = scgp->lun; scmd->cdb.g0_cdb.count = prevent & 1; scgp->cmdname = "prevent/allow medium removal"; if (scsicmd(scgp) < 0) return (-1); return (0);}EXPORT intscsi_start_stop_unit(scgp, flg, loej) SCSI *scgp; int flg; int loej;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->flags = SCG_DISRE_ENA; scmd->cdb_len = SC_G0_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = 0x1B; /* Start Stop Unit */ scmd->cdb.g0_cdb.lun = scgp->lun; scmd->cdb.g0_cdb.count = (flg ? 1:0) | (loej ? 2:0); scgp->cmdname = "start/stop unit"; return (scsicmd(scgp));}EXPORT intscsi_set_speed(scgp, readspeed, writespeed) SCSI *scgp; int readspeed; int writespeed;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->flags = SCG_DISRE_ENA; scmd->cdb_len = SC_G5_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g5_cdb.cmd = 0xBB; scmd->cdb.g5_cdb.lun = scgp->lun; i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], readspeed); i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], writespeed); scgp->cmdname = "set cd speed"; if (scsicmd(scgp) < 0) return (-1); return (0);}EXPORT intscsi_get_speed(scgp, readspeedp, writespeedp) SCSI *scgp; int *readspeedp; int *writespeedp;{ struct cd_mode_page_2A *mp; Uchar m[256]; int val; scgp->silent++; mp = mmc_cap(scgp, m);/* Get MMC capabilities in allocated mp */ scgp->silent--; if (mp == NULL) return (-1); /* Pre SCSI-3/mmc drive */ val = a_to_u_2_byte(mp->cur_read_speed); if (readspeedp) *readspeedp = val; val = a_to_u_2_byte(mp->cur_write_speed); if (writespeedp) *writespeedp = val; return (0);}EXPORT intqic02(scgp, cmd) SCSI *scgp; int cmd;{ register struct scg_cmd *scmd = scgp->scmd; fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = (caddr_t)0; scmd->size = 0; scmd->flags = SCG_DISRE_ENA; scmd->cdb_len = SC_G0_CDBLEN; scmd->sense_len = DEF_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = 0x0D; /* qic02 Sysgen SC4000 */ scmd->cdb.g0_cdb.lun = scgp->lun; scmd->cdb.g0_cdb.mid_addr = cmd; scgp->cmdname = "qic 02"; return (scsicmd(scgp));}EXPORT intwrite_xg0(scgp, bp, addr, size, cnt) SCSI *scgp; caddr_t bp; /* address of buffer */ long addr; /* disk address (sector) to put */ long size; /* number of bytes to transfer */ int cnt; /* sectorcount */{ 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_G0_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = SC_WRITE; scmd->cdb.g0_cdb.lun = scgp->lun;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -