1 /* @(#)scsi_cdr.c 1.160 12/03/16 Copyright 1995-2012 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)scsi_cdr.c 1.160 12/03/16 Copyright 1995-2012 J. Schilling";
6 #endif
7 /*
8 * SCSI command functions for cdrecord
9 * covering pre-MMC standard functions up to MMC-2
10 *
11 * Copyright (c) 1995-2012 J. Schilling
12 */
13 /*
14 * The contents of this file are subject to the terms of the
15 * Common Development and Distribution License, Version 1.0 only
16 * (the "License"). You may not use this file except in compliance
17 * with the License.
18 *
19 * See the file CDDL.Schily.txt in this distribution for details.
20 * A copy of the CDDL is also available via the Internet at
21 * http://www.opensource.org/licenses/cddl1.txt
22 *
23 * When distributing Covered Code, include this CDDL HEADER in each
24 * file and include the License file CDDL.Schily.txt from this distribution.
25 */
26
27 /*
28 * NOTICE: The Philips CDD 521 has several firmware bugs.
29 * One of them is not to respond to a SCSI selection
30 * within 200ms if the general load on the
31 * SCSI bus is high. To deal with this problem
32 * most of the SCSI commands are send with the
33 * SCG_CMD_RETRY flag enabled.
34 */
35 #include <schily/mconfig.h>
36
37 #include <schily/stdio.h>
38 #include <schily/standard.h>
39 #include <schily/stdlib.h>
40 #include <schily/unistd.h>
41 #include <schily/fcntl.h>
42 #include <schily/errno.h>
43 #include <schily/string.h>
44 #include <schily/time.h>
45
46 #include <schily/utypes.h>
47 #include <schily/btorder.h>
48 #include <schily/intcvt.h>
49 #include <schily/schily.h>
50 #include <schily/nlsdefs.h>
51
52 #include <scg/scgcmd.h>
53 #include <scg/scsidefs.h>
54 #include <scg/scsireg.h>
55 #include <scg/scsitransp.h>
56
57 #include "scsimmc.h"
58 #include "cdrecord.h"
59
60 #define strbeg(s1, s2) (strstr((s2), (s1)) == (s2))
61
62 EXPORT BOOL unit_ready __PR((SCSI *scgp));
63 EXPORT BOOL wait_unit_ready __PR((SCSI *scgp, int secs));
64 EXPORT BOOL scsi_in_progress __PR((SCSI *scgp));
65 EXPORT BOOL cdr_underrun __PR((SCSI *scgp));
66 EXPORT int test_unit_ready __PR((SCSI *scgp));
67 EXPORT int rezero_unit __PR((SCSI *scgp));
68 EXPORT int request_sense __PR((SCSI *scgp));
69 EXPORT int request_sense_b __PR((SCSI *scgp, caddr_t bp, int cnt));
70 EXPORT int inquiry __PR((SCSI *scgp, caddr_t, int));
71 EXPORT int read_capacity __PR((SCSI *scgp));
72 EXPORT void print_capacity __PR((SCSI *scgp, FILE *f));
73 EXPORT int scsi_load_unload __PR((SCSI *scgp, int));
74 EXPORT int scsi_prevent_removal __PR((SCSI *scgp, int));
75 EXPORT int scsi_start_stop_unit __PR((SCSI *scgp, int, int, BOOL immed));
76 EXPORT int scsi_set_speed __PR((SCSI *scgp, int readspeed, int writespeed, int rotctl));
77 EXPORT int scsi_get_speed __PR((SCSI *scgp, int *readspeedp, int *writespeedp));
78 EXPORT int qic02 __PR((SCSI *scgp, int));
79 EXPORT int write_xscsi __PR((SCSI *scgp, caddr_t, long, long, int));
80 EXPORT int write_xg0 __PR((SCSI *scgp, caddr_t, long, long, int));
81 EXPORT int write_xg1 __PR((SCSI *scgp, caddr_t, long, long, int));
82 EXPORT int write_xg5 __PR((SCSI *scgp, caddr_t, long, long, int));
83 EXPORT int seek_scsi __PR((SCSI *scgp, long addr));
84 EXPORT int seek_g0 __PR((SCSI *scgp, long addr));
85 EXPORT int seek_g1 __PR((SCSI *scgp, long addr));
86 EXPORT int scsi_flush_cache __PR((SCSI *scgp, BOOL immed));
87 EXPORT int read_buffer __PR((SCSI *scgp, caddr_t bp, int cnt, int mode));
88 EXPORT int write_buffer __PR((SCSI *scgp, char *buffer, long length, int mode, int bufferid, long offset));
89 EXPORT int read_subchannel __PR((SCSI *scgp, caddr_t bp, int track,
90 int cnt, int msf, int subq, int fmt));
91 EXPORT int read_toc __PR((SCSI *scgp, caddr_t, int, int, int, int));
92 EXPORT int read_toc_philips __PR((SCSI *scgp, caddr_t, int, int, int, int));
93 EXPORT int read_header __PR((SCSI *scgp, caddr_t, long, int, int));
94 EXPORT int read_disk_info __PR((SCSI *scgp, caddr_t, int));
95 EXPORT int read_track_info __PR((SCSI *scgp, caddr_t, int type, int addr, int cnt));
96 EXPORT int get_trackinfo __PR((SCSI *scgp, caddr_t, int type, int addr, int cnt));
97 EXPORT int read_rzone_info __PR((SCSI *scgp, caddr_t bp, int cnt));
98 EXPORT int reserve_tr_rzone __PR((SCSI *scgp, long size));
99 EXPORT int read_dvd_structure __PR((SCSI *scgp, caddr_t bp, int cnt, int mt, int addr, int layer, int fmt));
100 EXPORT int send_dvd_structure __PR((SCSI *scgp, caddr_t bp, int cnt, int fmt));
101 EXPORT int send_opc __PR((SCSI *scgp, caddr_t, int cnt, int doopc));
102 EXPORT int read_track_info_philips __PR((SCSI *scgp, caddr_t, int, int));
103 EXPORT int scsi_close_tr_session __PR((SCSI *scgp, int type, int track, BOOL immed));
104 EXPORT int read_master_cue __PR((SCSI *scgp, caddr_t bp, int sheet, int cnt));
105 EXPORT int send_cue_sheet __PR((SCSI *scgp, caddr_t bp, long size));
106 EXPORT int read_buff_cap __PR((SCSI *scgp, long *, long *));
107 EXPORT int scsi_blank __PR((SCSI *scgp, long addr, int blanktype, BOOL immed));
108 EXPORT BOOL allow_atapi __PR((SCSI *scgp, BOOL new));
109 EXPORT int mode_select __PR((SCSI *scgp, Uchar *, int, int, int));
110 EXPORT int mode_sense __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
111 EXPORT int mode_select_sg0 __PR((SCSI *scgp, Uchar *, int, int, int));
112 EXPORT int mode_sense_sg0 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
113 EXPORT int mode_select_g0 __PR((SCSI *scgp, Uchar *, int, int, int));
114 EXPORT int mode_select_g1 __PR((SCSI *scgp, Uchar *, int, int, int));
115 EXPORT int mode_sense_g0 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
116 EXPORT int mode_sense_g1 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
117 EXPORT int read_tochdr __PR((SCSI *scgp, cdr_t *, int *, int *));
118 EXPORT int read_cdtext __PR((SCSI *scgp));
119 EXPORT int read_trackinfo __PR((SCSI *scgp, int, long *, struct msf *, int *, int *, int *));
120 EXPORT int read_B0 __PR((SCSI *scgp, BOOL isbcd, long *b0p, long *lop));
121 EXPORT int read_session_offset __PR((SCSI *scgp, long *));
122 EXPORT int read_session_offset_philips __PR((SCSI *scgp, long *));
123 EXPORT int sense_secsize __PR((SCSI *scgp, int current));
124 EXPORT int select_secsize __PR((SCSI *scgp, int));
125 EXPORT BOOL is_cddrive __PR((SCSI *scgp));
126 EXPORT BOOL is_unknown_dev __PR((SCSI *scgp));
127 EXPORT int read_scsi __PR((SCSI *scgp, caddr_t, long, int));
128 EXPORT int read_g0 __PR((SCSI *scgp, caddr_t, long, int));
129 EXPORT int read_g1 __PR((SCSI *scgp, caddr_t, long, int));
130 EXPORT BOOL getdev __PR((SCSI *scgp, BOOL));
131 EXPORT void printinq __PR((SCSI *scgp, FILE *f));
132 EXPORT void printdev __PR((SCSI *scgp));
133 EXPORT BOOL do_inquiry __PR((SCSI *scgp, BOOL));
134 EXPORT BOOL recovery_needed __PR((SCSI *scgp, cdr_t *));
135 EXPORT int scsi_load __PR((SCSI *scgp, cdr_t *));
136 EXPORT int scsi_unload __PR((SCSI *scgp, cdr_t *));
137 EXPORT int scsi_cdr_write __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
138 EXPORT struct cd_mode_page_2A * mmc_cap __PR((SCSI *scgp, Uchar *modep));
139 EXPORT void mmc_getval __PR((struct cd_mode_page_2A *mp,
140 BOOL *cdrrp, BOOL *cdwrp,
141 BOOL *cdrrwp, BOOL *cdwrwp,
142 BOOL *dvdp, BOOL *dvdwp));
143 EXPORT BOOL is_mmc __PR((SCSI *scgp, BOOL *cdwp, BOOL *dvdwp));
144 EXPORT BOOL mmc_check __PR((SCSI *scgp, BOOL *cdrrp, BOOL *cdwrp,
145 BOOL *cdrrwp, BOOL *cdwrwp,
146 BOOL *dvdp, BOOL *dvdwp));
147 LOCAL void print_speed __PR((char *fmt, int val));
148 EXPORT void print_capabilities __PR((SCSI *scgp));
149 extern int verify __PR((SCSI *scgp, long start, int count, long *bad_block));
150
151 EXPORT BOOL
unit_ready(scgp)152 unit_ready(scgp)
153 SCSI *scgp;
154 {
155 register struct scg_cmd *scmd = scgp->scmd;
156
157 if (test_unit_ready(scgp) >= 0) /* alles OK */
158 return (TRUE);
159 else if (scmd->error >= SCG_FATAL) /* nicht selektierbar */
160 return (FALSE);
161
162 if (scg_sense_key(scgp) == SC_UNIT_ATTENTION) {
163 if (test_unit_ready(scgp) >= 0) /* alles OK */
164 return (TRUE);
165 }
166 if ((scg_cmd_status(scgp) & ST_BUSY) != 0) {
167 /*
168 * Busy/reservation_conflict
169 */
170 usleep(500000);
171 if (test_unit_ready(scgp) >= 0) /* alles OK */
172 return (TRUE);
173 }
174 if (scg_sense_key(scgp) == -1) { /* non extended Sense */
175 if (scg_sense_code(scgp) == 4) /* NOT_READY */
176 return (FALSE);
177 return (TRUE);
178 }
179 /* FALSE wenn NOT_READY */
180 return (scg_sense_key(scgp) != SC_NOT_READY);
181 }
182
183 EXPORT BOOL
wait_unit_ready(scgp,secs)184 wait_unit_ready(scgp, secs)
185 SCSI *scgp;
186 int secs;
187 {
188 int i;
189 int c;
190 int k;
191 int ret;
192 int err;
193
194 seterrno(0);
195 scgp->silent++;
196 ret = test_unit_ready(scgp); /* eat up unit attention */
197 if (ret < 0) {
198 err = geterrno();
199
200 if (err == EPERM || err == EACCES) {
201 scgp->silent--;
202 return (FALSE);
203 }
204 ret = test_unit_ready(scgp); /* got power on condition? */
205 }
206 scgp->silent--;
207
208 if (ret >= 0) /* success that's enough */
209 return (TRUE);
210
211 scgp->silent++;
212 for (i = 0; i < secs && (ret = test_unit_ready(scgp)) < 0; i++) {
213 if (scgp->scmd->scb.busy != 0) {
214 sleep(1);
215 continue;
216 }
217 c = scg_sense_code(scgp);
218 k = scg_sense_key(scgp);
219 /*
220 * Abort quickly if it does not make sense to wait.
221 * 0x30 == Cannot read medium
222 * 0x3A == Medium not present
223 */
224 if ((k == SC_NOT_READY && (c == 0x3A || c == 0x30)) ||
225 (k == SC_MEDIUM_ERROR)) {
226 if (scgp->silent <= 1)
227 scg_printerr(scgp);
228 scgp->silent--;
229 return (FALSE);
230 }
231 sleep(1);
232 }
233 scgp->silent--;
234 if (ret < 0)
235 return (FALSE);
236 return (TRUE);
237 }
238
239 EXPORT BOOL
scsi_in_progress(scgp)240 scsi_in_progress(scgp)
241 SCSI *scgp;
242 {
243 if (scg_sense_key(scgp) == SC_NOT_READY &&
244 /*
245 * Logigal unit not ready operation/long_write in progress
246 */
247 scg_sense_code(scgp) == 0x04 &&
248 (scg_sense_qual(scgp) == 0x04 || /* CyberDr. "format in progress"*/
249 scg_sense_qual(scgp) == 0x07 || /* "operation in progress" */
250 scg_sense_qual(scgp) == 0x08)) { /* "long write in progress" */
251 return (TRUE);
252 } else {
253 if (scgp->silent <= 1)
254 scg_printerr(scgp);
255 }
256 return (FALSE);
257 }
258
259 EXPORT BOOL
cdr_underrun(scgp)260 cdr_underrun(scgp)
261 SCSI *scgp;
262 {
263 if ((scg_sense_key(scgp) != SC_ILLEGAL_REQUEST &&
264 scg_sense_key(scgp) != SC_MEDIUM_ERROR))
265 return (FALSE);
266
267 if ((scg_sense_code(scgp) == 0x21 &&
268 (scg_sense_qual(scgp) == 0x00 || /* logical block address out of range */
269 scg_sense_qual(scgp) == 0x02)) || /* invalid address for write */
270
271 (scg_sense_code(scgp) == 0x0C &&
272 scg_sense_qual(scgp) == 0x09)) { /* write error - loss of streaming */
273 return (TRUE);
274 }
275 /*
276 * XXX Bei manchen Brennern kommt mach dem der Brennvorgang bereits
277 * XXX eine Weile gelaufen ist ein 5/24/0 Invalid field in CDB.
278 * XXX Daher sollte man testen ob schon geschrieben wurde...
279 */
280 return (FALSE);
281 }
282
283 EXPORT int
test_unit_ready(scgp)284 test_unit_ready(scgp)
285 SCSI *scgp;
286 {
287 register struct scg_cmd *scmd = scgp->scmd;
288
289 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
290 scmd->addr = (caddr_t)0;
291 scmd->size = 0;
292 scmd->flags = SCG_DISRE_ENA | (scgp->silent ? SCG_SILENT:0);
293 scmd->cdb_len = SC_G0_CDBLEN;
294 scmd->sense_len = CCS_SENSE_LEN;
295 scmd->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
296 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
297
298 scgp->cmdname = "test unit ready";
299
300 return (scg_cmd(scgp));
301 }
302
303 EXPORT int
rezero_unit(scgp)304 rezero_unit(scgp)
305 SCSI *scgp;
306 {
307 register struct scg_cmd *scmd = scgp->scmd;
308
309 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
310 scmd->addr = (caddr_t)0;
311 scmd->size = 0;
312 scmd->flags = SCG_DISRE_ENA;
313 scmd->cdb_len = SC_G0_CDBLEN;
314 scmd->sense_len = CCS_SENSE_LEN;
315 scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT;
316 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
317
318 scgp->cmdname = "rezero unit";
319
320 return (scg_cmd(scgp));
321 }
322
323 EXPORT int
request_sense(scgp)324 request_sense(scgp)
325 SCSI *scgp;
326 {
327 char sensebuf[CCS_SENSE_LEN];
328 char *cmdsave;
329
330 cmdsave = scgp->cmdname;
331
332 if (request_sense_b(scgp, sensebuf, sizeof (sensebuf)) < 0)
333 return (-1);
334 scgp->cmdname = cmdsave;
335 scg_prsense((Uchar *)sensebuf, CCS_SENSE_LEN - scg_getresid(scgp));
336 return (0);
337 }
338
339 EXPORT int
request_sense_b(scgp,bp,cnt)340 request_sense_b(scgp, bp, cnt)
341 SCSI *scgp;
342 caddr_t bp;
343 int cnt;
344 {
345 register struct scg_cmd *scmd = scgp->scmd;
346
347
348 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
349 scmd->addr = bp;
350 scmd->size = cnt;
351 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
352 scmd->cdb_len = SC_G0_CDBLEN;
353 scmd->sense_len = CCS_SENSE_LEN;
354 scmd->cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
355 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
356 scmd->cdb.g0_cdb.count = cnt;
357
358 scgp->cmdname = "request_sense";
359
360 if (scg_cmd(scgp) < 0)
361 return (-1);
362 return (0);
363 }
364
365 EXPORT int
inquiry(scgp,bp,cnt)366 inquiry(scgp, bp, cnt)
367 SCSI *scgp;
368 caddr_t bp;
369 int cnt;
370 {
371 register struct scg_cmd *scmd = scgp->scmd;
372
373 fillbytes(bp, cnt, '\0');
374 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
375 scmd->addr = bp;
376 scmd->size = cnt;
377 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
378 scmd->cdb_len = SC_G0_CDBLEN;
379 scmd->sense_len = CCS_SENSE_LEN;
380 scmd->cdb.g0_cdb.cmd = SC_INQUIRY;
381 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
382 scmd->cdb.g0_cdb.count = cnt;
383
384 scgp->cmdname = "inquiry";
385
386 if (scg_cmd(scgp) < 0)
387 return (-1);
388 if (scgp->verbose)
389 scg_prbytes(_("Inquiry Data :"), (Uchar *)bp, cnt - scg_getresid(scgp));
390 return (0);
391 }
392
393 EXPORT int
read_capacity(scgp)394 read_capacity(scgp)
395 SCSI *scgp;
396 {
397 register struct scg_cmd *scmd = scgp->scmd;
398
399 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
400 scmd->addr = (caddr_t)scgp->cap;
401 scmd->size = sizeof (struct scsi_capacity);
402 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
403 scmd->cdb_len = SC_G1_CDBLEN;
404 scmd->sense_len = CCS_SENSE_LEN;
405 scmd->cdb.g1_cdb.cmd = 0x25; /* Read Capacity */
406 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
407 g1_cdblen(&scmd->cdb.g1_cdb, 0); /* Full Media */
408
409 scgp->cmdname = "read capacity";
410
411 if (scg_cmd(scgp) < 0) {
412 return (-1);
413 } else {
414 long cbsize;
415 long cbaddr;
416
417 /*
418 * c_bsize & c_baddr are signed Int32_t
419 * so we use signed int conversion here.
420 */
421 cbsize = a_to_4_byte(&scgp->cap->c_bsize);
422 cbaddr = a_to_4_byte(&scgp->cap->c_baddr);
423 scgp->cap->c_bsize = cbsize;
424 scgp->cap->c_baddr = cbaddr;
425 }
426 return (0);
427 }
428
429 EXPORT void
print_capacity(scgp,f)430 print_capacity(scgp, f)
431 SCSI *scgp;
432 FILE *f;
433 {
434 long kb;
435 long mb;
436 long prmb;
437 double dkb;
438
439 dkb = (scgp->cap->c_baddr+1.0) * (scgp->cap->c_bsize/1024.0);
440 kb = dkb;
441 mb = dkb / 1024.0;
442 prmb = dkb / 1000.0 * 1.024;
443 fprintf(f, _("Capacity: %ld Blocks = %ld kBytes = %ld MBytes = %ld prMB\n"),
444 (long)scgp->cap->c_baddr+1, kb, mb, prmb);
445 fprintf(f, _("Sectorsize: %ld Bytes\n"), (long)scgp->cap->c_bsize);
446 }
447
448 EXPORT int
scsi_load_unload(scgp,load)449 scsi_load_unload(scgp, load)
450 SCSI *scgp;
451 int load;
452 {
453 register struct scg_cmd *scmd = scgp->scmd;
454
455 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
456 scmd->flags = SCG_DISRE_ENA;
457 scmd->cdb_len = SC_G5_CDBLEN;
458 scmd->sense_len = CCS_SENSE_LEN;
459 scmd->cdb.g5_cdb.cmd = 0xA6;
460 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
461 scmd->cdb.g5_cdb.addr[1] = load?3:2;
462 scmd->cdb.g5_cdb.count[2] = 0; /* slot # */
463
464 scgp->cmdname = "medium load/unload";
465
466 if (scg_cmd(scgp) < 0)
467 return (-1);
468 return (0);
469 }
470
471 EXPORT int
scsi_prevent_removal(scgp,prevent)472 scsi_prevent_removal(scgp, prevent)
473 SCSI *scgp;
474 int prevent;
475 {
476 register struct scg_cmd *scmd = scgp->scmd;
477
478 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
479 scmd->flags = SCG_DISRE_ENA;
480 scmd->cdb_len = SC_G0_CDBLEN;
481 scmd->sense_len = CCS_SENSE_LEN;
482 scmd->cdb.g0_cdb.cmd = 0x1E;
483 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
484 scmd->cdb.g0_cdb.count = prevent & 1;
485
486 scgp->cmdname = "prevent/allow medium removal";
487
488 if (scg_cmd(scgp) < 0)
489 return (-1);
490 return (0);
491 }
492
493
494 EXPORT int
scsi_start_stop_unit(scgp,flg,loej,immed)495 scsi_start_stop_unit(scgp, flg, loej, immed)
496 SCSI *scgp;
497 int flg;
498 int loej;
499 BOOL immed;
500 {
501 register struct scg_cmd *scmd = scgp->scmd;
502
503 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
504 scmd->flags = SCG_DISRE_ENA;
505 scmd->cdb_len = SC_G0_CDBLEN;
506 scmd->sense_len = CCS_SENSE_LEN;
507 scmd->cdb.g0_cdb.cmd = 0x1B; /* Start Stop Unit */
508 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
509 scmd->cdb.g0_cdb.count = (flg ? 1:0) | (loej ? 2:0);
510
511 if (immed)
512 scmd->cdb.cmd_cdb[1] |= 0x01;
513
514 scgp->cmdname = "start/stop unit";
515
516 return (scg_cmd(scgp));
517 }
518
519 EXPORT int
scsi_set_speed(scgp,readspeed,writespeed,rotctl)520 scsi_set_speed(scgp, readspeed, writespeed, rotctl)
521 SCSI *scgp;
522 int readspeed;
523 int writespeed;
524 int rotctl;
525 {
526 register struct scg_cmd *scmd = scgp->scmd;
527
528 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
529 scmd->flags = SCG_DISRE_ENA;
530 scmd->cdb_len = SC_G5_CDBLEN;
531 scmd->sense_len = CCS_SENSE_LEN;
532 scmd->cdb.g5_cdb.cmd = 0xBB;
533 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
534
535 if (readspeed < 0)
536 i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], 0xFFFF);
537 else
538 i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], readspeed);
539 if (writespeed < 0)
540 i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], 0xFFFF);
541 else
542 i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], writespeed);
543
544 scmd->cdb.cmd_cdb[1] |= rotctl & 0x03;
545
546 scgp->cmdname = "set cd speed";
547
548 if (scg_cmd(scgp) < 0)
549 return (-1);
550 return (0);
551 }
552
553 EXPORT int
scsi_get_speed(scgp,readspeedp,writespeedp)554 scsi_get_speed(scgp, readspeedp, writespeedp)
555 SCSI *scgp;
556 int *readspeedp;
557 int *writespeedp;
558 {
559 struct cd_mode_page_2A *mp;
560 Uchar m[256];
561 int val;
562
563 scgp->silent++;
564 mp = mmc_cap(scgp, m); /* Get MMC capabilities in allocated mp */
565 scgp->silent--;
566 if (mp == NULL)
567 return (-1); /* Pre SCSI-3/mmc drive */
568
569 val = a_to_u_2_byte(mp->cur_read_speed);
570 if (readspeedp)
571 *readspeedp = val;
572
573 if (mp->p_len >= 28)
574 val = a_to_u_2_byte(mp->v3_cur_write_speed);
575 else
576 val = a_to_u_2_byte(mp->cur_write_speed);
577 if (writespeedp)
578 *writespeedp = val;
579
580 return (0);
581 }
582
583
584 EXPORT int
qic02(scgp,cmd)585 qic02(scgp, cmd)
586 SCSI *scgp;
587 int cmd;
588 {
589 register struct scg_cmd *scmd = scgp->scmd;
590
591 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
592 scmd->addr = (caddr_t)0;
593 scmd->size = 0;
594 scmd->flags = SCG_DISRE_ENA;
595 scmd->cdb_len = SC_G0_CDBLEN;
596 scmd->sense_len = DEF_SENSE_LEN;
597 scmd->cdb.g0_cdb.cmd = 0x0D; /* qic02 Sysgen SC4000 */
598 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
599 scmd->cdb.g0_cdb.mid_addr = cmd;
600
601 scgp->cmdname = "qic 02";
602 return (scg_cmd(scgp));
603 }
604
605 #define G0_MAXADDR 0x1FFFFFL
606
607 EXPORT int
write_xscsi(scgp,bp,addr,size,cnt)608 write_xscsi(scgp, bp, addr, size, cnt)
609 SCSI *scgp;
610 caddr_t bp; /* address of buffer */
611 long addr; /* disk address (sector) to put */
612 long size; /* number of bytes to transfer */
613 int cnt; /* sectorcount */
614 {
615 if (addr <= G0_MAXADDR)
616 return (write_xg0(scgp, bp, addr, size, cnt));
617 else
618 return (write_xg1(scgp, bp, addr, size, cnt));
619 }
620
621 EXPORT int
write_xg0(scgp,bp,addr,size,cnt)622 write_xg0(scgp, bp, addr, size, cnt)
623 SCSI *scgp;
624 caddr_t bp; /* address of buffer */
625 long addr; /* disk address (sector) to put */
626 long size; /* number of bytes to transfer */
627 int cnt; /* sectorcount */
628 {
629 register struct scg_cmd *scmd = scgp->scmd;
630
631 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
632 scmd->addr = bp;
633 scmd->size = size;
634 scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
635 /* scmd->flags = SCG_DISRE_ENA;*/
636 scmd->cdb_len = SC_G0_CDBLEN;
637 scmd->sense_len = CCS_SENSE_LEN;
638 scmd->cdb.g0_cdb.cmd = SC_WRITE;
639 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
640 g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
641 scmd->cdb.g0_cdb.count = cnt;
642
643 scgp->cmdname = "write_g0";
644
645 if (scg_cmd(scgp) < 0)
646 return (-1);
647 return (size - scg_getresid(scgp));
648 }
649
650 EXPORT int
write_xg1(scgp,bp,addr,size,cnt)651 write_xg1(scgp, bp, addr, size, cnt)
652 SCSI *scgp;
653 caddr_t bp; /* address of buffer */
654 long addr; /* disk address (sector) to put */
655 long size; /* number of bytes to transfer */
656 int cnt; /* sectorcount */
657 {
658 register struct scg_cmd *scmd = scgp->scmd;
659
660 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
661 scmd->addr = bp;
662 scmd->size = size;
663 scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
664 /* scmd->flags = SCG_DISRE_ENA;*/
665 scmd->cdb_len = SC_G1_CDBLEN;
666 scmd->sense_len = CCS_SENSE_LEN;
667 scmd->cdb.g1_cdb.cmd = SC_EWRITE;
668 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
669 g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
670 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
671
672 scgp->cmdname = "write_g1";
673
674 if (scg_cmd(scgp) < 0)
675 return (-1);
676 return (size - scg_getresid(scgp));
677 }
678
679 EXPORT int
write_xg5(scgp,bp,addr,size,cnt)680 write_xg5(scgp, bp, addr, size, cnt)
681 SCSI *scgp;
682 caddr_t bp; /* address of buffer */
683 long addr; /* disk address (sector) to put */
684 long size; /* number of bytes to transfer */
685 int cnt; /* sectorcount */
686 {
687 register struct scg_cmd *scmd = scgp->scmd;
688
689 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
690 scmd->addr = bp;
691 scmd->size = size;
692 scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
693 /* scmd->flags = SCG_DISRE_ENA;*/
694 scmd->cdb_len = SC_G5_CDBLEN;
695 scmd->sense_len = CCS_SENSE_LEN;
696 scmd->cdb.g5_cdb.cmd = 0xAA;
697 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
698 g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
699 g5_cdblen(&scmd->cdb.g5_cdb, cnt);
700
701 scgp->cmdname = "write_g5";
702
703 if (scg_cmd(scgp) < 0)
704 return (-1);
705 return (size - scg_getresid(scgp));
706 }
707
708 EXPORT int
seek_scsi(scgp,addr)709 seek_scsi(scgp, addr)
710 SCSI *scgp;
711 long addr;
712 {
713 if (addr <= G0_MAXADDR)
714 return (seek_g0(scgp, addr));
715 else
716 return (seek_g1(scgp, addr));
717 }
718
719 EXPORT int
seek_g0(scgp,addr)720 seek_g0(scgp, addr)
721 SCSI *scgp;
722 long addr;
723 {
724 register struct scg_cmd *scmd = scgp->scmd;
725
726 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
727 scmd->flags = SCG_DISRE_ENA;
728 scmd->cdb_len = SC_G0_CDBLEN;
729 scmd->sense_len = CCS_SENSE_LEN;
730 scmd->cdb.g0_cdb.cmd = 0x0B; /* Seek */
731 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
732 g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
733
734 scgp->cmdname = "seek_g0";
735
736 return (scg_cmd(scgp));
737 }
738
739 EXPORT int
seek_g1(scgp,addr)740 seek_g1(scgp, addr)
741 SCSI *scgp;
742 long addr;
743 {
744 register struct scg_cmd *scmd = scgp->scmd;
745
746 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
747 scmd->flags = SCG_DISRE_ENA;
748 scmd->cdb_len = SC_G1_CDBLEN;
749 scmd->sense_len = CCS_SENSE_LEN;
750 scmd->cdb.g1_cdb.cmd = 0x2B; /* Seek G1 */
751 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
752 g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
753
754 scgp->cmdname = "seek_g1";
755
756 return (scg_cmd(scgp));
757 }
758
759 EXPORT int
scsi_flush_cache(scgp,immed)760 scsi_flush_cache(scgp, immed)
761 SCSI *scgp;
762 BOOL immed;
763 {
764 register struct scg_cmd *scmd = scgp->scmd;
765
766 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
767 scmd->flags = SCG_DISRE_ENA;
768 scmd->cdb_len = SC_G1_CDBLEN;
769 scmd->sense_len = CCS_SENSE_LEN;
770 scmd->timeout = 2 * 60; /* Max: sizeof (CDR-cache)/150KB/s */
771 scmd->cdb.g1_cdb.cmd = 0x35;
772 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
773
774 if (immed)
775 scmd->cdb.cmd_cdb[1] |= 0x02;
776
777 scgp->cmdname = "flush cache";
778
779 if (scg_cmd(scgp) < 0)
780 return (-1);
781 return (0);
782 }
783
784 EXPORT int
read_buffer(scgp,bp,cnt,mode)785 read_buffer(scgp, bp, cnt, mode)
786 SCSI *scgp;
787 caddr_t bp;
788 int cnt;
789 int mode;
790 {
791 register struct scg_cmd *scmd = scgp->scmd;
792
793 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
794 scmd->addr = bp;
795 scmd->size = cnt;
796 scmd->dma_read = 1;
797 scmd->cdb_len = SC_G1_CDBLEN;
798 scmd->sense_len = CCS_SENSE_LEN;
799 scmd->cdb.g1_cdb.cmd = 0x3C; /* Read Buffer */
800 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
801 scmd->cdb.cmd_cdb[1] |= (mode & 7);
802 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
803
804 scgp->cmdname = "read buffer";
805
806 return (scg_cmd(scgp));
807 }
808
809 EXPORT int
write_buffer(scgp,buffer,length,mode,bufferid,offset)810 write_buffer(scgp, buffer, length, mode, bufferid, offset)
811 SCSI *scgp;
812 char *buffer;
813 long length;
814 int mode;
815 int bufferid;
816 long offset;
817 {
818 register struct scg_cmd *scmd = scgp->scmd;
819 char *cdb;
820
821 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
822 scmd->addr = buffer;
823 scmd->size = length;
824 scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
825 scmd->cdb_len = SC_G1_CDBLEN;
826 scmd->sense_len = CCS_SENSE_LEN;
827
828 cdb = (char *)scmd->cdb.cmd_cdb;
829
830 cdb[0] = 0x3B;
831 cdb[1] = mode & 7;
832 cdb[2] = bufferid;
833 cdb[3] = offset >> 16;
834 cdb[4] = (offset >> 8) & 0xff;
835 cdb[5] = offset & 0xff;
836 cdb[6] = length >> 16;
837 cdb[7] = (length >> 8) & 0xff;
838 cdb[8] = length & 0xff;
839
840 scgp->cmdname = "write_buffer";
841
842 if (scg_cmd(scgp) >= 0)
843 return (1);
844 return (0);
845 }
846
847 EXPORT int
read_subchannel(scgp,bp,track,cnt,msf,subq,fmt)848 read_subchannel(scgp, bp, track, cnt, msf, subq, fmt)
849 SCSI *scgp;
850 caddr_t bp;
851 int track;
852 int cnt;
853 int msf;
854 int subq;
855 int fmt;
856
857 {
858 register struct scg_cmd *scmd = scgp->scmd;
859
860 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
861 scmd->addr = bp;
862 scmd->size = cnt;
863 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
864 scmd->cdb_len = SC_G1_CDBLEN;
865 scmd->sense_len = CCS_SENSE_LEN;
866 scmd->cdb.g1_cdb.cmd = 0x42;
867 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
868 if (msf)
869 scmd->cdb.g1_cdb.res = 1;
870 if (subq)
871 scmd->cdb.g1_cdb.addr[0] = 0x40;
872 scmd->cdb.g1_cdb.addr[1] = fmt;
873 scmd->cdb.g1_cdb.res6 = track;
874 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
875
876 scgp->cmdname = "read subchannel";
877
878 if (scg_cmd(scgp) < 0)
879 return (-1);
880 return (0);
881 }
882
883 EXPORT int
read_toc(scgp,bp,track,cnt,msf,fmt)884 read_toc(scgp, bp, track, cnt, msf, fmt)
885 SCSI *scgp;
886 caddr_t bp;
887 int track;
888 int cnt;
889 int msf;
890 int fmt;
891
892 {
893 register struct scg_cmd *scmd = scgp->scmd;
894
895 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
896 scmd->addr = bp;
897 scmd->size = cnt;
898 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
899 scmd->cdb_len = SC_G1_CDBLEN;
900 scmd->sense_len = CCS_SENSE_LEN;
901 scmd->cdb.g1_cdb.cmd = 0x43;
902 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
903 if (msf)
904 scmd->cdb.g1_cdb.res = 1;
905 scmd->cdb.g1_cdb.addr[0] = fmt & 0x0F;
906 scmd->cdb.g1_cdb.res6 = track;
907 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
908
909 scgp->cmdname = "read toc";
910
911 if (scg_cmd(scgp) < 0)
912 return (-1);
913 return (0);
914 }
915
916 EXPORT int
read_toc_philips(scgp,bp,track,cnt,msf,fmt)917 read_toc_philips(scgp, bp, track, cnt, msf, fmt)
918 SCSI *scgp;
919 caddr_t bp;
920 int track;
921 int cnt;
922 int msf;
923 int fmt;
924
925 {
926 register struct scg_cmd *scmd = scgp->scmd;
927
928 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
929 scmd->addr = bp;
930 scmd->size = cnt;
931 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
932 scmd->cdb_len = SC_G1_CDBLEN;
933 scmd->sense_len = CCS_SENSE_LEN;
934 scmd->timeout = 4 * 60; /* May last 174s on a TEAC CD-R55S */
935 scmd->cdb.g1_cdb.cmd = 0x43;
936 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
937 if (msf)
938 scmd->cdb.g1_cdb.res = 1;
939 scmd->cdb.g1_cdb.res6 = track;
940 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
941
942 if (fmt & 1)
943 scmd->cdb.g1_cdb.vu_96 = 1;
944 if (fmt & 2)
945 scmd->cdb.g1_cdb.vu_97 = 1;
946
947 scgp->cmdname = "read toc";
948
949 if (scg_cmd(scgp) < 0)
950 return (-1);
951 return (0);
952 }
953
954 EXPORT int
read_header(scgp,bp,addr,cnt,msf)955 read_header(scgp, bp, addr, cnt, msf)
956 SCSI *scgp;
957 caddr_t bp;
958 long addr;
959 int cnt;
960 int msf;
961 {
962 register struct scg_cmd *scmd = scgp->scmd;
963
964 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
965 scmd->addr = bp;
966 scmd->size = cnt;
967 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
968 scmd->cdb_len = SC_G1_CDBLEN;
969 scmd->sense_len = CCS_SENSE_LEN;
970 scmd->cdb.g1_cdb.cmd = 0x44;
971 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
972 if (msf)
973 scmd->cdb.g1_cdb.res = 1;
974 g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
975 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
976
977 scgp->cmdname = "read header";
978
979 if (scg_cmd(scgp) < 0)
980 return (-1);
981 return (0);
982 }
983
984 EXPORT int
read_disk_info(scgp,bp,cnt)985 read_disk_info(scgp, bp, cnt)
986 SCSI *scgp;
987 caddr_t bp;
988 int cnt;
989
990 {
991 register struct scg_cmd *scmd = scgp->scmd;
992
993 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
994 scmd->addr = bp;
995 scmd->size = cnt;
996 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
997 scmd->cdb_len = SC_G1_CDBLEN;
998 scmd->sense_len = CCS_SENSE_LEN;
999 scmd->timeout = 4 * 60; /* Needs up to 2 minutes */
1000 scmd->cdb.g1_cdb.cmd = 0x51;
1001 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1002 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1003
1004 scgp->cmdname = "read disk info";
1005
1006 if (scg_cmd(scgp) < 0)
1007 return (-1);
1008 return (0);
1009 }
1010
1011 EXPORT int
read_track_info(scgp,bp,type,addr,cnt)1012 read_track_info(scgp, bp, type, addr, cnt)
1013 SCSI *scgp;
1014 caddr_t bp;
1015 int type;
1016 int addr;
1017 int cnt;
1018
1019 {
1020 register struct scg_cmd *scmd = scgp->scmd;
1021
1022 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1023 scmd->addr = bp;
1024 scmd->size = cnt;
1025 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1026 scmd->cdb_len = SC_G1_CDBLEN;
1027 scmd->sense_len = CCS_SENSE_LEN;
1028 scmd->timeout = 4 * 60; /* Needs up to 2 minutes */
1029 scmd->cdb.g1_cdb.cmd = 0x52;
1030 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1031 /* scmd->cdb.cmd_cdb[1] = type & 0x03;*/
1032 scmd->cdb.cmd_cdb[1] = type;
1033 g1_cdbaddr(&scmd->cdb.g1_cdb, addr); /* LBA/Track/Session */
1034 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1035
1036 scgp->cmdname = "read track info";
1037
1038 if (scg_cmd(scgp) < 0)
1039 return (-1);
1040 return (0);
1041 }
1042
1043 EXPORT int
get_trackinfo(scgp,bp,type,addr,cnt)1044 get_trackinfo(scgp, bp, type, addr, cnt)
1045 SCSI *scgp;
1046 caddr_t bp;
1047 int type;
1048 int addr;
1049 int cnt;
1050 {
1051 int len;
1052 int ret;
1053
1054 fillbytes(bp, cnt, '\0');
1055
1056 /*
1057 * Used to be 2 instead of 4 (now). But some Y2k ATAPI drives as used
1058 * by IOMEGA create a DMA overrun if we try to transfer only 2 bytes.
1059 */
1060 if (read_track_info(scgp, bp, type, addr, 4) < 0)
1061 return (-1);
1062
1063 len = a_to_u_2_byte(bp);
1064 len += 2;
1065 if (len > cnt)
1066 len = cnt;
1067 ret = read_track_info(scgp, bp, type, addr, len);
1068
1069 #ifdef DEBUG
1070 if (lverbose > 1)
1071 scg_prbytes(_("Track info:"), (Uchar *)bp,
1072 len-scg_getresid(scgp));
1073 #endif
1074 return (ret);
1075 }
1076
1077 EXPORT int
read_rzone_info(scgp,bp,cnt)1078 read_rzone_info(scgp, bp, cnt)
1079 SCSI *scgp;
1080 caddr_t bp;
1081 int cnt;
1082 {
1083 return (get_trackinfo(scgp, bp, TI_TYPE_LBA, 0, cnt));
1084 }
1085
1086 EXPORT int
reserve_tr_rzone(scgp,size)1087 reserve_tr_rzone(scgp, size)
1088 SCSI *scgp;
1089 long size; /* number of blocks */
1090 {
1091 register struct scg_cmd *scmd = scgp->scmd;
1092
1093 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1094 scmd->addr = (caddr_t)0;
1095 scmd->size = 0;
1096 scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
1097 scmd->cdb_len = SC_G1_CDBLEN;
1098 scmd->sense_len = CCS_SENSE_LEN;
1099 scmd->cdb.g1_cdb.cmd = 0x53;
1100 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1101
1102 i_to_4_byte(&scmd->cdb.cmd_cdb[5], size);
1103
1104 scgp->cmdname = "reserve_track_rzone";
1105
1106 if (scg_cmd(scgp) < 0)
1107 return (-1);
1108 return (0);
1109 }
1110
1111 EXPORT int
read_dvd_structure(scgp,bp,cnt,mt,addr,layer,fmt)1112 read_dvd_structure(scgp, bp, cnt, mt, addr, layer, fmt)
1113 SCSI *scgp;
1114 caddr_t bp;
1115 int cnt;
1116 int mt;
1117 int addr;
1118 int layer;
1119 int fmt;
1120 {
1121 register struct scg_cmd *scmd = scgp->scmd;
1122
1123 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1124 scmd->addr = bp;
1125 scmd->size = cnt;
1126 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1127 scmd->cdb_len = SC_G5_CDBLEN;
1128 scmd->sense_len = CCS_SENSE_LEN;
1129 scmd->timeout = 4 * 60; /* Needs up to 2 minutes ??? */
1130 scmd->cdb.g5_cdb.cmd = 0xAD;
1131 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1132 scmd->cdb.cmd_cdb[1] |= (mt & 0x0F); /* Media Type */
1133 g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
1134 g5_cdblen(&scmd->cdb.g5_cdb, cnt);
1135 scmd->cdb.g5_cdb.count[0] = layer;
1136 scmd->cdb.g5_cdb.count[1] = fmt;
1137
1138 scgp->cmdname = "read dvd structure";
1139
1140 if (scg_cmd(scgp) < 0)
1141 return (-1);
1142 return (0);
1143 }
1144
1145 EXPORT int
send_dvd_structure(scgp,bp,cnt,fmt)1146 send_dvd_structure(scgp, bp, cnt, fmt)
1147 SCSI *scgp;
1148 caddr_t bp;
1149 int cnt;
1150 int fmt;
1151 {
1152 register struct scg_cmd *scmd = scgp->scmd;
1153
1154 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1155 scmd->addr = bp;
1156 scmd->size = cnt;
1157 scmd->flags = SCG_DISRE_ENA;
1158 scmd->cdb_len = SC_G5_CDBLEN;
1159 scmd->sense_len = CCS_SENSE_LEN;
1160 scmd->timeout = 4 * 60; /* Needs up to 2 minutes ??? */
1161 scmd->cdb.g5_cdb.cmd = 0xBF;
1162 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1163 g5_cdblen(&scmd->cdb.g5_cdb, cnt);
1164 scmd->cdb.g5_cdb.count[0] = 0;
1165 scmd->cdb.g5_cdb.count[1] = fmt;
1166
1167 scgp->cmdname = "send dvd structure";
1168
1169 if (scg_cmd(scgp) < 0)
1170 return (-1);
1171 return (0);
1172 }
1173
1174 EXPORT int
send_opc(scgp,bp,cnt,doopc)1175 send_opc(scgp, bp, cnt, doopc)
1176 SCSI *scgp;
1177 caddr_t bp;
1178 int cnt;
1179 int doopc;
1180 {
1181 register struct scg_cmd *scmd = scgp->scmd;
1182
1183 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1184 scmd->addr = bp;
1185 scmd->size = cnt;
1186 scmd->flags = SCG_DISRE_ENA;
1187 scmd->cdb_len = SC_G1_CDBLEN;
1188 scmd->sense_len = CCS_SENSE_LEN;
1189 scmd->timeout = 60;
1190 scmd->cdb.g1_cdb.cmd = 0x54;
1191 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1192 scmd->cdb.g1_cdb.reladr = doopc?1:0;
1193 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1194
1195 scgp->cmdname = "send opc";
1196
1197 if (scg_cmd(scgp) < 0)
1198 return (-1);
1199 return (0);
1200 }
1201
1202 EXPORT int
read_track_info_philips(scgp,bp,track,cnt)1203 read_track_info_philips(scgp, bp, track, cnt)
1204 SCSI *scgp;
1205 caddr_t bp;
1206 int track;
1207 int cnt;
1208
1209 {
1210 register struct scg_cmd *scmd = scgp->scmd;
1211
1212 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1213 scmd->addr = bp;
1214 scmd->size = cnt;
1215 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1216 scmd->cdb_len = SC_G1_CDBLEN;
1217 scmd->sense_len = CCS_SENSE_LEN;
1218 scmd->cdb.g1_cdb.cmd = 0xE5;
1219 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1220 g1_cdbaddr(&scmd->cdb.g1_cdb, track);
1221 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1222
1223 scgp->cmdname = "read track info";
1224
1225 if (scg_cmd(scgp) < 0)
1226 return (-1);
1227 return (0);
1228 }
1229
1230 EXPORT int
scsi_close_tr_session(scgp,type,track,immed)1231 scsi_close_tr_session(scgp, type, track, immed)
1232 SCSI *scgp;
1233 int type;
1234 int track;
1235 BOOL immed;
1236 {
1237 register struct scg_cmd *scmd = scgp->scmd;
1238
1239 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1240 scmd->flags = SCG_DISRE_ENA;
1241 scmd->cdb_len = SC_G1_CDBLEN;
1242 scmd->sense_len = CCS_SENSE_LEN;
1243 scmd->timeout = 8 * 60; /* Needs up to 4 minutes */
1244 scmd->cdb.g1_cdb.cmd = 0x5B;
1245 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1246 scmd->cdb.g1_cdb.addr[0] = type;
1247 scmd->cdb.g1_cdb.addr[3] = track;
1248
1249 if (immed)
1250 scmd->cdb.g1_cdb.reladr = 1;
1251 /* scmd->cdb.cmd_cdb[1] |= 0x01;*/
1252 #ifdef nono
1253 scmd->cdb.g1_cdb.reladr = 1; /* IMM hack to test Mitsumi behaviour*/
1254 #endif
1255
1256 scgp->cmdname = "close track/session";
1257
1258 if (scg_cmd(scgp) < 0)
1259 return (-1);
1260 return (0);
1261 }
1262
1263 EXPORT int
read_master_cue(scgp,bp,sheet,cnt)1264 read_master_cue(scgp, bp, sheet, cnt)
1265 SCSI *scgp;
1266 caddr_t bp; /* address of master cue sheet */
1267 int sheet; /* Sheet number */
1268 int cnt; /* Transfer count */
1269 {
1270 register struct scg_cmd *scmd = scgp->scmd;
1271
1272 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1273 scmd->addr = bp;
1274 scmd->size = cnt;
1275 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1276 scmd->cdb_len = SC_G1_CDBLEN;
1277 scmd->sense_len = CCS_SENSE_LEN;
1278 scmd->cdb.g1_cdb.cmd = 0x59; /* Read master cue */
1279 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1280 scmd->cdb.g1_cdb.addr[2] = sheet;
1281 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1282
1283 scgp->cmdname = "read master cue";
1284
1285 if (scg_cmd(scgp) < 0)
1286 return (-1);
1287 return (0);
1288 }
1289
1290 EXPORT int
send_cue_sheet(scgp,bp,size)1291 send_cue_sheet(scgp, bp, size)
1292 SCSI *scgp;
1293 caddr_t bp; /* address of cue sheet buffer */
1294 long size; /* number of bytes to transfer */
1295 {
1296 register struct scg_cmd *scmd = scgp->scmd;
1297
1298 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1299 scmd->addr = bp;
1300 scmd->size = size;
1301 scmd->flags = SCG_DISRE_ENA;
1302 scmd->cdb_len = SC_G1_CDBLEN;
1303 scmd->sense_len = CCS_SENSE_LEN;
1304 scmd->cdb.g1_cdb.cmd = 0x5D; /* Send CUE sheet */
1305 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1306 g1_cdblen(&scmd->cdb.g1_cdb, size);
1307
1308 scgp->cmdname = "send_cue_sheet";
1309
1310 if (scg_cmd(scgp) < 0)
1311 return (-1);
1312 return (size - scmd->resid);
1313 }
1314
1315 EXPORT int
read_buff_cap(scgp,sp,fp)1316 read_buff_cap(scgp, sp, fp)
1317 SCSI *scgp;
1318 long *sp; /* Size pointer */
1319 long *fp; /* Free pointer */
1320 {
1321 char resp[12];
1322 Ulong freespace;
1323 Ulong bufsize;
1324 int per;
1325 register struct scg_cmd *scmd = scgp->scmd;
1326
1327 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1328 scmd->addr = (caddr_t)resp;
1329 scmd->size = sizeof (resp);
1330 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1331 scmd->cdb_len = SC_G1_CDBLEN;
1332 scmd->sense_len = CCS_SENSE_LEN;
1333 scmd->cdb.g1_cdb.cmd = 0x5C; /* Read buffer cap */
1334 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1335 g1_cdblen(&scmd->cdb.g1_cdb, sizeof (resp));
1336
1337 scgp->cmdname = "read buffer cap";
1338
1339 if (scg_cmd(scgp) < 0)
1340 return (-1);
1341
1342 bufsize = a_to_u_4_byte(&resp[4]);
1343 freespace = a_to_u_4_byte(&resp[8]);
1344 if (sp)
1345 *sp = bufsize;
1346 if (fp)
1347 *fp = freespace;
1348
1349 if (scgp->verbose || (sp == 0 && fp == 0))
1350 printf(_("BFree: %ld K BSize: %ld K\n"), freespace >> 10, bufsize >> 10);
1351
1352 if (bufsize == 0)
1353 return (0);
1354 per = (100 * (bufsize - freespace)) / bufsize;
1355 if (per < 0)
1356 return (0);
1357 if (per > 100)
1358 return (100);
1359 return (per);
1360 }
1361
1362 EXPORT int
scsi_blank(scgp,addr,blanktype,immed)1363 scsi_blank(scgp, addr, blanktype, immed)
1364 SCSI *scgp;
1365 long addr;
1366 int blanktype;
1367 BOOL immed;
1368 {
1369 register struct scg_cmd *scmd = scgp->scmd;
1370
1371 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1372 scmd->flags = SCG_DISRE_ENA;
1373 scmd->cdb_len = SC_G5_CDBLEN;
1374 scmd->sense_len = CCS_SENSE_LEN;
1375 scmd->timeout = 160 * 60; /* full blank at 1x could take 80 minutes */
1376 scmd->cdb.g5_cdb.cmd = 0xA1; /* Blank */
1377 scmd->cdb.g0_cdb.high_addr = blanktype;
1378 g1_cdbaddr(&scmd->cdb.g5_cdb, addr);
1379
1380 if (immed)
1381 scmd->cdb.g5_cdb.res |= 8;
1382 /* scmd->cdb.cmd_cdb[1] |= 0x10;*/
1383
1384 scgp->cmdname = "blank unit";
1385
1386 return (scg_cmd(scgp));
1387 }
1388
1389 /*
1390 * XXX First try to handle ATAPI:
1391 * XXX ATAPI cannot handle SCSI 6 byte commands.
1392 * XXX We try to simulate 6 byte mode sense/select.
1393 */
1394 LOCAL BOOL is_atapi;
1395
1396 EXPORT BOOL
allow_atapi(scgp,new)1397 allow_atapi(scgp, new)
1398 SCSI *scgp;
1399 BOOL new;
1400 {
1401 BOOL old = is_atapi;
1402 Uchar mode[256];
1403
1404 if (new == old)
1405 return (old);
1406
1407 scgp->silent++;
1408 /*
1409 * If a bad drive has been reset before, we may need to fire up two
1410 * test unit ready commands to clear status.
1411 */
1412 (void) unit_ready(scgp);
1413 if (new &&
1414 mode_sense_g1(scgp, mode, 8, 0x3F, 0) < 0) { /* All pages current */
1415 new = FALSE;
1416 }
1417 scgp->silent--;
1418
1419 is_atapi = new;
1420 return (old);
1421 }
1422
1423 EXPORT int
mode_select(scgp,dp,cnt,smp,pf)1424 mode_select(scgp, dp, cnt, smp, pf)
1425 SCSI *scgp;
1426 Uchar *dp;
1427 int cnt;
1428 int smp;
1429 int pf;
1430 {
1431 if (is_atapi)
1432 return (mode_select_sg0(scgp, dp, cnt, smp, pf));
1433 return (mode_select_g0(scgp, dp, cnt, smp, pf));
1434 }
1435
1436 EXPORT int
mode_sense(scgp,dp,cnt,page,pcf)1437 mode_sense(scgp, dp, cnt, page, pcf)
1438 SCSI *scgp;
1439 Uchar *dp;
1440 int cnt;
1441 int page;
1442 int pcf;
1443 {
1444 if (is_atapi)
1445 return (mode_sense_sg0(scgp, dp, cnt, page, pcf));
1446 return (mode_sense_g0(scgp, dp, cnt, page, pcf));
1447 }
1448
1449 /*
1450 * Simulate mode select g0 with mode select g1.
1451 */
1452 EXPORT int
mode_select_sg0(scgp,dp,cnt,smp,pf)1453 mode_select_sg0(scgp, dp, cnt, smp, pf)
1454 SCSI *scgp;
1455 Uchar *dp;
1456 int cnt;
1457 int smp;
1458 int pf;
1459 {
1460 Uchar xmode[256+4];
1461 int amt = cnt;
1462
1463 if (amt < 1 || amt > 255) {
1464 /* XXX clear SCSI error codes ??? */
1465 return (-1);
1466 }
1467
1468 if (amt < 4) { /* Data length. medium type & VU */
1469 amt += 1;
1470 } else {
1471 amt += 4;
1472 movebytes(&dp[4], &xmode[8], cnt-4);
1473 }
1474 xmode[0] = 0;
1475 xmode[1] = 0;
1476 xmode[2] = dp[1];
1477 xmode[3] = dp[2];
1478 xmode[4] = 0;
1479 xmode[5] = 0;
1480 i_to_2_byte(&xmode[6], (unsigned int)dp[3]);
1481
1482 if (scgp->verbose) scg_prbytes(_("Mode Parameters (un-converted)"), dp, cnt);
1483
1484 return (mode_select_g1(scgp, xmode, amt, smp, pf));
1485 }
1486
1487 /*
1488 * Simulate mode sense g0 with mode sense g1.
1489 */
1490 EXPORT int
mode_sense_sg0(scgp,dp,cnt,page,pcf)1491 mode_sense_sg0(scgp, dp, cnt, page, pcf)
1492 SCSI *scgp;
1493 Uchar *dp;
1494 int cnt;
1495 int page;
1496 int pcf;
1497 {
1498 Uchar xmode[256+4];
1499 int amt = cnt;
1500 int len;
1501
1502 if (amt < 1 || amt > 255) {
1503 /* XXX clear SCSI error codes ??? */
1504 return (-1);
1505 }
1506
1507 fillbytes((caddr_t)xmode, sizeof (xmode), '\0');
1508 if (amt < 4) { /* Data length. medium type & VU */
1509 amt += 1;
1510 } else {
1511 amt += 4;
1512 }
1513 if (mode_sense_g1(scgp, xmode, amt, page, pcf) < 0)
1514 return (-1);
1515
1516 amt = cnt - scg_getresid(scgp);
1517 /*
1518 * For tests: Solaris 8 & LG CD-ROM always returns resid == amt
1519 */
1520 /* amt = cnt;*/
1521 if (amt > 4)
1522 movebytes(&xmode[8], &dp[4], amt-4);
1523 len = a_to_u_2_byte(xmode);
1524 if (len == 0) {
1525 dp[0] = 0;
1526 } else if (len < 6) {
1527 if (len > 2)
1528 len = 2;
1529 dp[0] = len;
1530 } else {
1531 dp[0] = len - 3;
1532 }
1533 dp[1] = xmode[2];
1534 dp[2] = xmode[3];
1535 len = a_to_u_2_byte(&xmode[6]);
1536 dp[3] = len;
1537
1538 if (scgp->verbose) scg_prbytes(_("Mode Sense Data (converted)"), dp, amt);
1539 return (0);
1540 }
1541
1542 EXPORT int
mode_select_g0(scgp,dp,cnt,smp,pf)1543 mode_select_g0(scgp, dp, cnt, smp, pf)
1544 SCSI *scgp;
1545 Uchar *dp;
1546 int cnt;
1547 int smp;
1548 int pf;
1549 {
1550 register struct scg_cmd *scmd = scgp->scmd;
1551
1552 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1553 scmd->addr = (caddr_t)dp;
1554 scmd->size = cnt;
1555 scmd->flags = SCG_DISRE_ENA;
1556 scmd->cdb_len = SC_G0_CDBLEN;
1557 scmd->sense_len = CCS_SENSE_LEN;
1558 scmd->cdb.g0_cdb.cmd = SC_MODE_SELECT;
1559 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
1560 scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
1561 scmd->cdb.g0_cdb.count = cnt;
1562
1563 if (scgp->verbose) {
1564 error("%s ", smp?_("Save"):_("Set "));
1565 scg_prbytes(_("Mode Parameters"), dp, cnt);
1566 }
1567
1568 scgp->cmdname = "mode select g0";
1569
1570 return (scg_cmd(scgp));
1571 }
1572
1573 EXPORT int
mode_select_g1(scgp,dp,cnt,smp,pf)1574 mode_select_g1(scgp, dp, cnt, smp, pf)
1575 SCSI *scgp;
1576 Uchar *dp;
1577 int cnt;
1578 int smp;
1579 int pf;
1580 {
1581 register struct scg_cmd *scmd = scgp->scmd;
1582
1583 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1584 scmd->addr = (caddr_t)dp;
1585 scmd->size = cnt;
1586 scmd->flags = SCG_DISRE_ENA;
1587 scmd->cdb_len = SC_G1_CDBLEN;
1588 scmd->sense_len = CCS_SENSE_LEN;
1589 scmd->cdb.g1_cdb.cmd = 0x55;
1590 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1591 scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
1592 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1593
1594 if (scgp->verbose) {
1595 printf("%s ", smp?_("Save"):_("Set "));
1596 scg_prbytes(_("Mode Parameters"), dp, cnt);
1597 }
1598
1599 scgp->cmdname = "mode select g1";
1600
1601 return (scg_cmd(scgp));
1602 }
1603
1604 EXPORT int
mode_sense_g0(scgp,dp,cnt,page,pcf)1605 mode_sense_g0(scgp, dp, cnt, page, pcf)
1606 SCSI *scgp;
1607 Uchar *dp;
1608 int cnt;
1609 int page;
1610 int pcf;
1611 {
1612 register struct scg_cmd *scmd = scgp->scmd;
1613
1614 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1615 scmd->addr = (caddr_t)dp;
1616 scmd->size = 0xFF;
1617 scmd->size = cnt;
1618 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1619 scmd->cdb_len = SC_G0_CDBLEN;
1620 scmd->sense_len = CCS_SENSE_LEN;
1621 scmd->cdb.g0_cdb.cmd = SC_MODE_SENSE;
1622 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
1623 #ifdef nonono
1624 scmd->cdb.g0_cdb.high_addr = 1<<4; /* DBD Disable Block desc. */
1625 #endif
1626 scmd->cdb.g0_cdb.mid_addr = (page&0x3F) | ((pcf<<6)&0xC0);
1627 scmd->cdb.g0_cdb.count = page ? 0xFF : 24;
1628 scmd->cdb.g0_cdb.count = cnt;
1629
1630 scgp->cmdname = "mode sense g0";
1631
1632 if (scg_cmd(scgp) < 0)
1633 return (-1);
1634 if (scgp->verbose) scg_prbytes(_("Mode Sense Data"), dp, cnt - scg_getresid(scgp));
1635 return (0);
1636 }
1637
1638 EXPORT int
mode_sense_g1(scgp,dp,cnt,page,pcf)1639 mode_sense_g1(scgp, dp, cnt, page, pcf)
1640 SCSI *scgp;
1641 Uchar *dp;
1642 int cnt;
1643 int page;
1644 int pcf;
1645 {
1646 register struct scg_cmd *scmd = scgp->scmd;
1647
1648 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1649 scmd->addr = (caddr_t)dp;
1650 scmd->size = cnt;
1651 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1652 scmd->cdb_len = SC_G1_CDBLEN;
1653 scmd->sense_len = CCS_SENSE_LEN;
1654 scmd->cdb.g1_cdb.cmd = 0x5A;
1655 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1656 #ifdef nonono
1657 scmd->cdb.g0_cdb.high_addr = 1<<4; /* DBD Disable Block desc. */
1658 #endif
1659 scmd->cdb.g1_cdb.addr[0] = (page&0x3F) | ((pcf<<6)&0xC0);
1660 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1661
1662 scgp->cmdname = "mode sense g1";
1663
1664 if (scg_cmd(scgp) < 0)
1665 return (-1);
1666 if (scgp->verbose) scg_prbytes(_("Mode Sense Data"), dp, cnt - scg_getresid(scgp));
1667 return (0);
1668 }
1669
1670 struct trackdesc {
1671 Uchar res0;
1672
1673 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
1674 Ucbit control : 4;
1675 Ucbit adr : 4;
1676 #else /* Motorola byteorder */
1677 Ucbit adr : 4;
1678 Ucbit control : 4;
1679 #endif
1680
1681 Uchar track;
1682 Uchar res3;
1683 Uchar addr[4];
1684 };
1685
1686 struct diskinfo {
1687 struct tocheader hd;
1688 struct trackdesc desc[1];
1689 };
1690
1691 struct siheader {
1692 Uchar len[2];
1693 Uchar finished;
1694 Uchar unfinished;
1695 };
1696
1697 struct sidesc {
1698 Uchar sess_number;
1699 Uchar res1;
1700 Uchar track;
1701 Uchar res3;
1702 Uchar addr[4];
1703 };
1704
1705 struct sinfo {
1706 struct siheader hd;
1707 struct sidesc desc[1];
1708 };
1709
1710 struct trackheader {
1711 Uchar mode;
1712 Uchar res[3];
1713 Uchar addr[4];
1714 };
1715 #define TRM_ZERO 0
1716 #define TRM_USER_ECC 1 /* 2048 bytes user data + 288 Bytes ECC/EDC */
1717 #define TRM_USER 2 /* All user data (2336 bytes) */
1718
1719
1720 EXPORT int
read_tochdr(scgp,dp,fp,lp)1721 read_tochdr(scgp, dp, fp, lp)
1722 SCSI *scgp;
1723 cdr_t *dp;
1724 int *fp;
1725 int *lp;
1726 {
1727 struct tocheader *tp;
1728 char xb[256];
1729 int len;
1730
1731 tp = (struct tocheader *)xb;
1732
1733 fillbytes((caddr_t)xb, sizeof (xb), '\0');
1734 if (read_toc(scgp, xb, 0, sizeof (struct tocheader), 0, FMT_TOC) < 0) {
1735 if (scgp->silent == 0)
1736 errmsgno(EX_BAD, _("Cannot read TOC header\n"));
1737 return (-1);
1738 }
1739 len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
1740 if (len >= 4) {
1741 if (fp)
1742 *fp = tp->first;
1743 if (lp)
1744 *lp = tp->last;
1745 return (0);
1746 }
1747 return (-1);
1748 }
1749
1750 EXPORT int
read_cdtext(scgp)1751 read_cdtext(scgp)
1752 SCSI *scgp;
1753 {
1754 struct tocheader *tp;
1755 char xb[256];
1756 int len;
1757 char xxb[10000];
1758
1759 tp = (struct tocheader *)xb;
1760
1761 fillbytes((caddr_t)xb, sizeof (xb), '\0');
1762 if (read_toc(scgp, xb, 0, sizeof (struct tocheader), 0, FMT_CDTEXT) < 0) {
1763 if (scgp->silent == 0 || scgp->verbose > 0)
1764 errmsgno(EX_BAD, _("Cannot read CD-Text header\n"));
1765 return (-1);
1766 }
1767 len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
1768 printf(_("CD-Text len: %d\n"), len);
1769
1770 if (read_toc(scgp, xxb, 0, len, 0, FMT_CDTEXT) < 0) {
1771 if (scgp->silent == 0)
1772 errmsgno(EX_BAD, _("Cannot read CD-Text\n"));
1773 return (-1);
1774 }
1775 {
1776 FILE *f = fileopen("cdtext.dat", "wctb");
1777 filewrite(f, xxb, len);
1778 }
1779 return (0);
1780 }
1781
1782 EXPORT int
read_trackinfo(scgp,track,offp,msfp,adrp,controlp,modep)1783 read_trackinfo(scgp, track, offp, msfp, adrp, controlp, modep)
1784 SCSI *scgp;
1785 int track;
1786 long *offp;
1787 struct msf *msfp;
1788 int *adrp;
1789 int *controlp;
1790 int *modep;
1791 {
1792 struct diskinfo *dp;
1793 char xb[256];
1794 int len;
1795 long off;
1796
1797 dp = (struct diskinfo *)xb;
1798
1799 fillbytes((caddr_t)xb, sizeof (xb), '\0');
1800 if (read_toc(scgp, xb, track, sizeof (struct diskinfo), 0, FMT_TOC) < 0) {
1801 if (scgp->silent <= 0)
1802 errmsgno(EX_BAD, _("Cannot read TOC\n"));
1803 return (-1);
1804 }
1805 len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
1806 if (len < (int)sizeof (struct diskinfo))
1807 return (-1);
1808
1809 off = a_to_4_byte(dp->desc[0].addr);
1810 if (offp)
1811 *offp = off;
1812 if (adrp)
1813 *adrp = dp->desc[0].adr;
1814 if (controlp)
1815 *controlp = dp->desc[0].control;
1816
1817 if (msfp) {
1818 scgp->silent++;
1819 if (read_toc(scgp, xb, track, sizeof (struct diskinfo), 1, FMT_TOC)
1820 >= 0) {
1821 msfp->msf_min = dp->desc[0].addr[1];
1822 msfp->msf_sec = dp->desc[0].addr[2];
1823 msfp->msf_frame = dp->desc[0].addr[3];
1824 } else if (read_toc(scgp, xb, track, sizeof (struct diskinfo), 0, FMT_TOC)
1825 >= 0) {
1826 /*
1827 * Some drives (e.g. the Philips CDD-522) don't support
1828 * to read the TOC in MSF mode.
1829 */
1830 long moff = a_to_4_byte(dp->desc[0].addr);
1831
1832 lba_to_msf(moff, msfp);
1833 } else {
1834 msfp->msf_min = 0;
1835 msfp->msf_sec = 0;
1836 msfp->msf_frame = 0;
1837 }
1838 scgp->silent--;
1839 }
1840
1841 if (modep == NULL)
1842 return (0);
1843
1844 if (track == 0xAA) {
1845 *modep = -1;
1846 return (0);
1847 }
1848
1849 fillbytes((caddr_t)xb, sizeof (xb), '\0');
1850
1851 scgp->silent++;
1852 if (read_header(scgp, xb, off, 8, 0) >= 0) {
1853 *modep = xb[0];
1854 } else if (read_track_info_philips(scgp, xb, track, 14) >= 0) {
1855 *modep = xb[0xb] & 0xF;
1856 } else {
1857 *modep = -1;
1858 }
1859 scgp->silent--;
1860 return (0);
1861 }
1862
1863 EXPORT int
read_B0(scgp,isbcd,b0p,lop)1864 read_B0(scgp, isbcd, b0p, lop)
1865 SCSI *scgp;
1866 BOOL isbcd;
1867 long *b0p;
1868 long *lop;
1869 {
1870 struct fdiskinfo *dp;
1871 struct ftrackdesc *tp;
1872 char xb[8192];
1873 char *pe;
1874 int len;
1875 long l;
1876
1877 dp = (struct fdiskinfo *)xb;
1878
1879 fillbytes((caddr_t)xb, sizeof (xb), '\0');
1880 if (read_toc_philips(scgp, xb, 1, sizeof (struct tocheader), 0, FMT_FULLTOC) < 0) {
1881 return (-1);
1882 }
1883 len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
1884 if (len < (int)sizeof (struct fdiskinfo))
1885 return (-1);
1886 if (read_toc_philips(scgp, xb, 1, len, 0, FMT_FULLTOC) < 0) {
1887 return (-1);
1888 }
1889 if (scgp->verbose) {
1890 scg_prbytes(_("TOC data: "), (Uchar *)xb,
1891 len > (int)sizeof (xb) - scg_getresid(scgp) ?
1892 sizeof (xb) - scg_getresid(scgp) : len);
1893
1894 tp = &dp->desc[0];
1895 pe = &xb[len];
1896
1897 while ((char *)tp < pe) {
1898 scg_prbytes(_("ENT: "), (Uchar *)tp, 11);
1899 tp++;
1900 }
1901 }
1902 tp = &dp->desc[0];
1903 pe = &xb[len];
1904
1905 for (; (char *)tp < pe; tp++) {
1906 if (tp->sess_number != dp->hd.last)
1907 continue;
1908 if (tp->point != 0xB0)
1909 continue;
1910 if (scgp->verbose)
1911 scg_prbytes("B0: ", (Uchar *)tp, 11);
1912 if (isbcd) {
1913 l = msf_to_lba(from_bcd(tp->amin),
1914 from_bcd(tp->asec),
1915 from_bcd(tp->aframe), TRUE);
1916 } else {
1917 l = msf_to_lba(tp->amin,
1918 tp->asec,
1919 tp->aframe, TRUE);
1920 }
1921 if (b0p)
1922 *b0p = l;
1923
1924 if (scgp->verbose)
1925 printf(_("B0 start: %ld\n"), l);
1926
1927 if (isbcd) {
1928 l = msf_to_lba(from_bcd(tp->pmin),
1929 from_bcd(tp->psec),
1930 from_bcd(tp->pframe), TRUE);
1931 } else {
1932 l = msf_to_lba(tp->pmin,
1933 tp->psec,
1934 tp->pframe, TRUE);
1935 }
1936
1937 if (scgp->verbose)
1938 printf(("B0 lout: %ld\n"), l);
1939 if (lop)
1940 *lop = l;
1941 return (0);
1942 }
1943 return (-1);
1944 }
1945
1946
1947 /*
1948 * Return address of first track in last session (SCSI-3/mmc version).
1949 */
1950 EXPORT int
read_session_offset(scgp,offp)1951 read_session_offset(scgp, offp)
1952 SCSI *scgp;
1953 long *offp;
1954 {
1955 struct diskinfo *dp;
1956 char xb[256];
1957 int len;
1958
1959 dp = (struct diskinfo *)xb;
1960
1961 fillbytes((caddr_t)xb, sizeof (xb), '\0');
1962 if (read_toc(scgp, (caddr_t)xb, 0, sizeof (struct tocheader), 0, FMT_SINFO) < 0)
1963 return (-1);
1964
1965 if (scgp->verbose)
1966 scg_prbytes(_("tocheader: "),
1967 (Uchar *)xb, sizeof (struct tocheader) - scg_getresid(scgp));
1968
1969 len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
1970 if (len > (int)sizeof (xb)) {
1971 errmsgno(EX_BAD, _("Session info too big.\n"));
1972 return (-1);
1973 }
1974 if (read_toc(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
1975 return (-1);
1976
1977 if (scgp->verbose)
1978 scg_prbytes(_("tocheader: "),
1979 (Uchar *)xb, len - scg_getresid(scgp));
1980
1981 dp = (struct diskinfo *)xb;
1982 if (offp)
1983 *offp = a_to_u_4_byte(dp->desc[0].addr);
1984 return (0);
1985 }
1986
1987 /*
1988 * Return address of first track in last session (pre SCSI-3 version).
1989 */
1990 EXPORT int
read_session_offset_philips(scgp,offp)1991 read_session_offset_philips(scgp, offp)
1992 SCSI *scgp;
1993 long *offp;
1994 {
1995 struct sinfo *sp;
1996 char xb[256];
1997 int len;
1998
1999 sp = (struct sinfo *)xb;
2000
2001 fillbytes((caddr_t)xb, sizeof (xb), '\0');
2002 if (read_toc_philips(scgp, (caddr_t)xb, 0, sizeof (struct siheader), 0, FMT_SINFO) < 0)
2003 return (-1);
2004 len = a_to_u_2_byte(sp->hd.len) + sizeof (struct siheader)-2;
2005 if (len > (int)sizeof (xb)) {
2006 errmsgno(EX_BAD, _("Session info too big.\n"));
2007 return (-1);
2008 }
2009 if (read_toc_philips(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
2010 return (-1);
2011 /*
2012 * Old drives return the number of finished sessions in first/finished
2013 * a descriptor is returned for each session.
2014 * New drives return the number of the first and last session
2015 * one descriptor for the last finished session is returned
2016 * as in SCSI-3
2017 * In all cases the lowest session number is set to 1.
2018 */
2019 sp = (struct sinfo *)xb;
2020 if (offp)
2021 *offp = a_to_u_4_byte(sp->desc[sp->hd.finished-1].addr);
2022 return (0);
2023 }
2024
2025 EXPORT int
sense_secsize(scgp,current)2026 sense_secsize(scgp, current)
2027 SCSI *scgp;
2028 int current;
2029 {
2030 Uchar mode[0x100];
2031 Uchar *p;
2032 Uchar *ep;
2033 int len;
2034 int secsize = -1;
2035
2036 scgp->silent++;
2037 (void) unit_ready(scgp);
2038 scgp->silent--;
2039
2040 /* XXX Quick and dirty, musz verallgemeinert werden !!! */
2041
2042 fillbytes(mode, sizeof (mode), '\0');
2043 scgp->silent++;
2044
2045 len = sizeof (struct scsi_mode_header) +
2046 sizeof (struct scsi_mode_blockdesc);
2047 /*
2048 * Wenn wir hier get_mode_params() nehmen bekommen wir die Warnung:
2049 * Warning: controller returns wrong page 1 for All pages page (3F).
2050 */
2051 if (mode_sense(scgp, mode, len, 0x3F, current?0:2) < 0) {
2052 fillbytes(mode, sizeof (mode), '\0');
2053 if (mode_sense(scgp, mode, len, 0, current?0:2) < 0) { /* VU (block desc) */
2054 scgp->silent--;
2055 return (-1);
2056 }
2057 }
2058 if (mode[3] == 8) {
2059 if (scgp->debug) {
2060 printf(_("Density: 0x%X\n"), mode[4]);
2061 printf(_("Blocks: %ld\n"), a_to_u_3_byte(&mode[5]));
2062 printf(_("Blocklen:%ld\n"), a_to_u_3_byte(&mode[9]));
2063 }
2064 secsize = a_to_u_3_byte(&mode[9]);
2065 }
2066 fillbytes(mode, sizeof (mode), '\0');
2067 /*
2068 * The ACARD TECH AEC-7720 ATAPI<->SCSI adaptor
2069 * chokes if we try to transfer more than 0x40 bytes with
2070 * mode_sense of all pages. So try to avoid to run this
2071 * command if possible.
2072 */
2073 if (scgp->debug &&
2074 mode_sense(scgp, mode, 0xFE, 0x3F, current?0:2) >= 0) { /* All Pages */
2075
2076 ep = mode+mode[0]; /* Points to last byte of data */
2077 p = &mode[4];
2078 p += mode[3];
2079 printf(_("Pages: "));
2080 while (p < ep) {
2081 printf("0x%X ", *p&0x3F);
2082 p += p[1]+2;
2083 }
2084 printf("\n");
2085 }
2086 scgp->silent--;
2087
2088 return (secsize);
2089 }
2090
2091 EXPORT int
select_secsize(scgp,secsize)2092 select_secsize(scgp, secsize)
2093 SCSI *scgp;
2094 int secsize;
2095 {
2096 struct scsi_mode_data md;
2097 int count = sizeof (struct scsi_mode_header) +
2098 sizeof (struct scsi_mode_blockdesc);
2099
2100 (void) test_unit_ready(scgp); /* clear any error situation */
2101
2102 fillbytes((caddr_t)&md, sizeof (md), '\0');
2103 md.header.blockdesc_len = 8;
2104 i_to_3_byte(md.blockdesc.lblen, secsize);
2105
2106 return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
2107 }
2108
2109 EXPORT BOOL
is_cddrive(scgp)2110 is_cddrive(scgp)
2111 SCSI *scgp;
2112 {
2113 return (scgp->inq->type == INQ_ROMD || scgp->inq->type == INQ_WORM);
2114 }
2115
2116 EXPORT BOOL
is_unknown_dev(scgp)2117 is_unknown_dev(scgp)
2118 SCSI *scgp;
2119 {
2120 return (scgp->dev == DEV_UNKNOWN);
2121 }
2122
2123 #ifndef DEBUG
2124 #define DEBUG
2125 #endif
2126 #ifdef DEBUG
2127
2128 EXPORT int
read_scsi(scgp,bp,addr,cnt)2129 read_scsi(scgp, bp, addr, cnt)
2130 SCSI *scgp;
2131 caddr_t bp;
2132 long addr;
2133 int cnt;
2134 {
2135 if (addr <= G0_MAXADDR && cnt < 256 && !is_atapi)
2136 return (read_g0(scgp, bp, addr, cnt));
2137 else
2138 return (read_g1(scgp, bp, addr, cnt));
2139 }
2140
2141 EXPORT int
read_g0(scgp,bp,addr,cnt)2142 read_g0(scgp, bp, addr, cnt)
2143 SCSI *scgp;
2144 caddr_t bp;
2145 long addr;
2146 int cnt;
2147 {
2148 register struct scg_cmd *scmd = scgp->scmd;
2149
2150 if (scgp->cap->c_bsize <= 0)
2151 raisecond("capacity_not_set", 0L);
2152
2153 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2154 scmd->addr = bp;
2155 scmd->size = cnt*scgp->cap->c_bsize;
2156 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2157 scmd->cdb_len = SC_G0_CDBLEN;
2158 scmd->sense_len = CCS_SENSE_LEN;
2159 scmd->cdb.g0_cdb.cmd = SC_READ;
2160 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
2161 g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
2162 scmd->cdb.g0_cdb.count = cnt;
2163 /* scmd->cdb.g0_cdb.vu_56 = 1;*/
2164
2165 scgp->cmdname = "read_g0";
2166
2167 return (scg_cmd(scgp));
2168 }
2169
2170 EXPORT int
read_g1(scgp,bp,addr,cnt)2171 read_g1(scgp, bp, addr, cnt)
2172 SCSI *scgp;
2173 caddr_t bp;
2174 long addr;
2175 int cnt;
2176 {
2177 register struct scg_cmd *scmd = scgp->scmd;
2178
2179 if (scgp->cap->c_bsize <= 0)
2180 raisecond("capacity_not_set", 0L);
2181
2182 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2183 scmd->addr = bp;
2184 scmd->size = cnt*scgp->cap->c_bsize;
2185 scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2186 scmd->cdb_len = SC_G1_CDBLEN;
2187 scmd->sense_len = CCS_SENSE_LEN;
2188 scmd->cdb.g1_cdb.cmd = SC_EREAD;
2189 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
2190 g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
2191 g1_cdblen(&scmd->cdb.g1_cdb, cnt);
2192
2193 scgp->cmdname = "read_g1";
2194
2195 return (scg_cmd(scgp));
2196 }
2197 #endif /* DEBUG */
2198
2199 EXPORT BOOL
getdev(scgp,print)2200 getdev(scgp, print)
2201 SCSI *scgp;
2202 BOOL print;
2203 {
2204 BOOL got_inquiry = TRUE;
2205 char vendor_info[8+1];
2206 char prod_ident[16+1];
2207 char prod_revision[4+1];
2208 int inq_len = 0;
2209 register struct scg_cmd *scmd = scgp->scmd;
2210 register struct scsi_inquiry *inq = scgp->inq;
2211
2212
2213 fillbytes((caddr_t)inq, sizeof (*inq), '\0');
2214 scgp->dev = DEV_UNKNOWN;
2215 scgp->silent++;
2216 (void) unit_ready(scgp);
2217 if (scmd->error >= SCG_FATAL &&
2218 !(scmd->scb.chk && scmd->sense_count > 0)) {
2219 scgp->silent--;
2220 return (FALSE);
2221 }
2222
2223
2224 /* if (scmd->error < SCG_FATAL || scmd->scb.chk && scmd->sense_count > 0){*/
2225
2226 if (inquiry(scgp, (caddr_t)inq, sizeof (*inq)) < 0) {
2227 got_inquiry = FALSE;
2228 } else {
2229 inq_len = sizeof (*inq) - scg_getresid(scgp);
2230 }
2231 if (!got_inquiry) {
2232 if (scgp->verbose) {
2233 printf(
2234 _("error: %d scb.chk: %d sense_count: %d sense.code: 0x%x\n"),
2235 scmd->error, scmd->scb.chk,
2236 scmd->sense_count, scmd->sense.code);
2237 }
2238 /*
2239 * Folgende Kontroller kennen das Kommando
2240 * INQUIRY nicht:
2241 *
2242 * ADAPTEC ACB-4000, ACB-4010, ACB 4070
2243 * SYSGEN SC4000
2244 *
2245 * Leider reagieren ACB40X0 und ACB5500 identisch
2246 * wenn drive not ready (code == not ready),
2247 * sie sind dann nicht zu unterscheiden.
2248 */
2249
2250 if (scmd->scb.chk && scmd->sense_count == 4) {
2251 /* Test auf SYSGEN */
2252 (void) qic02(scgp, 0x12); /* soft lock on */
2253 if (qic02(scgp, 1) < 0) { /* soft lock off */
2254 scgp->dev = DEV_ACB40X0;
2255 /* scgp->dev = acbdev();*/
2256 } else {
2257 scgp->dev = DEV_SC4000;
2258 inq->type = INQ_SEQD;
2259 inq->removable = 1;
2260 }
2261 }
2262 } else if (scgp->verbose) {
2263 int i;
2264 int len = inq->add_len + 5;
2265 Uchar ibuf[256+5];
2266 Uchar *ip = (Uchar *)inq;
2267 Uchar c;
2268
2269 if (len > (int)sizeof (*inq) &&
2270 inquiry(scgp, (caddr_t)ibuf, inq->add_len+5) >= 0) {
2271 len = inq->add_len+5 - scg_getresid(scgp);
2272 ip = ibuf;
2273 } else {
2274 len = sizeof (*inq);
2275 }
2276 printf(_("Inquiry Data : "));
2277 for (i = 0; i < len; i++) {
2278 c = ip[i];
2279 if (c >= ' ' && c < 0177)
2280 printf("%c", c);
2281 else
2282 printf(".");
2283 }
2284 printf("\n");
2285 }
2286
2287 strncpy(vendor_info, inq->inq_vendor_info, sizeof (inq->inq_vendor_info));
2288 strncpy(prod_ident, inq->inq_prod_ident, sizeof (inq->inq_prod_ident));
2289 strncpy(prod_revision, inq->inq_prod_revision, sizeof (inq->inq_prod_revision));
2290
2291 vendor_info[sizeof (inq->inq_vendor_info)] = '\0';
2292 prod_ident[sizeof (inq->inq_prod_ident)] = '\0';
2293 prod_revision[sizeof (inq->inq_prod_revision)] = '\0';
2294
2295 switch (inq->type) {
2296
2297 case INQ_DASD:
2298 if (inq->add_len == 0 && inq->inq_vendor_info[0] != '\0') {
2299 Uchar *p;
2300 /*
2301 * NT-4.0 creates fake inquiry data for IDE disks.
2302 * Unfortunately, it does not set add_len wo we
2303 * check if vendor_info, prod_ident and prod_revision
2304 * contains valid chars for a CCS inquiry.
2305 */
2306 if (inq_len >= 36)
2307 inq->add_len = 31;
2308
2309 for (p = (Uchar *)&inq->inq_vendor_info[0];
2310 p < (Uchar *)&inq->inq_prod_revision[4];
2311 p++) {
2312 if (*p < 0x20 || *p > 0x7E) {
2313 inq->add_len = 0;
2314 break;
2315 }
2316 }
2317 }
2318 if (inq->add_len == 0) {
2319 if (scgp->dev == DEV_UNKNOWN && got_inquiry) {
2320 scgp->dev = DEV_ACB5500;
2321 strncpy(inq->inq_info_space,
2322 "ADAPTEC ACB-5500 FAKE",
2323 sizeof (inq->inq_info_space));
2324
2325 } else switch (scgp->dev) {
2326
2327 case DEV_ACB40X0:
2328 strncpy(inq->inq_info_space,
2329 "ADAPTEC ACB-40X0 FAKE",
2330 sizeof (inq->inq_info_space));
2331 break;
2332 case DEV_ACB4000:
2333 strncpy(inq->inq_info_space,
2334 "ADAPTEC ACB-4000 FAKE",
2335 sizeof (inq->inq_info_space));
2336 break;
2337 case DEV_ACB4010:
2338 strncpy(inq->inq_info_space,
2339 "ADAPTEC ACB-4010 FAKE",
2340 sizeof (inq->inq_info_space));
2341 break;
2342 case DEV_ACB4070:
2343 strncpy(inq->inq_info_space,
2344 "ADAPTEC ACB-4070 FAKE",
2345 sizeof (inq->inq_info_space));
2346 break;
2347 }
2348 } else if (inq->add_len < 31) {
2349 scgp->dev = DEV_NON_CCS_DSK;
2350
2351 } else if (strbeg("EMULEX", vendor_info)) {
2352 if (strbeg("MD21", prod_ident))
2353 scgp->dev = DEV_MD21;
2354 if (strbeg("MD23", prod_ident))
2355 scgp->dev = DEV_MD23;
2356 else
2357 scgp->dev = DEV_CCS_GENDISK;
2358 } else if (strbeg("ADAPTEC", vendor_info)) {
2359 if (strbeg("ACB-4520", prod_ident))
2360 scgp->dev = DEV_ACB4520A;
2361 if (strbeg("ACB-4525", prod_ident))
2362 scgp->dev = DEV_ACB4525;
2363 else
2364 scgp->dev = DEV_CCS_GENDISK;
2365 } else if (strbeg("SONY", vendor_info) &&
2366 strbeg("SMO-C501", prod_ident)) {
2367 scgp->dev = DEV_SONY_SMO;
2368 } else {
2369 scgp->dev = DEV_CCS_GENDISK;
2370 }
2371 break;
2372
2373 case INQ_SEQD:
2374 if (scgp->dev == DEV_SC4000) {
2375 strncpy(inq->inq_info_space,
2376 "SYSGEN SC4000 FAKE",
2377 sizeof (inq->inq_info_space));
2378 } else if (inq->add_len == 0 &&
2379 inq->removable &&
2380 inq->ansi_version == 1) {
2381 scgp->dev = DEV_MT02;
2382 strncpy(inq->inq_info_space,
2383 "EMULEX MT02 FAKE",
2384 sizeof (inq->inq_info_space));
2385 }
2386 break;
2387
2388 /* case INQ_OPTD:*/
2389 case INQ_ROMD:
2390 case INQ_WORM:
2391 if (strbeg("RXT-800S", prod_ident))
2392 scgp->dev = DEV_RXT800S;
2393
2394 /*
2395 * Start of CD-Recorders:
2396 */
2397 if (strbeg("ACER", vendor_info)) {
2398 if (strbeg("CR-4020C", prod_ident))
2399 scgp->dev = DEV_RICOH_RO_1420C;
2400
2401 } else if (strbeg("CREATIVE", vendor_info)) {
2402 if (strbeg("CDR2000", prod_ident))
2403 scgp->dev = DEV_RICOH_RO_1060C;
2404
2405 } else if (strbeg("GRUNDIG", vendor_info)) {
2406 if (strbeg("CDR100IPW", prod_ident))
2407 scgp->dev = DEV_CDD_2000;
2408
2409 } else if (strbeg("JVC", vendor_info)) {
2410 if (strbeg("XR-W2001", prod_ident))
2411 scgp->dev = DEV_TEAC_CD_R50S;
2412 else if (strbeg("XR-W2010", prod_ident))
2413 scgp->dev = DEV_TEAC_CD_R50S;
2414 else if (strbeg("R2626", prod_ident))
2415 scgp->dev = DEV_TEAC_CD_R50S;
2416
2417 } else if (strbeg("MITSBISH", vendor_info)) {
2418
2419 #ifdef XXXX_REALLY
2420 /* It's MMC compliant */
2421 if (strbeg("CDRW226", prod_ident))
2422 scgp->dev = DEV_MMC_CDRW;
2423 #else
2424 /* EMPTY */
2425 #endif
2426
2427 } else if (strbeg("MITSUMI", vendor_info)) {
2428 /* Don't know any product string */
2429 scgp->dev = DEV_CDD_522;
2430
2431 } else if (strbeg("OPTIMA", vendor_info)) {
2432 if (strbeg("CD-R 650", prod_ident))
2433 scgp->dev = DEV_SONY_CDU_924;
2434
2435 } else if (strbeg("PHILIPS", vendor_info) ||
2436 strbeg("IMS", vendor_info) ||
2437 strbeg("KODAK", vendor_info) ||
2438 strbeg("HP", vendor_info)) {
2439
2440 if (strbeg("CDD521/00", prod_ident))
2441 scgp->dev = DEV_CDD_521_OLD;
2442 else if (strbeg("CDD521/02", prod_ident))
2443 scgp->dev = DEV_CDD_521_OLD; /* PCD 200R? */
2444 else if (strbeg("CDD521", prod_ident))
2445 scgp->dev = DEV_CDD_521;
2446
2447 if (strbeg("CDD522", prod_ident))
2448 scgp->dev = DEV_CDD_522;
2449 if (strbeg("PCD225", prod_ident))
2450 scgp->dev = DEV_CDD_522;
2451 if (strbeg("KHSW/OB", prod_ident)) /* PCD600 */
2452 scgp->dev = DEV_PCD_600;
2453 if (strbeg("CDR-240", prod_ident))
2454 scgp->dev = DEV_CDD_2000;
2455
2456 if (strbeg("CDD20", prod_ident))
2457 scgp->dev = DEV_CDD_2000;
2458 if (strbeg("CDD26", prod_ident))
2459 scgp->dev = DEV_CDD_2600;
2460
2461 if (strbeg("C4324/C4325", prod_ident))
2462 scgp->dev = DEV_CDD_2000;
2463 if (strbeg("CD-Writer 6020", prod_ident))
2464 scgp->dev = DEV_CDD_2600;
2465
2466 } else if (strbeg("PINNACLE", vendor_info)) {
2467 if (strbeg("RCD-1000", prod_ident))
2468 scgp->dev = DEV_TEAC_CD_R50S;
2469 if (strbeg("RCD5020", prod_ident))
2470 scgp->dev = DEV_TEAC_CD_R50S;
2471 if (strbeg("RCD5040", prod_ident))
2472 scgp->dev = DEV_TEAC_CD_R50S;
2473 if (strbeg("RCD 4X4", prod_ident))
2474 scgp->dev = DEV_TEAC_CD_R50S;
2475
2476 } else if (strbeg("PIONEER", vendor_info)) {
2477 if (strbeg("CD-WO DW-S114X", prod_ident))
2478 scgp->dev = DEV_PIONEER_DW_S114X;
2479 else if (strbeg("CD-WO DR-R504X", prod_ident)) /* Reoprt from philip@merge.com */
2480 scgp->dev = DEV_PIONEER_DW_S114X;
2481 else if (strbeg("DVD-R DVR-S101", prod_ident))
2482 scgp->dev = DEV_PIONEER_DVDR_S101;
2483
2484 } else if (strbeg("PLASMON", vendor_info)) {
2485 if (strbeg("RF4100", prod_ident))
2486 scgp->dev = DEV_PLASMON_RF_4100;
2487 else if (strbeg("CDR4220", prod_ident))
2488 scgp->dev = DEV_CDD_2000;
2489
2490 } else if (strbeg("PLEXTOR", vendor_info)) {
2491 if (strbeg("CD-R PX-R24CS", prod_ident))
2492 scgp->dev = DEV_RICOH_RO_1420C;
2493
2494 } else if (strbeg("RICOH", vendor_info)) {
2495 if (strbeg("RO-1420C", prod_ident))
2496 scgp->dev = DEV_RICOH_RO_1420C;
2497 if (strbeg("RO1060C", prod_ident))
2498 scgp->dev = DEV_RICOH_RO_1060C;
2499
2500 } else if (strbeg("SAF", vendor_info)) { /* Smart & Friendly */
2501 if (strbeg("CD-R2004", prod_ident) ||
2502 strbeg("CD-R2006 ", prod_ident))
2503 scgp->dev = DEV_SONY_CDU_924;
2504 else if (strbeg("CD-R2006PLUS", prod_ident))
2505 scgp->dev = DEV_TEAC_CD_R50S;
2506 else if (strbeg("CD-RW226", prod_ident))
2507 scgp->dev = DEV_TEAC_CD_R50S;
2508 else if (strbeg("CD-R4012", prod_ident))
2509 scgp->dev = DEV_TEAC_CD_R50S;
2510
2511 } else if (strbeg("SANYO", vendor_info)) {
2512 if (strbeg("CD-WO CRD-R24S", prod_ident))
2513 scgp->dev = DEV_CDD_521;
2514
2515 } else if (strbeg("SONY", vendor_info)) {
2516 if (strbeg("CD-R CDU92", prod_ident) ||
2517 strbeg("CD-R CDU94", prod_ident))
2518 scgp->dev = DEV_SONY_CDU_924;
2519
2520 } else if (strbeg("TEAC", vendor_info)) {
2521 if (strbeg("CD-R50S", prod_ident) ||
2522 strbeg("CD-R55S", prod_ident))
2523 scgp->dev = DEV_TEAC_CD_R50S;
2524
2525 } else if (strbeg("TRAXDATA", vendor_info) ||
2526 strbeg("Traxdata", vendor_info)) {
2527 if (strbeg("CDR4120", prod_ident))
2528 scgp->dev = DEV_TEAC_CD_R50S;
2529
2530 } else if (strbeg("T.YUDEN", vendor_info)) {
2531 if (strbeg("CD-WO EW-50", prod_ident))
2532 scgp->dev = DEV_TYUDEN_EW50;
2533
2534 } else if (strbeg("WPI", vendor_info)) { /* Wearnes */
2535 if (strbeg("CDR-632P", prod_ident))
2536 scgp->dev = DEV_CDD_2600;
2537
2538 } else if (strbeg("YAMAHA", vendor_info)) {
2539 if (strbeg("CDR10", prod_ident))
2540 scgp->dev = DEV_YAMAHA_CDR_100;
2541 if (strbeg("CDR200", prod_ident))
2542 scgp->dev = DEV_YAMAHA_CDR_400;
2543 if (strbeg("CDR400", prod_ident))
2544 scgp->dev = DEV_YAMAHA_CDR_400;
2545
2546 } else if (strbeg("MATSHITA", vendor_info)) {
2547 if (strbeg("CD-R CW-7501", prod_ident))
2548 scgp->dev = DEV_MATSUSHITA_7501;
2549 if (strbeg("CD-R CW-7502", prod_ident))
2550 scgp->dev = DEV_MATSUSHITA_7502;
2551 }
2552 if (scgp->dev == DEV_UNKNOWN) {
2553 /*
2554 * We do not have Manufacturer strings for
2555 * the following drives.
2556 */
2557 if (strbeg("CDS615E", prod_ident)) /* Olympus */
2558 scgp->dev = DEV_SONY_CDU_924;
2559 }
2560 if (scgp->dev == DEV_UNKNOWN && inq->type == INQ_ROMD) {
2561 BOOL cdrr = FALSE;
2562 BOOL cdwr = FALSE;
2563 BOOL cdrrw = FALSE;
2564 BOOL cdwrw = FALSE;
2565 BOOL dvd = FALSE;
2566 BOOL dvdwr = FALSE;
2567
2568 scgp->dev = DEV_CDROM;
2569
2570 if (mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw,
2571 &dvd, &dvdwr))
2572 scgp->dev = DEV_MMC_CDROM;
2573 if (cdwr)
2574 scgp->dev = DEV_MMC_CDR;
2575 if (cdwrw)
2576 scgp->dev = DEV_MMC_CDRW;
2577 if (dvd)
2578 scgp->dev = DEV_MMC_DVD;
2579 if (dvdwr)
2580 scgp->dev = DEV_MMC_DVD_WR;
2581 }
2582 break;
2583
2584 case INQ_PROCD:
2585 if (strbeg("BERTHOLD", vendor_info)) {
2586 if (strbeg("", prod_ident))
2587 scgp->dev = DEV_HRSCAN;
2588 }
2589 break;
2590
2591 case INQ_SCAN:
2592 scgp->dev = DEV_MS300A;
2593 break;
2594 }
2595 scgp->silent--;
2596 if (!print)
2597 return (TRUE);
2598
2599 if (scgp->dev == DEV_UNKNOWN && !got_inquiry) {
2600 #ifdef PRINT_INQ_ERR
2601 scg_printerr(scgp);
2602 #endif
2603 return (FALSE);
2604 }
2605
2606 printinq(scgp, stdout);
2607 return (TRUE);
2608 }
2609
2610 EXPORT void
printinq(scgp,f)2611 printinq(scgp, f)
2612 SCSI *scgp;
2613 FILE *f;
2614 {
2615 register struct scsi_inquiry *inq = scgp->inq;
2616
2617 fprintf(f, _("Device type : "));
2618 scg_fprintdev(f, inq);
2619 fprintf(f, ("Version : %d\n"), inq->ansi_version);
2620 fprintf(f, _("Response Format: %d\n"), inq->data_format);
2621 if (inq->data_format >= 2) {
2622 fprintf(f, _("Capabilities : "));
2623 if (inq->aenc) fprintf(f, "AENC ");
2624 if (inq->termiop) fprintf(f, "TERMIOP ");
2625 if (inq->reladr) fprintf(f, "RELADR ");
2626 if (inq->wbus32) fprintf(f, "WBUS32 ");
2627 if (inq->wbus16) fprintf(f, "WBUS16 ");
2628 if (inq->sync) fprintf(f, "SYNC ");
2629 if (inq->linked) fprintf(f, "LINKED ");
2630 if (inq->cmdque) fprintf(f, "CMDQUE ");
2631 if (inq->softreset) fprintf(f, "SOFTRESET ");
2632 fprintf(f, "\n");
2633 }
2634 if (inq->add_len >= 31 ||
2635 inq->inq_vendor_info[0] ||
2636 inq->inq_prod_ident[0] ||
2637 inq->inq_prod_revision[0]) {
2638 fprintf(f, _("Vendor_info : '%.8s'\n"), inq->inq_vendor_info);
2639 fprintf(f, _("Identifikation : '%.16s'\n"), inq->inq_prod_ident);
2640 fprintf(f, _("Revision : '%.4s'\n"), inq->inq_prod_revision);
2641 }
2642 }
2643
2644 EXPORT void
printdev(scgp)2645 printdev(scgp)
2646 SCSI *scgp;
2647 {
2648 printf(_("Device seems to be: "));
2649
2650 switch (scgp->dev) {
2651
2652 case DEV_UNKNOWN: printf(_("unknown")); break;
2653 case DEV_ACB40X0: printf("Adaptec 4000/4010/4070"); break;
2654 case DEV_ACB4000: printf("Adaptec 4000"); break;
2655 case DEV_ACB4010: printf("Adaptec 4010"); break;
2656 case DEV_ACB4070: printf("Adaptec 4070"); break;
2657 case DEV_ACB5500: printf("Adaptec 5500"); break;
2658 case DEV_ACB4520A: printf("Adaptec 4520A"); break;
2659 case DEV_ACB4525: printf("Adaptec 4525"); break;
2660 case DEV_MD21: printf("Emulex MD21"); break;
2661 case DEV_MD23: printf("Emulex MD23"); break;
2662 case DEV_NON_CCS_DSK: printf("Generic NON CCS Disk"); break;
2663 case DEV_CCS_GENDISK: printf("Generic CCS Disk"); break;
2664 case DEV_SONY_SMO: printf("Sony SMO-C501"); break;
2665 case DEV_MT02: printf("Emulex MT02"); break;
2666 case DEV_SC4000: printf("Sysgen SC4000"); break;
2667 case DEV_RXT800S: printf("Maxtor RXT800S"); break;
2668 case DEV_HRSCAN: printf("Berthold HR-Scanner"); break;
2669 case DEV_MS300A: printf("Microtek MS300A"); break;
2670
2671 case DEV_CDROM: printf("Generic CD-ROM"); break;
2672 case DEV_MMC_CDROM: printf("Generic mmc CD-ROM"); break;
2673 case DEV_MMC_CDR: printf("Generic mmc CD-R"); break;
2674 case DEV_MMC_CDRW: printf("Generic mmc CD-RW"); break;
2675 case DEV_MMC_DVD: printf("Generic mmc2 DVD-ROM"); break;
2676 case DEV_MMC_DVD_WR: printf("Generic mmc2 DVD-R/DVD-RW/DVD-RAM"); break;
2677 case DEV_CDD_521_OLD: printf("Philips old CDD-521"); break;
2678 case DEV_CDD_521: printf("Philips CDD-521"); break;
2679 case DEV_CDD_522: printf("Philips CDD-522"); break;
2680 case DEV_PCD_600: printf("Kodak PCD-600"); break;
2681 case DEV_CDD_2000: printf("Philips CDD-2000"); break;
2682 case DEV_CDD_2600: printf("Philips CDD-2600"); break;
2683 case DEV_YAMAHA_CDR_100:printf("Yamaha CDR-100"); break;
2684 case DEV_YAMAHA_CDR_400:printf("Yamaha CDR-400"); break;
2685 case DEV_PLASMON_RF_4100:printf("Plasmon RF-4100"); break;
2686 case DEV_SONY_CDU_924: printf("Sony CDU-924S"); break;
2687 case DEV_RICOH_RO_1060C:printf("Ricoh RO-1060C"); break;
2688 case DEV_RICOH_RO_1420C:printf("Ricoh RO-1420C"); break;
2689 case DEV_TEAC_CD_R50S: printf("Teac CD-R50S"); break;
2690 case DEV_MATSUSHITA_7501:printf("Matsushita CW-7501"); break;
2691 case DEV_MATSUSHITA_7502:printf("Matsushita CW-7502"); break;
2692
2693 case DEV_PIONEER_DW_S114X: printf("Pioneer DW-S114X"); break;
2694 case DEV_PIONEER_DVDR_S101:printf("Pioneer DVD-R S101"); break;
2695
2696 default: printf(_("Missing Entry for dev %d"),
2697 scgp->dev); break;
2698
2699 }
2700 printf(".\n");
2701
2702 }
2703
2704 EXPORT BOOL
do_inquiry(scgp,print)2705 do_inquiry(scgp, print)
2706 SCSI *scgp;
2707 int print;
2708 {
2709 if (getdev(scgp, print)) {
2710 if (print)
2711 printdev(scgp);
2712 return (TRUE);
2713 } else {
2714 return (FALSE);
2715 }
2716 }
2717
2718 EXPORT BOOL
recovery_needed(scgp,dp)2719 recovery_needed(scgp, dp)
2720 SCSI *scgp;
2721 cdr_t *dp;
2722 {
2723 int err;
2724 register struct scg_cmd *scmd = scgp->scmd;
2725
2726 scgp->silent++;
2727 err = test_unit_ready(scgp);
2728 scgp->silent--;
2729
2730 if (err >= 0)
2731 return (FALSE);
2732 else if (scmd->error >= SCG_FATAL) /* nicht selektierbar */
2733 return (FALSE);
2734
2735 if (scmd->sense.code < 0x70) /* non extended Sense */
2736 return (FALSE);
2737
2738 /* XXX Old Philips code */
2739 return (((struct scsi_ext_sense *)&scmd->sense)->sense_code == 0xD0);
2740 }
2741
2742 EXPORT int
scsi_load(scgp,dp)2743 scsi_load(scgp, dp)
2744 SCSI *scgp;
2745 cdr_t *dp;
2746 {
2747 int key;
2748 int code;
2749
2750 if (dp && (dp->cdr_flags & CDR_CADDYLOAD) == 0) {
2751 if (scsi_start_stop_unit(scgp, 1, 1, dp->cdr_cmdflags&F_IMMED) >= 0)
2752 return (0);
2753 }
2754
2755 if (wait_unit_ready(scgp, 60))
2756 return (0);
2757
2758 key = scg_sense_key(scgp);
2759 code = scg_sense_code(scgp);
2760
2761 if (key == SC_NOT_READY && (code == 0x3A || code == 0x30)) {
2762 errmsgno(EX_BAD, _("Cannot load media with %s drive!\n"),
2763 dp && (dp->cdr_flags & CDR_CADDYLOAD) ? _("caddy") : _("this"));
2764 errmsgno(EX_BAD, _("Try to load media by hand.\n"));
2765 }
2766 return (-1);
2767 }
2768
2769 EXPORT int
scsi_unload(scgp,dp)2770 scsi_unload(scgp, dp)
2771 SCSI *scgp;
2772 cdr_t *dp;
2773 {
2774 return (scsi_start_stop_unit(scgp, 0, 1, dp && (dp->cdr_cmdflags&F_IMMED)));
2775 }
2776
2777 EXPORT int
scsi_cdr_write(scgp,bp,sectaddr,size,blocks,islast)2778 scsi_cdr_write(scgp, bp, sectaddr, size, blocks, islast)
2779 SCSI *scgp;
2780 caddr_t bp; /* address of buffer */
2781 long sectaddr; /* disk address (sector) to put */
2782 long size; /* number of bytes to transfer */
2783 int blocks; /* sector count */
2784 BOOL islast; /* last write for track */
2785 {
2786 return (write_xg1(scgp, bp, sectaddr, size, blocks));
2787 }
2788
2789 EXPORT struct cd_mode_page_2A *
mmc_cap(scgp,modep)2790 mmc_cap(scgp, modep)
2791 SCSI *scgp;
2792 Uchar *modep;
2793 {
2794 int len;
2795 int val;
2796 Uchar mode[0x100];
2797 struct cd_mode_page_2A *mp;
2798 struct cd_mode_page_2A *mp2;
2799
2800
2801 retry:
2802 fillbytes((caddr_t)mode, sizeof (mode), '\0');
2803
2804 if (!get_mode_params(scgp, 0x2A, _("CD capabilities"),
2805 mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
2806
2807 if (scg_sense_key(scgp) == SC_NOT_READY) {
2808 if (wait_unit_ready(scgp, 60))
2809 goto retry;
2810 }
2811 return (NULL); /* Pre SCSI-3/mmc drive */
2812 }
2813
2814 if (len == 0) /* Pre SCSI-3/mmc drive */
2815 return (NULL);
2816
2817 mp = (struct cd_mode_page_2A *)
2818 (mode + sizeof (struct scsi_mode_header) +
2819 ((struct scsi_mode_header *)mode)->blockdesc_len);
2820
2821 /*
2822 * Do some heuristics against pre SCSI-3/mmc VU page 2A
2823 * We should test for a minimum p_len of 0x14, but some
2824 * buggy CD-ROM readers ommit the write speed values.
2825 */
2826 if (mp->p_len < 0x10)
2827 return (NULL);
2828
2829 val = a_to_u_2_byte(mp->max_read_speed);
2830 if (val != 0 && val < 176)
2831 return (NULL);
2832
2833 val = a_to_u_2_byte(mp->cur_read_speed);
2834 if (val != 0 && val < 176)
2835 return (NULL);
2836
2837 len -= sizeof (struct scsi_mode_header) +
2838 ((struct scsi_mode_header *)mode)->blockdesc_len;
2839 if (modep)
2840 mp2 = (struct cd_mode_page_2A *)modep;
2841 else
2842 mp2 = malloc(len);
2843 if (mp2)
2844 movebytes(mp, mp2, len);
2845
2846 return (mp2);
2847 }
2848
2849 EXPORT void
mmc_getval(mp,cdrrp,cdwrp,cdrrwp,cdwrwp,dvdp,dvdwp)2850 mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp, dvdwp)
2851 struct cd_mode_page_2A *mp;
2852 BOOL *cdrrp; /* CD ROM */
2853 BOOL *cdwrp; /* CD-R writer */
2854 BOOL *cdrrwp; /* CD-RW reader */
2855 BOOL *cdwrwp; /* CD-RW writer */
2856 BOOL *dvdp; /* DVD reader */
2857 BOOL *dvdwp; /* DVD writer */
2858 {
2859 BOOL isdvd; /* Any DVD reader */
2860 BOOL isdvd_wr; /* DVD writer (R / RAM) */
2861 BOOL iscd_wr; /* CD writer */
2862
2863 iscd_wr = (mp->cd_r_write != 0) || /* SCSI-3/mmc CD-R */
2864 (mp->cd_rw_write != 0); /* SCSI-3/mmc CD-RW */
2865
2866 if (cdrrp)
2867 *cdrrp = (mp->cd_r_read != 0); /* SCSI-3/mmc CD */
2868 if (cdwrp)
2869 *cdwrp = (mp->cd_r_write != 0); /* SCSI-3/mmc CD-R */
2870
2871 if (cdrrwp)
2872 *cdrrwp = (mp->cd_rw_read != 0); /* SCSI-3/mmc CD */
2873 if (cdwrwp)
2874 *cdwrwp = (mp->cd_rw_write != 0); /* SCSI-3/mmc CD-RW */
2875
2876 isdvd = /* SCSI-3/mmc2 DVD */
2877 (mp->dvd_ram_read + mp->dvd_r_read +
2878 mp->dvd_rom_read) != 0;
2879
2880 isdvd_wr = /* SCSI-3/mmc2 DVD writer*/
2881 (mp->dvd_ram_write + mp->dvd_r_write) != 0;
2882
2883 if (dvdp)
2884 *dvdp = isdvd;
2885 if (dvdwp)
2886 *dvdwp = isdvd_wr;
2887 }
2888
2889 EXPORT BOOL
is_mmc(scgp,cdwp,dvdwp)2890 is_mmc(scgp, cdwp, dvdwp)
2891 SCSI *scgp;
2892 BOOL *cdwp; /* CD writer */
2893 BOOL *dvdwp; /* DVD writer */
2894 {
2895 BOOL cdwr = FALSE;
2896 BOOL cdwrw = FALSE;
2897
2898 if (cdwp)
2899 *cdwp = FALSE;
2900 if (dvdwp)
2901 *dvdwp = FALSE;
2902
2903 if (!mmc_check(scgp, NULL, &cdwr, NULL, &cdwrw, NULL, dvdwp))
2904 return (FALSE);
2905
2906 if (cdwp)
2907 *cdwp = cdwr | cdwrw;
2908
2909 return (TRUE);
2910 }
2911
2912 EXPORT BOOL
mmc_check(scgp,cdrrp,cdwrp,cdrrwp,cdwrwp,dvdp,dvdwp)2913 mmc_check(scgp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp, dvdwp)
2914 SCSI *scgp;
2915 BOOL *cdrrp; /* CD ROM */
2916 BOOL *cdwrp; /* CD-R writer */
2917 BOOL *cdrrwp; /* CD-RW reader */
2918 BOOL *cdwrwp; /* CD-RW writer */
2919 BOOL *dvdp; /* DVD reader */
2920 BOOL *dvdwp; /* DVD writer */
2921 {
2922 Uchar mode[0x100];
2923 BOOL was_atapi;
2924 struct cd_mode_page_2A *mp;
2925
2926 if (scgp->inq->type != INQ_ROMD)
2927 return (FALSE);
2928
2929 fillbytes((caddr_t)mode, sizeof (mode), '\0');
2930
2931 was_atapi = allow_atapi(scgp, TRUE);
2932 scgp->silent++;
2933 mp = mmc_cap(scgp, mode);
2934 scgp->silent--;
2935 allow_atapi(scgp, was_atapi);
2936 if (mp == NULL)
2937 return (FALSE);
2938
2939 mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp, dvdwp);
2940
2941 return (TRUE); /* Generic SCSI-3/mmc CD */
2942 }
2943
2944 LOCAL void
print_speed(fmt,val)2945 print_speed(fmt, val)
2946 char *fmt;
2947 int val;
2948 {
2949 printf(" %s: %5d kB/s", fmt, val);
2950 printf(" (CD %3ux,", val/176);
2951 printf(" DVD %2ux,", val/1385);
2952 printf(" BD %2ux)\n", val/4495);
2953 }
2954
2955 #define DOES(what, flag) printf(_(" Does %s%s\n"), flag?"":_("not "), what)
2956 #define IS(what, flag) printf(_(" Is %s%s\n"), flag?"":_("not "), what)
2957 #define VAL(what, val) printf(_(" %s: %d\n"), what, val[0]*256 + val[1])
2958 #define SVAL(what, val) printf(_(" %s: %s\n"), what, val)
2959
2960 EXPORT void
print_capabilities(scgp)2961 print_capabilities(scgp)
2962 SCSI *scgp;
2963 {
2964 BOOL was_atapi;
2965 Uchar mode[0x100];
2966 struct cd_mode_page_2A *mp;
2967 static const char *bclk[4] = {"32", "16", "24", "24 (I2S)"};
2968 static const char *load[8] = {"caddy", "tray", "pop-up", "reserved(3)",
2969 "disc changer", "cartridge changer",
2970 "reserved(6)", "reserved(7)" };
2971 static const char *rotctl[4] = {"CLV/PCAV", "CAV", "reserved(2)", "reserved(3)"};
2972
2973
2974 if (scgp->inq->type != INQ_ROMD)
2975 return;
2976
2977 fillbytes((caddr_t)mode, sizeof (mode), '\0');
2978
2979 was_atapi = allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
2980 scgp->silent++;
2981 mp = mmc_cap(scgp, mode);
2982 scgp->silent--;
2983 allow_atapi(scgp, was_atapi);
2984 if (mp == NULL)
2985 return;
2986
2987 printf(_("\nDrive capabilities, per"));
2988 if (mp->p_len >= 28)
2989 printf(" MMC-3");
2990 else if (mp->p_len >= 24)
2991 printf(" MMC-2");
2992 else
2993 printf(" MMC");
2994 printf(_(" page 2A:\n\n"));
2995
2996 DOES(_("read CD-R media"), mp->cd_r_read);
2997 DOES(_("write CD-R media"), mp->cd_r_write);
2998 DOES(_("read CD-RW media"), mp->cd_rw_read);
2999 DOES(_("write CD-RW media"), mp->cd_rw_write);
3000 DOES(_("read DVD-ROM media"), mp->dvd_rom_read);
3001 DOES(_("read DVD-R media"), mp->dvd_r_read);
3002 DOES(_("write DVD-R media"), mp->dvd_r_write);
3003 DOES(_("read DVD-RAM media"), mp->dvd_ram_read);
3004 DOES(_("write DVD-RAM media"), mp->dvd_ram_write);
3005 DOES(_("support test writing"), mp->test_write);
3006 printf("\n");
3007 DOES(_("read Mode 2 Form 1 blocks"), mp->mode_2_form_1);
3008 DOES(_("read Mode 2 Form 2 blocks"), mp->mode_2_form_2);
3009 DOES(_("read digital audio blocks"), mp->cd_da_supported);
3010 if (mp->cd_da_supported)
3011 DOES(_("restart non-streamed digital audio reads accurately"), mp->cd_da_accurate);
3012 DOES(_("support Buffer-Underrun-Free recording"), mp->BUF);
3013 DOES(_("read multi-session CDs"), mp->multi_session);
3014 DOES(_("read fixed-packet CD media using Method 2"), mp->method2);
3015 DOES(_("read CD bar code"), mp->read_bar_code);
3016 DOES(_("read R-W subcode information"), mp->rw_supported);
3017 if (mp->rw_supported)
3018 DOES(_("return R-W subcode de-interleaved and error-corrected"), mp->rw_deint_corr);
3019 DOES(_("read raw P-W subcode data from lead in"), mp->pw_in_lead_in);
3020 DOES(_("return CD media catalog number"), mp->UPC);
3021 DOES(_("return CD ISRC information"), mp->ISRC);
3022 DOES(_("support C2 error pointers"), mp->c2_pointers);
3023 DOES(_("deliver composite A/V data"), mp->composite);
3024 printf("\n");
3025 DOES(_("play audio CDs"), mp->audio_play);
3026 if (mp->audio_play) {
3027 VAL(_("Number of volume control levels"), mp->num_vol_levels);
3028 DOES(_("support individual volume control setting for each channel"), mp->sep_chan_vol);
3029 DOES(_("support independent mute setting for each channel"), mp->sep_chan_mute);
3030 DOES(_("support digital output on port 1"), mp->digital_port_1);
3031 DOES(_("support digital output on port 2"), mp->digital_port_2);
3032 if (mp->digital_port_1 || mp->digital_port_2) {
3033 DOES(_("send digital data LSB-first"), mp->LSBF);
3034 DOES(_("set LRCK high for left-channel data"), mp->RCK);
3035 DOES(_("have valid data on falling edge of clock"), mp->BCK);
3036 SVAL(_("Length of data in BCLKs"), bclk[mp->length]);
3037 }
3038 }
3039 printf("\n");
3040 SVAL(_("Loading mechanism type"), load[mp->loading_type]);
3041 DOES(_("support ejection of CD via START/STOP command"), mp->eject);
3042 DOES(_("lock media on power up via prevent jumper"), mp->prevent_jumper);
3043 DOES(_("allow media to be locked in the drive via PREVENT/ALLOW command"), mp->lock);
3044 IS(_("currently in a media-locked state"), mp->lock_state);
3045 DOES(_("support changing side of disk"), mp->side_change);
3046 DOES(_("have load-empty-slot-in-changer feature"), mp->sw_slot_sel);
3047 DOES(_("support Individual Disk Present feature"), mp->disk_present_rep);
3048 printf("\n");
3049 print_speed(_("Maximum read speed"), a_to_u_2_byte(mp->max_read_speed));
3050 print_speed(_("Current read speed"), a_to_u_2_byte(mp->cur_read_speed));
3051 print_speed(_("Maximum write speed"), a_to_u_2_byte(mp->max_write_speed));
3052 if (mp->p_len >= 28)
3053 print_speed(_("Current write speed"), a_to_u_2_byte(mp->v3_cur_write_speed));
3054 else
3055 print_speed(_("Current write speed"), a_to_u_2_byte(mp->cur_write_speed));
3056 if (mp->p_len >= 28) {
3057 SVAL(_("Rotational control selected"), rotctl[mp->rot_ctl_sel]);
3058 }
3059 VAL(_("Buffer size in KB"), mp->buffer_size);
3060
3061 if (mp->p_len >= 24) {
3062 VAL(_("Copy management revision supported"), mp->copy_man_rev);
3063 }
3064
3065 if (mp->p_len >= 28) {
3066 struct cd_wr_speed_performance *pp;
3067 Uint ndesc;
3068 Uint i;
3069 Uint n;
3070
3071 ndesc = a_to_u_2_byte(mp->num_wr_speed_des);
3072 pp = mp->wr_speed_des;
3073 printf(_(" Number of supported write speeds: %d\n"), ndesc);
3074 for (i = 0; i < ndesc; i++, pp++) {
3075 printf(_(" Write speed # %d:"), i);
3076 n = a_to_u_2_byte(pp->wr_speed_supp);
3077 printf(" %5d kB/s", n);
3078 printf(" %s", rotctl[pp->rot_ctl_sel]);
3079 printf(" (CD %3ux,", n/176);
3080 printf(" DVD %2ux,", n/1385);
3081 printf(" BD %2ux)\n", n/4495);
3082 }
3083 }
3084
3085 /* Generic SCSI-3/mmc CD */
3086 }
3087
3088 EXPORT int
verify(scgp,start,count,bad_block)3089 verify(scgp, start, count, bad_block)
3090 SCSI *scgp;
3091 long start;
3092 int count;
3093 long *bad_block;
3094 {
3095 register struct scg_cmd *scmd = scgp->scmd;
3096
3097 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
3098 scmd->addr = (caddr_t)0;
3099 scmd->size = 0;
3100 scmd->flags = SCG_DISRE_ENA;
3101 scmd->cdb_len = SC_G1_CDBLEN;
3102 scmd->sense_len = CCS_SENSE_LEN;
3103 scmd->cdb.g1_cdb.cmd = 0x2F; /* Verify */
3104 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
3105 g1_cdbaddr(&scmd->cdb.g1_cdb, start);
3106 g1_cdblen(&scmd->cdb.g1_cdb, count);
3107
3108 scgp->cmdname = "verify";
3109
3110 if (scg_cmd(scgp) < 0) {
3111 if (scmd->sense.code >= 0x70) { /* extended Sense */
3112 *bad_block =
3113 a_to_4_byte(&((struct scsi_ext_sense *)
3114 &scmd->sense)->info_1);
3115 } else {
3116 *bad_block = a_to_u_3_byte(&scmd->sense.high_addr);
3117 }
3118 return (-1);
3119 }
3120 return (0);
3121 }
3122