2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)readcd.c 1.80 06/02/05 Copyright 1987, 1995-2006 J. Schilling */
15 * Skeleton for the use of the usal genearal SCSI - driver
17 * Copyright (c) 1987, 1995-2004 J. Schilling
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License version 2
22 * as published by the Free Software Foundation.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License along with
30 * this program; see the file COPYING. If not, write to the Free Software
31 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
49 #include <io.h> /* for setmode() prototype */
52 #include <usal/usalcmd.h>
53 #include <usal/scsireg.h>
54 #include <usal/scsitransp.h>
56 #include "scsi_scan.h"
58 #define qpto96 __nothing__
64 char cdr_version[] = "2.01.01a05";
66 #if defined(PROTOTYPES)
67 #define UINT_C(a) (a##u)
68 #define ULONG_C(a) (a##ul)
69 #define USHORT_C(a) (a##uh)
70 #define CONCAT(a, b) a##b
72 #define UINT_C(a) ((unsigned)(a))
73 #define ULONG_C(a) ((unsigned long)(a))
74 #define USHORT_C(a) ((unsigned short)(a))
76 #define CONCAT(a, b) a/**/b
79 extern BOOL getlong(char *, long *, long, long);
80 extern BOOL getint(char *, int *, int, int);
85 long sptr; /* sectors per transfer */
109 BOOL cvt_bcyls(void);
110 void print_defect_list(void);
111 static void usage(int ret);
112 static void intr(int sig);
113 static void exscsi(int excode, void *arg);
114 static void excdr(int excode, void *arg);
115 static int prstats(void);
116 static int prstats_silent(void);
117 static void dorw(SCSI *usalp, char *filename, char *sectors);
118 static void doit(SCSI *usalp);
119 static void read_disk(SCSI *usalp, parm_t *parmp);
121 static void readcd_disk(SCSI *usalp, parm_t *parmp);
122 static void read_lin(SCSI *usalp, parm_t *parmp);
123 static int read_secheader(SCSI *usalp, long addr);
124 static int read_ftoc(SCSI *usalp, parm_t *parmp, BOOL do_sectype);
125 static void read_sectypes(SCSI *usalp, FILE *f);
126 static void get_sectype(SCSI *usalp, long addr, char *st);
129 static void readc2_disk(SCSI *usalp, parm_t *parmp);
130 static int fread_data(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr,
133 static int fread_2448(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr,
135 static int fread_2448_16(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr,
137 static int fread_2352(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr,
139 static int fread_lin(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr,
142 static int bits(int c);
143 static int bitidx(int c);
144 static int fread_c2(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr,
147 static int fdata_null(rparm_t *rp, caddr_t bp, long addr, int cnt);
148 static int fdata_c2(rparm_t *rp, caddr_t bp, long addr, int cnt);
151 static int read_scsi_g1(SCSI *usalp, caddr_t bp, long addr, int cnt);
154 int write_scsi(SCSI *usalp, caddr_t bp, long addr, int cnt);
155 int write_g0(SCSI *usalp, caddr_t bp, long addr, int cnt);
156 int write_g1(SCSI *usalp, caddr_t bp, long addr, int cnt);
159 static void Xrequest_sense(SCSI *usalp);
161 static int read_retry(SCSI *usalp, caddr_t bp, long addr, long cnt,
162 int (*rfunc)(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt),
164 static void read_generic(SCSI *usalp, parm_t *parmp,
165 int (*rfunc)(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt),
167 int (*dfunc)(rparm_t *rp, caddr_t bp, long addr, int cnt));
168 static void write_disk(SCSI *usalp, parm_t *parmp);
169 static int choice(int n);
170 static void ra(SCSI *usalp);
172 int read_da(SCSI *usalp, caddr_t bp, long addr, int cnt, int framesize,
174 int read_cd(SCSI *usalp, caddr_t bp, long addr, int cnt, int framesize,
175 int data, int subch);
177 static void oldmode(SCSI *usalp, int *errp, int *retrp);
178 static void domode(SCSI *usalp, int err, int retr);
180 static void qpto96(Uchar *sub, Uchar *subq, int dop);
181 static void ovtime(SCSI *usalp);
182 static void add_bad(long addr);
183 static void print_bad(void);
185 struct timeval starttime;
186 struct timeval stoptime;
193 /*#define MAX_RETRY 32*/
194 #define MAX_RETRY 128
210 int retries = MAX_RETRY;
215 struct scsi_format_data fmt;
217 /*XXX*/EXPORT BOOL cvt_cyls(void) { return (FALSE); }
218 /*XXX*/EXPORT BOOL cvt_bcyls(void) { return (FALSE); }
219 /*XXX*/EXPORT void print_defect_list(void) {}
224 fprintf(stderr, "Usage:\treadom [options]\n");
225 fprintf(stderr, "options:\n");
226 fprintf(stderr, "\t-version print version information and exit\n");
227 fprintf(stderr, "\tdev=target SCSI target to use\n");
228 fprintf(stderr, "\tf=filename Name of file to read/write\n");
229 fprintf(stderr, "\tsectors=range Range of sectors to read/write\n");
230 fprintf(stderr, "\tspeed=# set speed of drive (MMC only)\n");
231 fprintf(stderr, "\tts=# set maximum transfer size for a single SCSI command\n");
232 fprintf(stderr, "\t-w Switch to write mode\n");
233 fprintf(stderr, "\t-c2scan Do a C2 error scan\n");
235 fprintf(stderr, "\t-fulltoc Retrieve the full TOC\n");
236 fprintf(stderr, "\t-clone Retrieve the full TOC and all data\n");
238 fprintf(stderr, "\ttimeout=# set the default SCSI command timeout to #.\n");
239 fprintf(stderr, "\tdebug=#,-d Set to # or increment misc debug level\n");
240 fprintf(stderr, "\tkdebug=#,kd=# do Kernel debugging\n");
241 fprintf(stderr, "\t-quiet,-q be more quiet in error retry mode\n");
242 fprintf(stderr, "\t-verbose,-v increment general verbose level by one\n");
243 fprintf(stderr, "\t-Verbose,-V increment SCSI command transport verbose level by one\n");
244 fprintf(stderr, "\t-silent,-s do not print status of failed SCSI commands\n");
245 fprintf(stderr, "\t-scanbus scan the SCSI bus and exit\n");
246 fprintf(stderr, "\t-noerror do not abort on error\n");
248 fprintf(stderr, "\t-nocorr do not apply error correction in drive\n");
250 fprintf(stderr, "\t-notrunc do not truncate outputfile in read mode\n");
251 fprintf(stderr, "\tretries=# set retry count (default is %d)\n", retries);
252 fprintf(stderr, "\t-overhead meter SCSI command overhead times\n");
253 fprintf(stderr, "\tmeshpoints=# print read-speed at # locations\n");
254 fprintf(stderr, "\t-factor try to use speed factor with meshpoints=# if possible\n");
255 fprintf(stderr, "\n");
256 fprintf(stderr, "sectors=0-0 will read nothing, sectors=0-1 will read one sector starting from 0\n");
261 char opts[] = "debug#,d+,kdebug#,kd#,timeout#,quiet,q,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,help,h,version,scanbus,dev*,sectors*,w,c2scan,fulltoc,clone,noerror,nocorr,notrunc,retries#,factor,f*,speed#,ts&,overhead,meshpoints#";
264 main(int argc, char *argv[])
283 char *filename = NULL;
284 char *sectors = NULL;
286 save_args(argc, argv);
291 if (getallargs(&cac, &cav, opts,
296 &lverbose, &lverbose,
300 &help, &help, &pversion,
301 &scanbus, &dev, §ors, &do_write,
303 &fulltoc, &clonemode,
305 ¬runc, &retries, &do_factor, &filename,
306 &speed, getnum, &Sbufsize,
307 &dooverhead, &meshpoints) < 0) {
308 errmsgno(EX_BAD, "Bad flag: %s.\n", cav[0]);
314 printf("readcd %s is not what you see here. This line is only a fake for too clever\n"
315 "GUIs and other frontend applications. In fact, this program is:\n", cdr_version);
317 printf("readom " CDRKIT_VERSION " (" HOST_SYSTEM ")\n"
318 "Copyright (C) 1987, 1995-2006 Joerg Schilling\n"
319 "Copyright (C) 2006 Cdrkit maintainers\n"
320 "(modified version of <censored> -- "
321 "don't bother Joerg Schilling with problems)\n");
329 while (getfiles(&cac, &cav, opts) > 0) {
332 if (*astoi(cav[0], &target) != '\0') {
334 "Target '%s' is not a Number.\n",
341 if (*astoi(cav[0], &lun) != '\0') {
343 "Lun is '%s' not a Number.\n",
350 if (*astoi(cav[0], &scsibus) != '\0') {
352 "Scsibus is '%s' not a Number.\n",
361 /*fprintf(stderr, "dev: '%s'\n", dev);*/
363 cdr_defaults(&dev, NULL, NULL, NULL);
365 printf("dev: '%s'\n", dev);
367 if (!scanbus && dev == NULL &&
368 scsibus == -1 && (target == -1 || lun == -1)) {
369 errmsgno(EX_BAD, "No SCSI device specified.\n");
372 if (dev || scanbus) {
376 * Call usal_remote() to force loading the remote SCSI transport
377 * library code that is located in librusal instead of the dummy
378 * remote routines that are located inside libusal.
382 ((strncmp(dev, "HELP", 4) == 0) ||
383 (strncmp(dev, "help", 4) == 0))) {
387 if ((usalp = usal_open(dev, errstr, sizeof (errstr), debug, lverbose)) == (SCSI *)0) {
388 int err = geterrno();
390 errmsgno(err, "%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
391 errmsgno(EX_BAD, "For possible targets try 'wodim -scanbus'.%s\n",
392 geteuid() ? " Make sure you are root.":"");
393 errmsgno(EX_BAD, "For possible transport specifiers try 'wodim dev=help'.\n");
397 if (scsibus == -1 && target >= 0 && lun >= 0)
400 usalp = usal_smalloc();
401 usalp->debug = debug;
402 usalp->kdebug = kdebug;
404 usal_settarget(usalp, scsibus, target, lun);
405 if (usal__open(usalp, NULL) <= 0)
406 comerr("Cannot open SCSI driver.\n");
408 usalp->silent = silent;
409 usalp->verbose = verbose;
410 usalp->debug = debug;
411 usalp->kdebug = kdebug;
412 usal_settimeout(usalp, deftimeout);
415 Sbufsize = 256*1024L;
416 Sbufsize = usal_bufsize(usalp, Sbufsize);
417 if ((Sbuf = usal_getbuf(usalp, Sbufsize)) == NULL)
418 comerr("Cannot get SCSI I/O buffer.\n");
421 is_suid = priv_ineffect(PRIV_FILE_DAC_READ) &&
422 !priv_ineffect(PRIV_PROC_SETID);
424 * Give up privs we do not need anymore.
426 * file_dac_read,net_privaddr
430 priv_set(PRIV_OFF, PRIV_EFFECTIVE,
431 PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, NULL);
432 priv_set(PRIV_OFF, PRIV_PERMITTED,
433 PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, NULL);
434 priv_set(PRIV_OFF, PRIV_INHERITABLE,
435 PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, PRIV_SYS_DEVICES, NULL);
438 * This is only for OS that do not support fine grained privs.
441 is_suid = geteuid() != getuid();
443 * We don't need root privilleges anymore.
446 if (setreuid(-1, getuid()) < 0)
449 if (seteuid(getuid()) < 0)
451 if (setuid(getuid()) < 0)
454 comerr("Panic cannot set back effective uid.\n");
456 /* code to use SCG */
459 select_target(usalp, stdout);
462 do_inquiry(usalp, FALSE);
463 allow_atapi(usalp, TRUE); /* Try to switch to 10 byte mode cmds */
464 if (is_mmc(usalp, NULL, NULL)) {
468 * At this point we know that we have a SCSI-3/mmc compliant drive.
469 * Unfortunately ATAPI drives violate the SCSI spec in returning
470 * a response data format of '1' which from the SCSI spec would
471 * tell us not to use the "PF" bit in mode select. As ATAPI drives
472 * require the "PF" bit to be set, we 'correct' the inquiry data.
474 if (usalp->inq->data_format < 2)
475 usalp->inq->data_format = 2;
477 if ((rspeed = get_curprofile(usalp)) >= 0) {
478 if (rspeed >= 0x08 && rspeed < 0x10)
480 if (rspeed >= 0x10 && rspeed < 0x20)
485 mmc_check(usalp, NULL, NULL, NULL, NULL, &dvd, NULL);
491 if (read_dvd_structure(usalp, (caddr_t)xb, 32, 0, 0, 0) >= 0) {
493 * If read DVD structure is supported and works, then
494 * we must have a DVD media in the drive. Signal to
495 * use the DVD driver.
506 if (speed > 0xFFFF || speed < 0)
508 scsi_set_speed(usalp, speed, speed, ROTCTL_CLV);
509 if (scsi_get_speed(usalp, &rspeed, &wspeed) >= 0) {
510 fprintf(stderr, "Read speed: %5d kB/s (CD %3dx, DVD %2dx).\n",
511 rspeed, rspeed/176, rspeed/1385);
512 fprintf(stderr, "Write speed: %5d kB/s (CD %3dx, DVD %2dx).\n",
513 wspeed, wspeed/176, wspeed/1385);
516 exargs.usalp = usalp;
517 exargs.old_secsize = -1;
518 /* exargs.flags = flags;*/
522 * Install exit handler before we change the drive status.
524 on_comerr(exscsi, &exargs);
525 signal(SIGINT, intr);
526 signal(SIGTERM, intr);
534 if (usalp->inq->type != INQ_ROMD)
535 comerrno(EX_BAD, "Not root. Will only work on CD-ROM in suid/priv mode\n");
538 if (filename || sectors || c2scan || meshpoints || fulltoc || clonemode) {
539 dorw(usalp, filename, sectors);
548 * XXX Leider kann man vim Signalhandler keine SCSI Kommandos verschicken
549 * XXX da meistens das letzte SCSI Kommando noch laeuft.
550 * XXX Eine Loesung waere ein Abort Callback in SCSI *.
562 exscsi(int excode, void *arg)
564 struct exargs *exp = (struct exargs *)arg;
568 * Try to restore the old sector size.
570 if (exp != NULL && exp->exflags == 0) {
571 for (i = 0; i < 10*100; i++) {
572 if (!exp->usalp->running)
576 "Waiting for current SCSI command to finish.\n");
581 if (!exp->usalp->running) {
582 if (exp->oerr[2] != 0) {
583 domode(exp->usalp, exp->oerr[0], exp->oerr[1]);
585 if (exp->old_secsize > 0 && exp->old_secsize != 2048)
586 select_secsize(exp->usalp, exp->old_secsize);
588 exp->exflags++; /* Make sure that it only get called once */
593 excdr(int excode, void *arg)
598 /* Do several other restores/statistics here (see cdrecord.c) */
603 * Return milliseconds since start time.
612 if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
613 comerr("Cannot get time\n");
615 sec = stoptime.tv_sec - starttime.tv_sec;
616 usec = stoptime.tv_usec - starttime.tv_usec;
617 tmsec = sec*1000 + usec/1000;
619 tmsec = tmsec; /* Bisz spaeter */
626 fprintf(stderr, "Time total: %d.%03dsec\n", sec, usec/1000);
627 return (1000*sec + (usec / 1000));
631 * Return milliseconds since start time, but be silent this time.
640 if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
641 comerr("Cannot get time\n");
643 sec = stoptime.tv_sec - starttime.tv_sec;
644 usec = stoptime.tv_usec - starttime.tv_usec;
645 tmsec = sec*1000 + usec/1000;
647 tmsec = tmsec; /* Bisz spaeter */
654 return (1000*sec + (usec / 1000));
658 dorw(SCSI *usalp, char *filename, char *sectors)
666 params.askrange = FALSE;
670 params.name = filename;
671 if (meshpoints > 0) {
672 if (params.name == NULL)
673 params.name = "/dev/null";
676 p = astol(sectors, ¶ms.start);
678 p = astol(++p, ¶ms.end);
680 comerrno(EX_BAD, "Not a valid sector range '%s'\n", sectors);
682 if (!wait_unit_ready(usalp, 60))
683 comerrno(EX_BAD, "Device not ready.\n");
687 if (params.name == NULL)
688 params.name = "/dev/null";
689 read_ftoc(usalp, ¶ms, FALSE);
690 } else if (clonemode) {
691 if (!is_mmc(usalp, NULL, NULL))
692 comerrno(EX_BAD, "Unsupported device for clone mode.\n");
694 if (retries == MAX_RETRY)
696 if (params.name == NULL)
697 params.name = "/dev/null";
699 if (read_ftoc(usalp, ¶ms, TRUE) < 0)
700 comerrno(EX_BAD, "Read fulltoc problems.\n");
701 readcd_disk(usalp, ¶ms);
706 if (retries == MAX_RETRY)
708 if (params.name == NULL)
709 params.name = "/dev/null";
710 readc2_disk(usalp, ¶ms);
712 write_disk(usalp, ¶ms);
714 read_disk(usalp, ¶ms);
726 params.askrange = TRUE;
727 params.name = "/dev/null";
730 if (!wait_unit_ready(usalp, 60))
731 comerrno(EX_BAD, "Device not ready.\n");
733 printf("0:read 1:veri 2:erase 3:read buffer 4:cache 5:ovtime 6:cap\n");
734 printf("7:wne 8:floppy 9:verify 10:checkcmds 11:read disk 12:write disk\n");
735 printf("13:scsireset 14:seektest 15: readda 16: reada 17: c2err\n");
737 printf("18:readom 19: lin 20: full toc\n");
740 getint("Enter selection:", &i, 0, 20);
746 case 5: ovtime(usalp); break;
747 case 11: read_disk(usalp, 0); break;
748 case 12: write_disk(usalp, 0); break;
749 case 15: ra(usalp); break;
750 /* case 16: reada_disk(usalp, 0, 0); break;*/
751 case 17: readc2_disk(usalp, ¶ms); break;
753 case 18: readcd_disk(usalp, 0); break;
754 case 19: read_lin(usalp, 0); break;
755 case 20: read_ftoc(usalp, 0, FALSE); break;
762 read_disk(SCSI *usalp, parm_t *parmp)
766 read_capacity(usalp);
767 print_capacity(usalp, stderr);
774 rp.secsize = usalp->cap->c_bsize;
776 read_generic(usalp, parmp, fread_data, &rp, fdata_null);
781 readcd_disk(SCSI *usalp, parm_t *parmp)
787 int (*funcp)(SCSI *_usalp, rparm_t *_rp, caddr_t bp, long addr, int cnt);
790 if (read_capacity(usalp) >= 0)
791 osecsize = usalp->cap->c_bsize;
793 if (osecsize != 2048)
794 select_secsize(usalp, 2048);
796 read_capacity(usalp);
797 print_capacity(usalp, stderr);
805 rp.ismmc = is_mmc(usalp, NULL, NULL);
808 wait_unit_ready(usalp, 10);
809 if (fread_2448(usalp, &rp, Sbuf, 0, 0) < 0) {
810 errmsgno(EX_BAD, "read 2448 failed\n");
812 fread_2448_16(usalp, &rp, Sbuf, 0, 0) >= 0) {
813 errmsgno(EX_BAD, "read 2448_16 : OK\n");
815 funcp = fread_2448_16;
819 oldmode(usalp, &oerr, &oretr);
820 exargs.oerr[0] = oerr;
821 exargs.oerr[1] = oretr;
822 exargs.oerr[2] = 0xFF;
823 if (parmp == NULL) /* XXX Nur am Anfang!!! */
824 domode(usalp, -1, -1);
826 domode(usalp, nocorr?0x21:0x20, 10);
828 read_generic(usalp, parmp, funcp, &rp, fdata_null);
829 if (osecsize != 2048)
830 select_secsize(usalp, osecsize);
831 domode(usalp, oerr, oretr);
836 read_lin(SCSI *usalp, parm_t *parmp)
841 read_capacity(usalp);
842 print_capacity(usalp, stderr);
844 parm.start = ULONG_C(0xF0000000);
845 parm.end = ULONG_C(0xFF000000);
854 rp.ismmc = is_mmc(usalp, NULL, NULL);
855 domode(usalp, -1, -1);
856 read_generic(usalp, &parm, fread_lin, &rp, fdata_null);
860 read_secheader(SCSI *usalp, long addr)
867 if (read_capacity(usalp) >= 0)
868 osecsize = usalp->cap->c_bsize;
870 if (osecsize != 2048)
871 select_secsize(usalp, 2048);
873 read_capacity(usalp);
881 rp.ismmc = is_mmc(usalp, NULL, NULL);
883 wait_unit_ready(usalp, 10);
885 fillbytes(Sbuf, 2352, '\0');
886 if (fread_2352(usalp, &rp, Sbuf, addr, 1) < 0) {
889 if (osecsize != 2048)
890 select_secsize(usalp, osecsize);
896 read_ftoc(SCSI *usalp, parm_t *parmp, BOOL do_sectype)
901 struct tocheader *tp;
908 strcpy(filename, "toc.dat");
909 if (strcmp(parmp->name, "/dev/null") != 0) {
911 len = strlen(parmp->name);
912 if (len > (sizeof (filename)-5)) {
913 len = sizeof (filename)-5;
915 snprintf(filename, sizeof (filename), "%.*s.toc", len, parmp->name);
918 tp = (struct tocheader *)xb;
920 fillbytes((caddr_t)xb, sizeof (xb), '\0');
921 if (read_toc(usalp, xb, 0, sizeof (struct tocheader), 0, FMT_FULLTOC) < 0) {
922 if (usalp->silent == 0 || usalp->verbose > 0)
923 errmsgno(EX_BAD, "Cannot read TOC header\n");
926 len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
927 fprintf(stderr, "TOC len: %d. First Session: %d Last Session: %d.\n", len, tp->first, tp->last);
929 if (read_toc(usalp, xxb, 0, len, 0, FMT_FULLTOC) < 0) {
932 * Work around a bug in some operating systems that do not
933 * handle odd byte DMA correctly for ATAPI drives.
935 wait_unit_ready(usalp, 30);
936 read_toc(usalp, xb, 0, sizeof (struct tocheader), 0, FMT_FULLTOC);
937 wait_unit_ready(usalp, 30);
938 if (read_toc(usalp, xxb, 0, len+1, 0, FMT_FULLTOC) >= 0) {
942 if (usalp->silent == 0)
943 errmsgno(EX_BAD, "Cannot read full TOC\n");
948 f = fileopen(filename, "wctb");
951 comerr("Cannot open '%s'.\n", filename);
952 filewrite(f, xxb, len);
954 read_sectypes(usalp, f);
959 for (; p < &xxb[len]; p += 11) {
960 for (i = 0; i < 11; i++)
961 fprintf(stderr, "%02X ", p[i] & 0xFF);
962 fprintf(stderr, "\n");
965 * List all lead out start times to give information about multi
969 for (; p < &xxb[len]; p += 11) {
970 if ((p[3] & 0xFF) == 0xA2) {
971 fprintf(stderr, "Lead out %d: %ld\n", p[0], msf_to_lba(p[8], p[9], p[10], TRUE));
978 read_sectypes(SCSI *usalp, FILE *f)
983 get_sectype(usalp, 4, §);
985 filewrite(f, §, 1);
987 usal_prbytes("sec 0", (Uchar *)Sbuf, 16);
990 get_sectype(usalp, usalp->cap->c_baddr-4, §);
992 filewrite(f, §, 1);
994 usal_prbytes("sec E", (Uchar *)Sbuf, 16);
995 fprintf(stderr, "baddr: %ld\n", (long)usalp->cap->c_baddr);
1000 get_sectype(SCSI *usalp, long addr, char *st)
1002 char *synchdr = "\0\377\377\377\377\377\377\377\377\377\377\0";
1003 int sectype = SECT_AUDIO;
1006 #define _MAX_TRY_ 20
1009 for (i = 0; i < _MAX_TRY_ && read_secheader(usalp, raddr) < 0; i++) {
1016 if (i >= _MAX_TRY_) {
1017 fprintf(stderr, "Sectype (%ld) is CANNOT\n", addr);
1020 fprintf(stderr, "Sectype (%ld) needed %d retries\n", addr, i);
1024 if (cmpbytes(Sbuf, synchdr, 12) < 12) {
1026 fprintf(stderr, "Sectype (%ld) is AUDIO\n", addr);
1032 fprintf(stderr, "Sectype (%ld) is DATA\n", addr);
1033 if (Sbuf[15] == 0) {
1035 fprintf(stderr, "Sectype (%ld) is MODE 0\n", addr);
1036 sectype = SECT_MODE_0;
1038 } else if (Sbuf[15] == 1) {
1040 fprintf(stderr, "Sectype (%ld) is MODE 1\n", addr);
1043 } else if (Sbuf[15] == 2) {
1045 fprintf(stderr, "Sectype (%ld) is MODE 2\n", addr);
1047 if ((Sbuf[16+2] & 0x20) == 0 &&
1048 (Sbuf[16+4+2] & 0x20) == 0) {
1050 fprintf(stderr, "Sectype (%ld) is MODE 2 form 1\n", addr);
1051 sectype = SECT_MODE_2_F1;
1053 } else if ((Sbuf[16+2] & 0x20) != 0 &&
1054 (Sbuf[16+4+2] & 0x20) != 0) {
1056 fprintf(stderr, "Sectype (%ld) is MODE 2 form 2\n", addr);
1057 sectype = SECT_MODE_2_F2;
1060 fprintf(stderr, "Sectype (%ld) is MODE 2 formless\n", addr);
1061 sectype = SECT_MODE_2;
1064 fprintf(stderr, "Sectype (%ld) is UNKNOWN\n", addr);
1069 fprintf(stderr, "Sectype (%ld) is 0x%02X\n", addr, sectype);
1072 #endif /* CLONE_WRITE */
1077 readc2_disk(SCSI *usalp, parm_t *parmp)
1080 int osecsize = 2048;
1085 if (read_capacity(usalp) >= 0)
1086 osecsize = usalp->cap->c_bsize;
1088 if (osecsize != 2048)
1089 select_secsize(usalp, 2048);
1091 read_capacity(usalp);
1092 print_capacity(usalp, stderr);
1099 rp.secsize = 2352 + 294;
1100 rp.ismmc = is_mmc(usalp, NULL, NULL);
1102 oldmode(usalp, &oerr, &oretr);
1103 exargs.oerr[0] = oerr;
1104 exargs.oerr[1] = oretr;
1105 exargs.oerr[2] = 0xFF;
1106 domode(usalp, 0x21, 10);
1109 read_generic(usalp, parmp, fread_c2, &rp, fdata_c2);
1110 if (osecsize != 2048)
1111 select_secsize(usalp, osecsize);
1112 domode(usalp, oerr, oretr);
1114 printf("Total of %d hard read errors.\n", rp.errors);
1115 printf("C2 errors total: %d bytes in %d sectors on disk\n", rp.c2_errors, rp.c2_errsecs);
1116 printf("C2 errors rate: %f%% \n", (100.0*rp.c2_errors)/usalp->cap->c_baddr/2352);
1117 printf("C2 errors on worst sector: %d, sectors with 100+ C2 errors: %d\n", rp.c2_maxerrs, rp.c2_badsecs);
1122 fread_data(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
1124 return (read_g1(usalp, bp, addr, cnt));
1129 fread_2448(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
1132 return (read_cd(usalp, bp, addr, cnt, rp->secsize,
1133 /* Sync + all headers + user data + EDC/ECC */
1134 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
1135 /* plus all subchannels RAW */
1138 return (read_da(usalp, bp, addr, cnt, rp->secsize,
1139 /* Sync + all headers + user data + EDC/ECC + all subch */
1145 fread_2448_16(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
1154 trackdesc.isecsize = 2368;
1155 trackdesc.secsize = 2448;
1156 ret = read_cd(usalp, bp, addr, cnt, 2368,
1157 /* Sync + all headers + user data + EDC/ECC */
1158 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
1159 /* subchannels P/Q */
1164 scatter_secs(&trackdesc, bp, cnt);
1165 for (i = 0, p = bp+2352; i < cnt; i++) {
1166 #ifdef more_than_q_sub
1167 if ((p[15] & 0x80) != 0)
1171 * As the drives don't return P-sub, we check
1172 * whether the index equals 0.
1174 qpto96((Uchar *)p, (Uchar *)p, p[2] == 0);
1179 comerrno(EX_BAD, "Cannot fread_2448_16 on non MMC drives\n");
1181 return (read_da(usalp, bp, addr, cnt, rp->secsize,
1182 /* Sync + all headers + user data + EDC/ECC + all subch */
1188 fread_2352(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
1191 return (read_cd(usalp, bp, addr, cnt, rp->secsize,
1192 /* Sync + all headers + user data + EDC/ECC */
1193 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
1194 /* NO subchannels */
1197 comerrno(EX_BAD, "Cannot fread_2352 on non MMC drives\n");
1199 return (read_da(usalp, bp, addr, cnt, rp->secsize,
1200 /* Sync + all headers + user data + EDC/ECC + all subch */
1206 fread_lin(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
1208 if (addr != ULONG_C(0xF0000000))
1209 addr = ULONG_C(0xFFFFFFFF);
1211 return (read_cd(usalp, bp, addr, cnt, rp->secsize,
1212 /* Sync + all headers + user data + EDC/ECC */
1213 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
1214 /* plus all subchannels RAW */
1217 #endif /* CLONE_WRITE */
1266 fread_c2(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
1269 return (read_cd(usalp, bp, addr, cnt, rp->secsize,
1270 /* Sync + all headers + user data + EDC/ECC + C2 */
1271 /* (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3 | 2 << 1),*/
1272 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3 | 1 << 1),
1273 /* without subchannels */
1276 return (read_da(usalp, bp, addr, cnt, rp->secsize,
1277 /* Sync + all headers + user data + EDC/ECC + C2 */
1284 fdata_null(rparm_t *rp, caddr_t bp, long addr, int cnt)
1290 fdata_c2(rparm_t *rp, caddr_t bp, long addr, int cnt)
1299 for (i = 0; i < cnt; i++, p += (2352+294)) {
1300 /* usal_prbytes("XXX ", p, 294);*/
1301 if ((j = cmpbytes(p, zeroblk, 294)) < 294) {
1302 printf("C2 in sector: %3ld first at byte: %4d (0x%02X)", addr+i,
1303 j*8 + bitidx(p[j]), p[j]&0xFF);
1304 for (j = 0, k = 0; j < 294; j++)
1306 printf(" total: %4d errors\n", k);
1307 /* usal_prbytes("XXX ", p, 294);*/
1309 if (k > rp->c2_maxerrs)
1313 rp->c2_badsecs += 1;
1321 read_scsi_g1(SCSI *usalp, caddr_t bp, long addr, int cnt)
1323 register struct usal_cmd *scmd = usalp->scmd;
1325 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1327 /* scmd->size = cnt*512;*/
1328 scmd->size = cnt*usalp->cap->c_bsize;
1329 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1330 scmd->cdb_len = SC_G1_CDBLEN;
1331 scmd->sense_len = CCS_SENSE_LEN;
1332 scmd->cdb.g1_cdb.cmd = 0x28;
1333 scmd->cdb.g1_cdb.lun = usal_lun(usalp);
1334 g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
1335 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1337 usalp->cmdname = "read extended";
1339 return (usal_cmd(usalp));
1343 #define G0_MAXADDR 0x1FFFFFL
1346 write_scsi(SCSI *usalp, caddr_t bp, long addr, int cnt)
1348 if (addr <= G0_MAXADDR)
1349 return (write_g0(usalp, bp, addr, cnt));
1351 return (write_g1(usalp, bp, addr, cnt));
1355 write_g0(SCSI *usalp, caddr_t bp, long addr, int cnt)
1357 register struct usal_cmd *scmd = usalp->scmd;
1359 if (usalp->cap->c_bsize <= 0)
1360 raisecond("capacity_not_set", 0L);
1362 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1364 scmd->size = cnt*usalp->cap->c_bsize;
1365 scmd->flags = SCG_DISRE_ENA;
1366 scmd->cdb_len = SC_G0_CDBLEN;
1367 scmd->sense_len = CCS_SENSE_LEN;
1368 scmd->cdb.g0_cdb.cmd = SC_WRITE;
1369 scmd->cdb.g0_cdb.lun = usal_lun(usalp);
1370 g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
1371 scmd->cdb.g0_cdb.count = (Uchar)cnt;
1373 usalp->cmdname = "write_g0";
1375 return (usal_cmd(usalp));
1379 write_g1(SCSI *usalp, caddr_t bp, long addr, int cnt)
1381 register struct usal_cmd *scmd = usalp->scmd;
1383 if (usalp->cap->c_bsize <= 0)
1384 raisecond("capacity_not_set", 0L);
1386 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1388 scmd->size = cnt*usalp->cap->c_bsize;
1389 scmd->flags = SCG_DISRE_ENA;
1390 scmd->cdb_len = SC_G1_CDBLEN;
1391 scmd->sense_len = CCS_SENSE_LEN;
1392 scmd->cdb.g1_cdb.cmd = SC_EWRITE;
1393 scmd->cdb.g1_cdb.lun = usal_lun(usalp);
1394 g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
1395 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1397 usalp->cmdname = "write_g1";
1399 return (usal_cmd(usalp));
1404 Xrequest_sense(SCSI *usalp)
1407 struct usal_cmd ocmd;
1410 register struct usal_cmd *scmd = usalp->scmd;
1412 cmdsave = usalp->cmdname;
1414 movebytes(scmd, &ocmd, sizeof (*scmd));
1416 fillbytes((caddr_t)sense_buf, sizeof (sense_buf), '\0');
1418 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1419 scmd->addr = (caddr_t)sense_buf;
1420 scmd->size = sizeof (sense_buf);
1421 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1422 scmd->cdb_len = SC_G0_CDBLEN;
1423 scmd->sense_len = CCS_SENSE_LEN;
1424 scmd->cdb.g1_cdb.cmd = 0x3;
1425 scmd->cdb.g1_cdb.lun = usal_lun(usalp);
1426 scmd->cdb.g0_cdb.count = sizeof (sense_buf);
1428 usalp->cmdname = "request sense";
1432 sense_count = sizeof (sense_buf) - usal_getresid(usalp);
1433 movebytes(&ocmd, scmd, sizeof (*scmd));
1434 scmd->sense_count = sense_count;
1435 movebytes(sense_buf, (Uchar *)&scmd->sense, scmd->sense_count);
1437 usalp->cmdname = cmdsave;
1438 usal_printerr(usalp);
1439 usal_printresult(usalp); /* XXX restore key/code in future */
1444 read_retry(SCSI *usalp, caddr_t bp, long addr, long cnt,
1445 int (*rfunc)(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt),
1448 /* int secsize = usalp->cap->c_bsize;*/
1449 int secsize = rp->secsize;
1452 char dummybuf[8192];
1454 if (secsize > sizeof (dummybuf)) {
1455 errmsgno(EX_BAD, "Cannot retry, sector size %d too big.\n", secsize);
1459 errmsgno(EX_BAD, "Retrying from sector %ld.\n", addr);
1461 fprintf(stderr, ".");
1465 comexit(exsig); /* XXX besseres Konzept?!*/
1466 wait_unit_ready(usalp, 120);
1467 if (try >= 10) { /* First 10 retries without seek */
1468 if ((try % 8) == 0) {
1469 fprintf(stderr, "+"); /* Read last sector */
1471 (*rfunc)(usalp, rp, dummybuf, usalp->cap->c_baddr, 1);
1473 } else if ((try % 4) == 0) {
1474 fprintf(stderr, "-"); /* Read first sector */
1476 (*rfunc)(usalp, rp, dummybuf, 0, 1);
1479 fprintf(stderr, "~"); /* Read random sector */
1481 (*rfunc)(usalp, rp, dummybuf, choice(usalp->cap->c_baddr), 1);
1485 comexit(exsig); /* XXX besseres Konzept?!*/
1486 wait_unit_ready(usalp, 120);
1489 comexit(exsig); /* XXX besseres Konzept?!*/
1491 fillbytes(bp, secsize, 0);
1494 err = (*rfunc)(usalp, rp, bp, addr, 1);
1498 err = usalp->scmd->ux_errno;
1499 /* fprintf(stderr, "\n");*/
1500 /* errmsgno(err, "Cannot read source disk\n");*/
1502 if (usal_getresid(usalp)) {
1503 fprintf(stderr, "\nresid: %d\n", usal_getresid(usalp));
1508 } while (++try < retries);
1510 if (try >= retries) {
1511 fprintf(stderr, "\n");
1512 errmsgno(err, "Error on sector %ld not corrected. Total of %d errors.\n",
1513 addr, ++rp->errors);
1515 if (usalp->silent <= 1 && lverbose > 0)
1516 usal_printerr(usalp);
1522 errmsgno(EX_BAD, "-noerror set, continuing ...\n");
1528 fprintf(stderr, "\n");
1530 "Error on sector %ld corrected after %d tries. Total of %d errors.\n",
1531 addr, try, rp->errors);
1543 read_generic(SCSI *usalp, parm_t *parmp,
1544 int (*rfunc)(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt),
1546 int (*dfunc)(rparm_t *rp, caddr_t bp, long addr, int cnt))
1549 char *defname = NULL;
1557 long next_point = 0L;
1558 long secs_per_point = 0L;
1563 BOOL askrange = FALSE;
1564 BOOL isrange = FALSE;
1565 int secsize = rp->secsize;
1569 if (usalp->inq->type != INQ_ROMD)
1570 comerrno(EX_BAD, "Not root. Will only read from CD in suid/priv mode\n");
1573 if (parmp == NULL || parmp->askrange)
1575 if (parmp != NULL && !askrange && (parmp->start <= parmp->end))
1581 if (read_capacity(usalp) >= 0)
1582 end = usalp->cap->c_baddr + 1;
1585 if ((end <= 0 && isrange) || (askrange && usal_yes("Ignore disk size? ")))
1586 end = 10000000; /* Hack to read empty (e.g. blank=fast) disks */
1590 defname = parmp->name;
1591 if (defname != NULL) {
1592 fprintf(stderr, "Copy from SCSI (%d,%d,%d) disk to file '%s'\n",
1593 usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp),
1597 addr = start = parmp->start;
1598 if (parmp->end != -1 && parmp->end < end)
1600 cnt = Sbufsize / secsize;
1603 if (defname == NULL) {
1604 defname = "disk.out";
1605 fprintf(stderr, "Copy from SCSI (%d,%d,%d) disk to file\n",
1606 usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
1607 fprintf(stderr, "Enter filename [%s]: ", defname); flush();
1608 (void) rols_getline(filename, sizeof (filename));
1613 getlong("Enter starting sector for copy:", &addr, start, end-1);
1614 /* getlong("Enter starting sector for copy:", &addr, -300, end-1);*/
1620 getlong("Enter number of sectors to copy:", &num, 1L, num);
1626 cnt = Sbufsize / secsize;
1627 getlong("Enter number of sectors per copy:", &cnt, 1L, cnt);
1630 if (filename[0] == '\0')
1631 strncpy(filename, defname, sizeof (filename));
1632 filename[sizeof (filename)-1] = '\0';
1633 if (streql(filename, "-")) {
1635 #ifdef NEED_O_BINARY
1636 setmode(STDOUT_FILENO, O_BINARY);
1638 } else if ((f = fileopen(filename, notrunc?"wcub":"wctub")) == NULL)
1639 comerr("Cannot open '%s'.\n", filename);
1641 fprintf(stderr, "end: %8ld\n", end);
1642 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
1643 comerr("Cannot get start time\n");
1645 if (meshpoints > 0) {
1646 if ((end-start) < meshpoints)
1649 secs_per_point = (end-start) / meshpoints;
1650 next_point = start + secs_per_point;
1654 for (; addr < end; addr += cnt) {
1656 comexit(exsig); /* XXX besseres Konzept?!*/
1658 if ((addr + cnt) > end)
1661 if (meshpoints > 0) {
1662 if (addr > next_point) {
1664 msec = prstats_silent();
1665 if ((msec - old_msec) == 0) /* Avoid division by zero */
1666 msec = old_msec + 1;
1667 speed = ((addr - old_addr)/(1000.0/secsize)) / (0.001*(msec - old_msec));
1674 fprintf(stderr, "addr: %8ld cnt: %ld", addr, cnt);
1675 printf("%8ld %8.2f\n", addr, speed);
1676 fprintf(stderr, "\r");
1677 next_point += secs_per_point;
1681 if (meshpoints < 100)
1683 else if (i % (meshpoints/100) == 0)
1687 fprintf(stderr, "addr: %8ld cnt: %ld\r", addr, cnt);
1690 if ((*rfunc)(usalp, rp, Sbuf, addr, cnt) < 0) {
1692 err = usalp->scmd->ux_errno;
1694 fprintf(stderr, "\n");
1695 } else if (usalp->silent == 0) {
1696 usal_printerr(usalp);
1698 errmsgno(err, "Cannot read source disk\n");
1700 if (read_retry(usalp, Sbuf, addr, cnt, rfunc, rp) < 0)
1704 if (usal_getresid(usalp)) {
1705 fprintf(stderr, "\nresid: %d\n", usal_getresid(usalp));
1709 (*dfunc)(rp, Sbuf, addr, cnt);
1710 if (filewrite(f, Sbuf, cnt * secsize) < 0) {
1712 fprintf(stderr, "\n");
1713 errmsgno(err, "Cannot write '%s'\n", filename);
1717 fprintf(stderr, "addr: %8ld", addr);
1719 fprintf(stderr, "\n");
1721 if (msec == 0) /* Avoid division by zero */
1724 fprintf(stderr, "Read %.2f kB at %.1f kB/sec.\n",
1725 (double)(addr - start)/(1024.0/usalp->cap->c_bsize),
1726 (double)((addr - start)/(1024.0/usalp->cap->c_bsize)) / (0.001*msec));
1728 fprintf(stderr, "Read %.2f kB at %.1f kB/sec.\n",
1729 (double)(addr - start)/(1024.0/secsize),
1730 (double)((addr - start)/(1024.0/secsize)) / (0.001*msec));
1736 write_disk(SCSI *usalp, parm_t *parmp)
1739 char *defname = "disk.out";
1749 comerrno(EX_BAD, "Not root. Will not write in suid/priv mode\n");
1752 if (read_capacity(usalp) >= 0) {
1753 end = usalp->cap->c_baddr + 1;
1754 print_capacity(usalp, stderr);
1758 end = 10000000; /* Hack to write empty disks */
1762 defname = parmp->name;
1763 fprintf(stderr, "Copy from file '%s' to SCSI (%d,%d,%d) disk\n",
1765 usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
1767 addr = start = parmp->start;
1768 if (parmp->end != -1 && parmp->end < end)
1770 cnt = Sbufsize / usalp->cap->c_bsize;
1772 fprintf(stderr, "Copy from file to SCSI (%d,%d,%d) disk\n",
1773 usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
1774 fprintf(stderr, "Enter filename [%s]: ", defname); flush();
1775 (void) rols_getline(filename, sizeof (filename));
1776 fprintf(stderr, "Notice: reading from file always starts at file offset 0.\n");
1778 getlong("Enter starting sector for copy:", &addr, 0L, end-1);
1781 getlong("Enter number of sectors to copy:", &end, 1L, end);
1784 cnt = Sbufsize / usalp->cap->c_bsize;
1785 getlong("Enter number of sectors per copy:", &cnt, 1L, cnt);
1786 /* fprintf(stderr, "end: %8ld\n", end);*/
1789 if (filename[0] == '\0')
1790 strncpy(filename, defname, sizeof (filename));
1791 filename[sizeof (filename)-1] = '\0';
1792 if (streql(filename, "-")) {
1794 #ifdef NEED_O_BINARY
1795 setmode(STDIN_FILENO, O_BINARY);
1797 } else if ((f = fileopen(filename, "rub")) == NULL)
1798 comerr("Cannot open '%s'.\n", filename);
1800 fprintf(stderr, "end: %8ld\n", end);
1801 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
1802 comerr("Cannot get start time\n");
1804 for (; addr < end; addr += cnt) {
1806 comexit(exsig); /* XXX besseres Konzept?!*/
1808 if ((addr + cnt) > end)
1811 fprintf(stderr, "addr: %8ld cnt: %ld\r", addr, cnt);
1813 if ((amt = fileread(f, Sbuf, cnt * usalp->cap->c_bsize)) < 0)
1814 comerr("Cannot read '%s'\n", filename);
1817 if ((amt / usalp->cap->c_bsize) < cnt)
1818 cnt = amt / usalp->cap->c_bsize;
1819 if (write_scsi(usalp, Sbuf, addr, cnt) < 0)
1820 comerrno(usalp->scmd->ux_errno,
1821 "Cannot write destination disk\n");
1823 fprintf(stderr, "addr: %8ld\n", addr);
1825 if (msec == 0) /* Avoid division by zero */
1827 fprintf(stderr, "Wrote %.2f kB at %.1f kB/sec.\n",
1828 (double)(addr - start)/(1024.0/usalp->cap->c_bsize),
1829 (double)((addr - start)/(1024.0/usalp->cap->c_bsize)) / (0.001*msec));
1835 #if defined(HAVE_DRAND48)
1836 extern double drand48(void);
1838 return (drand48() * n);
1840 # if defined(HAVE_RAND)
1841 extern int rand(void);
1843 return (rand() % n);
1853 /* char filename[512];*/
1855 /* long addr = 0L;*/
1862 select_secsize(usalp, 2352);
1863 read_capacity(usalp);
1864 print_capacity(usalp, stderr);
1865 fillbytes(Sbuf, 50*2352, 0);
1866 if (read_g1(usalp, Sbuf, 0, 50) < 0)
1867 errmsg("read CD\n");
1868 f = fileopen("DDA", "wctb");
1869 /* filewrite(f, Sbuf, 50 * 2352 - usal_getresid(usalp));*/
1870 filewrite(f, Sbuf, 50 * 2352);
1874 #define g5x_cdblen(cdb, len) ((cdb)->count[0] = ((len) >> 16L)& 0xFF,\
1875 (cdb)->count[1] = ((len) >> 8L) & 0xFF,\
1876 (cdb)->count[2] = (len) & 0xFF)
1879 read_da(SCSI *usalp, caddr_t bp, long addr, int cnt, int framesize, int subcode)
1881 register struct usal_cmd *scmd = usalp->scmd;
1883 if (usalp->cap->c_bsize <= 0)
1884 raisecond("capacity_not_set", 0L);
1886 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1888 scmd->size = cnt*framesize;
1889 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1890 scmd->cdb_len = SC_G5_CDBLEN;
1891 scmd->sense_len = CCS_SENSE_LEN;
1892 scmd->cdb.g5_cdb.cmd = 0xd8;
1893 scmd->cdb.g5_cdb.lun = usal_lun(usalp);
1894 g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
1895 g5_cdblen(&scmd->cdb.g5_cdb, cnt);
1896 scmd->cdb.g5_cdb.res10 = subcode;
1898 usalp->cmdname = "read_da";
1900 return (usal_cmd(usalp));
1904 read_cd(SCSI *usalp, caddr_t bp, long addr, int cnt, int framesize, int data,
1907 register struct usal_cmd *scmd = usalp->scmd;
1909 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1911 scmd->size = cnt*framesize;
1912 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1913 scmd->cdb_len = SC_G5_CDBLEN;
1914 scmd->sense_len = CCS_SENSE_LEN;
1915 scmd->cdb.g5_cdb.cmd = 0xBE;
1916 scmd->cdb.g5_cdb.lun = usal_lun(usalp);
1917 scmd->cdb.g5_cdb.res = 0; /* expected sector type field ALL */
1918 g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
1919 g5x_cdblen(&scmd->cdb.g5_cdb, cnt);
1921 scmd->cdb.g5_cdb.count[3] = data & 0xFF;
1922 scmd->cdb.g5_cdb.res10 = subch & 0x07;
1924 usalp->cmdname = "read_cd";
1926 return (usal_cmd(usalp));
1930 oldmode(SCSI *usalp, int *errp, int *retrp)
1938 fillbytes(mode, sizeof (mode), '\0');
1939 fillbytes(cmode, sizeof (cmode), '\0');
1941 if (!get_mode_params(usalp, 0x01, "CD error recovery parameter",
1942 mode, (Uchar *)0, (Uchar *)cmode, (Uchar *)0, &len)) {
1946 usal_prbytes("Mode Sense Data", mode, len);
1949 mode[2] = 0; /* ??? ist manchmal 0x80 */
1955 usal_prbytes("Mode page 1:", p, 0x10);
1967 domode(SCSI *usalp, int err, int retr)
1975 fillbytes(mode, sizeof (mode), '\0');
1976 fillbytes(cmode, sizeof (cmode), '\0');
1978 if (!get_mode_params(usalp, 0x01, "CD error recovery parameter",
1979 mode, (Uchar *)0, (Uchar *)cmode, (Uchar *)0, &len)) {
1982 if (xdebug || (err == -1 && retr == -1)) {
1983 usal_prbytes("Mode Sense Data", mode, len);
1987 mode[2] = 0; /* ??? ist manchmal 0x80 */
1992 if (xdebug || (err == -1 && retr == -1))
1993 usal_prbytes("Mode page 1:", p, 0x10);
1997 getint("Error handling? ", &i, 0, 255);
2001 fprintf(stderr, "Error handling set from %02X to %02X\n",
2008 getint("Retry count? ", &i, 0, 255);
2012 fprintf(stderr, "Retry count set from %d to %d\n",
2017 if (xdebug || (err == -1 && retr == -1))
2018 usal_prbytes("Mode Select Data", mode, len);
2019 mode_select(usalp, mode, len, 0, usalp->inq->data_format >= 2);
2023 /*--------------------------------------------------------------------------*/
2024 static void qpto96(Uchar *sub, Uchar *subq, int dop);
2025 /*EXPORT void qpto96 __PR((Uchar *sub, Uchar *subq, int dop));*/
2027 * Q-Sub auf 96 Bytes blähen und P-Sub addieren
2029 * OUT: sub, IN: subqptr
2033 qpto96(Uchar *sub, Uchar *subqptr, int dop)
2040 if (subqptr == sub) {
2041 movebytes(subqptr, tmp, 12);
2044 fillbytes(sub, 96, '\0');
2047 if (dop) for (i = 0, p = sub; i < 96; i++) {
2050 for (i = 0, p = sub; i < 12; i++) {
2051 c = subqptr[i] & 0xFF;
2052 /*printf("%02X\n", c);*/
2088 /*--------------------------------------------------------------------------*/
2096 (void) test_unit_ready(usalp);
2098 if (test_unit_ready(usalp) < 0)
2101 printf("Doing 1000 'TEST UNIT READY' operations.\n");
2103 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
2104 comerr("Cannot get start time\n");
2106 for (i = 1000; --i >= 0; ) {
2107 (void) test_unit_ready(usalp);
2116 * ATAPI drives do not like seek_g0()
2119 i = seek_g0(usalp, 0L);
2123 printf("Doing 1000 'SEEK_G0 (0)' operations.\n");
2125 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
2126 comerr("Cannot get start time\n");
2128 for (i = 1000; --i >= 0; ) {
2129 (void) seek_g0(usalp, 0L);
2139 i = seek_g1(usalp, 0L);
2144 printf("Doing 1000 'SEEK_G1 (0)' operations.\n");
2146 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
2147 comerr("Cannot get start time\n");
2149 for (i = 1000; --i >= 0; ) {
2150 (void) seek_g1(usalp, 0L);
2169 badsecs = malloc(maxbad * sizeof (long));
2170 if (badsecs == NULL)
2171 comerr("No memory for bad sector list\n.");
2173 if (nbad >= maxbad) {
2175 badsecs = realloc(badsecs, maxbad * sizeof (long));
2176 if (badsecs == NULL)
2177 comerr("No memory to grow bad sector list\n.");
2179 badsecs[nbad++] = addr;
2190 fprintf(stderr, "Max corected retry count was %d (limited to %d).\n", maxtry, retries);
2191 fprintf(stderr, "The following %d sector(s) could not be read correctly:\n", nbad);
2192 for (i = 0; i < nbad; i++)
2193 fprintf(stderr, "%ld\n", badsecs[i]);