1 /* @(#)readcd.c 1.129 19/04/11 Copyright 1987, 1995-2018 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)readcd.c 1.129 19/04/11 Copyright 1987, 1995-2018 J. Schilling";
6 #endif
7 /*
8 * Skeleton for the use of the scg genearal SCSI - driver
9 *
10 * Copyright (c) 1987, 1995-2018 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include <schily/mconfig.h>
27 #include <schily/stdio.h>
28 #include <schily/standard.h>
29 #include <schily/unistd.h>
30 #include <schily/stdlib.h>
31 #include <schily/string.h>
32 #include <schily/fcntl.h>
33 #include <schily/time.h>
34 #include <schily/errno.h>
35 #include <schily/signal.h>
36 #include <schily/schily.h>
37 #include <schily/nlsdefs.h>
38 #include <schily/priv.h>
39 #include <schily/io.h> /* for setmode() prototype */
40
41 #include <scg/scgcmd.h>
42 #include <scg/scsireg.h>
43 #include <scg/scsitransp.h>
44
45 #include "scsi_scan.h"
46 #include "scsimmc.h"
47 #define qpto96 __nothing__
48 #include "cdrecord.h"
49 #include "cdrdeflt.h"
50 #undef qpto96
51 #include "movesect.h"
52
53 #include <ecc.h>
54 #include <edc.h>
55 #include "version.h"
56
57 char cdr_version[] = VERSION;
58
59 #if defined(PROTOTYPES)
60 #define UINT_C(a) (a##u)
61 #define ULONG_C(a) (a##ul)
62 #define USHORT_C(a) (a##uh)
63 #define CONCAT(a, b) a##b
64 #else
65 #define UINT_C(a) ((unsigned)(a))
66 #define ULONG_C(a) ((unsigned long)(a))
67 #define USHORT_C(a) ((unsigned short)(a))
68 /* CSTYLED */
69 #define CONCAT(a, b) a/**/b
70 #endif
71
72 extern BOOL getlong __PR((char *, long *, long, long));
73 extern BOOL getint __PR((char *, int *, int, int));
74
75 typedef struct {
76 long start;
77 long end;
78 long sptr; /* sectors per transfer */
79 BOOL askrange;
80 char *name;
81 } parm_t;
82
83 typedef struct {
84 int errors;
85 int c2_errors;
86 int c2_maxerrs;
87 int c2_errsecs;
88 int c2_badsecs;
89 int secsize; /* The output sector size on the file */
90 int isecsize; /* The input sector size from the medium */
91 BOOL ismmc;
92 } rparm_t;
93
94 typedef struct {
95 int c1_errors;
96 int c2_errors;
97 int cu_errors;
98 int pi_errors;
99 } cxerror_t;
100
101 typedef int (*start_cx_func_t) __PR((SCSI*)); /* initiates a scan */
102 typedef int (*end_cx_func_t) __PR((SCSI*)); /* ends a scan */
103 typedef int (*one_interval_func_t) __PR((SCSI *, /* scans a certain range, */
104 cxerror_t *, /* should be 75 sectors. */
105 long, void *)); /* Return value is the next */
106 /* sector to be scanned */
107 /*
108 * Describes one set of functions needed to perform an cx scan.
109 */
110 typedef struct {
111 start_cx_func_t start_func;
112 end_cx_func_t end_func;
113 one_interval_func_t one_interval_func;
114 } cx_scan_procedure_t;
115
116 LOCAL BOOL mmc_isplextor __PR((SCSI* scgp));
117 LOCAL int plextor_init_cx_scan __PR((SCSI* scgp));
118 LOCAL int plextor_init_pi8_scan __PR((SCSI* scgp));
119 LOCAL int plextor_init_pif_scan __PR((SCSI* scgp));
120 LOCAL int plextor_end_scan __PR((SCSI* scgp));
121 LOCAL int plextor_read_cx_values __PR((SCSI* scgp, cxerror_t *pe, BOOL dopi));
122 LOCAL int nec_init_cx_scan __PR((SCSI* scgp));
123 LOCAL int nec_end_scan __PR((SCSI* scgp));
124 LOCAL int nec_scan_one_interval __PR((SCSI* scgp, cxerror_t *pe, long addr, void *p));
125 LOCAL int plextor_scan_one_interval __PR((SCSI* scgp, cxerror_t *pe, long addr, void *p));
126 LOCAL int plextor_scan_one_dvd_interval __PR((SCSI* scgp, cxerror_t *pe, long addr, void *p));
127
128
129 /*
130 * Currently, Plextor and NEC cx scanning is supported
131 */
132 cx_scan_procedure_t cx_scan_procedures[] = {
133 { plextor_init_cx_scan,
134 plextor_end_scan,
135 plextor_scan_one_interval },
136
137 { nec_init_cx_scan,
138 nec_end_scan,
139 nec_scan_one_interval },
140
141 { NULL }
142 };
143
144 struct exargs {
145 SCSI *scgp;
146 int old_secsize;
147 int flags;
148 int exflags;
149 int excode;
150 char oerr[3];
151 } exargs;
152
153 EXPORT BOOL cvt_cyls __PR((void));
154 EXPORT BOOL cvt_bcyls __PR((void));
155 EXPORT void print_defect_list __PR((void));
156 LOCAL void usage __PR((int ret));
157 EXPORT int main __PR((int ac, char **av));
158 LOCAL void scg_openerr __PR((char *errstr));
159 LOCAL int find_drive __PR((SCSI *scgp, char *dev));
160 LOCAL void intr __PR((int sig));
161 LOCAL void exscsi __PR((int excode, void *arg));
162 #ifdef __needed__
163 LOCAL void excdr __PR((int excode, void *arg));
164 #endif
165 LOCAL int prstats __PR((void));
166 LOCAL int prstats_silent __PR((void));
167 LOCAL void dorw __PR((SCSI *scgp, char *filename, char *sectors));
168 LOCAL void doit __PR((SCSI *scgp));
169 LOCAL void read_disk __PR((SCSI *scgp, parm_t *parmp));
170 #ifdef CLONE_WRITE
171 LOCAL void readcd_disk __PR((SCSI *scgp, parm_t *parmp));
172 LOCAL void read_lin __PR((SCSI *scgp, parm_t *parmp));
173 LOCAL int read_secheader __PR((SCSI *scgp, long addr));
174 LOCAL int read_ftoc __PR((SCSI *scgp, parm_t *parmp, BOOL do_sectype));
175 LOCAL void read_sectypes __PR((SCSI *scgp, FILE *f));
176 LOCAL void get_sectype __PR((SCSI *scgp, long addr, char *st));
177 #endif
178
179 LOCAL void readc2_disk __PR((SCSI *scgp, parm_t *parmp));
180 LOCAL void readcx_disk __PR((SCSI *scgp, parm_t *parmp));
181 LOCAL void readpi_disk __PR((SCSI *scgp, parm_t *parmp));
182 LOCAL int fread_data __PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
183 #ifdef CLONE_WRITE
184 LOCAL int fread_2448 __PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
185 LOCAL int fread_2448_16 __PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
186 LOCAL int fread_2352 __PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
187 LOCAL int fread_2048 __PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
188 LOCAL int fread_lin __PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
189 #endif
190 LOCAL int bits __PR((int c));
191 LOCAL int bitidx __PR((int c));
192 LOCAL int fread_c2 __PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
193
194 LOCAL int fdata_null __PR((rparm_t *rp, caddr_t bp, long addr, int cnt));
195 LOCAL int fdata_c2 __PR((rparm_t *rp, caddr_t bp, long addr, int cnt));
196
197 #ifdef used
198 LOCAL int read_scsi_g1 __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
199 #endif
200
201 EXPORT int write_scsi __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
202 EXPORT int write_g0 __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
203 EXPORT int write_g1 __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
204
205 #ifdef used
206 LOCAL void Xrequest_sense __PR((SCSI *scgp));
207 #endif
208 LOCAL int read_retry __PR((SCSI *scgp, caddr_t bp, long addr, long cnt,
209 int (*rfunc)(SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt),
210 rparm_t *rp));
211 LOCAL void read_generic __PR((SCSI *scgp, parm_t *parmp,
212 int (*rfunc)(SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt),
213 rparm_t *rp,
214 int (*dfunc)(rparm_t *rp, caddr_t bp, long addr, int cnt)
215 ));
216 LOCAL void write_disk __PR((SCSI *scgp, parm_t *parmp));
217 LOCAL int choice __PR((int n));
218 LOCAL void ra __PR((SCSI *scgp));
219
220 EXPORT int read_da __PR((SCSI *scgp, caddr_t bp, long addr, int cnt, int framesize, int subcode));
221 LOCAL int read_sectors __PR((SCSI *scgp, void *p, long addr, int cnt));
222 LOCAL int read_dvd_sectors __PR((SCSI *scgp, void *p, long addr, int cnt));
223 EXPORT int read_cd __PR((SCSI *scgp, caddr_t bp, long addr, int cnt, int framesize, int data, int subch));
224
225 LOCAL void oldmode __PR((SCSI *scgp, int *errp, int *retrp));
226 LOCAL void domode __PR((SCSI *scgp, int err, int retr));
227
228 LOCAL void qpto96 __PR((Uchar *sub, Uchar *subq, int dop));
229 LOCAL void ovtime __PR((SCSI *scgp));
230 LOCAL void add_bad __PR((long addr));
231 LOCAL void print_bad __PR((void));
232 LOCAL void priv_warn __PR((const char *what, const char *msg));
233
234 struct timeval starttime;
235 struct timeval stoptime;
236 int didintr;
237 int exsig;
238
239 char *Sbuf;
240 long Sbufsize = -1L;
241 int spt = 0;
242
243 /*#define MAX_RETRY 32*/
244 #define MAX_RETRY 128
245
246 int help;
247 int xdebug;
248 int lverbose;
249 int quiet;
250 BOOL is_suid;
251 BOOL is_cdrom;
252 BOOL is_dvd;
253 BOOL is_bd;
254 BOOL do_write;
255 BOOL c2scan;
256 BOOL cxscan;
257 BOOL pi8scan;
258 BOOL pifscan;
259 BOOL plot;
260 BOOL fulltoc;
261 BOOL clone;
262 BOOL edc_corr;
263 BOOL noerror;
264 BOOL nocorr;
265 BOOL notrunc;
266 int retries = MAX_RETRY;
267 int maxtry = 0;
268 int meshpoints;
269 BOOL do_factor;
270
271 struct scsi_format_data fmt;
272
cvt_cyls()273 /*XXX*/EXPORT BOOL cvt_cyls() { return (FALSE); }
cvt_bcyls()274 /*XXX*/EXPORT BOOL cvt_bcyls() { return (FALSE); }
print_defect_list()275 /*XXX*/EXPORT void print_defect_list() {}
276
277 LOCAL void
usage(ret)278 usage(ret)
279 int ret;
280 {
281 error(_("Usage:\treadcd [options]\n"));
282 error(_("Options:\n"));
283 error(_("\t-version print version information and exit\n"));
284 error(_("\tdev=target SCSI target to use\n"));
285 error(_("\tscgopts=spec SCSI options for libscg\n"));
286 error(_("\tf=filename Name of file to read/write\n"));
287 error(_("\tsectors=range Range of sectors to read/write\n"));
288 error(_("\tspeed=# set speed of drive (MMC only)\n"));
289 error(_("\tts=# set maximum transfer size for a single SCSI command\n"));
290 error(_("\tspt=# set maximum nuber of sectors for a single SCSI command\n"));
291 error(_("\t-w Switch to write mode\n"));
292 error(_("\t-c2scan Do a C2 error scan\n"));
293 error(_("\t-cxscan Do a C1/C2/CU scan (only available on a few drives)\n"));
294 error(_("\t-pi8scan Do a DVD pisum8 scan (only available on a few drives)\n"));
295 error(_("\t-pifscan Do a DVD pif scan (only available on a few drives)\n"));
296 error(_("\t-plot Print data suitable for gnuplot\n"));
297 #ifdef CLONE_WRITE
298 error(_("\t-fulltoc Retrieve the full TOC\n"));
299 error(_("\t-clone Retrieve the full TOC and all data\n"));
300 error(_("\t-edc-corr Try to do user level Reed Solomon repair (experimental)\n"));
301 #endif
302 error(_("\ttimeout=# set the default SCSI command timeout to #.\n"));
303 error(_("\tdebug=#,-d Set to # or increment misc debug level\n"));
304 error(_("\tkdebug=#,kd=# do Kernel debugging\n"));
305 error(_("\t-quiet,-q be more quiet in error retry mode\n"));
306 error(_("\t-verbose,-v increment general verbose level by one\n"));
307 error(_("\t-Verbose,-V increment SCSI command transport verbose level by one\n"));
308 error(_("\t-silent,-s do not print status of failed SCSI commands\n"));
309 error(_("\t-scanbus scan the SCSI bus and exit\n"));
310 error(_("\t-noerror do not abort on error\n"));
311 #ifdef CLONE_WRITE
312 error(_("\t-nocorr do not apply error correction in drive\n"));
313 #endif
314 error(_("\t-notrunc do not truncate outputfile in read mode\n"));
315 error(_("\tretries=# set retry count (default is %d)\n"), retries);
316 error(_("\t-overhead meter SCSI command overhead times\n"));
317 error(_("\tmeshpoints=# print read-speed at # locations\n"));
318 error(_("\t-factor try to use speed factor with meshpoints=# if possible\n"));
319 error("\n");
320 error(_("sectors=0-0 will read nothing, sectors=0-1 will read one sector starting from 0\n"));
321 exit(ret);
322 }
323
324 /* CSTYLED */
325 char opts[] = "debug#,d+,kdebug#,kd#,timeout#,quiet,q,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,help,h,version,scanbus,dev*,scgopts*,sectors*,w,c2scan,cxscan,pi8scan,pifscan,plot,fulltoc,clone,edc-corr,noerror,nocorr,notrunc,retries#,factor,f*,speed#,ts&,spt#,overhead,meshpoints#";
326
327 EXPORT int
main(ac,av)328 main(ac, av)
329 int ac;
330 char *av[];
331 {
332 char *dev = NULL;
333 char *scgopts = NULL;
334 int fcount;
335 int cac;
336 char * const *cav;
337 #if defined(USE_NLS)
338 char *dir;
339 #endif
340 int scsibus = -1;
341 int target = -1;
342 int lun = -1;
343 int silent = 0;
344 int verbose = 0;
345 int kdebug = 0;
346 int debug = 0;
347 int deftimeout = 40;
348 int pversion = 0;
349 int scanbus = 0;
350 int speed = -1;
351 int dooverhead = 0;
352 SCSI *scgp;
353 char *filename = NULL;
354 char *sectors = NULL;
355
356 #ifdef HAVE_SOLARIS_PPRIV
357 /*
358 * Try to gain additional privs on Solaris
359 */
360 do_pfexec(ac, av,
361 PRIV_FILE_DAC_READ,
362 PRIV_SYS_DEVICES,
363 PRIV_NET_PRIVADDR,
364 NULL);
365 #endif
366 save_args(ac, av);
367
368 #if defined(USE_NLS)
369 (void) setlocale(LC_ALL, "");
370 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
371 #define TEXT_DOMAIN "cdrecord" /* Use this only if it weren't */
372 #endif
373 dir = searchfileinpath("share/locale", F_OK,
374 SIP_ANY_FILE|SIP_NO_PATH, NULL);
375 if (dir)
376 (void) bindtextdomain(TEXT_DOMAIN, dir);
377 else
378 #if defined(PROTOTYPES) && defined(INS_BASE)
379 (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
380 #else
381 (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
382 #endif
383 (void) textdomain(TEXT_DOMAIN);
384 #endif
385
386 cac = --ac;
387 cav = ++av;
388
389 if (getallargs(&cac, &cav, opts,
390 &debug, &debug,
391 &kdebug, &kdebug,
392 &deftimeout,
393 &quiet, &quiet,
394 &lverbose, &lverbose,
395 &verbose, &verbose,
396 &xdebug, &xdebug,
397 &silent, &silent,
398 &help, &help, &pversion,
399 &scanbus, &dev, &scgopts, §ors, &do_write,
400 &c2scan, &cxscan, &pi8scan, &pifscan,
401 &plot,
402 &fulltoc, &clone,
403 &edc_corr,
404 &noerror, &nocorr,
405 ¬runc, &retries, &do_factor, &filename,
406 &speed, getnum, &Sbufsize, &spt,
407 &dooverhead, &meshpoints) < 0) {
408 errmsgno(EX_BAD, _("Bad flag: %s.\n"), cav[0]);
409 usage(EX_BAD);
410 }
411 if (help)
412 usage(0);
413 if (pversion) {
414 printf(_("readcd %s %s (%s-%s-%s) Copyright (C) 1987, 1995-2018 %s\n"),
415 cdr_version, VERSION_DATE,
416 HOST_CPU, HOST_VENDOR, HOST_OS,
417 _("Joerg Schilling"));
418 exit(0);
419 }
420
421 fcount = 0;
422 cac = ac;
423 cav = av;
424
425 while (getfiles(&cac, &cav, opts) > 0) {
426 fcount++;
427 if (fcount == 1) {
428 if (*astoi(cav[0], &target) != '\0') {
429 errmsgno(EX_BAD,
430 _("Target '%s' is not a Number.\n"),
431 cav[0]);
432 usage(EX_BAD);
433 /* NOTREACHED */
434 }
435 }
436 if (fcount == 2) {
437 if (*astoi(cav[0], &lun) != '\0') {
438 errmsgno(EX_BAD,
439 _("Lun is '%s' not a Number.\n"),
440 cav[0]);
441 usage(EX_BAD);
442 /* NOTREACHED */
443 }
444 }
445 if (fcount == 3) {
446 if (*astoi(cav[0], &scsibus) != '\0') {
447 errmsgno(EX_BAD,
448 _("Scsibus is '%s' not a Number.\n"),
449 cav[0]);
450 usage(EX_BAD);
451 /* NOTREACHED */
452 }
453 }
454 cac--;
455 cav++;
456 }
457
458 /*
459 * The following scg_open() call needs more privileges, so we check for
460 * sufficient privileges here.
461 * The check has been introduced as some Linux distributions miss the
462 * skills to perceive the necessity for the needed privileges. So we
463 * warn which features are impaired by actually missing privileges.
464 */
465 if (!priv_eff_priv(SCHILY_PRIV_FILE_DAC_READ))
466 priv_warn("file read", "You will not be able to open all needed devices.");
467 #ifndef __SUNOS5
468 /*
469 * Due to a design bug in the Solaris USCSI ioctl, we don't need
470 * PRIV_FILE_DAC_WRITE to send SCSI commands and most installations
471 * probably don't grant PRIV_FILE_DAC_WRITE. Once we need /dev/scg*,
472 * we would need to test for PRIV_FILE_DAC_WRITE also.
473 */
474 if (!priv_eff_priv(SCHILY_PRIV_FILE_DAC_WRITE))
475 priv_warn("file write", "You will not be able to open all needed devices.");
476 #endif
477 if (!priv_eff_priv(SCHILY_PRIV_SYS_DEVICES))
478 priv_warn("device",
479 "You may not be able to send all needed SCSI commands, this my cause various unexplainable problems.");
480 if (!priv_eff_priv(SCHILY_PRIV_NET_PRIVADDR))
481 priv_warn("network", "You will not be able to do remote SCSI.");
482
483 /*error("dev: '%s'\n", dev);*/
484 if (!scanbus)
485 cdr_defaults(&dev, NULL, NULL, &Sbufsize, NULL);
486 if (debug) {
487 printf("dev: '%s'\n", dev);
488 }
489 if (dev || scanbus || (scsibus < 0 && target < 0 && lun < 0)) {
490 char errstr[80];
491
492 /*
493 * Call scg_remote() to force loading the remote SCSI transport
494 * library code that is located in librscg instead of the dummy
495 * remote routines that are located inside libscg.
496 */
497 scg_remote();
498 if (dev != NULL &&
499 ((strncmp(dev, "HELP", 4) == 0) ||
500 (strncmp(dev, "help", 4) == 0))) {
501 scg_help(stderr);
502 exit(0);
503 }
504 if ((scgp = scg_open(dev, errstr, sizeof (errstr), debug, lverbose)) == (SCSI *)0) {
505 scg_openerr(errstr);
506 /* NOTREACHED */
507 }
508 if (!scanbus && scg_scsibus(scgp) < 0 &&
509 scg_target(scgp) < 0 && scg_lun(scgp) < 0) {
510 int i = find_drive(scgp, dev);
511
512 if (i < 0) {
513 scg_openerr("");
514 /* NOTREACHED */
515 }
516 }
517 } else {
518 if (scsibus == -1 && target >= 0 && lun >= 0)
519 scsibus = 0;
520
521 scgp = scg_smalloc();
522 scgp->debug = debug;
523 scgp->kdebug = kdebug;
524
525 scg_settarget(scgp, scsibus, target, lun);
526 if (scg__open(scgp, NULL) <= 0)
527 comerr(_("Cannot open SCSI driver.\n"));
528 }
529 if (scgopts) {
530 int i = scg_opts(scgp, scgopts);
531 if (i <= 0)
532 exit(i < 0 ? EX_BAD : 0);
533 }
534 scgp->silent = silent;
535 scgp->verbose = verbose;
536 scgp->debug = debug;
537 scgp->kdebug = kdebug;
538 scg_settimeout(scgp, deftimeout);
539
540 if (Sbufsize < 0)
541 Sbufsize = 256*1024L;
542 Sbufsize = scg_bufsize(scgp, Sbufsize);
543 if ((Sbuf = scg_getbuf(scgp, Sbufsize)) == NULL)
544 comerr(_("Cannot get SCSI I/O buffer.\n"));
545
546 /*
547 * Did we get our privs from suid?
548 */
549 is_suid = priv_from_priv();
550 /*
551 * This is only for OS that do not support fine grained privs.
552 */
553 if (!is_suid) {
554 #ifdef HAVE_ISSETUGID
555 is_suid = issetugid();
556 #else
557 is_suid = geteuid() != getuid();
558 #endif
559 }
560 /*
561 * Drop privs we do not need anymore.
562 * We no longer need:
563 * file_dac_read,net_privaddr
564 * We still need:
565 * sys_devices
566 */
567 if (is_suid || getuid() != 0)
568 priv_drop();
569 /*
570 * We don't need root privilleges anymore.
571 */
572 #ifdef HAVE_SETREUID
573 if (setreuid(-1, getuid()) < 0)
574 #else
575 #ifdef HAVE_SETEUID
576 if (seteuid(getuid()) < 0)
577 #else
578 if (setuid(getuid()) < 0)
579 #endif
580 #endif
581 comerr(_("Panic cannot set back effective uid.\n"));
582
583 /* code to use SCG */
584
585 if (scanbus) {
586 int i = select_target(scgp, stdout);
587
588 if (i < 0) {
589 scg_openerr("");
590 /* NOTREACHED */
591 }
592 exit(0);
593 }
594 seterrno(0);
595 if (!do_inquiry(scgp, FALSE)) {
596 int err = geterrno();
597
598 if (err == EPERM || err == EACCES) {
599 scg_openerr("");
600 /* NOTREACHED */
601 }
602 }
603 allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
604 if (is_mmc(scgp, NULL, NULL)) {
605 int rspeed;
606 int wspeed;
607 /*
608 * At this point we know that we have a SCSI-3/mmc compliant drive.
609 * Unfortunately ATAPI drives violate the SCSI spec in returning
610 * a response data format of '1' which from the SCSI spec would
611 * tell us not to use the "PF" bit in mode select. As ATAPI drives
612 * require the "PF" bit to be set, we 'correct' the inquiry data.
613 */
614 if (scgp->inq->data_format < 2)
615 scgp->inq->data_format = 2;
616
617 if ((rspeed = get_curprofile(scgp)) >= 0) {
618 if (rspeed >= 0x08 && rspeed < 0x10)
619 is_cdrom = TRUE;
620 if (rspeed >= 0x10 && rspeed < 0x20)
621 is_dvd = TRUE;
622 if (rspeed >= 0x40 && rspeed < 0x50)
623 is_bd = TRUE;
624 } else {
625 BOOL dvd;
626
627 mmc_check(scgp, NULL, NULL, NULL, NULL, &dvd, NULL);
628 if (dvd == FALSE) {
629 is_cdrom = TRUE;
630 } else {
631 char xb[32];
632
633 if (read_dvd_structure(scgp, (caddr_t)xb, 32, 0, 0, 0, 0) >= 0) {
634 /*
635 * If read DVD structure is supported and works, then
636 * we must have a DVD media in the drive. Signal to
637 * use the DVD driver.
638 */
639 is_dvd = TRUE;
640 } else {
641 is_cdrom = TRUE;
642 }
643 }
644 }
645
646 if (speed > 0)
647 speed *= 177;
648 if (speed > 0xFFFF || speed < 0)
649 speed = 0xFFFF;
650 scsi_set_speed(scgp, speed, speed, ROTCTL_CLV);
651 if (scsi_get_speed(scgp, &rspeed, &wspeed) >= 0) {
652 error(_("Read speed: %5d kB/s (CD %3dx, DVD %2dx, BD %2dx).\n"),
653 rspeed, rspeed/176, rspeed/1385, rspeed/4495);
654 error(_("Write speed: %5d kB/s (CD %3dx, DVD %2dx, BD %2dx).\n"),
655 wspeed, wspeed/176, wspeed/1385, wspeed/4495);
656 }
657 }
658 exargs.scgp = scgp;
659 exargs.old_secsize = -1;
660 /* exargs.flags = flags;*/
661 exargs.exflags = 0;
662 exargs.excode = 0;
663 exargs.oerr[2] = 0;
664
665 /*
666 * Install exit handler before we change the drive status.
667 */
668 on_comerr(exscsi, &exargs);
669 signal(SIGINT, intr);
670 signal(SIGTERM, intr);
671
672 if (dooverhead) {
673 ovtime(scgp);
674 comexit(0);
675 }
676
677 if (is_suid) {
678 if (scgp->inq->type != INQ_ROMD)
679 comerrno(EX_BAD, _("Not root. Will only work on CD-ROM in suid/priv mode\n"));
680 }
681
682 if (filename || sectors || c2scan || cxscan || pi8scan || pifscan ||
683 meshpoints || fulltoc ||
684 clone || edc_corr) {
685 dorw(scgp, filename, sectors);
686 } else {
687 doit(scgp);
688 }
689 comexit(exargs.excode);
690 return (exargs.excode);
691 }
692
693 LOCAL void
scg_openerr(errstr)694 scg_openerr(errstr)
695 char *errstr;
696 {
697 int err = geterrno();
698
699 errmsgno(err, _("%s%sCannot open or use SCSI driver.\n"), errstr, errstr[0]?". ":"");
700 errmsgno(EX_BAD, _("For possible targets try 'readcd -scanbus'.%s\n"),
701 geteuid() ? _(" Make sure you are root."):"");
702 errmsgno(EX_BAD, _("For possible transport specifiers try 'readcd dev=help'.\n"));
703 exit(err);
704 }
705
706 LOCAL int
find_drive(scgp,dev)707 find_drive(scgp, dev)
708 SCSI *scgp;
709 char *dev;
710 {
711 int ntarget;
712
713 error(_("No target specified, trying to find one...\n"));
714 ntarget = find_target(scgp, INQ_ROMD, -1);
715 if (ntarget < 0)
716 return (ntarget);
717 if (ntarget == 1) {
718 /*
719 * Simple case, exactly one CD-ROM found.
720 */
721 find_target(scgp, INQ_ROMD, 1);
722 } else if (ntarget <= 0 && (ntarget = find_target(scgp, INQ_WORM, -1)) == 1) {
723 /*
724 * Exactly one CD-ROM acting as WORM found.
725 */
726 find_target(scgp, INQ_WORM, 1);
727 } else if (ntarget <= 0) {
728 /*
729 * No single CD-ROM or WORM found.
730 */
731 errmsgno(EX_BAD, _("No CD/DVD/BD-Recorder target found.\n"));
732 errmsgno(EX_BAD, _("Your platform may not allow to scan for SCSI devices.\n"));
733 comerrno(EX_BAD, _("Call 'readcd dev=help' or ask your sysadmin for possible targets.\n"));
734 } else {
735 errmsgno(EX_BAD, _("Too many CD/DVD/BD-Recorder targets found.\n"));
736 select_target(scgp, stdout);
737 comerrno(EX_BAD, _("Select a target from the list above and use 'readcd dev=%s%sb,t,l'.\n"),
738 dev?dev:"", dev?(dev[strlen(dev)-1] == ':'?"":":"):"");
739 }
740 error(_("Using dev=%s%s%d,%d,%d.\n"),
741 dev?dev:"", dev?(dev[strlen(dev)-1] == ':'?"":":"):"",
742 scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
743 return (ntarget);
744 }
745
746 /*
747 * XXX Leider kann man vim Signalhandler keine SCSI Kommandos verschicken
748 * XXX da meistens das letzte SCSI Kommando noch laeuft.
749 * XXX Eine Loesung waere ein Abort Callback in SCSI *.
750 */
751 LOCAL void
intr(sig)752 intr(sig)
753 int sig;
754 {
755 didintr++;
756 exsig = sig;
757 /* comexit(sig);*/
758 }
759
760 /* ARGSUSED */
761 LOCAL void
exscsi(excode,arg)762 exscsi(excode, arg)
763 int excode;
764 void *arg;
765 {
766 struct exargs *exp = (struct exargs *)arg;
767 int i;
768
769 /*
770 * Try to restore the old sector size.
771 */
772 if (exp != NULL && exp->exflags == 0) {
773 for (i = 0; i < 10*100; i++) {
774 if (!exp->scgp->running)
775 break;
776 if (i == 10) {
777 errmsgno(EX_BAD,
778 _("Waiting for current SCSI command to finish.\n"));
779 }
780 usleep(100000);
781 }
782
783 if (!exp->scgp->running) {
784 if (exp->oerr[2] != 0) {
785 domode(exp->scgp, exp->oerr[0], exp->oerr[1]);
786 }
787 if (exp->old_secsize > 0 && exp->old_secsize != 2048)
788 select_secsize(exp->scgp, exp->old_secsize);
789 }
790 exp->exflags++; /* Make sure that it only get called once */
791 }
792 }
793
794 #ifdef __needed__
795 LOCAL void
excdr(excode,arg)796 excdr(excode, arg)
797 int excode;
798 void *arg;
799 {
800 exscsi(excode, arg);
801
802 #ifdef needed
803 /* Do several other restores/statistics here (see cdrecord.c) */
804 #endif
805 }
806 #endif
807
808 /*
809 * Return milliseconds since start time.
810 */
811 LOCAL int
prstats()812 prstats()
813 {
814 int sec;
815 int usec;
816 int tmsec;
817
818 if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
819 comerr(_("Cannot get time\n"));
820
821 sec = stoptime.tv_sec - starttime.tv_sec;
822 usec = stoptime.tv_usec - starttime.tv_usec;
823 tmsec = sec*1000 + usec/1000;
824 #ifdef lint
825 tmsec = tmsec; /* Bisz spaeter */
826 #endif
827 if (usec < 0) {
828 sec--;
829 usec += 1000000;
830 }
831
832 error(_("Time total: %d.%03dsec\n"), sec, usec/1000);
833 return (1000*sec + (usec / 1000));
834 }
835
836 /*
837 * Return milliseconds since start time, but be silent this time.
838 */
839 LOCAL int
prstats_silent()840 prstats_silent()
841 {
842 int sec;
843 int usec;
844 int tmsec;
845
846 if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
847 comerr(_("Cannot get time\n"));
848
849 sec = stoptime.tv_sec - starttime.tv_sec;
850 usec = stoptime.tv_usec - starttime.tv_usec;
851 tmsec = sec*1000 + usec/1000;
852 #ifdef lint
853 tmsec = tmsec; /* Bisz spaeter */
854 #endif
855 if (usec < 0) {
856 sec--;
857 usec += 1000000;
858 }
859
860 return (1000*sec + (usec / 1000));
861 }
862
863 LOCAL void
dorw(scgp,filename,sectors)864 dorw(scgp, filename, sectors)
865 SCSI *scgp;
866 char *filename;
867 char *sectors;
868 {
869 parm_t params;
870 char *p = NULL;
871
872 params.start = 0;
873 params.end = -1;
874 params.sptr = -1;
875 params.askrange = FALSE;
876 params.name = NULL;
877
878 if (filename)
879 params.name = filename;
880 if (meshpoints > 0) {
881 if (params.name == NULL)
882 params.name = "/dev/null";
883 }
884 if (sectors)
885 p = astol(sectors, ¶ms.start);
886 if (p && *p == '-')
887 p = astol(++p, ¶ms.end);
888 if (p && *p != '\0')
889 comerrno(EX_BAD, _("Not a valid sector range '%s'\n"), sectors);
890
891 if (!wait_unit_ready(scgp, 60))
892 comerrno(EX_BAD, _("Device not ready.\n"));
893
894 #ifdef CLONE_WRITE
895 if (fulltoc) {
896 if (params.name == NULL)
897 params.name = "/dev/null";
898 read_ftoc(scgp, ¶ms, FALSE);
899 } else if (clone || edc_corr) {
900 if (!is_mmc(scgp, NULL, NULL))
901 comerrno(EX_BAD, _("Unsupported device for clone mode.\n"));
902 if (!edc_corr)
903 noerror = TRUE;
904 if (retries == MAX_RETRY)
905 retries = 10;
906 if (params.name == NULL)
907 params.name = "/dev/null";
908
909 if (clone)
910 if (read_ftoc(scgp, ¶ms, TRUE) < 0)
911 comerrno(EX_BAD, _("Read fulltoc problems.\n"));
912 readcd_disk(scgp, ¶ms);
913 } else
914 #endif
915 if (c2scan) {
916 noerror = TRUE;
917 if (retries == MAX_RETRY)
918 retries = 10;
919 if (params.name == NULL)
920 params.name = "/dev/null";
921 readc2_disk(scgp, ¶ms);
922 } else if (cxscan) {
923 if (plot && lverbose == 0)
924 lverbose = 1;
925 noerror = TRUE;
926 if (retries == MAX_RETRY)
927 retries = 10;
928 if (params.name == NULL)
929 params.name = "/dev/null";
930 readcx_disk(scgp, ¶ms);
931 } else if (pi8scan || pifscan) {
932 if (plot && lverbose == 0)
933 lverbose = 1;
934 noerror = TRUE;
935 if (retries == MAX_RETRY)
936 retries = 10;
937 if (params.name == NULL)
938 params.name = "/dev/null";
939 readpi_disk(scgp, ¶ms);
940 } else if (do_write)
941 write_disk(scgp, ¶ms);
942 else
943 read_disk(scgp, ¶ms);
944 }
945
946 LOCAL void
doit(scgp)947 doit(scgp)
948 SCSI *scgp;
949 {
950 int i = 0;
951 parm_t params;
952
953 params.start = 0;
954 params.end = -1;
955 params.sptr = -1;
956 params.askrange = TRUE;
957 params.name = "/dev/null";
958
959 for (;;) {
960 if (!wait_unit_ready(scgp, 60))
961 comerrno(EX_BAD, _("Device not ready.\n"));
962
963 printf(_("0:read 1:veri 2:erase 3:read buffer 4:cache 5:ovtime 6:cap\n"));
964 printf(_("7:wne 8:floppy 9:verify 10:checkcmds 11:read disk 12:write disk\n"));
965 printf(_("13:scsireset 14:seektest 15: readda 16: reada 17: c2err\n"));
966 #ifdef CLONE_WRITE
967 printf(_("18:readcd 19: lin 20: full toc\n"));
968 #endif
969
970 getint(_("Enter selection:"), &i, 0, 20);
971 if (didintr)
972 return;
973
974 switch (i) {
975
976 case 5: ovtime(scgp); break;
977 case 11: read_disk(scgp, 0); break;
978 case 12: write_disk(scgp, 0); break;
979 case 15: ra(scgp); break;
980 /* case 16: reada_disk(scgp, 0, 0); break;*/
981 case 17: readc2_disk(scgp, ¶ms); break;
982 #ifdef CLONE_WRITE
983 case 18: readcd_disk(scgp, 0); break;
984 case 19: read_lin(scgp, 0); break;
985 case 20: read_ftoc(scgp, 0, FALSE); break;
986 #endif
987 }
988 }
989 }
990
991 LOCAL void
read_disk(scgp,parmp)992 read_disk(scgp, parmp)
993 SCSI *scgp;
994 parm_t *parmp;
995 {
996 rparm_t rp;
997
998 read_capacity(scgp);
999 print_capacity(scgp, stderr);
1000
1001 rp.errors = 0;
1002 rp.c2_errors = 0;
1003 rp.c2_maxerrs = 0;
1004 rp.c2_errsecs = 0;
1005 rp.c2_badsecs = 0;
1006 rp.isecsize = rp.secsize = scgp->cap->c_bsize;
1007
1008 read_generic(scgp, parmp, fread_data, &rp, fdata_null);
1009 }
1010
1011 #ifdef CLONE_WRITE
1012 LOCAL void
readcd_disk(scgp,parmp)1013 readcd_disk(scgp, parmp)
1014 SCSI *scgp;
1015 parm_t *parmp;
1016 {
1017 rparm_t rp;
1018 int osecsize = 2048;
1019 int oerr = 0;
1020 int oretr = 10;
1021 int (*funcp)__PR((SCSI *_scgp, rparm_t *_rp, caddr_t bp, long addr, int cnt));
1022
1023 scgp->silent++;
1024 if (read_capacity(scgp) >= 0)
1025 osecsize = scgp->cap->c_bsize;
1026 scgp->silent--;
1027 if (osecsize != 2048)
1028 select_secsize(scgp, 2048);
1029
1030 read_capacity(scgp);
1031 print_capacity(scgp, stderr);
1032
1033 rp.errors = 0;
1034 rp.c2_errors = 0;
1035 rp.c2_maxerrs = 0;
1036 rp.c2_errsecs = 0;
1037 rp.c2_badsecs = 0;
1038 rp.isecsize = rp.secsize = 2448;
1039 rp.ismmc = is_mmc(scgp, NULL, NULL);
1040 funcp = fread_2448;
1041
1042 wait_unit_ready(scgp, 10);
1043 if (fread_2448(scgp, &rp, Sbuf, 0, 0) < 0) {
1044 errmsgno(EX_BAD, _("read 2448 failed\n"));
1045 if (rp.ismmc &&
1046 fread_2448_16(scgp, &rp, Sbuf, 0, 0) >= 0) {
1047 errmsgno(EX_BAD, _("read 2448_16 : OK\n"));
1048
1049 funcp = fread_2448_16;
1050 }
1051 }
1052 if (edc_corr) {
1053 funcp = fread_2048;
1054 rp.secsize = 2048; /* We ouput CD-ROM data sectors */
1055 rp.isecsize = 2352; /* We read CD-DA sectors from CD */
1056 }
1057
1058 oldmode(scgp, &oerr, &oretr);
1059 exargs.oerr[0] = oerr;
1060 exargs.oerr[1] = oretr;
1061 exargs.oerr[2] = 0xFF;
1062 if (parmp == NULL) /* XXX Nur am Anfang!!! */
1063 domode(scgp, -1, -1);
1064 else
1065 domode(scgp, nocorr?0x21:0x20, 10);
1066
1067 read_generic(scgp, parmp, funcp, &rp, fdata_null);
1068 if (osecsize != 2048)
1069 select_secsize(scgp, osecsize);
1070 domode(scgp, oerr, oretr);
1071 }
1072
1073 /* ARGSUSED */
1074 LOCAL void
read_lin(scgp,parmp)1075 read_lin(scgp, parmp)
1076 SCSI *scgp;
1077 parm_t *parmp;
1078 {
1079 parm_t parm;
1080 rparm_t rp;
1081
1082 read_capacity(scgp);
1083 print_capacity(scgp, stderr);
1084
1085 parm.start = ULONG_C(0xF0000000);
1086 parm.end = ULONG_C(0xFF000000);
1087 parm.name = "DDD";
1088
1089 rp.errors = 0;
1090 rp.c2_errors = 0;
1091 rp.c2_maxerrs = 0;
1092 rp.c2_errsecs = 0;
1093 rp.c2_badsecs = 0;
1094 rp.isecsize = rp.secsize = 2448;
1095 rp.ismmc = is_mmc(scgp, NULL, NULL);
1096 domode(scgp, -1, -1);
1097 read_generic(scgp, &parm, fread_lin, &rp, fdata_null);
1098 }
1099
1100 LOCAL int
read_secheader(scgp,addr)1101 read_secheader(scgp, addr)
1102 SCSI *scgp;
1103 long addr;
1104 {
1105 rparm_t rp;
1106 int osecsize = 2048;
1107 int ret = 0;
1108
1109 scgp->silent++;
1110 if (read_capacity(scgp) >= 0)
1111 osecsize = scgp->cap->c_bsize;
1112 scgp->silent--;
1113 if (osecsize != 2048)
1114 select_secsize(scgp, 2048);
1115
1116 read_capacity(scgp);
1117
1118 rp.errors = 0;
1119 rp.c2_errors = 0;
1120 rp.c2_maxerrs = 0;
1121 rp.c2_errsecs = 0;
1122 rp.c2_badsecs = 0;
1123 rp.isecsize = rp.secsize = 2352;
1124 rp.ismmc = is_mmc(scgp, NULL, NULL);
1125
1126 wait_unit_ready(scgp, 10);
1127
1128 fillbytes(Sbuf, 2352, '\0');
1129 if (fread_2352(scgp, &rp, Sbuf, addr, 1) < 0) {
1130 ret = -1;
1131 }
1132 if (osecsize != 2048)
1133 select_secsize(scgp, osecsize);
1134 return (ret);
1135 }
1136
1137 /* ARGSUSED */
1138 LOCAL int
read_ftoc(scgp,parmp,do_sectype)1139 read_ftoc(scgp, parmp, do_sectype)
1140 SCSI *scgp;
1141 parm_t *parmp;
1142 BOOL do_sectype;
1143 {
1144 FILE *f;
1145 int i;
1146 char filename[1024];
1147 struct tocheader *tp;
1148 char *p;
1149 char xb[256];
1150 int len;
1151 char xxb[10000];
1152
1153
1154 strcpy(filename, "toc.dat");
1155 if (parmp != NULL &&
1156 strcmp(parmp->name, "/dev/null") != 0) {
1157
1158 len = strlen(parmp->name);
1159 if (len > (sizeof (filename)-5)) {
1160 len = sizeof (filename)-5;
1161 }
1162 js_snprintf(filename, sizeof (filename), "%.*s.toc", len, parmp->name);
1163 }
1164
1165 tp = (struct tocheader *)xb;
1166
1167 fillbytes((caddr_t)xb, sizeof (xb), '\0');
1168 if (read_toc(scgp, xb, 0, sizeof (struct tocheader), 0, FMT_FULLTOC) < 0) {
1169 if (scgp->silent == 0 || scgp->verbose > 0)
1170 errmsgno(EX_BAD, _("Cannot read TOC header\n"));
1171 return (-1);
1172 }
1173 len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
1174 error(_("TOC len: %d. First Session: %d Last Session: %d.\n"), len, tp->first, tp->last);
1175
1176 /*
1177 * XXX there is a bug in some ASPI versions that
1178 * XXX cause a hang with odd transfer lengths.
1179 * XXX We should workaround the problem where it exists
1180 * XXX but the problem may exist elsewhere too.
1181 */
1182 if (len & 1)
1183 len++;
1184 if (read_toc(scgp, xxb, 0, len, 0, FMT_FULLTOC) < 0) {
1185 if (len & 1) {
1186 /*
1187 * Work around a bug in some operating systems that do not
1188 * handle odd byte DMA correctly for ATAPI drives.
1189 */
1190 wait_unit_ready(scgp, 30);
1191 read_toc(scgp, xb, 0, sizeof (struct tocheader), 0, FMT_FULLTOC);
1192 wait_unit_ready(scgp, 30);
1193 if (read_toc(scgp, xxb, 0, len+1, 0, FMT_FULLTOC) >= 0) {
1194 goto itworked;
1195 }
1196 }
1197 if (scgp->silent == 0)
1198 errmsgno(EX_BAD, _("Cannot read full TOC\n"));
1199 return (-1);
1200 }
1201
1202 itworked:
1203 f = fileopen(filename, "wctb");
1204
1205 if (f == NULL)
1206 comerr(_("Cannot open '%s'.\n"), filename);
1207 filewrite(f, xxb, len);
1208 if (do_sectype)
1209 read_sectypes(scgp, f);
1210 fflush(f);
1211 fclose(f);
1212
1213 p = &xxb[4];
1214 for (; p < &xxb[len]; p += 11) {
1215 for (i = 0; i < 11; i++)
1216 error("%02X ", p[i] & 0xFF);
1217 error("\n");
1218 }
1219 /*
1220 * List all lead out start times to give information about multi
1221 * session disks.
1222 */
1223 p = &xxb[4];
1224 for (; p < &xxb[len]; p += 11) {
1225 if ((p[3] & 0xFF) == 0xA2) {
1226 error(_("Lead out %d: %ld\n"), p[0], msf_to_lba(p[8], p[9], p[10], TRUE));
1227 }
1228 }
1229 return (0);
1230 }
1231
1232 LOCAL void
read_sectypes(scgp,f)1233 read_sectypes(scgp, f)
1234 SCSI *scgp;
1235 FILE *f;
1236 {
1237 char sect;
1238
1239 sect = SECT_AUDIO;
1240 get_sectype(scgp, 4, §);
1241 if (f != NULL)
1242 filewrite(f, §, 1);
1243 if (xdebug)
1244 scg_prbytes(_("sec 0"), (Uchar *)Sbuf, 16);
1245
1246 sect = SECT_AUDIO;
1247 get_sectype(scgp, scgp->cap->c_baddr-4, §);
1248 if (f != NULL)
1249 filewrite(f, §, 1);
1250 if (xdebug) {
1251 scg_prbytes(_("sec E"), (Uchar *)Sbuf, 16);
1252 error(_("baddr: %ld\n"), (long)scgp->cap->c_baddr);
1253 }
1254 }
1255
1256 LOCAL void
get_sectype(scgp,addr,st)1257 get_sectype(scgp, addr, st)
1258 SCSI *scgp;
1259 long addr;
1260 char *st;
1261 {
1262 char *synchdr = "\0\377\377\377\377\377\377\377\377\377\377\0";
1263 int sectype = SECT_AUDIO;
1264 int i;
1265 long raddr = addr;
1266 #define _MAX_TRY_ 20
1267
1268 scgp->silent++;
1269 for (i = 0; i < _MAX_TRY_ && read_secheader(scgp, raddr) < 0; i++) {
1270 if (addr == 0)
1271 raddr++;
1272 else
1273 raddr--;
1274 }
1275 scgp->silent--;
1276 if (i >= _MAX_TRY_) {
1277 error(_("Sectype (%ld) is CANNOT\n"), addr);
1278 return;
1279 } else if (i > 0) {
1280 error(_("Sectype (%ld) needed %d retries\n"), addr, i);
1281 }
1282 #undef _MAX_TRY_
1283
1284 if (cmpbytes(Sbuf, synchdr, 12) < 12) {
1285 if (xdebug)
1286 error(_("Sectype (%ld) is AUDIO\n"), addr);
1287 if (st)
1288 *st = SECT_AUDIO;
1289 return;
1290 }
1291 if (xdebug)
1292 error(_("Sectype (%ld) is DATA\n"), addr);
1293 if (Sbuf[15] == 0) {
1294 if (xdebug)
1295 error(_("Sectype (%ld) is MODE 0\n"), addr);
1296 sectype = SECT_MODE_0;
1297
1298 } else if (Sbuf[15] == 1) {
1299 if (xdebug)
1300 error(_("Sectype (%ld) is MODE 1\n"), addr);
1301 sectype = SECT_ROM;
1302
1303 } else if (Sbuf[15] == 2) {
1304 if (xdebug)
1305 error(_("Sectype (%ld) is MODE 2\n"), addr);
1306
1307 if ((Sbuf[16+2] & 0x20) == 0 &&
1308 (Sbuf[16+4+2] & 0x20) == 0) {
1309 if (xdebug)
1310 error(_("Sectype (%ld) is MODE 2 form 1\n"), addr);
1311 sectype = SECT_MODE_2_F1;
1312
1313 } else if ((Sbuf[16+2] & 0x20) != 0 &&
1314 (Sbuf[16+4+2] & 0x20) != 0) {
1315 if (xdebug)
1316 error(_("Sectype (%ld) is MODE 2 form 2\n"), addr);
1317 sectype = SECT_MODE_2_F2;
1318 } else {
1319 if (xdebug)
1320 error(_("Sectype (%ld) is MODE 2 formless\n"), addr);
1321 sectype = SECT_MODE_2;
1322 }
1323 } else {
1324 error(_("Sectype (%ld) is UNKNOWN\n"), addr);
1325 }
1326 if (st)
1327 *st = sectype;
1328 if (xdebug)
1329 error(_("Sectype (%ld) is 0x%02X\n"), addr, sectype);
1330 }
1331
1332 #endif /* CLONE_WRITE */
1333
1334 char zeroblk[512];
1335
1336 LOCAL void
readc2_disk(scgp,parmp)1337 readc2_disk(scgp, parmp)
1338 SCSI *scgp;
1339 parm_t *parmp;
1340 {
1341 rparm_t rp;
1342 int osecsize = 2048;
1343 int oerr = 0;
1344 int oretr = 10;
1345
1346 scgp->silent++;
1347 if (read_capacity(scgp) >= 0)
1348 osecsize = scgp->cap->c_bsize;
1349 scgp->silent--;
1350 if (osecsize != 2048)
1351 select_secsize(scgp, 2048);
1352
1353 read_capacity(scgp);
1354 print_capacity(scgp, stderr);
1355
1356 rp.errors = 0;
1357 rp.c2_errors = 0;
1358 rp.c2_maxerrs = 0;
1359 rp.c2_errsecs = 0;
1360 rp.c2_badsecs = 0;
1361 rp.isecsize = rp.secsize = 2352 + 294; /* CD-DA + C2 bit pointers */
1362 rp.ismmc = is_mmc(scgp, NULL, NULL);
1363
1364 oldmode(scgp, &oerr, &oretr);
1365 exargs.oerr[0] = oerr;
1366 exargs.oerr[1] = oretr;
1367 exargs.oerr[2] = 0xFF;
1368 domode(scgp, 0x21, 10);
1369
1370
1371 read_generic(scgp, parmp, fread_c2, &rp, fdata_c2);
1372 if (osecsize != 2048)
1373 select_secsize(scgp, osecsize);
1374 domode(scgp, oerr, oretr);
1375
1376 printf(_("Total of %d hard read errors.\n"), rp.errors);
1377 printf(_("C2 errors total: %d bytes in %d sectors on disk\n"), rp.c2_errors, rp.c2_errsecs);
1378 printf(_("C2 errors rate: %f%% per byte, %f%% per sector\n"),
1379 (100.0*rp.c2_errors)/scgp->cap->c_baddr/2352,
1380 (100.0*rp.c2_errsecs)/scgp->cap->c_baddr);
1381 printf(_("C2 errors on worst sector: %d, sectors with 100+ C2 errors: %d\n"), rp.c2_maxerrs, rp.c2_badsecs);
1382 }
1383
1384
1385 LOCAL void
readcx_disk(scgp,parmp)1386 readcx_disk(scgp, parmp)
1387 SCSI *scgp;
1388 parm_t *parmp;
1389 {
1390 long addr = 0L;
1391 long end = 0L;
1392 int secs; /* # of seconds */
1393 cxerror_t errors;
1394 cxerror_t stats;
1395 cxerror_t max_errors;
1396 cx_scan_procedure_t *sp;
1397 BOOL askrange = FALSE;
1398 BOOL isrange = FALSE;
1399 FILE *f = stdout;
1400
1401 if (is_suid) {
1402 if (scgp->inq->type != INQ_ROMD)
1403 comerrno(EX_BAD, _("Not root. Will only read from CD in suid/priv mode\n"));
1404 }
1405
1406 scgp->silent++;
1407 if (read_capacity(scgp) >= 0)
1408 end = scgp->cap->c_baddr + 1;
1409 scgp->silent--;
1410 print_capacity(scgp, stderr);
1411
1412 if (parmp == NULL || parmp->askrange)
1413 askrange = TRUE;
1414 if (parmp != NULL && !askrange && (parmp->start <= parmp->end))
1415 isrange = TRUE;
1416
1417 if ((end <= 0 && isrange) || (askrange && scg_yes(_("Ignore disk size? "))))
1418 end = 10000000; /* Hack to read empty (e.g. blank=fast) disks */
1419
1420 if (parmp) {
1421 addr = parmp->start;
1422 if (parmp->end != -1 && parmp->end < end)
1423 end = parmp->end;
1424 }
1425
1426 for (sp = cx_scan_procedures; sp->start_func; sp++) {
1427 if ((*sp->start_func)(scgp) >= 0)
1428 break;
1429 }
1430 if (sp->start_func == NULL)
1431 comerrno(EX_BAD, _("Unsupported drive for -cxscan\n"));
1432
1433 secs = (end - addr) / 75; /* Compute # of seconds */
1434
1435 fillbytes(&stats, sizeof (stats), '\0');
1436 fillbytes(&max_errors, sizeof (max_errors), '\0');
1437
1438 while (addr < end) {
1439 addr = (*sp->one_interval_func)(scgp, &errors, addr, Sbuf);
1440 stats.c1_errors += errors.c1_errors;
1441 stats.c2_errors += errors.c2_errors;
1442 stats.cu_errors += errors.cu_errors;
1443 stats.pi_errors += errors.pi_errors;
1444 max_errors.c1_errors = max(max_errors.c1_errors, errors.c1_errors);
1445 max_errors.c2_errors = max(max_errors.c2_errors, errors.c2_errors);
1446 max_errors.cu_errors = max(max_errors.cu_errors, errors.cu_errors);
1447 max_errors.pi_errors = max(max_errors.pi_errors, errors.pi_errors);
1448 if (lverbose > 1 ||
1449 (lverbose > 0 &&
1450 (errors.c1_errors || errors.c2_errors || errors.cu_errors))) {
1451 if (plot) {
1452 printf("%8ld %4d %4d %4d\n",
1453 addr,
1454 errors.c1_errors, errors.c2_errors,
1455 errors.cu_errors);
1456 flush();
1457 } else {
1458 printf(" %3ldm %02lds: C1: %4d, C2: %4d, CU: %4d\n",
1459 addr/75/60, addr/75%60,
1460 errors.c1_errors, errors.c2_errors,
1461 errors.cu_errors);
1462 }
1463 }
1464 if (didintr) {
1465 (*sp->end_func)(scgp);
1466 comexit(exsig);
1467 }
1468 }
1469
1470 if (plot)
1471 f = stderr;
1472 fprintf(f, _("\n\ntotal result:\n\n"));
1473 fprintf(f, _("total: C1: %5d, C2: %5d, CU: %5d\n"),
1474 stats.c1_errors, stats.c2_errors, stats.cu_errors);
1475 fprintf(f, _("max : C1: %5d, C2: %5d, CU: %5d\n"),
1476 max_errors.c1_errors, max_errors.c2_errors,
1477 max_errors.cu_errors);
1478 fprintf(f, _("avg/s: C1: %5.1f, C2: %5.1f, CU: %5.1f\n\n"),
1479 (float)stats.c1_errors/secs,
1480 (float)stats.c2_errors/secs,
1481 (float)stats.cu_errors/secs);
1482
1483 (*sp->end_func)(scgp);
1484 }
1485
1486
1487 LOCAL void
readpi_disk(scgp,parmp)1488 readpi_disk(scgp, parmp)
1489 SCSI *scgp;
1490 parm_t *parmp;
1491 {
1492 long addr = 0L;
1493 long end = 0L;
1494 int secs; /* # of seconds */
1495 cxerror_t errors;
1496 cxerror_t stats;
1497 cxerror_t max_errors;
1498 BOOL askrange = FALSE;
1499 BOOL isrange = FALSE;
1500 FILE *f = stdout;
1501
1502 if (is_suid) {
1503 if (scgp->inq->type != INQ_ROMD)
1504 comerrno(EX_BAD, _("Not root. Will only read from CD in suid/priv mode\n"));
1505 }
1506
1507 scgp->silent++;
1508 if (read_capacity(scgp) >= 0)
1509 end = scgp->cap->c_baddr + 1;
1510 scgp->silent--;
1511 print_capacity(scgp, stderr);
1512
1513 if (parmp == NULL || parmp->askrange)
1514 askrange = TRUE;
1515 if (parmp != NULL && !askrange && (parmp->start <= parmp->end))
1516 isrange = TRUE;
1517
1518 if ((end <= 0 && isrange) || (askrange && scg_yes(_("Ignore disk size? "))))
1519 end = 10000000; /* Hack to read empty (e.g. blank=fast) disks */
1520
1521 if (parmp) {
1522 addr = parmp->start;
1523 if (parmp->end != -1 && parmp->end < end)
1524 end = parmp->end;
1525 }
1526
1527 if (pifscan) {
1528 if (plextor_init_pif_scan(scgp) < 0)
1529 comerrno(EX_BAD, _("Unsupported drive for -pifscan\n"));
1530 } else if (plextor_init_pi8_scan(scgp) < 0)
1531 comerrno(EX_BAD, _("Unsupported drive for -pi8scan\n"));
1532
1533 secs = (end - addr) / (8*16); /* Compute # of blocks */
1534 if (pifscan)
1535 secs = (end - addr) / (16); /* Compute # of blocks */
1536
1537 fillbytes(&stats, sizeof (stats), '\0');
1538 fillbytes(&max_errors, sizeof (max_errors), '\0');
1539
1540 while (addr < end) {
1541 addr = plextor_scan_one_dvd_interval(scgp, &errors, addr, Sbuf);
1542 stats.c1_errors += errors.c1_errors;
1543 stats.c2_errors += errors.c2_errors;
1544 stats.cu_errors += errors.cu_errors;
1545 stats.pi_errors += errors.pi_errors;
1546 max_errors.c1_errors = max(max_errors.c1_errors, errors.c1_errors);
1547 max_errors.c2_errors = max(max_errors.c2_errors, errors.c2_errors);
1548 max_errors.cu_errors = max(max_errors.cu_errors, errors.cu_errors);
1549 max_errors.pi_errors = max(max_errors.pi_errors, errors.pi_errors);
1550 if (lverbose > 1 ||
1551 (lverbose > 0 && errors.pi_errors)) {
1552 printf(" %8ld %6d\n",
1553 addr,
1554 errors.pi_errors);
1555 if (plot)
1556 flush();
1557 }
1558 if (didintr) {
1559 plextor_end_scan(scgp);
1560 comexit(exsig);
1561 }
1562 }
1563
1564 if (plot)
1565 f = stderr;
1566 fprintf(f, _("\n\ntotal result:\n\n"));
1567 fprintf(f, _("total: PI: %8d\n"),
1568 stats.pi_errors);
1569 fprintf(f, _("max : PI: %8d\n"),
1570 max_errors.pi_errors);
1571 fprintf(f, _("avg sum: PI: %8.1f\n\n"),
1572 (float)stats.pi_errors/secs);
1573
1574 plextor_end_scan(scgp);
1575 }
1576
1577
1578 /* ARGSUSED */
1579 LOCAL int
fread_data(scgp,rp,bp,addr,cnt)1580 fread_data(scgp, rp, bp, addr, cnt)
1581 SCSI *scgp;
1582 rparm_t *rp;
1583 caddr_t bp;
1584 long addr;
1585 int cnt;
1586 {
1587 return (read_g1(scgp, bp, addr, cnt));
1588 }
1589
1590 #ifdef CLONE_WRITE
1591 LOCAL int
fread_2448(scgp,rp,bp,addr,cnt)1592 fread_2448(scgp, rp, bp, addr, cnt)
1593 SCSI *scgp;
1594 rparm_t *rp;
1595 caddr_t bp;
1596 long addr;
1597 int cnt;
1598 {
1599 if (rp->ismmc) {
1600 return (read_cd(scgp, bp, addr, cnt, rp->secsize,
1601 /* Sync + all headers + user data + EDC/ECC */
1602 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
1603 /* plus all subchannels RAW */
1604 1));
1605 } else {
1606 return (read_da(scgp, bp, addr, cnt, rp->secsize,
1607 /* Sync + all headers + user data + EDC/ECC + all subch */
1608 0x02));
1609 }
1610 }
1611
1612 LOCAL int
fread_2448_16(scgp,rp,bp,addr,cnt)1613 fread_2448_16(scgp, rp, bp, addr, cnt)
1614 SCSI *scgp;
1615 rparm_t *rp;
1616 caddr_t bp;
1617 long addr;
1618 int cnt;
1619 {
1620
1621 if (rp->ismmc) {
1622 track_t trackdesc;
1623 int ret;
1624 int i;
1625 char *p;
1626
1627 trackdesc.isecsize = 2368;
1628 trackdesc.secsize = 2448;
1629 ret = read_cd(scgp, bp, addr, cnt, 2368,
1630 /* Sync + all headers + user data + EDC/ECC */
1631 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
1632 /* subchannels P/Q */
1633 2);
1634 if (ret < 0)
1635 return (ret);
1636
1637 scatter_secs(&trackdesc, bp, cnt);
1638 for (i = 0, p = bp+2352; i < cnt; i++) {
1639 #ifdef more_than_q_sub
1640 if ((p[15] & 0x80) != 0)
1641 printf("P");
1642 #endif
1643 /*
1644 * As the drives don't return P-sub, we check
1645 * whether the index equals 0.
1646 */
1647 qpto96((Uchar *)p, (Uchar *)p, p[2] == 0);
1648 p += 2448;
1649 }
1650 return (ret);
1651 } else {
1652 comerrno(EX_BAD, _("Cannot fread_2448_16 on non MMC drives\n"));
1653
1654 return (read_da(scgp, bp, addr, cnt, rp->secsize,
1655 /* Sync + all headers + user data + EDC/ECC + all subch */
1656 0x02));
1657 }
1658 }
1659
1660 LOCAL int
fread_2352(scgp,rp,bp,addr,cnt)1661 fread_2352(scgp, rp, bp, addr, cnt)
1662 SCSI *scgp;
1663 rparm_t *rp;
1664 caddr_t bp;
1665 long addr;
1666 int cnt;
1667 {
1668 if (rp->ismmc) {
1669 return (read_cd(scgp, bp, addr, cnt, rp->secsize,
1670 /* Sync + all headers + user data + EDC/ECC */
1671 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
1672 /* NO subchannels */
1673 0));
1674 } else {
1675 comerrno(EX_BAD, _("Cannot fread_2352 on non MMC drives\n"));
1676
1677 return (read_da(scgp, bp, addr, cnt, rp->secsize,
1678 /* Sync + all headers + user data + EDC/ECC + all subch */
1679 0x02));
1680 }
1681 }
1682
1683 /*
1684 * -ledc_ecc_dec read variant: read CD-DA sectors (2352 bytes) and output
1685 * corrected CD-ROM sectors (2048 bytes).
1686 */
1687 int edc_OK = 0;
1688 LOCAL int
fread_2048(scgp,rp,bp,addr,cnt)1689 fread_2048(scgp, rp, bp, addr, cnt)
1690 SCSI *scgp;
1691 rparm_t *rp;
1692 caddr_t bp;
1693 long addr;
1694 int cnt;
1695 {
1696 int ret;
1697 char *from;
1698 char *to;
1699 char *p;
1700 int i = 0;
1701 int secsize = rp->secsize;
1702 BOOL OK = TRUE;
1703
1704 rp->secsize = rp->isecsize;
1705 fillbytes(bp, rp->secsize * cnt, '\0');
1706 ret = fread_2352(scgp, rp, bp, addr, cnt);
1707 rp->secsize = secsize;
1708
1709 from = bp;
1710 from += 16;
1711 to = bp;
1712 p = bp;
1713 while (i < cnt) {
1714 int crc;
1715
1716 crc = crc_check((unsigned char *)p, MODE_1);
1717 ret = do_decode_L2((unsigned char *)p, MODE_1, FALSE, 0);
1718
1719 if (ret < 0)
1720 OK = FALSE;
1721 if (crc == 0 && ret == 0) {
1722 edc_OK++;
1723 error("Corrected: total %d Block %ld\n", edc_OK, addr+i);
1724 }
1725 move2048(from, to);
1726 from += 2352;
1727 to += 2048;
1728 p += 2352;
1729 i++;
1730 }
1731 if (OK)
1732 return (0);
1733 else
1734 return (-1);
1735 }
1736
1737 LOCAL int
fread_lin(scgp,rp,bp,addr,cnt)1738 fread_lin(scgp, rp, bp, addr, cnt)
1739 SCSI *scgp;
1740 rparm_t *rp;
1741 caddr_t bp;
1742 long addr;
1743 int cnt;
1744 {
1745 if (addr != ULONG_C(0xF0000000))
1746 addr = ULONG_C(0xFFFFFFFF);
1747
1748 return (read_cd(scgp, bp, addr, cnt, rp->secsize,
1749 /* Sync + all headers + user data + EDC/ECC */
1750 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
1751 /* plus all subchannels RAW */
1752 1));
1753 }
1754 #endif /* CLONE_WRITE */
1755
1756 LOCAL int
bits(c)1757 bits(c)
1758 int c;
1759 {
1760 int n = 0;
1761
1762 if (c & 0x01)
1763 n++;
1764 if (c & 0x02)
1765 n++;
1766 if (c & 0x04)
1767 n++;
1768 if (c & 0x08)
1769 n++;
1770 if (c & 0x10)
1771 n++;
1772 if (c & 0x20)
1773 n++;
1774 if (c & 0x40)
1775 n++;
1776 if (c & 0x80)
1777 n++;
1778 return (n);
1779 }
1780
1781 LOCAL int
bitidx(c)1782 bitidx(c)
1783 int c;
1784 {
1785 if (c & 0x80)
1786 return (0);
1787 if (c & 0x40)
1788 return (1);
1789 if (c & 0x20)
1790 return (2);
1791 if (c & 0x10)
1792 return (3);
1793 if (c & 0x08)
1794 return (4);
1795 if (c & 0x04)
1796 return (5);
1797 if (c & 0x02)
1798 return (6);
1799 if (c & 0x01)
1800 return (7);
1801 return (-1);
1802 }
1803
1804 LOCAL int
fread_c2(scgp,rp,bp,addr,cnt)1805 fread_c2(scgp, rp, bp, addr, cnt)
1806 SCSI *scgp;
1807 rparm_t *rp;
1808 caddr_t bp;
1809 long addr;
1810 int cnt;
1811 {
1812 if (rp->ismmc) {
1813 return (read_cd(scgp, bp, addr, cnt, rp->secsize,
1814 /* Sync + all headers + user data + EDC/ECC + C2 */
1815 /* (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3 | 2 << 1),*/
1816 (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3 | 1 << 1),
1817 /* without subchannels */
1818 0));
1819 } else {
1820 return (read_da(scgp, bp, addr, cnt, rp->secsize,
1821 /* Sync + all headers + user data + EDC/ECC + C2 */
1822 0x04));
1823 }
1824 }
1825
1826 /* ARGSUSED */
1827 LOCAL int
fdata_null(rp,bp,addr,cnt)1828 fdata_null(rp, bp, addr, cnt)
1829 rparm_t *rp;
1830 caddr_t bp;
1831 long addr;
1832 int cnt;
1833 {
1834 return (0);
1835 }
1836
1837 LOCAL int
fdata_c2(rp,bp,addr,cnt)1838 fdata_c2(rp, bp, addr, cnt)
1839 rparm_t *rp;
1840 caddr_t bp;
1841 long addr;
1842 int cnt;
1843 {
1844 int i;
1845 int j;
1846 int k;
1847 char *p;
1848
1849 p = &bp[2352];
1850
1851 for (i = 0; i < cnt; i++, p += (2352+294)) {
1852 /* scg_prbytes("XXX ", p, 294);*/
1853 if ((j = cmpbytes(p, zeroblk, 294)) < 294) {
1854 printf(_("C2 in sector: %3ld first at byte: %4d (0x%02X)"), addr+i,
1855 j*8 + bitidx(p[j]), p[j]&0xFF);
1856 for (j = 0, k = 0; j < 294; j++)
1857 k += bits(p[j]);
1858 printf(_(" total: %4d errors\n"), k);
1859 /* scg_prbytes("XXX ", p, 294);*/
1860 rp->c2_errors += k;
1861 if (k > rp->c2_maxerrs)
1862 rp->c2_maxerrs = k;
1863 rp->c2_errsecs++;
1864 if (k >= 100)
1865 rp->c2_badsecs += 1;
1866 }
1867 }
1868 return (0);
1869 }
1870
1871 #ifdef used
1872 LOCAL int
read_scsi_g1(scgp,bp,addr,cnt)1873 read_scsi_g1(scgp, bp, addr, cnt)
1874 SCSI *scgp;
1875 caddr_t bp;
1876 long addr;
1877 int cnt;
1878 {
1879 register struct scg_cmd *scmd = scgp->scmd;
1880
1881 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1882 scmd->addr = bp;
1883 /* scmd->size = cnt*512;*/
1884 scmd->size = cnt*scgp->cap->c_bsize;
1885 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1886 scmd->cdb_len = SC_G1_CDBLEN;
1887 scmd->sense_len = CCS_SENSE_LEN;
1888 scmd->cdb.g1_cdb.cmd = 0x28;
1889 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1890 g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
1891 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1892
1893 scgp->cmdname = "read extended";
1894
1895 return (scg_cmd(scgp));
1896 }
1897 #endif
1898
1899 #define G0_MAXADDR 0x1FFFFFL
1900
1901 EXPORT int
write_scsi(scgp,bp,addr,cnt)1902 write_scsi(scgp, bp, addr, cnt)
1903 SCSI *scgp;
1904 caddr_t bp;
1905 long addr;
1906 int cnt;
1907 {
1908 if (addr <= G0_MAXADDR)
1909 return (write_g0(scgp, bp, addr, cnt));
1910 else
1911 return (write_g1(scgp, bp, addr, cnt));
1912 }
1913
1914 EXPORT int
write_g0(scgp,bp,addr,cnt)1915 write_g0(scgp, bp, addr, cnt)
1916 SCSI *scgp;
1917 caddr_t bp;
1918 long addr;
1919 int cnt;
1920 {
1921 register struct scg_cmd *scmd = scgp->scmd;
1922
1923 if (scgp->cap->c_bsize <= 0)
1924 raisecond("capacity_not_set", 0L);
1925
1926 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1927 scmd->addr = bp;
1928 scmd->size = cnt*scgp->cap->c_bsize;
1929 scmd->flags = SCG_DISRE_ENA;
1930 scmd->cdb_len = SC_G0_CDBLEN;
1931 scmd->sense_len = CCS_SENSE_LEN;
1932 scmd->cdb.g0_cdb.cmd = SC_WRITE;
1933 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
1934 g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
1935 scmd->cdb.g0_cdb.count = (Uchar)cnt;
1936
1937 scgp->cmdname = "write_g0";
1938
1939 return (scg_cmd(scgp));
1940 }
1941
1942 EXPORT int
write_g1(scgp,bp,addr,cnt)1943 write_g1(scgp, bp, addr, cnt)
1944 SCSI *scgp;
1945 caddr_t bp;
1946 long addr;
1947 int cnt;
1948 {
1949 register struct scg_cmd *scmd = scgp->scmd;
1950
1951 if (scgp->cap->c_bsize <= 0)
1952 raisecond("capacity_not_set", 0L);
1953
1954 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1955 scmd->addr = bp;
1956 scmd->size = cnt*scgp->cap->c_bsize;
1957 scmd->flags = SCG_DISRE_ENA;
1958 scmd->cdb_len = SC_G1_CDBLEN;
1959 scmd->sense_len = CCS_SENSE_LEN;
1960 scmd->cdb.g1_cdb.cmd = SC_EWRITE;
1961 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1962 g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
1963 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1964
1965 scgp->cmdname = "write_g1";
1966
1967 return (scg_cmd(scgp));
1968 }
1969
1970 #ifdef used
1971 LOCAL void
Xrequest_sense(scgp)1972 Xrequest_sense(scgp)
1973 SCSI *scgp;
1974 {
1975 char sense_buf[32];
1976 struct scg_cmd ocmd;
1977 int sense_count;
1978 char *cmdsave;
1979 register struct scg_cmd *scmd = scgp->scmd;
1980
1981 cmdsave = scgp->cmdname;
1982
1983 movebytes(scmd, &ocmd, sizeof (*scmd));
1984
1985 fillbytes((caddr_t)sense_buf, sizeof (sense_buf), '\0');
1986
1987 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1988 scmd->addr = (caddr_t)sense_buf;
1989 scmd->size = sizeof (sense_buf);
1990 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1991 scmd->cdb_len = SC_G0_CDBLEN;
1992 scmd->sense_len = CCS_SENSE_LEN;
1993 scmd->cdb.g1_cdb.cmd = 0x3;
1994 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1995 scmd->cdb.g0_cdb.count = sizeof (sense_buf);
1996
1997 scgp->cmdname = "request sense";
1998
1999 scg_cmd(scgp);
2000
2001 sense_count = sizeof (sense_buf) - scg_getresid(scgp);
2002 movebytes(&ocmd, scmd, sizeof (*scmd));
2003 scmd->sense_count = sense_count;
2004 movebytes(sense_buf, (Uchar *)&scmd->sense, scmd->sense_count);
2005
2006 scgp->cmdname = cmdsave;
2007 scg_printerr(scgp);
2008 scg_printresult(scgp); /* XXX restore key/code in future */
2009 }
2010 #endif
2011
2012 LOCAL int
read_retry(scgp,bp,addr,cnt,rfunc,rp)2013 read_retry(scgp, bp, addr, cnt, rfunc, rp)
2014 SCSI *scgp;
2015 caddr_t bp;
2016 long addr;
2017 long cnt;
2018 int (*rfunc)__PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
2019 rparm_t *rp;
2020 {
2021 /* int secsize = scgp->cap->c_bsize;*/
2022 int secsize = rp->secsize;
2023 int try = 0;
2024 int err;
2025 char dummybuf[8192];
2026
2027 if (secsize > sizeof (dummybuf)) {
2028 errmsgno(EX_BAD, _("Cannot retry, sector size %d too big.\n"), secsize);
2029 return (-1);
2030 }
2031
2032 errmsgno(EX_BAD, _("Retrying from sector %ld.\n"), addr);
2033 while (cnt > 0) {
2034 error(".");
2035
2036 do {
2037 if (didintr)
2038 comexit(exsig); /* XXX besseres Konzept?!*/
2039 wait_unit_ready(scgp, 120);
2040 if (try >= 10) { /* First 10 retries without seek */
2041 if ((try % 8) == 0) {
2042 error("+"); /* Read last sector */
2043 scgp->silent++;
2044 (*rfunc)(scgp, rp, dummybuf, scgp->cap->c_baddr, 1);
2045 scgp->silent--;
2046 } else if ((try % 4) == 0) {
2047 error("-"); /* Read first sector */
2048 scgp->silent++;
2049 (*rfunc)(scgp, rp, dummybuf, 0, 1);
2050 scgp->silent--;
2051 } else {
2052 error("~"); /* Read random sector */
2053 scgp->silent++;
2054 (*rfunc)(scgp, rp, dummybuf, choice(scgp->cap->c_baddr), 1);
2055 scgp->silent--;
2056 }
2057 if (didintr)
2058 comexit(exsig); /* XXX besseres Konzept?!*/
2059 wait_unit_ready(scgp, 120);
2060 }
2061 if (didintr)
2062 comexit(exsig); /* XXX besseres Konzept?!*/
2063
2064 fillbytes(bp, secsize, 0);
2065
2066 scgp->silent++;
2067 err = (*rfunc)(scgp, rp, bp, addr, 1);
2068 scgp->silent--;
2069
2070 if (err < 0) {
2071 err = scgp->scmd->ux_errno;
2072 /* error("\n");*/
2073 /* errmsgno(err, "Cannot read source disk\n");*/
2074 } else {
2075 if (scg_getresid(scgp)) {
2076 error(_("\nresid: %d\n"), scg_getresid(scgp));
2077 /*
2078 * If we use -ledc_ecc_dec for
2079 * correction, let the correction
2080 * happen on an upper layer.
2081 */
2082 if (!edc_corr)
2083 return (-1);
2084 }
2085 break;
2086 }
2087 } while (++try < retries);
2088
2089 if (try >= retries) {
2090 error("\n");
2091 errmsgno(err, _("Error on sector %ld not corrected. Total of %d errors.\n"),
2092 addr, ++rp->errors);
2093
2094 if (scgp->silent <= 1 && lverbose > 0)
2095 scg_printerr(scgp);
2096
2097 add_bad(addr);
2098
2099 if (!noerror)
2100 return (-1);
2101 errmsgno(EX_BAD, _("-noerror set, continuing ...\n"));
2102 } else {
2103 if (try >= maxtry)
2104 maxtry = try;
2105
2106 if (try > 1) {
2107 error("\n");
2108 errmsgno(EX_BAD,
2109 _("Error on sector %ld corrected after %d tries. Total of %d errors.\n"),
2110 addr, try, rp->errors);
2111 }
2112 }
2113 try = 0;
2114 cnt -= 1;
2115 addr += 1;
2116 bp += secsize;
2117 }
2118 return (0);
2119 }
2120
2121 LOCAL void
read_generic(scgp,parmp,rfunc,rp,dfunc)2122 read_generic(scgp, parmp, rfunc, rp, dfunc)
2123 SCSI *scgp;
2124 parm_t *parmp;
2125 int (*rfunc)__PR((SCSI *scgp, rparm_t *rp, caddr_t bp, long addr, int cnt));
2126 rparm_t *rp;
2127 int (*dfunc)__PR((rparm_t *rp, caddr_t bp, long addr, int cnt));
2128 {
2129 char filename[512];
2130 char *defname = NULL;
2131 FILE *f;
2132 long addr = 0L;
2133 long old_addr = 0L;
2134 long num;
2135 long end = 0L;
2136 long start = 0L;
2137 long cnt = 0L;
2138 long next_point = 0L;
2139 long secs_per_point = 0L;
2140 double speed;
2141 int msec;
2142 int old_msec = 0;
2143 int err = 0;
2144 BOOL askrange = FALSE;
2145 BOOL isrange = FALSE;
2146 int secsize = rp->secsize;
2147 int i = 0;
2148
2149 if (is_suid) {
2150 if (scgp->inq->type != INQ_ROMD)
2151 comerrno(EX_BAD, _("Not root. Will only read from CD in suid/priv mode\n"));
2152 }
2153
2154 if (parmp == NULL || parmp->askrange)
2155 askrange = TRUE;
2156 if (parmp != NULL && !askrange && (parmp->start <= parmp->end))
2157 isrange = TRUE;
2158
2159 filename[0] = '\0';
2160
2161 scgp->silent++;
2162 if (read_capacity(scgp) >= 0)
2163 end = scgp->cap->c_baddr + 1;
2164 scgp->silent--;
2165
2166 if ((end <= 0 && isrange) || (askrange && scg_yes(_("Ignore disk size? "))))
2167 end = 10000000; /* Hack to read empty (e.g. blank=fast) disks */
2168
2169 if (parmp) {
2170 if (parmp->name)
2171 defname = parmp->name;
2172 if (defname != NULL) {
2173 error(_("Copy from SCSI (%d,%d,%d) disk to file '%s'\n"),
2174 scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp),
2175 defname);
2176 }
2177
2178 addr = start = parmp->start;
2179 if (parmp->end != -1 && parmp->end < end)
2180 end = parmp->end;
2181 cnt = Sbufsize / secsize;
2182 /*
2183 * XXX clean up this hack in future.
2184 */
2185 if (edc_corr)
2186 cnt = Sbufsize / rp->isecsize;
2187 if (cnt > spt && spt > 0)
2188 cnt = spt;
2189 }
2190
2191 if (defname == NULL) {
2192 defname = "disk.out";
2193 error(_("Copy from SCSI (%d,%d,%d) disk to file\n"),
2194 scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
2195 error(_("Enter filename [%s]: "), defname); flush();
2196 (void) getline(filename, sizeof (filename));
2197 }
2198
2199 if (askrange) {
2200 addr = start;
2201 getlong(_("Enter starting sector for copy:"), &addr, start, end-1);
2202 /* getlong(_("Enter starting sector for copy:"), &addr, -300, end-1);*/
2203 start = addr;
2204 }
2205
2206 if (askrange) {
2207 num = end - addr;
2208 getlong(_("Enter number of sectors to copy:"), &num, 1L, num);
2209 end = addr + num;
2210 }
2211
2212 if (askrange) {
2213 /* XXX askcnt */
2214 cnt = Sbufsize / secsize;
2215 /*
2216 * XXX clean up this hack in future.
2217 */
2218 if (edc_corr)
2219 cnt = Sbufsize / rp->isecsize;
2220 if (cnt > spt && spt > 0)
2221 cnt = spt;
2222 getlong(_("Enter number of sectors per copy:"), &cnt, 1L, cnt);
2223 }
2224
2225 if (filename[0] == '\0')
2226 strncpy(filename, defname, sizeof (filename));
2227 filename[sizeof (filename)-1] = '\0';
2228 if (streql(filename, "-")) {
2229 f = stdout;
2230 setmode(STDOUT_FILENO, O_BINARY);
2231 } else if ((f = fileopen(filename, notrunc?"wcub":"wctub")) == NULL)
2232 comerr(_("Cannot open '%s'.\n"), filename);
2233 file_raise(f, FALSE);
2234
2235 error(_("end: %8ld\n"), end);
2236 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
2237 comerr(_("Cannot get start time\n"));
2238
2239 if (meshpoints > 0) {
2240 if ((end-start) < meshpoints)
2241 secs_per_point = 1;
2242 else
2243 secs_per_point = (end-start) / meshpoints;
2244 next_point = start + secs_per_point;
2245 old_addr = start;
2246 }
2247
2248 for (; addr < end; addr += cnt) {
2249 if (didintr)
2250 comexit(exsig); /* XXX besseres Konzept?!*/
2251
2252 if ((addr + cnt) > end)
2253 cnt = end - addr;
2254
2255 if (meshpoints > 0) {
2256 if (addr > next_point) {
2257
2258 msec = prstats_silent();
2259 if ((msec - old_msec) == 0) /* Avoid division by zero */
2260 msec = old_msec + 1;
2261 speed = ((addr - old_addr)/(1000.0/secsize)) / (0.001*(msec - old_msec));
2262 if (do_factor) {
2263 if (is_cdrom)
2264 speed /= 176.400 * (secsize/2352.0);
2265 else if (is_dvd)
2266 speed /= 1385.0;
2267 if (is_bd)
2268 speed /= 4495.0;
2269 }
2270 error(_("addr: %8ld cnt: %ld"), addr, cnt);
2271 printf("%8ld %8.2f\n", addr, speed);
2272 if (plot)
2273 flush();
2274 error("\r");
2275 next_point += secs_per_point;
2276 old_addr = addr;
2277 old_msec = msec;
2278 i++;
2279 if (meshpoints < 100)
2280 flush();
2281 else if (i % (meshpoints/100) == 0)
2282 flush();
2283 }
2284 }
2285 error(_("addr: %8ld cnt: %ld\r"), addr, cnt);
2286
2287 scgp->silent++;
2288 if ((*rfunc)(scgp, rp, Sbuf, addr, cnt) < 0) {
2289 scgp->silent--;
2290 err = scgp->scmd->ux_errno;
2291 if (quiet) {
2292 error("\n");
2293 } else if (scgp->silent == 0) {
2294 scg_printerr(scgp);
2295 }
2296 errmsgno(err, _("Cannot read source disk\n"));
2297
2298 if (read_retry(scgp, Sbuf, addr, cnt, rfunc, rp) < 0) {
2299 exargs.excode = -2;
2300 goto out;
2301 }
2302 } else {
2303 scgp->silent--;
2304 if (scg_getresid(scgp)) {
2305 error(_("\nresid: %d\n"), scg_getresid(scgp));
2306 /*
2307 * If we use -ledc_ecc_dec for
2308 * correction, let the correction
2309 * happen on an upper layer, but make it an
2310 * error in case of DMA residual problems.
2311 */
2312 if (!edc_corr)
2313 goto out;
2314 }
2315 }
2316 (*dfunc)(rp, Sbuf, addr, cnt);
2317 if (filewrite(f, Sbuf, cnt * secsize) < 0) {
2318 err = geterrno();
2319 error("\n");
2320 errmsgno(err, _("Cannot write '%s'\n"), filename);
2321 exargs.excode = err;
2322 break;
2323 }
2324 }
2325 error(_("addr: %8ld"), addr);
2326 out:
2327 error("\n");
2328 msec = prstats();
2329 if (msec == 0) /* Avoid division by zero */
2330 msec = 1;
2331 #ifdef OOO
2332 error(_("Read %.2f kB at %.1f kB/sec.\n"),
2333 (double)(addr - start)/(1024.0/scgp->cap->c_bsize),
2334 (double)((addr - start)/(1024.0/scgp->cap->c_bsize)) / (0.001*msec));
2335 #else
2336 error(_("Read %.2f kB at %.1f kB/sec.\n"),
2337 (double)(addr - start)/(1024.0/secsize),
2338 (double)((addr - start)/(1024.0/secsize)) / (0.001*msec));
2339 #endif
2340 print_bad();
2341 }
2342
2343 LOCAL void
write_disk(scgp,parmp)2344 write_disk(scgp, parmp)
2345 SCSI *scgp;
2346 parm_t *parmp;
2347 {
2348 char filename[512];
2349 char *defname = "disk.out";
2350 FILE *f;
2351 long addr = 0L;
2352 long cnt;
2353 long amt;
2354 long end = 0L;
2355 int msec;
2356 int start;
2357
2358 if (is_suid)
2359 comerrno(EX_BAD, _("Not root. Will not write in suid/priv mode\n"));
2360
2361 filename[0] = '\0';
2362 if (read_capacity(scgp) >= 0) {
2363 end = scgp->cap->c_baddr + 1;
2364 print_capacity(scgp, stderr);
2365 }
2366
2367 if (end <= 1)
2368 end = 10000000; /* Hack to write empty disks */
2369
2370 if (parmp) {
2371 if (parmp->name)
2372 defname = parmp->name;
2373 error(_("Copy from file '%s' to SCSI (%d,%d,%d) disk\n"),
2374 defname,
2375 scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
2376
2377 addr = start = parmp->start;
2378 if (parmp->end != -1 && parmp->end < end)
2379 end = parmp->end;
2380 cnt = Sbufsize / scgp->cap->c_bsize;
2381 if (cnt > spt && spt > 0)
2382 cnt = spt;
2383 } else {
2384 error(_("Copy from file to SCSI (%d,%d,%d) disk\n"),
2385 scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
2386 error(_("Enter filename [%s]: "), defname); flush();
2387 (void) getline(filename, sizeof (filename));
2388 error(_("Notice: reading from file always starts at file offset 0.\n"));
2389
2390 getlong(_("Enter starting sector for copy:"), &addr, 0L, end-1);
2391 start = addr;
2392 cnt = end - addr;
2393 getlong(_("Enter number of sectors to copy:"), &end, 1L, end);
2394 end = addr + cnt;
2395
2396 cnt = Sbufsize / scgp->cap->c_bsize;
2397 if (cnt > spt && spt > 0)
2398 cnt = spt;
2399 getlong(_("Enter number of sectors per copy:"), &cnt, 1L, cnt);
2400 /* error("end: %8ld\n", end);*/
2401 }
2402
2403 if (filename[0] == '\0')
2404 strncpy(filename, defname, sizeof (filename));
2405 filename[sizeof (filename)-1] = '\0';
2406 if (streql(filename, "-")) {
2407 f = stdin;
2408 setmode(STDIN_FILENO, O_BINARY);
2409 } else if ((f = fileopen(filename, "rub")) == NULL)
2410 comerr(_("Cannot open '%s'.\n"), filename);
2411
2412 error(_("end: %8ld\n"), end);
2413 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
2414 comerr(_("Cannot get start time\n"));
2415
2416 for (; addr < end; addr += cnt) {
2417 if (didintr)
2418 comexit(exsig); /* XXX besseres Konzept?!*/
2419
2420 if ((addr + cnt) > end)
2421 cnt = end - addr;
2422
2423 error(_("addr: %8ld cnt: %ld\r"), addr, cnt);
2424
2425 if ((amt = fileread(f, Sbuf, cnt * scgp->cap->c_bsize)) < 0)
2426 comerr(_("Cannot read '%s'\n"), filename);
2427 if (amt == 0)
2428 break;
2429 if ((amt / scgp->cap->c_bsize) < cnt)
2430 cnt = amt / scgp->cap->c_bsize;
2431 if (write_scsi(scgp, Sbuf, addr, cnt) < 0)
2432 comerrno(scgp->scmd->ux_errno,
2433 _("Cannot write destination disk\n"));
2434 }
2435 error(_("addr: %8ld\n"), addr);
2436 msec = prstats();
2437 if (msec == 0) /* Avoid division by zero */
2438 msec = 1;
2439 error(_("Wrote %.2f kB at %.1f kB/sec.\n"),
2440 (double)(addr - start)/(1024.0/scgp->cap->c_bsize),
2441 (double)((addr - start)/(1024.0/scgp->cap->c_bsize)) / (0.001*msec));
2442 }
2443
2444 LOCAL int
choice(n)2445 choice(n)
2446 int n;
2447 {
2448 #if defined(HAVE_DRAND48)
2449 extern double drand48 __PR((void));
2450
2451 return (drand48() * n);
2452 #else
2453 # if defined(HAVE_RAND)
2454 extern int rand __PR((void));
2455
2456 return (rand() % n);
2457 # else
2458 return (0);
2459 # endif
2460 #endif
2461 }
2462
2463 LOCAL void
ra(scgp)2464 ra(scgp)
2465 SCSI *scgp;
2466 {
2467 /* char filename[512];*/
2468 FILE *f;
2469 /* long addr = 0L;*/
2470 /* long cnt;*/
2471 /* long end;*/
2472 /* int msec;*/
2473 /* int start;*/
2474 /* int err = 0;*/
2475
2476 select_secsize(scgp, 2352);
2477 read_capacity(scgp);
2478 print_capacity(scgp, stderr);
2479 fillbytes(Sbuf, 50*2352, 0);
2480 if (read_g1(scgp, Sbuf, 0, 50) < 0)
2481 errmsg(_("read CD\n"));
2482 f = fileopen("DDA", "wctb");
2483 /* filewrite(f, Sbuf, 50 * 2352 - scg_getresid(scgp));*/
2484 filewrite(f, Sbuf, 50 * 2352);
2485 fclose(f);
2486 }
2487
2488 #define g5x_cdblen(cdb, len) ((cdb)->count[0] = ((len) >> 16L)& 0xFF,\
2489 (cdb)->count[1] = ((len) >> 8L) & 0xFF,\
2490 (cdb)->count[2] = (len) & 0xFF)
2491
2492 EXPORT int
read_da(scgp,bp,addr,cnt,framesize,subcode)2493 read_da(scgp, bp, addr, cnt, framesize, subcode)
2494 SCSI *scgp;
2495 caddr_t bp;
2496 long addr;
2497 int cnt;
2498 int framesize;
2499 int subcode;
2500 {
2501 register struct scg_cmd *scmd = scgp->scmd;
2502
2503 if (scgp->cap->c_bsize <= 0)
2504 raisecond("capacity_not_set", 0L);
2505
2506 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2507 scmd->addr = bp;
2508 scmd->size = cnt*framesize;
2509 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2510 scmd->cdb_len = SC_G5_CDBLEN;
2511 scmd->sense_len = CCS_SENSE_LEN;
2512 scmd->cdb.g5_cdb.cmd = 0xd8;
2513 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2514 g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
2515 g5_cdblen(&scmd->cdb.g5_cdb, cnt);
2516 scmd->cdb.g5_cdb.res10 = subcode;
2517
2518 scgp->cmdname = "read_da";
2519
2520 return (scg_cmd(scgp));
2521 }
2522
2523 LOCAL int
read_sectors(scgp,p,addr,cnt)2524 read_sectors(scgp, p, addr, cnt)
2525 SCSI *scgp;
2526 void *p;
2527 long addr;
2528 int cnt;
2529 {
2530 int csize;
2531 int clusters;
2532 int rest;
2533 int i;
2534 int pos;
2535
2536 if (addr + cnt > scgp->cap->c_baddr + 1)
2537 cnt = scgp->cap->c_baddr + 1 - addr;
2538
2539 csize = Sbufsize / (2352 + 294);
2540 if (csize > spt && spt > 0)
2541 csize = spt;
2542 clusters = cnt / csize;
2543 rest = cnt % csize;
2544 pos = addr;
2545
2546 for (i = 0; i < clusters; i++) {
2547 read_cd(scgp, p, pos, csize, 2352 + 294, 0xFA, 0);
2548 pos += csize;
2549 }
2550
2551 if (rest)
2552 read_cd(scgp, p, pos, rest, 2352 + 294, 0xFA, 0);
2553
2554 return (csize * clusters + rest);
2555 }
2556
2557 LOCAL int
read_dvd_sectors(scgp,p,addr,cnt)2558 read_dvd_sectors(scgp, p, addr, cnt)
2559 SCSI *scgp;
2560 void *p;
2561 long addr;
2562 int cnt;
2563 {
2564 int csize;
2565 int clusters;
2566 int rest;
2567 int i;
2568 int pos;
2569
2570 if (addr + cnt > scgp->cap->c_baddr + 1)
2571 cnt = scgp->cap->c_baddr + 1 - addr;
2572
2573 csize = Sbufsize / 2048;
2574 if (csize > spt && spt > 0)
2575 csize = spt;
2576 clusters = cnt / csize;
2577 rest = cnt % csize;
2578 pos = addr;
2579
2580 for (i = 0; i < clusters; i++) {
2581 read_g1(scgp, p, pos, csize);
2582 pos += csize;
2583 }
2584
2585 if (rest)
2586 read_g1(scgp, p, pos, rest);
2587
2588 return (csize * clusters + rest);
2589 }
2590
2591 LOCAL BOOL
mmc_isplextor(scgp)2592 mmc_isplextor(scgp)
2593 SCSI *scgp;
2594 {
2595 if (scgp->inq != NULL &&
2596 strncmp(scgp->inq->inq_vendor_info, "PLEXTOR", 7) == 0) {
2597 return (TRUE);
2598 }
2599 return (FALSE);
2600 }
2601
2602 LOCAL int
plextor_init_cx_scan(scgp)2603 plextor_init_cx_scan(scgp)
2604 SCSI *scgp;
2605 {
2606 register struct scg_cmd *scmd = scgp->scmd;
2607
2608 if (!mmc_isplextor(scgp))
2609 return (-1);
2610
2611 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2612
2613 scmd->size = 0;
2614 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2615 scmd->cdb_len = SC_G5_CDBLEN;
2616 scmd->sense_len = CCS_SENSE_LEN;
2617 scmd->cdb.g5_cdb.cmd = 0xEA;
2618 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2619 scmd->cdb.cmd_cdb[1] |= 0x15;
2620 scmd->cdb.cmd_cdb[3] = 0x01;
2621
2622 scgp->cmdname = "plextor_init_cx_scan";
2623
2624 return (scg_cmd(scgp));
2625 }
2626
2627 LOCAL int
plextor_init_pi8_scan(scgp)2628 plextor_init_pi8_scan(scgp)
2629 SCSI *scgp;
2630 {
2631 register struct scg_cmd *scmd = scgp->scmd;
2632
2633 if (!mmc_isplextor(scgp))
2634 return (-1);
2635
2636 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2637
2638 scmd->size = 0;
2639 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2640 scmd->cdb_len = SC_G5_CDBLEN;
2641 scmd->sense_len = CCS_SENSE_LEN;
2642 scmd->cdb.g5_cdb.cmd = 0xEA;
2643 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2644 scmd->cdb.cmd_cdb[1] |= 0x15;
2645 scmd->cdb.cmd_cdb[8] = 0x08;
2646 scmd->cdb.cmd_cdb[9] = 0x10;
2647
2648 scgp->cmdname = "plextor_init_pi8_scan";
2649
2650 return (scg_cmd(scgp));
2651 }
2652
2653 LOCAL int
plextor_init_pif_scan(scgp)2654 plextor_init_pif_scan(scgp)
2655 SCSI *scgp;
2656 {
2657 register struct scg_cmd *scmd = scgp->scmd;
2658
2659 if (!mmc_isplextor(scgp))
2660 return (-1);
2661
2662 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2663
2664 scmd->size = 0;
2665 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2666 scmd->cdb_len = SC_G5_CDBLEN;
2667 scmd->sense_len = CCS_SENSE_LEN;
2668 scmd->cdb.g5_cdb.cmd = 0xEA;
2669 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2670 scmd->cdb.cmd_cdb[1] |= 0x15;
2671 scmd->cdb.cmd_cdb[8] = 0x01;
2672 scmd->cdb.cmd_cdb[9] = 0x12;
2673
2674 scgp->cmdname = "plextor_init_pif_scan";
2675
2676 return (scg_cmd(scgp));
2677 }
2678
2679 LOCAL int
nec_init_cx_scan(scgp)2680 nec_init_cx_scan(scgp)
2681 SCSI *scgp;
2682 {
2683 register struct scg_cmd *scmd = scgp->scmd;
2684 int ret;
2685
2686 /*
2687 * initialize scan mode
2688 */
2689 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2690
2691 scmd->size = 0;
2692 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2693 scmd->cdb_len = SC_G5_CDBLEN;
2694 scmd->sense_len = CCS_SENSE_LEN;
2695 scmd->cdb.g5_cdb.cmd = 0xF3;
2696 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2697 scmd->cdb.cmd_cdb[1] |= 0x01;
2698
2699 scgp->cmdname = "nec_init_cx_scan";
2700
2701 ret = scg_cmd(scgp);
2702 if (ret < 0)
2703 return (ret);
2704
2705 /*
2706 * set scan interval = 75 sectors
2707 */
2708 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2709 scmd->size = 0;
2710 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2711 scmd->cdb_len = SC_G5_CDBLEN;
2712 scmd->sense_len = CCS_SENSE_LEN;
2713 scmd->cdb.g5_cdb.cmd = 0xF3;
2714 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2715 scmd->cdb.cmd_cdb[1] |= 0x02;
2716 scmd->cdb.cmd_cdb[8] = 75;
2717
2718 scgp->cmdname = "nec_set_cx_scan_interval";
2719
2720 return (scg_cmd(scgp));
2721 }
2722
2723 LOCAL int
plextor_scan_one_interval(scgp,pe,addr,p)2724 plextor_scan_one_interval(scgp, pe, addr, p)
2725 SCSI* scgp;
2726 cxerror_t *pe;
2727 long addr;
2728 void *p;
2729 {
2730 int i;
2731
2732 i = read_sectors(scgp, p, addr, 75);
2733 plextor_read_cx_values(scgp, pe, FALSE);
2734
2735 return (addr + i);
2736 }
2737
2738 LOCAL int
plextor_scan_one_dvd_interval(scgp,pe,addr,p)2739 plextor_scan_one_dvd_interval(scgp, pe, addr, p)
2740 SCSI* scgp;
2741 cxerror_t *pe;
2742 long addr;
2743 void *p;
2744 {
2745 int i;
2746
2747 if (pifscan)
2748 i = read_dvd_sectors(scgp, p, addr, 16);
2749 else
2750 i = read_dvd_sectors(scgp, p, addr, 16*8);
2751 plextor_read_cx_values(scgp, pe, TRUE);
2752
2753 return (addr + i);
2754 }
2755
2756 /* ARGSUSED */
2757 LOCAL int
nec_scan_one_interval(scgp,pe,addr,p)2758 nec_scan_one_interval(scgp, pe, addr, p)
2759 SCSI *scgp;
2760 cxerror_t *pe;
2761 long addr;
2762 void *p;
2763 {
2764 register struct scg_cmd *scmd = scgp->scmd;
2765 Uchar data[8];
2766 int ret;
2767
2768 fillbytes(data, sizeof (data), '\0');
2769 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2770 scmd->size = 8;
2771 scmd->addr = (caddr_t)data;
2772 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2773 scmd->cdb_len = SC_G5_CDBLEN;
2774 scmd->sense_len = CCS_SENSE_LEN;
2775 scmd->cdb.g5_cdb.cmd = 0xF3;
2776 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2777 scmd->cdb.cmd_cdb[1] |= 0x03;
2778
2779 scgp->cmdname = "nec_set_cx_scan_interval";
2780
2781 ret = scg_cmd(scgp);
2782
2783 if (ret < 0)
2784 return (ret);
2785
2786 pe->c1_errors = a_to_u_2_byte(data+4);
2787 pe->c2_errors = a_to_u_2_byte(data+6);
2788 pe->cu_errors = 0;
2789
2790 return ((int)data[1] * 4500 + (int)data[2] * 75 + (int)data[3]);
2791 }
2792
2793 LOCAL int
plextor_end_scan(scgp)2794 plextor_end_scan(scgp)
2795 SCSI *scgp;
2796 {
2797 register struct scg_cmd *scmd = scgp->scmd;
2798
2799 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2800
2801 scmd->size = 0;
2802 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2803 scmd->cdb_len = SC_G5_CDBLEN;
2804 scmd->sense_len = CCS_SENSE_LEN;
2805 scmd->cdb.g5_cdb.cmd = 0xEA;
2806 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2807 scmd->cdb.cmd_cdb[1] |= 0x17;
2808
2809 scgp->cmdname = "plextor_end_scan";
2810
2811 return (scg_cmd(scgp));
2812 }
2813
2814 LOCAL int
nec_end_scan(scgp)2815 nec_end_scan(scgp)
2816 SCSI *scgp;
2817 {
2818 register struct scg_cmd *scmd = scgp->scmd;
2819 char data[8];
2820
2821 fillbytes(data, sizeof (data), '\0');
2822 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2823
2824 scmd->addr = data;
2825 scmd->size = 8;
2826 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2827 scmd->cdb_len = SC_G5_CDBLEN;
2828 scmd->sense_len = CCS_SENSE_LEN;
2829 scmd->cdb.g5_cdb.cmd = 0xF3;
2830 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2831 scmd->cdb.cmd_cdb[1] |= 0x0F;
2832
2833 scgp->cmdname = "nec_end_cx_scan";
2834
2835 return (scg_cmd(scgp));
2836 }
2837
2838 LOCAL int
plextor_read_cx_values(scgp,pe,dopi)2839 plextor_read_cx_values(scgp, pe, dopi)
2840 SCSI *scgp;
2841 cxerror_t *pe;
2842 BOOL dopi;
2843 {
2844 register struct scg_cmd *scmd = scgp->scmd;
2845 char data[52];
2846 int ret;
2847
2848 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2849 fillbytes(data, sizeof (data), '\0');
2850
2851 scmd->addr = data;
2852 scmd->size = dopi ? 52:0x1A;
2853 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2854 scmd->cdb_len = SC_G5_CDBLEN;
2855 scmd->sense_len = CCS_SENSE_LEN;
2856
2857 scmd->cdb.g5_cdb.cmd = 0xEA;
2858 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2859 scmd->cdb.cmd_cdb[1] |= 0x16;
2860 scmd->cdb.cmd_cdb[2] = 0x01;
2861 scmd->cdb.cmd_cdb[10] = dopi ? 52:0x1A;
2862
2863 scgp->cmdname = "plextor_read_cx_values";
2864
2865 ret = scg_cmd(scgp);
2866 if (ret < 0) {
2867 return (ret);
2868 }
2869
2870 pe->c1_errors = a_to_u_2_byte(data+16) + /* E11 ??? */
2871 a_to_u_2_byte(data+14) + /* E21 ??? */
2872 a_to_u_2_byte(data+12); /* E31 ??? */
2873 pe->c2_errors = a_to_u_2_byte(data+22);
2874 pe->cu_errors = a_to_u_2_byte(data+20);
2875
2876 pe->pi_errors = a_to_u_4_byte(data+36);
2877
2878 return (ret);
2879 }
2880
2881 EXPORT int
read_cd(scgp,bp,addr,cnt,framesize,data,subch)2882 read_cd(scgp, bp, addr, cnt, framesize, data, subch)
2883 SCSI *scgp;
2884 caddr_t bp;
2885 long addr;
2886 int cnt;
2887 int framesize;
2888 int data;
2889 int subch;
2890 {
2891 register struct scg_cmd *scmd = scgp->scmd;
2892
2893 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2894 scmd->addr = bp;
2895 scmd->size = cnt*framesize;
2896 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2897 scmd->cdb_len = SC_G5_CDBLEN;
2898 scmd->sense_len = CCS_SENSE_LEN;
2899 scmd->cdb.g5_cdb.cmd = 0xBE;
2900 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
2901 scmd->cdb.g5_cdb.res = 0; /* expected sector type field ALL */
2902 g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
2903 g5x_cdblen(&scmd->cdb.g5_cdb, cnt);
2904
2905 scmd->cdb.g5_cdb.count[3] = data & 0xFF;
2906 scmd->cdb.g5_cdb.res10 = subch & 0x07;
2907
2908 scgp->cmdname = "read_cd";
2909
2910 return (scg_cmd(scgp));
2911 }
2912
2913 LOCAL void
oldmode(scgp,errp,retrp)2914 oldmode(scgp, errp, retrp)
2915 SCSI *scgp;
2916 int *errp;
2917 int *retrp;
2918 {
2919 Uchar mode[0x100];
2920 Uchar cmode[0x100];
2921 Uchar *p;
2922 int i;
2923 int len;
2924
2925 fillbytes(mode, sizeof (mode), '\0');
2926 fillbytes(cmode, sizeof (cmode), '\0');
2927
2928 if (!get_mode_params(scgp, 0x01, _("CD error recovery parameter"),
2929 mode, (Uchar *)0, (Uchar *)cmode, (Uchar *)0, &len)) {
2930 return;
2931 }
2932 if (xdebug)
2933 scg_prbytes(_("Mode Sense Data"), mode, len);
2934
2935 mode[0] = 0;
2936 mode[2] = 0; /* ??? ist manchmal 0x80 */
2937 p = mode;
2938 p += mode[3] + 4;
2939 *p &= 0x3F;
2940
2941 if (xdebug)
2942 scg_prbytes(_("Mode page 1:"), p, 0x10);
2943
2944 i = p[2];
2945 if (errp != NULL)
2946 *errp = i;
2947
2948 i = p[3];
2949 if (retrp != NULL)
2950 *retrp = i;
2951 }
2952
2953 LOCAL void
domode(scgp,err,retr)2954 domode(scgp, err, retr)
2955 SCSI *scgp;
2956 int err;
2957 int retr;
2958 {
2959 Uchar mode[0x100];
2960 Uchar cmode[0x100];
2961 Uchar *p;
2962 int i;
2963 int len;
2964
2965 fillbytes(mode, sizeof (mode), '\0');
2966 fillbytes(cmode, sizeof (cmode), '\0');
2967
2968 if (!get_mode_params(scgp, 0x01, _("CD error recovery parameter"),
2969 mode, (Uchar *)0, (Uchar *)cmode, (Uchar *)0, &len)) {
2970 return;
2971 }
2972 if (xdebug || (err == -1 && retr == -1)) {
2973 scg_prbytes(_("Mode Sense Data"), mode, len);
2974 }
2975
2976 mode[0] = 0;
2977 mode[2] = 0; /* ??? ist manchmal 0x80 */
2978 p = mode;
2979 p += mode[3] + 4;
2980 *p &= 0x3F;
2981
2982 if (xdebug || (err == -1 && retr == -1))
2983 scg_prbytes(_("Mode page 1:"), p, 0x10);
2984
2985 i = p[2];
2986 if (err == -1) {
2987 getint(_("Error handling? "), &i, 0, 255);
2988 p[2] = i;
2989 } else {
2990 if (xdebug)
2991 error(_("Error handling set from %02X to %02X\n"),
2992 p[2], err);
2993 p[2] = err;
2994 }
2995
2996 i = p[3];
2997 if (retr == -1) {
2998 getint(_("Retry count? "), &i, 0, 255);
2999 p[3] = i;
3000 } else {
3001 if (xdebug)
3002 error(_("Retry count set from %d to %d\n"),
3003 p[3] & 0xFF, retr);
3004 p[3] = retr;
3005 }
3006
3007 if (xdebug || (err == -1 && retr == -1))
3008 scg_prbytes(_("Mode Select Data"), mode, len);
3009 mode_select(scgp, mode, len, 0, scgp->inq->data_format >= 2);
3010 }
3011
3012
3013 /*--------------------------------------------------------------------------*/
3014 LOCAL void qpto96 __PR((Uchar *sub, Uchar *subq, int dop));
3015 /*EXPORT void qpto96 __PR((Uchar *sub, Uchar *subq, int dop));*/
3016 /*
3017 * Q-Sub auf 96 Bytes bl�hen und P-Sub addieren
3018 *
3019 * OUT: sub, IN: subqptr
3020 */
3021 LOCAL void
3022 /*EXPORT void*/
qpto96(sub,subqptr,dop)3023 qpto96(sub, subqptr, dop)
3024 Uchar *sub;
3025 Uchar *subqptr;
3026 int dop;
3027 {
3028 Uchar tmp[16];
3029 Uchar *p;
3030 int c;
3031 int i;
3032
3033 if (subqptr == sub) {
3034 movebytes(subqptr, tmp, 12);
3035 subqptr = tmp;
3036 }
3037 fillbytes(sub, 96, '\0');
3038
3039 /* CSTYLED */
3040 if (dop) for (i = 0, p = sub; i < 96; i++) {
3041 *p++ |= 0x80;
3042 }
3043 for (i = 0, p = sub; i < 12; i++) {
3044 c = subqptr[i] & 0xFF;
3045 /*printf("%02X\n", c);*/
3046 if (c & 0x80)
3047 *p++ |= 0x40;
3048 else
3049 p++;
3050 if (c & 0x40)
3051 *p++ |= 0x40;
3052 else
3053 p++;
3054 if (c & 0x20)
3055 *p++ |= 0x40;
3056 else
3057 p++;
3058 if (c & 0x10)
3059 *p++ |= 0x40;
3060 else
3061 p++;
3062 if (c & 0x08)
3063 *p++ |= 0x40;
3064 else
3065 p++;
3066 if (c & 0x04)
3067 *p++ |= 0x40;
3068 else
3069 p++;
3070 if (c & 0x02)
3071 *p++ |= 0x40;
3072 else
3073 p++;
3074 if (c & 0x01)
3075 *p++ |= 0x40;
3076 else
3077 p++;
3078 }
3079 }
3080
3081 /*--------------------------------------------------------------------------*/
3082
3083 LOCAL void
ovtime(scgp)3084 ovtime(scgp)
3085 SCSI *scgp;
3086 {
3087 register int i;
3088
3089 scgp->silent++;
3090 (void) test_unit_ready(scgp);
3091 scgp->silent--;
3092 if (test_unit_ready(scgp) < 0)
3093 return;
3094
3095 printf(_("Doing 1000 'TEST UNIT READY' operations.\n"));
3096
3097 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
3098 comerr(_("Cannot get start time\n"));
3099
3100 for (i = 1000; --i >= 0; ) {
3101 (void) test_unit_ready(scgp);
3102
3103 if (didintr)
3104 return;
3105 }
3106
3107 prstats();
3108
3109 /*
3110 * ATAPI drives do not like seek_g0()
3111 */
3112 scgp->silent++;
3113 i = seek_g0(scgp, 0L);
3114 scgp->silent--;
3115
3116 if (i >= 0) {
3117 printf(_("Doing 1000 'SEEK_G0 (0)' operations.\n"));
3118
3119 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
3120 comerr(_("Cannot get start time\n"));
3121
3122 for (i = 1000; --i >= 0; ) {
3123 (void) seek_g0(scgp, 0L);
3124
3125 if (didintr)
3126 return;
3127 }
3128
3129 prstats();
3130 }
3131
3132 scgp->silent++;
3133 i = seek_g1(scgp, 0L);
3134 scgp->silent--;
3135 if (i < 0)
3136 return;
3137
3138 printf(_("Doing 1000 'SEEK_G1 (0)' operations.\n"));
3139
3140 if (gettimeofday(&starttime, (struct timezone *)0) < 0)
3141 comerr(_("Cannot get start time\n"));
3142
3143 for (i = 1000; --i >= 0; ) {
3144 (void) seek_g1(scgp, 0L);
3145
3146 if (didintr)
3147 return;
3148 }
3149
3150 prstats();
3151 }
3152
3153 #define BAD_INC 16
3154 long *badsecs;
3155 int nbad;
3156 int maxbad;
3157
3158 LOCAL void
add_bad(addr)3159 add_bad(addr)
3160 long addr;
3161 {
3162 if (maxbad == 0) {
3163 maxbad = BAD_INC;
3164 badsecs = malloc(maxbad * sizeof (long));
3165 if (badsecs == NULL)
3166 comerr(_("No memory for bad sector list.\n"));
3167 }
3168 if (nbad >= maxbad) {
3169 maxbad += BAD_INC;
3170 badsecs = realloc(badsecs, maxbad * sizeof (long));
3171 if (badsecs == NULL)
3172 comerr(_("No memory to grow bad sector list.\n"));
3173 }
3174 badsecs[nbad++] = addr;
3175 }
3176
3177 LOCAL void
print_bad()3178 print_bad()
3179 {
3180 int i;
3181
3182 if (nbad == 0)
3183 return;
3184
3185 error(_("Max corected retry count was %d (limited to %d).\n"), maxtry, retries);
3186 error(_("The following %d sector(s) could not be read correctly:\n"), nbad);
3187 for (i = 0; i < nbad; i++)
3188 error("%ld\n", badsecs[i]);
3189 if (edc_corr)
3190 error(_("Corrected by EDC: %d\n"), edc_OK);
3191 }
3192
3193 LOCAL void
priv_warn(what,msg)3194 priv_warn(what, msg)
3195 const char *what;
3196 const char *msg;
3197 {
3198 errmsgno(EX_BAD, "Insufficient '%s' privileges. %s\n", what, msg);
3199 }
3200