scsi_cdr.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:62k
- /*
- XXX
- SIZEOF testen !!!
- */
- /* @(#)scsi_cdr.c 1.84 00/01/28 Copyright 1995 J. Schilling */
- #ifndef lint
- static char sccsid[] =
- "@(#)scsi_cdr.c 1.84 00/01/28 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 <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 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 read_track_info_philips __PR((SCSI *scgp, caddr_t, int, int));
- EXPORT int scsi_close_tr_session __PR((SCSI *scgp, int type, int track));
- 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));
- 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 BOOL
- unit_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 BOOL
- wait_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 int
- test_unit_ready(scgp)
- SCSI *scgp;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 int
- rezero_unit(scgp)
- SCSI *scgp;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 int
- request_sense(scgp)
- SCSI *scgp;
- {
- char sensebuf[CCS_SENSE_LEN];
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 int
- inquiry(scgp, bp, cnt)
- SCSI *scgp;
- caddr_t bp;
- int cnt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes(bp, cnt, ' ');
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 int
- read_capacity(scgp)
- SCSI *scgp;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 prMBn",
- (long)scgp->cap->c_baddr+1, kb, mb, prmb);
- printf("Sectorsize: %ld Bytesn", (long)scgp->cap->c_bsize);
- }
- return (0);
- }
- EXPORT int
- scsi_load_unload(scgp, load)
- SCSI *scgp;
- int load;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 int
- scsi_prevent_removal(scgp, prevent)
- SCSI *scgp;
- int prevent;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 int
- scsi_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), ' ');
- 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 int
- scsi_set_speed(scgp, readspeed, writespeed)
- SCSI *scgp;
- int readspeed;
- int writespeed;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 int
- scsi_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)
- *writespeedp = val;
- val = a_to_u_2_byte(mp->cur_write_speed);
- if (writespeedp)
- *writespeedp = val;
- return (0);
- }
- EXPORT int
- qic02(scgp, cmd)
- SCSI *scgp;
- int cmd;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- 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 int
- write_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), ' ');
- 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;
- g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
- scmd->cdb.g0_cdb.count = cnt;
-
- scgp->cmdname = "write_g0";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (size - scsigetresid(scgp));
- }
- EXPORT int
- write_xg1(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), ' ');
- 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, addr);
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
-
- scgp->cmdname = "write_g1";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (size - scsigetresid(scgp));
- }
- EXPORT int
- write_xg5(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), ' ');
- scmd->addr = bp;
- scmd->size = size;
- scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
- /* 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 = 0xAA;
- scmd->cdb.g5_cdb.lun = scgp->lun;
- g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
- g5_cdblen(&scmd->cdb.g5_cdb, cnt);
-
- scgp->cmdname = "write_g5";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (size - scsigetresid(scgp));
- }
- EXPORT int
- scsi_flush_cache(scgp)
- SCSI *scgp;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->flags = SCG_DISRE_ENA;
- scmd->cdb_len = SC_G1_CDBLEN;
- scmd->sense_len = CCS_SENSE_LEN;
- scmd->target = scgp->target;
- scmd->timeout = 2 * 60; /* Max: sizeof(CDR-cache)/150KB/s */
- scmd->cdb.g1_cdb.cmd = 0x35;
- scmd->cdb.g1_cdb.lun = scgp->lun;
-
- scgp->cmdname = "flush cache";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- read_buffer(scgp, bp, cnt, mode)
- SCSI *scgp;
- caddr_t bp;
- int cnt;
- int mode;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- scmd->dma_read = 1;
- scmd->cdb_len = SC_G1_CDBLEN;
- scmd->sense_len = CCS_SENSE_LEN;
- scmd->target = scgp->target;
- scmd->cdb.g1_cdb.cmd = 0x3C; /* Read Buffer */
- scmd->cdb.g1_cdb.lun = scgp->lun;
- scmd->cdb.cmd_cdb[1] |= (mode & 7);
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
-
- scgp->cmdname = "read buffer";
- return (scsicmd(scgp));
- }
- EXPORT int
- read_subchannel(scgp, bp, track, cnt, msf, subq, fmt)
- SCSI *scgp;
- caddr_t bp;
- int track;
- int cnt;
- int msf;
- int subq;
- int fmt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- 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 = 0x42;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- if (msf)
- scmd->cdb.g1_cdb.res = 1;
- if (subq)
- scmd->cdb.g1_cdb.addr[0] = 0x40;
- scmd->cdb.g1_cdb.addr[1] = fmt;
- scmd->cdb.g1_cdb.res6 = track;
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- scgp->cmdname = "read subchannel";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- read_toc(scgp, bp, track, cnt, msf, fmt)
- SCSI *scgp;
- caddr_t bp;
- int track;
- int cnt;
- int msf;
- int fmt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- 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 = 0x43;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- if (msf)
- scmd->cdb.g1_cdb.res = 1;
- scmd->cdb.g1_cdb.addr[0] = fmt & 0x0F;
- scmd->cdb.g1_cdb.res6 = track;
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- scgp->cmdname = "read toc";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- read_toc_philips(scgp, bp, track, cnt, msf, fmt)
- SCSI *scgp;
- caddr_t bp;
- int track;
- int cnt;
- int msf;
- int fmt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- 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->timeout = 4 * 60; /* May last 174s on a TEAC CD-R55S */
- scmd->cdb.g1_cdb.cmd = 0x43;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- if (msf)
- scmd->cdb.g1_cdb.res = 1;
- scmd->cdb.g1_cdb.res6 = track;
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- if (fmt & 1)
- scmd->cdb.g1_cdb.vu_96 = 1;
- if (fmt & 2)
- scmd->cdb.g1_cdb.vu_97 = 1;
- scgp->cmdname = "read toc";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- read_header(scgp, bp, addr, cnt, msf)
- SCSI *scgp;
- caddr_t bp;
- long addr;
- int cnt;
- int msf;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- 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 = 0x44;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- if (msf)
- scmd->cdb.g1_cdb.res = 1;
- g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- scgp->cmdname = "read header";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- read_disk_info(scgp, bp, cnt)
- SCSI *scgp;
- caddr_t bp;
- int cnt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- 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->timeout = 4 * 60; /* Needs up to 2 minutes */
- scmd->cdb.g1_cdb.cmd = 0x51;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- scgp->cmdname = "read disk info";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- read_track_info(scgp, bp, track, cnt)
- SCSI *scgp;
- caddr_t bp;
- int track;
- int cnt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- 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->timeout = 4 * 60; /* Needs up to 2 minutes */
- scmd->cdb.g1_cdb.cmd = 0x52;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- scmd->cdb.g1_cdb.reladr = 1; /* Track */
- g1_cdbaddr(&scmd->cdb.g1_cdb, track);
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- scgp->cmdname = "read track info";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- read_track_info_philips(scgp, bp, track, cnt)
- SCSI *scgp;
- caddr_t bp;
- int track;
- int cnt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- 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 = 0xE5;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- g1_cdbaddr(&scmd->cdb.g1_cdb, track);
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- scgp->cmdname = "read track info";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- scsi_close_tr_session(scgp, type, track)
- SCSI *scgp;
- int type;
- int track;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->flags = SCG_DISRE_ENA;
- scmd->cdb_len = SC_G1_CDBLEN;
- scmd->sense_len = CCS_SENSE_LEN;
- scmd->target = scgp->target;
- scmd->timeout = 8 * 60; /* Needs up to 4 minutes */
- scmd->cdb.g1_cdb.cmd = 0x5B;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- scmd->cdb.g1_cdb.addr[0] = type;
- scmd->cdb.g1_cdb.addr[3] = track;
- #ifdef nono
- scmd->cdb.g1_cdb.reladr = 1; /* IMM hack to test Mitsumi behaviour*/
- #endif
-
- scgp->cmdname = "close track/session";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- read_master_cue(scgp, bp, sheet, cnt)
- SCSI *scgp;
- caddr_t bp; /* address of master cue sheet */
- int sheet; /* Sheet number */
- int cnt; /* Transfer count */
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt;
- 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 = 0x59; /* Read master cue */
- scmd->cdb.g1_cdb.lun = scgp->lun;
- scmd->cdb.g1_cdb.addr[2] = sheet;
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- scgp->cmdname = "read master cue";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (0);
- }
- EXPORT int
- send_cue_sheet(scgp, bp, size)
- SCSI *scgp;
- caddr_t bp; /* address of cue sheet buffer */
- long size; /* number of bytes to transfer */
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = size;
- 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 = 0x5D; /* Send CUE sheet */
- scmd->cdb.g1_cdb.lun = scgp->lun;
- g1_cdblen(&scmd->cdb.g1_cdb, size);
- scgp->cmdname = "send_cue_sheet";
- if (scsicmd(scgp) < 0)
- return (-1);
- return (size - scmd->resid);
- }
- EXPORT int
- read_buff_cap(scgp, sp, fp)
- SCSI *scgp;
- long *sp; /* Size pointer */
- long *fp; /* Free pointer */
- {
- char resp[12];
- Ulong freespace;
- Ulong bufsize;
- int per;
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = (caddr_t)resp;
- scmd->size = sizeof(resp);
- 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 = 0x5C; /* Read buffer cap */
- scmd->cdb.g1_cdb.lun = scgp->lun;
- g1_cdblen(&scmd->cdb.g1_cdb, sizeof(resp));
-
- scgp->cmdname = "read buffer cap";
- if (scsicmd(scgp) < 0)
- return (-1);
- bufsize = a_to_u_4_byte(&resp[4]);
- freespace = a_to_u_4_byte(&resp[8]);
- if (sp)
- *sp = bufsize;
- if (fp)
- *fp = freespace;
-
- if (scgp->verbose || (sp == 0 && fp == 0))
- printf("BFree: %ld K BSize: %ld Kn", freespace >> 10, bufsize >> 10);
- if (bufsize == 0)
- return (0);
- per = (100 * (bufsize - freespace)) / bufsize;
- if (per < 0)
- return (0);
- if (per > 100)
- return (100);
- return (per);
- }
- EXPORT int
- scsi_blank(scgp, addr, blanktype)
- SCSI *scgp;
- long addr;
- int blanktype;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->flags = SCG_DISRE_ENA;
- scmd->cdb_len = SC_G5_CDBLEN;
- scmd->sense_len = CCS_SENSE_LEN;
- scmd->target = scgp->target;
- scmd->timeout = 160 * 60; /* full blank at 1x could take 80 minutes */
- scmd->cdb.g5_cdb.cmd = 0xA1; /* Blank */
- scmd->cdb.g0_cdb.high_addr = blanktype;
- g1_cdbaddr(&scmd->cdb.g5_cdb, addr);
- scgp->cmdname = "blank unit";
- return (scsicmd(scgp));
- }
- /*
- * XXX First try to handle ATAPI:
- * XXX ATAPI cannot handle SCSI 6 byte commands.
- * XXX We try to simulate 6 byte mode sense/select.
- */
- LOCAL BOOL is_atapi;
- EXPORT BOOL
- allow_atapi(scgp, new)
- SCSI *scgp;
- BOOL new;
- {
- BOOL old = is_atapi;
- Uchar mode[256];
- if (new == old)
- return (old);
- scgp->silent++;
- if (new &&
- mode_sense_g1(scgp, mode, 8, 0x3F, 0) < 0) { /* All pages current */
- new = FALSE;
- }
- scgp->silent--;
- is_atapi = new;
- return (old);
- }
- EXPORT int
- mode_select(scgp, dp, cnt, smp, pf)
- SCSI *scgp;
- Uchar *dp;
- int cnt;
- int smp;
- int pf;
- {
- if (is_atapi)
- return (mode_select_sg0(scgp, dp, cnt, smp, pf));
- return (mode_select_g0(scgp, dp, cnt, smp, pf));
- }
- EXPORT int
- mode_sense(scgp, dp, cnt, page, pcf)
- SCSI *scgp;
- Uchar *dp;
- int cnt;
- int page;
- int pcf;
- {
- if (is_atapi)
- return (mode_sense_sg0(scgp, dp, cnt, page, pcf));
- return (mode_sense_g0(scgp, dp, cnt, page, pcf));
- }
- /*
- * Simulate mode select g0 with mode select g1.
- */
- EXPORT int
- mode_select_sg0(scgp, dp, cnt, smp, pf)
- SCSI *scgp;
- Uchar *dp;
- int cnt;
- int smp;
- int pf;
- {
- Uchar xmode[256+4];
- int amt = cnt;
- if (amt < 1 || amt > 255) {
- /* XXX clear SCSI error codes ??? */
- return (-1);
- }
- if (amt < 4) { /* Data length. medium type & VU */
- amt += 1;
- } else {
- amt += 4;
- movebytes(&dp[4], &xmode[8], cnt-4);
- }
- xmode[0] = 0;
- xmode[1] = 0;
- xmode[2] = dp[1];
- xmode[3] = dp[2];
- xmode[4] = 0;
- xmode[5] = 0;
- i_to_2_byte(&xmode[6], (unsigned int)dp[3]);
- if (scgp->verbose) scsiprbytes("Mode Parameters (un-converted)", dp, cnt);
- return (mode_select_g1(scgp, xmode, amt, smp, pf));
- }
- /*
- * Simulate mode sense g0 with mode sense g1.
- */
- EXPORT int
- mode_sense_sg0(scgp, dp, cnt, page, pcf)
- SCSI *scgp;
- Uchar *dp;
- int cnt;
- int page;
- int pcf;
- {
- Uchar xmode[256+4];
- int amt = cnt;
- int len;
- if (amt < 1 || amt > 255) {
- /* XXX clear SCSI error codes ??? */
- return (-1);
- }
- fillbytes((caddr_t)xmode, sizeof(xmode), ' ');
- if (amt < 4) { /* Data length. medium type & VU */
- amt += 1;
- } else {
- amt += 4;
- }
- if (mode_sense_g1(scgp, xmode, amt, page, pcf) < 0)
- return (-1);
- amt = cnt - scsigetresid(scgp);
- if (amt > 4)
- movebytes(&xmode[8], &dp[4], amt-4);
- len = a_to_u_2_byte(xmode);
- if (len == 0) {
- dp[0] = 0;
- } else if (len < 6) {
- if (len > 2)
- len = 2;
- dp[0] = len;
- } else {
- dp[0] = len - 3;
- }
- dp[1] = xmode[2];
- dp[2] = xmode[3];
- len = a_to_u_2_byte(&xmode[6]);
- dp[3] = len;
- if (scgp->verbose) scsiprbytes("Mode Sense Data (converted)", dp, amt);
- return (0);
- }
- EXPORT int
- mode_select_g0(scgp, dp, cnt, smp, pf)
- SCSI *scgp;
- Uchar *dp;
- int cnt;
- int smp;
- int pf;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = (caddr_t)dp;
- scmd->size = cnt;
- 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_MODE_SELECT;
- scmd->cdb.g0_cdb.lun = scgp->lun;
- scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
- scmd->cdb.g0_cdb.count = cnt;
- if (scgp->verbose) {
- printf("%s ", smp?"Save":"Set ");
- scsiprbytes("Mode Parameters", dp, cnt);
- }
- scgp->cmdname = "mode select g0";
- return (scsicmd(scgp));
- }
- EXPORT int
- mode_select_g1(scgp, dp, cnt, smp, pf)
- SCSI *scgp;
- Uchar *dp;
- int cnt;
- int smp;
- int pf;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = (caddr_t)dp;
- scmd->size = cnt;
- 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 = 0x55;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- if (scgp->verbose) {
- printf("%s ", smp?"Save":"Set ");
- scsiprbytes("Mode Parameters", dp, cnt);
- }
- scgp->cmdname = "mode select g1";
- return (scsicmd(scgp));
- }
- EXPORT int
- mode_sense_g0(scgp, dp, cnt, page, pcf)
- SCSI *scgp;
- Uchar *dp;
- int cnt;
- int page;
- int pcf;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = (caddr_t)dp;
- scmd->size = 0xFF;
- 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_MODE_SENSE;
- scmd->cdb.g0_cdb.lun = scgp->lun;
- #ifdef nonono
- scmd->cdb.g0_cdb.high_addr = 1<<4; /* DBD Disable Block desc. */
- #endif
- scmd->cdb.g0_cdb.mid_addr = (page&0x3F) | ((pcf<<6)&0xC0);
- scmd->cdb.g0_cdb.count = page ? 0xFF : 24;
- scmd->cdb.g0_cdb.count = cnt;
- scgp->cmdname = "mode sense g0";
- if (scsicmd(scgp) < 0)
- return (-1);
- if (scgp->verbose) scsiprbytes("Mode Sense Data", dp, cnt - scsigetresid(scgp));
- return (0);
- }
- EXPORT int
- mode_sense_g1(scgp, dp, cnt, page, pcf)
- SCSI *scgp;
- Uchar *dp;
- int cnt;
- int page;
- int pcf;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = (caddr_t)dp;
- scmd->size = cnt;
- 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 = 0x5A;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- #ifdef nonono
- scmd->cdb.g0_cdb.high_addr = 1<<4; /* DBD Disable Block desc. */
- #endif
- scmd->cdb.g1_cdb.addr[0] = (page&0x3F) | ((pcf<<6)&0xC0);
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
- scgp->cmdname = "mode sense g1";
- if (scsicmd(scgp) < 0)
- return (-1);
- if (scgp->verbose) scsiprbytes("Mode Sense Data", dp, cnt - scsigetresid(scgp));
- return (0);
- }
- struct tocheader {
- Uchar len[2];
- Uchar first;
- Uchar last;
- };
- struct trackdesc {
- Uchar res0;
- #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
- Ucbit control : 4;
- Ucbit adr : 4;
- #else /* Motorola byteorder */
- Ucbit adr : 4;
- Ucbit control : 4;
- #endif
- Uchar track;
- Uchar res3;
- Uchar addr[4];
- };
- struct diskinfo {
- struct tocheader hd;
- struct trackdesc desc[1];
- };
- struct siheader {
- Uchar len[2];
- Uchar finished;
- Uchar unfinished;
- };
- struct sidesc {
- Uchar sess_number;
- Uchar res1;
- Uchar track;
- Uchar res3;
- Uchar addr[4];
- };
- struct sinfo {
- struct siheader hd;
- struct sidesc desc[1];
- };
- struct trackheader {
- Uchar mode;
- Uchar res[3];
- Uchar addr[4];
- };
- #define TRM_ZERO 0
- #define TRM_USER_ECC 1 /* 2048 bytes user data + 288 Bytes ECC/EDC */
- #define TRM_USER 2 /* All user data (2336 bytes) */
- struct ftrackdesc {
- Uchar sess_number;
- #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
- Ucbit control : 4;
- Ucbit adr : 4;
- #else /* Motorola byteorder */
- Ucbit adr : 4;
- Ucbit control : 4;
- #endif
- Uchar track;
- Uchar point;
- Uchar amin;
- Uchar asec;
- Uchar aframe;
- Uchar res7;
- Uchar pmin;
- Uchar psec;
- Uchar pframe;
- };
- struct fdiskinfo {
- struct tocheader hd;
- struct ftrackdesc desc[1];
- };
- EXPORT int
- read_tochdr(scgp, dp, fp, lp)
- SCSI *scgp;
- cdr_t *dp;
- int *fp;
- int *lp;
- {
- struct tocheader *tp;
- char xb[256];
- int len;
- tp = (struct tocheader *)xb;
- fillbytes((caddr_t)xb, sizeof(xb), ' ');
- if (read_toc(scgp, xb, 0, sizeof(struct tocheader), 0, FMT_TOC) < 0) {
- if (scgp->silent == 0)
- errmsgno(EX_BAD, "Cannot read TOC headern");
- return (-1);
- }
- len = a_to_u_2_byte(tp->len) + sizeof(struct tocheader)-2;
- if (len >= 4) {
- if (fp)
- *fp = tp->first;
- if (lp)
- *lp = tp->last;
- return (0);
- }
- return (-1);
- }
-
- EXPORT int
- read_cdtext(scgp)
- SCSI *scgp;
- {
- struct tocheader *tp;
- char xb[256];
- int len;
- char xxb[10000];
- tp = (struct tocheader *)xb;
- fillbytes((caddr_t)xb, sizeof(xb), ' ');
- if (read_toc(scgp, xb, 0, sizeof(struct tocheader), 0, FMT_CDTEXT) < 0) {
- if (scgp->silent == 0 || scgp->verbose > 0)
- errmsgno(EX_BAD, "Cannot read CD-Text headern");
- return (-1);
- }
- len = a_to_u_2_byte(tp->len) + sizeof(struct tocheader)-2;
- printf("CD-Text len: %dn", len);
- if (read_toc(scgp, xxb, 0, len, 0, FMT_CDTEXT) < 0) {
- if (scgp->silent == 0)
- errmsgno(EX_BAD, "Cannot read CD-Textn");
- return (-1);
- }
- {
- FILE *f = fileopen("cdtext.dat", "wct");
- filewrite(f, xxb, len);
- }
- return (0);
- }
-
- EXPORT int
- read_trackinfo(scgp, track, offp, msfp, adrp, controlp, modep)
- SCSI *scgp;
- int track;
- long *offp;
- struct msf *msfp;
- int *adrp;
- int *controlp;
- int *modep;
- {
- struct diskinfo *dp;
- char xb[256];
- int len;
- dp = (struct diskinfo *)xb;
- fillbytes((caddr_t)xb, sizeof(xb), ' ');
- if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 0, FMT_TOC) < 0) {
- if (scgp->silent <= 0)
- errmsgno(EX_BAD, "Cannot read TOCn");
- return (-1);
- }
- len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
- if (len < (int)sizeof(struct diskinfo))
- return (-1);
- if (offp)
- *offp = a_to_4_byte(dp->desc[0].addr);
- if (adrp)
- *adrp = dp->desc[0].adr;
- if (controlp)
- *controlp = dp->desc[0].control;
- if (msfp) {
- scgp->silent++;
- if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 1, FMT_TOC)
- >= 0) {
- msfp->msf_min = dp->desc[0].addr[1];
- msfp->msf_sec = dp->desc[0].addr[2];
- msfp->msf_frame = dp->desc[0].addr[3];
- } else if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 0, FMT_TOC)
- >= 0) {
- /*
- * Some drives (e.g. the Philips CDD-522) don't support
- * to read the TOC in MSF mode.
- */
- long off = a_to_4_byte(dp->desc[0].addr);
- lba_to_msf(off, msfp);
- } else {
- msfp->msf_min = 0;
- msfp->msf_sec = 0;
- msfp->msf_frame = 0;
- }
- scgp->silent--;
- }
- if (modep == NULL)
- return (0);
- if (track == 0xAA) {
- *modep = -1;
- return (0);
- }
- fillbytes((caddr_t)xb, sizeof(xb), ' ');
- scgp->silent++;
- if (read_header(scgp, xb, *offp, 8, 0) >= 0) {
- *modep = xb[0];
- } else if (read_track_info_philips(scgp, xb, track, 14) >= 0) {
- *modep = xb[0xb] & 0xF;
- } else {
- *modep = -1;
- }
- scgp->silent--;
- return (0);
- }
- EXPORT int
- read_B0(scgp, isbcd, b0p, lop)
- SCSI *scgp;
- BOOL isbcd;
- long *b0p;
- long *lop;
- {
- struct fdiskinfo *dp;
- struct ftrackdesc *tp;
- char xb[8192];
- char *pe;
- int len;
- long l;
- dp = (struct fdiskinfo *)xb;
- fillbytes((caddr_t)xb, sizeof(xb), ' ');
- if (read_toc_philips(scgp, xb, 1, sizeof(struct tocheader), 0, FMT_FULLTOC) < 0) {
- return (-1);
- }
- len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
- if (len < (int)sizeof(struct fdiskinfo))
- return (-1);
- if (read_toc_philips(scgp, xb, 1, len, 0, FMT_FULLTOC) < 0) {
- return (-1);
- }
- if (scgp->verbose) {
- scsiprbytes("TOC data: ", (Uchar *)xb,
- len > (int)sizeof(xb) - scsigetresid(scgp) ?
- sizeof(xb) - scsigetresid(scgp) : len);
- tp = &dp->desc[0];
- pe = &xb[len];
- while ((char *)tp < pe) {
- scsiprbytes("ENT: ", (Uchar *)tp, 11);
- tp++;
- }
- }
- tp = &dp->desc[0];
- pe = &xb[len];
- for (; (char *)tp < pe; tp++) {
- if (tp->sess_number != dp->hd.last)
- continue;
- if (tp->point != 0xB0)
- continue;
- if (scgp->verbose)
- scsiprbytes("B0: ", (Uchar *)tp, 11);
- if (isbcd) {
- l = msf_to_lba(from_bcd(tp->amin),
- from_bcd(tp->asec),
- from_bcd(tp->aframe));
- } else {
- l = msf_to_lba(tp->amin,
- tp->asec,
- tp->aframe);
- }
- if (b0p)
- *b0p = l;
- if (scgp->verbose)
- printf("B0 start: %ldn", l);
- if (isbcd) {
- l = msf_to_lba(from_bcd(tp->pmin),
- from_bcd(tp->psec),
- from_bcd(tp->pframe));
- } else {
- l = msf_to_lba(tp->pmin,
- tp->psec,
- tp->pframe);
- }
- if (scgp->verbose)
- printf("B0 lout: %ldn", l);
- if (lop)
- *lop = l;
- return (0);
- }
- return (-1);
- }
- /*
- * Return address of first track in last session (SCSI-3/mmc version).
- */
- EXPORT int
- read_session_offset(scgp, offp)
- SCSI *scgp;
- long *offp;
- {
- struct diskinfo *dp;
- char xb[256];
- int len;
- dp = (struct diskinfo *)xb;
- fillbytes((caddr_t)xb, sizeof(xb), ' ');
- if (read_toc(scgp, (caddr_t)xb, 0, sizeof(struct tocheader), 0, FMT_SINFO) < 0)
- return (-1);
- if (scgp->verbose)
- scsiprbytes("tocheader: ",
- (Uchar *)xb, sizeof(struct tocheader) - scsigetresid(scgp));
- len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
- if (len > (int)sizeof(xb)) {
- errmsgno(EX_BAD, "Session info too big.n");
- return (-1);
- }
- if (read_toc(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
- return (-1);
- if (scgp->verbose)
- scsiprbytes("tocheader: ",
- (Uchar *)xb, len - scsigetresid(scgp));
- dp = (struct diskinfo *)xb;
- if (offp)
- *offp = a_to_u_4_byte(dp->desc[0].addr);
- return (0);
- }
- /*
- * Return address of first track in last session (pre SCSI-3 version).
- */
- EXPORT int
- read_session_offset_philips(scgp, offp)
- SCSI *scgp;
- long *offp;
- {
- struct sinfo *sp;
- char xb[256];
- int len;
- sp = (struct sinfo *)xb;
- fillbytes((caddr_t)xb, sizeof(xb), ' ');
- if (read_toc_philips(scgp, (caddr_t)xb, 0, sizeof(struct siheader), 0, FMT_SINFO) < 0)
- return (-1);
- len = a_to_u_2_byte(sp->hd.len) + sizeof(struct siheader)-2;
- if (len > (int)sizeof(xb)) {
- errmsgno(EX_BAD, "Session info too big.n");
- return (-1);
- }
- if (read_toc_philips(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
- return (-1);
- /*
- * Old drives return the number of finished sessions in first/finished
- * a descriptor is returned for each session.
- * New drives return the number of the first and last session
- * one descriptor for the last finished session is returned
- * as in SCSI-3
- * In all cases the lowest session number is set to 1.
- */
- sp = (struct sinfo *)xb;
- if (offp)
- *offp = a_to_u_4_byte(sp->desc[sp->hd.finished-1].addr);
- return (0);
- }
- EXPORT int
- sense_secsize(scgp, current)
- SCSI *scgp;
- int current;
- {
- Uchar mode[0x100];
- Uchar *p;
- Uchar *ep;
- int secsize = -1;
- scgp->silent++;
- (void)unit_ready(scgp);
- scgp->silent--;
- /* XXX Quick and dirty, musz verallgemeinert werden !!! */
- fillbytes(mode, sizeof(mode), ' ');
- scgp->silent++;
- if (mode_sense(scgp, mode, 0xFF, 0x3F, current?0:2) < 0) { /* All Pages */
- fillbytes(mode, sizeof(mode), ' ');
- if (mode_sense(scgp, mode, 0xFF, 0, current?0:2) < 0) {/* VU (block desc) */
- scgp->silent--;
- return (-1);
- }
- }
- scgp->silent--;
- ep = mode+mode[0]; /* Points to last byte of data */
- p = &mode[4];
- p += mode[3];
- if (scgp->debug) {
- printf("Pages: ");
- while (p < ep) {
- printf("0x%x ", *p&0x3F);
- p += p[1]+2;
- }
- printf("n");
- }
- if (mode[3] == 8) {
- if (scgp->debug) {
- printf("Density: 0x%xn", mode[4]);
- printf("Blocks: %ldn", a_to_u_3_byte(&mode[5]));
- printf("Blocklen:%ldn", a_to_u_3_byte(&mode[9]));
- }
- secsize = a_to_u_3_byte(&mode[9]);
- }
- return (secsize);
- }
- EXPORT int
- select_secsize(scgp, secsize)
- SCSI *scgp;
- int secsize;
- {
- struct scsi_mode_data md;
- int count = sizeof(struct scsi_mode_header) +
- sizeof(struct scsi_mode_blockdesc);
- (void)test_unit_ready(scgp); /* clear any error situation */
- fillbytes((caddr_t)&md, sizeof(md), ' ');
- md.header.blockdesc_len = 8;
- i_to_3_byte(md.blockdesc.lblen, secsize);
-
- return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
- }
- EXPORT BOOL
- is_cddrive(scgp)
- SCSI *scgp;
- {
- return (scgp->inq->type == INQ_ROMD || scgp->inq->type == INQ_WORM);
- }
- EXPORT BOOL
- is_unknown_dev(scgp)
- SCSI *scgp;
- {
- return (scgp->dev == DEV_UNKNOWN);
- }
- #define DEBUG
- #ifdef DEBUG
- #define G0_MAXADDR 0x1FFFFFL
- EXPORT int
- read_scsi(scgp, bp, addr, cnt)
- SCSI *scgp;
- caddr_t bp;
- long addr;
- int cnt;
- {
- if(addr <= G0_MAXADDR && cnt < 256 && !is_atapi)
- return (read_g0(scgp, bp, addr, cnt));
- else
- return (read_g1(scgp, bp, addr, cnt));
- }
- EXPORT int
- read_g0(scgp, bp, addr, cnt)
- SCSI *scgp;
- caddr_t bp;
- long addr;
- int cnt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- if (scgp->cap->c_bsize <= 0)
- raisecond("capacity_not_set", 0L);
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt*scgp->cap->c_bsize;
- 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_READ;
- scmd->cdb.g0_cdb.lun = scgp->lun;
- g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
- scmd->cdb.g0_cdb.count = cnt;
- /* scmd->cdb.g0_cdb.vu_56 = 1;*/
-
- scgp->cmdname = "read_g0";
- return (scsicmd(scgp));
- }
- EXPORT int
- read_g1(scgp, bp, addr, cnt)
- SCSI *scgp;
- caddr_t bp;
- long addr;
- int cnt;
- {
- register struct scg_cmd *scmd = scgp->scmd;
- if (scgp->cap->c_bsize <= 0)
- raisecond("capacity_not_set", 0L);
- fillbytes((caddr_t)scmd, sizeof(*scmd), ' ');
- scmd->addr = bp;
- scmd->size = cnt*scgp->cap->c_bsize;
- 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 = SC_EREAD;
- scmd->cdb.g1_cdb.lun = scgp->lun;
- g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
- g1_cdblen(&scmd->cdb.g1_cdb, cnt);
-
- scgp->cmdname = "read_g1";
- return (scsicmd(scgp));
- }
- #endif /* DEBUG */
- EXPORT BOOL
- getdev(scgp, print)
- SCSI *scgp;
- BOOL print;
- {
- BOOL got_inquiry = TRUE;
- char vendor_info[8+1];
- char prod_ident[16+1];
- char prod_revision[4+1];
- int inq_len = 0;
- register struct scg_cmd *scmd = scgp->scmd;
- register struct scsi_inquiry *inq = scgp->inq;
- fillbytes((caddr_t)inq, sizeof(*inq), ' ');
- scgp->dev = DEV_UNKNOWN;
- scgp->silent++;
- (void)unit_ready(scgp);
- if (scmd->error >= SCG_FATAL &&
- !(scmd->scb.chk && scmd->sense_count > 0)) {
- scgp->silent--;
- return (FALSE);
- }
- /* if (scmd->error < SCG_FATAL || scmd->scb.chk && scmd->sense_count > 0){*/
- if (inquiry(scgp, (caddr_t)inq, sizeof(*inq)) < 0) {
- got_inquiry = FALSE;
- } else {
- inq_len = sizeof(*inq) - scsigetresid(scgp);
- }
- if (!got_inquiry) {
- if (scgp->verbose) {
- printf(
- "error: %d scb.chk: %d sense_count: %d sense.code: 0x%xn",
- scmd->error, scmd->scb.chk,
- scmd->sense_count, scmd->sense.code);
- }
- /*
- * Folgende Kontroller kennen das Kommando
- * INQUIRY nicht:
- *
- * ADAPTEC ACB-4000, ACB-4010, ACB 4070
- * SYSGEN SC4000
- *
- * Leider reagieren ACB40X0 und ACB5500 identisch
- * wenn drive not ready (code == not ready),
- * sie sind dann nicht zu unterscheiden.
- */
- if (scmd->scb.chk && scmd->sense_count == 4) {
- /* Test auf SYSGEN */
- (void)qic02(scgp, 0x12); /* soft lock on */
- if (qic02(scgp, 1) < 0) { /* soft lock off */
- scgp->dev = DEV_ACB40X0;
- /* scgp->dev = acbdev();*/
- } else {
- scgp->dev = DEV_SC4000;
- inq->type = INQ_SEQD;
- inq->removable = 1;
- }
- }
- } else if (scgp->verbose) {
- int i;
- int len = inq->add_len + 5;
- Uchar ibuf[256+5];
- Uchar *ip = (Uchar *)inq;
- Uchar c;
- if (len > (int)sizeof (*inq) &&
- inquiry(scgp, (caddr_t)ibuf, inq->add_len+5) >= 0) {
- len = inq->add_len+5 - scsigetresid(scgp);
- ip = ibuf;
- } else {
- len = sizeof (*inq);
- }
- printf("Inquiry Data : ");
- for (i = 0; i < len; i++) {
- c = ip[i];
- if (c >= ' ' && c < 0177)
- printf("%c", c);
- else
- printf(".");
- }
- printf("n");
- }
- strncpy(vendor_info, inq->vendor_info, sizeof(inq->vendor_info));
- strncpy(prod_ident, inq->prod_ident, sizeof(inq->prod_ident));
- strncpy(prod_revision, inq->prod_revision, sizeof(inq->prod_revision));
- vendor_info[sizeof(inq->vendor_info)] = ' ';
- prod_ident[sizeof(inq->prod_ident)] = ' ';
- prod_revision[sizeof(inq->prod_revision)] = ' ';
- switch (inq->type) {
- case INQ_DASD:
- if (inq->add_len == 0 && inq->vendor_info[0] != ' ') {
- Uchar *p;
- /*
- * NT-4.0 creates fake inquiry data for IDE disks.
- * Unfortunately, it does not set add_len wo we
- * check if vendor_info, prod_ident and prod_revision
- * contains valid chars for a CCS inquiry.
- */
- if (inq_len >= 36)
- inq->add_len = 31;
- for (p = (Uchar *)&inq->vendor_info[0];
- p < (Uchar *)&inq->prod_revision[4];
- p++) {
- if (*p < 0x20 || *p > 0x7E) {
- inq->add_len = 0;
- break;
- }
- }
- }
- if (inq->add_len == 0) {
- if (scgp->dev == DEV_UNKNOWN && got_inquiry) {
- scgp->dev = DEV_ACB5500;
- strcpy(inq->vendor_info,
- "ADAPTEC ACB-5500 FAKE");
- } else switch (scgp->dev) {
- case DEV_ACB40X0:
- strcpy(inq->vendor_info,
- "ADAPTEC ACB-40X0 FAKE");
- break;
- case DEV_ACB4000:
- strcpy(inq->vendor_info,
- "ADAPTEC ACB-4000 FAKE");
- break;
- case DEV_ACB4010:
- strcpy(inq->vendor_info,
- "ADAPTEC ACB-4010 FAKE");
- break;
- case DEV_ACB4070:
- strcpy(inq->vendor_info,
- "ADAPTEC ACB-4070 FAKE");
- break;
- }
- } else if (inq->add_len < 31) {
- scgp->dev = DEV_NON_CCS_DSK;
- } else if (strbeg("EMULEX", vendor_info)) {
- if (strbeg("MD21", prod_ident))
- scgp->dev = DEV_MD21;
- if (strbeg("MD23", prod_ident))
- scgp->dev = DEV_MD23;
- else
- scgp->dev = DEV_CCS_GENDISK;
- } else if (strbeg("ADAPTEC", vendor_info)) {
- if (strbeg("ACB-4520", prod_ident))
- scgp->dev = DEV_ACB4520A;
- if (strbeg("ACB-4525", prod_ident))
- scgp->dev = DEV_ACB4525;
- else
- scgp->dev = DEV_CCS_GENDISK;
- } else if (strbeg("SONY", vendor_info) &&
- strbeg("SMO-C501", prod_ident)) {
- scgp->dev = DEV_SONY_SMO;
- } else {
- scgp->dev = DEV_CCS_GENDISK;
- }
- break;
- case INQ_SEQD:
- if (scgp->dev == DEV_SC4000) {
- strcpy(inq->vendor_info,
- "SYSGEN SC4000 FAKE");
- } else if (inq->add_len == 0 &&
- inq->removable &&
- inq->ansi_version == 1) {
- scgp->dev = DEV_MT02;
- strcpy(inq->vendor_info,
- "EMULEX MT02 FAKE");
- }
- break;
- /* case INQ_OPTD:*/
- case INQ_ROMD:
- case INQ_WORM:
- if (strbeg("RXT-800S", prod_ident))
- scgp->dev = DEV_RXT800S;
- /*
- * Start of CD-Recorders:
- */
- if (strbeg("ACER", vendor_info)) {
- if (strbeg("CR-4020C", prod_ident))
- scgp->dev = DEV_RICOH_RO_1420C;
- } else if (strbeg("CREATIVE", vendor_info)) {
- if (strbeg("CDR2000", prod_ident))
- scgp->dev = DEV_RICOH_RO_1060C;
- } else if (strbeg("GRUNDIG", vendor_info)) {
- if (strbeg("CDR100IPW", prod_ident))
- scgp->dev = DEV_CDD_2000;
- } else if (strbeg("JVC", vendor_info)) {
- if (strbeg("XR-W2001", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- else if (strbeg("XR-W2010", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- else if (strbeg("R2626", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- } else if (strbeg("MITSBISH", vendor_info)) {
- #ifdef XXXX_REALLY
- /* It's MMC compliant */
- if (strbeg("CDRW226", prod_ident))
- scgp->dev = DEV_MMC_CDRW;
- #endif
- } else if (strbeg("MITSUMI", vendor_info)) {
- /* Don't know any product string */
- scgp->dev = DEV_CDD_522;
- } else if (strbeg("OPTIMA", vendor_info)) {
- if (strbeg("CD-R 650", prod_ident))
- scgp->dev = DEV_SONY_CDU_924;
- } else if (strbeg("PHILIPS", vendor_info) ||
- strbeg("IMS", vendor_info) ||
- strbeg("KODAK", vendor_info) ||
- strbeg("HP", vendor_info)) {
- if (strbeg("CDD521/00", prod_ident))
- scgp->dev = DEV_CDD_521_OLD;
- else if (strbeg("CDD521/02", prod_ident))
- scgp->dev = DEV_CDD_521_OLD; /* PCD 200R? */
- else if (strbeg("CDD521", prod_ident))
- scgp->dev = DEV_CDD_521;
- if (strbeg("CDD522", prod_ident))
- scgp->dev = DEV_CDD_522;
- if (strbeg("PCD225", prod_ident))
- scgp->dev = DEV_CDD_522;
- if (strbeg("KHSW/OB", prod_ident)) /* PCD600 */
- scgp->dev = DEV_PCD_600;
- if (strbeg("CDR-240", prod_ident))
- scgp->dev = DEV_CDD_2000;
- if (strbeg("CDD20", prod_ident))
- scgp->dev = DEV_CDD_2000;
- if (strbeg("CDD26", prod_ident))
- scgp->dev = DEV_CDD_2600;
- if (strbeg("C4324/C4325", prod_ident))
- scgp->dev = DEV_CDD_2000;
- if (strbeg("CD-Writer 6020", prod_ident))
- scgp->dev = DEV_CDD_2600;
- } else if (strbeg("PINNACLE", vendor_info)) {
- if (strbeg("RCD-1000", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- if (strbeg("RCD5020", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- if (strbeg("RCD5040", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- if (strbeg("RCD 4X4", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- } else if (strbeg("PIONEER", vendor_info)) {
- if (strbeg("CD-WO DW-S114X", prod_ident))
- scgp->dev = DEV_PIONEER_DW_S114X;
- else if (strbeg("DVD-R DVR-S101", prod_ident))
- scgp->dev = DEV_PIONEER_DVDR_S101;
- } else if (strbeg("PLASMON", vendor_info)) {
- if (strbeg("RF4100", prod_ident))
- scgp->dev = DEV_PLASMON_RF_4100;
- else if (strbeg("CDR4220", prod_ident))
- scgp->dev = DEV_CDD_2000;
- } else if (strbeg("PLEXTOR", vendor_info)) {
- if (strbeg("CD-R PX-R24CS", prod_ident))
- scgp->dev = DEV_RICOH_RO_1420C;
- } else if (strbeg("RICOH", vendor_info)) {
- if (strbeg("RO-1420C", prod_ident))
- scgp->dev = DEV_RICOH_RO_1420C;
- if (strbeg("RO1060C", prod_ident))
- scgp->dev = DEV_RICOH_RO_1060C;
- } else if (strbeg("SAF", vendor_info)) { /* Smart & Friendly */
- if (strbeg("CD-R2004", prod_ident) ||
- strbeg("CD-R2006 ", prod_ident))
- scgp->dev = DEV_SONY_CDU_924;
- else if (strbeg("CD-R2006PLUS", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- else if (strbeg("CD-RW226", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- else if (strbeg("CD-R4012", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- } else if (strbeg("SONY", vendor_info)) {
- if (strbeg("CD-R CDU92", prod_ident) ||
- strbeg("CD-R CDU94", prod_ident))
- scgp->dev = DEV_SONY_CDU_924;
- } else if (strbeg("TEAC", vendor_info)) {
- if (strbeg("CD-R50S", prod_ident) ||
- strbeg("CD-R55S", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- } else if (strbeg("TRAXDATA", vendor_info) ||
- strbeg("Traxdata", vendor_info)) {
- if (strbeg("CDR4120", prod_ident))
- scgp->dev = DEV_TEAC_CD_R50S;
- } else if (strbeg("T.YUDEN", vendor_info)) {
- if (strbeg("CD-WO EW-50", prod_ident))
- scgp->dev = DEV_CDD_521;
- } else if (strbeg("WPI", vendor_info)) { /* Wearnes */
- if (strbeg("CDR-632P", prod_ident))
- scgp->dev = DEV_CDD_2600;
- } else if (strbeg("YAMAHA", vendor_info)) {
- if (strbeg("CDR10", prod_ident))
- scgp->dev = DEV_YAMAHA_CDR_100;
- if (strbeg("CDR200", prod_ident))
- scgp->dev = DEV_YAMAHA_CDR_400;
- if (strbeg("CDR400", prod_ident))
- scgp->dev = DEV_YAMAHA_CDR_400;
- } else if (strbeg("MATSHITA", vendor_info)) {
- if (strbeg("CD-R CW-7501", prod_ident))
- scgp->dev = DEV_MATSUSHITA_7501;
- if (strbeg("CD-R CW-7502", prod_ident))
- scgp->dev = DEV_MATSUSHITA_7502;
- }
- if (scgp->dev == DEV_UNKNOWN) {
- /*
- * We do not have Manufacturer strings for
- * the following drives.
- */
- if (strbeg("CDS615E", prod_ident)) /* Olympus */
- scgp->dev = DEV_SONY_CDU_924;
- }
- if (scgp->dev == DEV_UNKNOWN && inq->type == INQ_ROMD) {
- BOOL cdrr = FALSE;
- BOOL cdwr = FALSE;
- BOOL cdrrw = FALSE;
- BOOL cdwrw = FALSE;
- BOOL dvd = FALSE;
- scgp->dev = DEV_CDROM;
- if (mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, &dvd))
- scgp->dev = DEV_MMC_CDROM;
- if (cdwr)
- scgp->dev = DEV_MMC_CDR;
- if (cdwrw)
- scgp->dev = DEV_MMC_CDRW;
- if (dvd)
- scgp->dev = DEV_MMC_DVD;
- }
- case INQ_PROCD:
- if (strbeg("BERTHOLD", vendor_info)) {
- if (strbeg("", prod_ident))
- scgp->dev = DEV_HRSCAN;
- }
- break;
- case INQ_SCAN:
- scgp->dev = DEV_MS300A;
- break;
- }
- scgp->silent--;
- if (!print)
- return (TRUE);
- if (scgp->dev == DEV_UNKNOWN && !got_inquiry) {
- #ifdef PRINT_INQ_ERR
- scsiprinterr(scgp);
- #endif
- return (FALSE);
- }
- printf("Device type : ");
- scsiprintdev(inq);
- printf("Version : %dn", inq->ansi_version);
- printf("Response Format: %dn", inq->data_format);
- if (inq->data_format >= 2) {
- printf("Capabilities : ");
- if (inq->aenc) printf("AENC ");
- if (inq->termiop) printf("TERMIOP ");
- if (inq->reladr) printf("RELADR ");
- if (inq->wbus32) printf("WBUS32 ");
- if (inq->wbus16) printf("WBUS16 ");
- if (inq->sync) printf("SYNC ");
- if (inq->linked) printf("LINKED ");
- if (inq->cmdque) printf("CMDQUE ");
- if (inq->softreset) printf("SOFTRESET ");
- printf("n");
- }
- if (inq->add_len >= 31 ||
- inq->info[0] || inq->ident[0] || inq->revision[0]) {
- printf("Vendor_info : '%.8s'n", inq->info);
- printf("Identifikation : '%.16s'n", inq->ident);
- printf("Revision : '%.4s'n", inq->revision);
- }
- return (TRUE);
- }
- EXPORT void
- printdev(scgp)
- SCSI *scgp;
- {
- printf("Device seems to be: ");
- switch (scgp->dev) {
- case DEV_UNKNOWN: printf("unknown"); break;
- case DEV_ACB40X0: printf("Adaptec 4000/4010/4070");break;
- case DEV_ACB4000: printf("Adaptec 4000"); break;
- case DEV_ACB4010: printf("Adaptec 4010"); break;
- case DEV_ACB4070: printf("Adaptec 4070"); break;
- case DEV_ACB5500: printf("Adaptec 5500"); break;
- case DEV_ACB4520A: printf("Adaptec 4520A"); break;
- case DEV_ACB4525: printf("Adaptec 4525"); break;
- case DEV_MD21: printf("Emulex MD21"); break;
- case DEV_MD23: printf("Emulex MD23"); break;
- case DEV_NON_CCS_DSK: printf("Generic NON CCS Disk"); break;
- case DEV_CCS_GENDISK: printf("Generic CCS Disk"); break;
- case DEV_SONY_SMO: printf("Sony SMO-C501"); break;
- case DEV_MT02: printf("Emulex MT02"); break;
- case DEV_SC4000: printf("Sysgen SC4000"); break;
- case DEV_RXT800S: printf("Maxtor RXT800S"); break;
- case DEV_HRSCAN: printf("Berthold HR-Scanner"); break;
- case DEV_MS300A: printf("Microtek MS300A"); break;
- case DEV_CDROM: printf("Generic CD-ROM"); break;
- case DEV_MMC_CDROM: printf("Generic mmc CD-ROM"); break;
- case DEV_MMC_CDR: printf("Generic mmc CD-R"); break;
- case DEV_MMC_CDRW: printf("Generic mmc CD-RW"); break;
- case DEV_MMC_DVD: printf("Generic mmc2 DVD"); break;
- case DEV_CDD_521_OLD: printf("Philips old CDD-521"); break;
- case DEV_CDD_521: printf("Philips CDD-521"); break;
- case DEV_CDD_522: printf("Philips CDD-522"); break;
- case DEV_PCD_600: printf("Kodak PCD-600"); break;
- case DEV_CDD_2000: printf("Philips CDD-2000"); break;
- case DEV_CDD_2600: printf("Philips CDD-2600"); break;
- case DEV_YAMAHA_CDR_100:printf("Yamaha CDR-100"); break;
- case DEV_YAMAHA_CDR_400:printf("Yamaha CDR-400"); break;
- case DEV_PLASMON_RF_4100:printf("Plasmon RF-4100"); break;
- case DEV_SONY_CDU_924: printf("Sony CDU-924S"); break;
- case DEV_RICOH_RO_1060C:printf("Ricoh RO-1060C"); break;
- case DEV_RICOH_RO_1420C:printf("Ricoh RO-1420C"); break;
- case DEV_TEAC_CD_R50S: printf("Teac CD-R50S"); break;
- case DEV_MATSUSHITA_7501:printf("Matsushita CW-7501"); break;
- case DEV_MATSUSHITA_7502:printf("Matsushita CW-7502"); break;
- case DEV_PIONEER_DW_S114X: printf("Pioneer DW-S114X"); break;
- case DEV_PIONEER_DVDR_S101:printf("Pioneer DVD-R S101");break;
- default: printf("Missing Entry for dev %d",
- scgp->dev); break;
- }
- printf(".n");
- }
- EXPORT BOOL
- do_inquiry(scgp, print)
- SCSI *scgp;
- int print;
- {
- if (getdev(scgp, print)) {
- if (print)
- printdev(scgp);
- return (TRUE);
- } else {
- return (FALSE);
- }
- }
- EXPORT BOOL
- recovery_needed(scgp)
- SCSI *scgp;
- {
- int err;
- register struct scg_cmd *scmd = scgp->scmd;
- scgp->silent++;
- err = test_unit_ready(scgp);
- scgp->silent--;
- if (err >= 0)
- return (FALSE);
- else if (scmd->error >= SCG_FATAL) /* nicht selektierbar */
- return (FALSE);
- if (scmd->sense.code < 0x70) /* non extended Sense */
- return (FALSE);
- /* XXX Old Philips code */
- return (((struct scsi_ext_sense *)&scmd->sense)->sense_code == 0xD0);
- }
- EXPORT int
- scsi_load(scgp)
- SCSI *scgp;
- {
- return (scsi_start_stop_unit(scgp, 1, 1));
- }
- EXPORT int
- scsi_unload(scgp)
- SCSI *scgp;
- {
- return (scsi_start_stop_unit(scgp, 0, 1));
- }
- EXPORT int
- scsi_cdr_write(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 */
- {
- return (write_xg1(scgp, bp, sectaddr, size, blocks));
- }
- EXPORT struct cd_mode_page_2A *
- mmc_cap(scgp, modep)
- SCSI *scgp;
- Uchar *modep;
- {
- int len;
- int val;
- Uchar mode[0x100];
- struct cd_mode_page_2A *mp;
- struct cd_mode_page_2A *mp2;
- retry:
- fillbytes((caddr_t)mode, sizeof(mode), ' ');
- if (!get_mode_params(scgp, 0x2A, "CD capabilities",
- mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
- if (scsi_sense_key(scgp) == SC_NOT_READY) {
- if (wait_unit_ready(scgp, 60))
- goto retry;
- }
- return (NULL); /* Pre SCSI-3/mmc drive */
- }
- if (len == 0) /* Pre SCSI-3/mmc drive */
- return (NULL);
- mp = (struct cd_mode_page_2A *)
- (mode + sizeof(struct scsi_mode_header) +
- ((struct scsi_mode_header *)mode)->blockdesc_len);
- /*
- * Do some heuristics against pre SCSI-3/mmc VU page 2A
- * We should test for a minimum p_len of 0x14, but some
- * buggy CD-ROM readers ommit the write speed values.
- */
- if (mp->p_len < 0x10)
- return (NULL);
- val = a_to_u_2_byte(mp->max_read_speed);
- if (val != 0 && val < 176)
- return (NULL);
- val = a_to_u_2_byte(mp->cur_read_speed);
- if (val != 0 && val < 176)
- return (NULL);
- len -= sizeof(struct scsi_mode_header) +
- ((struct scsi_mode_header *)mode)->blockdesc_len;
- if (modep)
- mp2 = (struct cd_mode_page_2A *)modep;
- else
- mp2 = (struct cd_mode_page_2A *)malloc(len);
- if (mp2)
- movebytes(mp, mp2, len);
- return (mp2);
- }
- EXPORT void
- mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp)
- struct cd_mode_page_2A *mp;
- BOOL *cdrrp;
- BOOL *cdwrp;
- BOOL *cdrrwp;
- BOOL *cdwrwp;
- BOOL *dvdp;
- {
- if (cdrrp)
- *cdrrp = (mp->cd_r_read != 0); /* SCSI-3/mmc CD */
- if (cdwrp)
- *cdwrp = (mp->cd_r_write != 0); /* SCSI-3/mmc CD-R */
- if (cdrrwp)
- *cdrrwp = (mp->cd_rw_read != 0);/* SCSI-3/mmc CD */
- if (cdwrwp)
- *cdwrwp = (mp->cd_rw_write != 0);/* SCSI-3/mmc CD-RW */
- if (dvdp) {
- *dvdp = /* SCSI-3/mmc2 DVD */
- (mp->dvd_ram_read + mp->dvd_r_read + mp->dvd_rom_read +
- mp->dvd_ram_write + mp->dvd_r_write) != 0;
- }
- }
- EXPORT BOOL
- is_mmc(scgp, dvdp)
- SCSI *scgp;
- BOOL *dvdp;
- {
- return (mmc_check(scgp, NULL, NULL, NULL, NULL, dvdp));
- }
- EXPORT BOOL
- mmc_check(scgp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp)
- SCSI *scgp;
- BOOL *cdrrp;
- BOOL *cdwrp;
- BOOL *cdrrwp;
- BOOL *cdwrwp;
- BOOL *dvdp;
- {
- Uchar mode[0x100];
- BOOL was_atapi;
- struct cd_mode_page_2A *mp;
- if (scgp->inq->type != INQ_ROMD)
- return (FALSE);
- fillbytes((caddr_t)mode, sizeof(mode), ' ');
- was_atapi = allow_atapi(scgp, TRUE);
- scgp->silent++;
- mp = mmc_cap(scgp, mode);
- scgp->silent--;
- allow_atapi(scgp, was_atapi);
- if (mp == NULL)
- return (FALSE);
- mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp);
- return (TRUE); /* Generic SCSI-3/mmc CD */
- }
- #define DOES(what,flag) printf(" Does %s%sn", flag?"":"not ",what);
- #define IS(what,flag) printf(" Is %s%sn", flag?"":"not ",what);
- #define VAL(what,val) printf(" %s: %dn", what, val[0]*256 + val[1]);
- #define SVAL(what,val) printf(" %s: %sn", what, val);
- EXPORT void
- print_capabilities(scgp)
- SCSI *scgp;
- {
- BOOL was_atapi;
- Uchar mode[0x100];
- struct cd_mode_page_2A *mp;
- static const char *bclk[4] = {"32", "16", "24", "24 (I2S)"};
- static const char *load[8] = {"caddy", "tray", "pop-up", "reserved(3)",
- "disc changer", "cartridge changer",
- "reserved(6)", "reserved(7)" };
- if (scgp->inq->type != INQ_ROMD)
- return;
- fillbytes((caddr_t)mode, sizeof(mode), ' ');
- was_atapi = allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
- scgp->silent++;
- mp = mmc_cap(scgp, mode);
- scgp->silent--;
- allow_atapi(scgp, was_atapi);
- if (mp == NULL)
- return;
- printf ("nDrive capabilities, per page 2A:nn");
- DOES("read CD-R media", mp->cd_r_read);
- DOES("write CD-R media", mp->cd_r_write);
- DOES("read CD-RW media", mp->cd_rw_read);
- DOES("write CD-RW media", mp->cd_rw_write);
- DOES("read DVD-ROM media", mp->dvd_rom_read);
- DOES("read DVD-R media", mp->dvd_r_read);
- DOES("write DVD-R media", mp->dvd_r_write);
- DOES("read DVD-RAM media", mp->dvd_ram_read);
- DOES("write DVD-RAM media", mp->dvd_ram_write);
- DOES("support test writing", mp->test_write);
- printf("n");
- DOES("read Mode 2 Form 1 blocks", mp->mode_2_form_1);
- DOES("read Mode 2 Form 2 blocks", mp->mode_2_form_2);
- DOES("read digital audio blocks", mp->cd_da_supported);
- if (mp->cd_da_supported)
- DOES("restart non-streamed digital audio reads accurately", mp->cd_da_accurate);
- DOES("read multi-session CDs", mp->multi_session);
- DOES("read fixed-packet CD media using Method 2", mp->method2);
- DOES("read CD bar code", mp->read_bar_code);
- DOES("read R-W subcode information", mp->rw_supported);
- if (mp->rw_supported)
- DOES("return R-W subcode de-interleaved and error-corrected", mp->rw_deint_corr);
- DOES("return CD media catalog number", mp->UPC);
- DOES("return CD ISRC information", mp->ISRC);
- DOES("support C2 error pointers", mp->c2_pointers);
- DOES("deliver composite A/V data", mp->composite);
- printf("n");
- DOES("play audio CDs", mp->audio_play);
- if (mp->audio_play) {
- VAL("Number of volume control levels", mp->num_vol_levels);
- DOES("support individual volume control setting for each channel", mp->sep_chan_vol);
- DOES("support independent mute setting for each channel", mp->sep_chan_mute);
- DOES("support digital output on port 1", mp->digital_port_1);
- DOES("support digital output on port 2", mp->digital_port_2);
- if (mp->digital_port_1 || mp->digital_port_2) {
- DOES("send digital data LSB-first", mp->LSBF);
- DOES("set LRCK high for left-channel data", mp->RCK);
- DOES("have valid data on falling edge of clock", mp->BCK);
- SVAL("Length of data in BCLKs", bclk[mp->length]);
- }
- }
- printf("n");
- SVAL("Loading mechanism type", load[mp->loading_type]);
- DOES("support ejection of CD via START/STOP command", mp->eject);
- DOES("lock media on power up via prevent jumper", mp->prevent_jumper);
- DOES("allow media to be locked in the drive via PREVENT/ALLOW command", mp->lock);
- IS("currently in a media-locked state", mp->lock_state);
- DOES("have load-empty-slot-in-changer feature", mp->sw_slot_sel);
- DOES("support Individual Disk Present feature", mp->disk_present_rep);
- printf("n");
- VAL("Maximum read speed in kB/s", mp->max_read_speed);
- VAL("Current read speed in kB/s", mp->cur_read_speed);
- VAL("Maximum write speed in kB/s", mp->max_write_speed);
- VAL("Current write speed in kB/s", mp->cur_write_speed);
- VAL("Buffer size in KB", mp->buffer_size);
- return; /* Generic SCSI-3/mmc CD */
- }