Contents of /trunk/cdparanoia/patches/cdparanoia-3.9.8-sgio.patch
Parent Directory | Revision Log
Revision 144 -
(show annotations)
(download)
Tue May 8 20:06:05 2007 UTC (17 years, 4 months ago) by niro
File size: 57470 byte(s)
Tue May 8 20:06:05 2007 UTC (17 years, 4 months ago) by niro
File size: 57470 byte(s)
-import
1 | diff --exclude CVS -u -N -r cdparanoia-III-alpha9.8/interface/cdda_interface.h paranoia-III/interface/cdda_interface.h |
2 | --- cdparanoia-III-alpha9.8/interface/cdda_interface.h 2004-02-21 13:16:47.000000000 -0500 |
3 | +++ cdparanoia-III-alpha9.8/interface/cdda_interface.h 2004-02-25 21:42:15.000000000 -0500 |
4 | @@ -99,10 +99,46 @@ |
5 | |
6 | } cdrom_drive; |
7 | |
8 | +/* buffers for use with the scsi code. d->sg_buffer is unused, |
9 | + and d->sg points to this struct. We can't really change struct |
10 | + cdrom_drive without breaking binary compatibility, so we do this |
11 | + instead. */ |
12 | +struct sg_info { |
13 | +#ifdef SG_IO |
14 | + struct sg_io_hdr *hdr; |
15 | +#else |
16 | + struct sg_header *hdr; |
17 | +#endif |
18 | + |
19 | + char *cmdp; |
20 | + ssize_t cmd_len; |
21 | + ssize_t cmdp_buffer_len; |
22 | + |
23 | + char *dxferp; |
24 | + ssize_t dxferp_buffer_len; |
25 | + ssize_t dxferp_max_buffer_len; |
26 | + |
27 | + unsigned char bytefill; |
28 | + int bytecheck; |
29 | + |
30 | + int in_size; |
31 | + int out_size; |
32 | + |
33 | + int (*handle_scsi_cmd)(struct cdrom_drive *d); |
34 | + void (*setup_scsi_cmd)(struct cdrom_drive *d, |
35 | + char *cmdp, unsigned int cmd_len, |
36 | + unsigned int in_size, unsigned int out_size); |
37 | +}; |
38 | + |
39 | + |
40 | #define IS_AUDIO(d,i) (!(d->disc_toc[i].bFlags & 0x04)) |
41 | |
42 | /******** Identification/autosense functions */ |
43 | |
44 | +#ifdef SG_IO |
45 | +extern int check_fd_sgio(int fd); |
46 | +#endif |
47 | + |
48 | extern cdrom_drive *cdda_find_a_cdrom(int messagedest, char **message); |
49 | extern cdrom_drive *cdda_identify(const char *device, int messagedest, |
50 | char **message); |
51 | diff --exclude CVS -u -N -r cdparanoia-III-alpha9.8/interface/interface.c paranoia-III/interface/interface.c |
52 | --- cdparanoia-III-alpha9.8/interface/interface.c 2004-02-21 13:16:49.000000000 -0500 |
53 | +++ cdparanoia-III-alpha9.8/interface/interface.c 2004-02-25 11:17:37.000000000 -0500 |
54 | @@ -30,7 +30,7 @@ |
55 | |
56 | _clean_messages(d); |
57 | if(d->cdda_device_name)free(d->cdda_device_name); |
58 | - if(d->ioctl_device_name)free(d->ioctl_device_name); |
59 | + if(d->ioctl_device_name && d->ioctl_device_name!=d->cdda_device_name)free(d->ioctl_device_name); |
60 | if(d->drive_model)free(d->drive_model); |
61 | if(d->cdda_fd!=-1)close(d->cdda_fd); |
62 | if(d->ioctl_fd!=-1 && d->ioctl_fd!=d->cdda_fd)close(d->ioctl_fd); |
63 | diff --exclude CVS -u -N -r cdparanoia-III-alpha9.8/interface/scan_devices.c paranoia-III/interface/scan_devices.c |
64 | --- cdparanoia-III-alpha9.8/interface/scan_devices.c 2004-02-21 13:16:51.000000000 -0500 |
65 | +++ cdparanoia-III-alpha9.8/interface/scan_devices.c 2004-02-26 19:26:15.000000000 -0500 |
66 | @@ -14,8 +14,8 @@ |
67 | #include <pwd.h> |
68 | #include <sys/stat.h> |
69 | #include <sys/types.h> |
70 | -#include "cdda_interface.h" |
71 | #include "low_interface.h" |
72 | +#include "cdda_interface.h" |
73 | #include "common_interface.h" |
74 | #include "utils.h" |
75 | |
76 | @@ -50,6 +50,8 @@ |
77 | "/dev/gscd", |
78 | "/dev/optcd",NULL}; |
79 | |
80 | +extern void sg2_init_sg_info(cdrom_drive *d); |
81 | +extern void sgio_init_sg_info(cdrom_drive *d); |
82 | /* Functions here look for a cdrom drive; full init of a drive type |
83 | happens in interface.c */ |
84 | |
85 | @@ -117,8 +119,13 @@ |
86 | } |
87 | #endif |
88 | |
89 | - d=cdda_identify_cooked(device,messagedest,messages); |
90 | +#ifdef SG_IO |
91 | + d=cdda_identify_scsi(device,NULL,messagedest,messages); |
92 | + if(!d)d=cdda_identify_cooked(device,messagedest,messages); |
93 | +#else |
94 | if(!d)d=cdda_identify_scsi(device,NULL,messagedest,messages); |
95 | + d=cdda_identify_cooked(device,messagedest,messages); |
96 | +#endif |
97 | |
98 | #ifdef CDDA_TEST |
99 | if(!d)d=cdda_identify_test(device,messagedest,messages); |
100 | @@ -412,17 +419,19 @@ |
101 | "\nFound an accessible SCSI CDROM drive." |
102 | "\nLooking at revision of the SG interface in use...",""); |
103 | |
104 | - if(ioctl(d->cdda_fd,SG_GET_VERSION_NUM,&version)){ |
105 | + if((version = ioctl(d->cdda_fd,SG_GET_VERSION_NUM,&major)) < 0){ |
106 | /* Up, guess not. */ |
107 | idmessage(messagedest,messages, |
108 | "\tOOPS! Old 2.0/early 2.1/early 2.2.x (non-ac patch) style " |
109 | "SG.\n\tCdparanoia no longer supports the old interface.\n",""); |
110 | return(0); |
111 | } |
112 | - major=version/10000; |
113 | - version-=major*10000; |
114 | - minor=version/100; |
115 | - version-=minor*100; |
116 | + if (!version) |
117 | + version = major; |
118 | + |
119 | + major = (version >> 16) & 0xff; |
120 | + minor = (version >> 8) & 0xff; |
121 | + version &= 0xff; |
122 | |
123 | sprintf(buffer,"\tSG interface version %d.%d.%d; OK.", |
124 | major,minor,version); |
125 | @@ -431,6 +440,138 @@ |
126 | return(major); |
127 | } |
128 | |
129 | +#ifdef SG_IO |
130 | +int get_sgio_fd(const char *device, int messagedest, char **messages) { |
131 | + int fd; |
132 | + |
133 | + if (!device) |
134 | + return -errno; |
135 | + /* we don't really care what type of device it is -- if it can do |
136 | + * SG_IO, then we'll put it through the normal mmc/atapi/etc tests |
137 | + * later, but it's good enough for now. */ |
138 | + fd = open(device, O_RDWR|O_EXCL|O_NONBLOCK); |
139 | + if (fd < 0) |
140 | + return -errno; |
141 | + return check_fd_sgio(fd); |
142 | +} |
143 | + |
144 | +/* removing generic_device breaks ABI; instead, just test both devices */ |
145 | +static cdrom_drive *sgio_cdda_identify_scsi(const char *generic_device, |
146 | + const char *ioctl_device, int messagedest, |
147 | + char **messages){ |
148 | + cdrom_drive *d = NULL; |
149 | + char *device = NULL; |
150 | + int fd = -1, g_fd = -1; |
151 | + char *p; |
152 | + |
153 | + /* with SG_IO in 2.6, we much prefer /dev/hdc and /dev/scd0, so |
154 | + * test ioctl_device before testing generic_device */ |
155 | + |
156 | + /* we need to resolve any symlinks for the lookup code to work */ |
157 | + if (ioctl_device) |
158 | + device = test_resolve_symlink(ioctl_device, messagedest, messages); |
159 | + /* test again, in case symlink resolution failed */ |
160 | + if (device) { |
161 | + fd = get_sgio_fd(ioctl_device, messagedest, messages); |
162 | + if (fd < 0) { |
163 | + /* ioctl_device didn't work, so we don't need to keep the strdup of its |
164 | + * real path around */ |
165 | + free(device); |
166 | + device = NULL; |
167 | + } |
168 | + } |
169 | + if (fd < 0) { |
170 | + if (!generic_device) |
171 | + goto cdda_identify_scsi_fail_free; |
172 | + device = test_resolve_symlink(generic_device, messagedest, messages); |
173 | + /* test again, in case symlink resolution failed */ |
174 | + if (!device) |
175 | + goto cdda_identify_scsi_fail_return; |
176 | + g_fd = get_sgio_fd(device, messagedest, messages); |
177 | + if (g_fd < 0) |
178 | + goto cdda_identify_scsi_fail_free; |
179 | + fd = g_fd; |
180 | + } |
181 | + |
182 | + d=calloc(1,sizeof(cdrom_drive)); |
183 | + |
184 | + d->drive_type=SCSI_CDROM_MAJOR; |
185 | + d->cdda_fd=fd; |
186 | + d->ioctl_fd=fd; |
187 | + d->bigendianp=-1; /* We don't know yet... */ |
188 | + d->nsectors=-1; |
189 | + |
190 | + d->interface=GENERIC_SCSI; |
191 | + |
192 | + /* alloc our big buffer for scsi commands */ |
193 | + d->sg=calloc(1, sizeof (struct sg_info)); |
194 | + ((struct sg_info *)d->sg)->dxferp_max_buffer_len = CD_FRAMESIZE_RAW; |
195 | + if (check_fd_sgio(d->cdda_fd)) |
196 | + sgio_init_sg_info(d); |
197 | + else |
198 | + sg2_init_sg_info(d); |
199 | + |
200 | + /* get the lun -- this used to set 0 on failure, maybe still should */ |
201 | + d->lun = -1; |
202 | + |
203 | + p = scsi_inquiry(d); |
204 | + if (!p) |
205 | + goto cdda_identify_scsi_fail_free_device; |
206 | + |
207 | + /* It would seem some TOSHIBA CDROMs gets things wrong */ |
208 | + |
209 | + if (!strncmp (p + 8, "TOSHIBA", 7) && |
210 | + !strncmp (p + 16, "CD-ROM", 6) && |
211 | + p[0] == TYPE_DISK) { |
212 | + p[0] = TYPE_ROM; |
213 | + p[1] |= 0x80; /* removable */ |
214 | + } |
215 | + |
216 | + if (!p || (*p != TYPE_ROM && *p != TYPE_WORM)) { |
217 | + idmessage(messagedest, messages, |
218 | + "\t\tDrive is neither a CDROM nor a WORM device\n", NULL); |
219 | + goto cdda_identify_scsi_fail_free_device; |
220 | + } |
221 | + |
222 | + memcpy(d->inqbytes, p, 4); |
223 | + d->cdda_device_name = device; |
224 | + d->ioctl_device_name = device; |
225 | + |
226 | + d->drive_model = calloc(1, 36); |
227 | + strscat(d->drive_model, p+8, 8); |
228 | + strscat(d->drive_model, p+16, 16); |
229 | + strscat(d->drive_model, p+32, 4); |
230 | + |
231 | + idmessage(messagedest, messages, "\nCDROM model sensed sensed: %s", d->drive_model); |
232 | + |
233 | + return d; |
234 | + |
235 | +cdda_identify_scsi_fail_free_device: |
236 | + if (d) { |
237 | + if (d->drive_model) |
238 | + free(d->drive_model); |
239 | + if (d->sg) { |
240 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
241 | + |
242 | + if (sgi->cmdp_buffer_len) |
243 | + free(sgi->cmdp); |
244 | + if (sgi->dxferp_buffer_len) |
245 | + free(sgi->dxferp); |
246 | + if (sgi->hdr) |
247 | + free(sgi->hdr); |
248 | + free(d->sg); |
249 | + } |
250 | + free(d); |
251 | + } |
252 | + if (fd >= 0) |
253 | + close(fd); |
254 | +cdda_identify_scsi_fail_free: |
255 | + if (device) |
256 | + free(device); |
257 | +cdda_identify_scsi_fail_return: |
258 | + return NULL; |
259 | +} |
260 | +#endif |
261 | cdrom_drive *cdda_identify_scsi(const char *generic_device, |
262 | const char *ioctl_device, int messagedest, |
263 | char **messages){ |
264 | @@ -444,6 +585,12 @@ |
265 | int type; |
266 | char *p; |
267 | |
268 | +#ifdef SG_IO |
269 | + d = sgio_cdda_identify_scsi(generic_device, ioctl_device, messagedest, messages); |
270 | + if (d) |
271 | + return d; |
272 | +#endif |
273 | + |
274 | if(generic_device) |
275 | idmessage(messagedest,messages,"\tTesting %s for SCSI interface", |
276 | generic_device); |
277 | @@ -580,7 +727,6 @@ |
278 | "major number",generic_device); |
279 | goto cdda_identify_scsi_fail; |
280 | } |
281 | - |
282 | |
283 | d=calloc(1,sizeof(cdrom_drive)); |
284 | |
285 | @@ -601,8 +747,9 @@ |
286 | } |
287 | |
288 | /* malloc our big buffer for scsi commands */ |
289 | - d->sg=malloc(MAX_BIG_BUFF_SIZE); |
290 | - d->sg_buffer=d->sg+SG_OFF; |
291 | + d->sg=calloc(1, sizeof (struct sg_info)); |
292 | + ((struct sg_info *)d->sg)->dxferp_max_buffer_len = CD_FRAMESIZE_RAW; |
293 | + sg2_init_sg_info(d); |
294 | |
295 | { |
296 | /* get the lun */ |
297 | @@ -614,6 +761,8 @@ |
298 | } |
299 | |
300 | p = scsi_inquiry(d); |
301 | + if (!p) |
302 | + goto cdda_identify_scsi_fail; |
303 | |
304 | /* It would seem some TOSHIBA CDROMs gets things wrong */ |
305 | |
306 | @@ -632,12 +781,11 @@ |
307 | goto cdda_identify_scsi_fail; |
308 | } |
309 | |
310 | - d->drive_model=calloc(36,1); |
311 | memcpy(d->inqbytes,p,4); |
312 | d->cdda_device_name=copystring(generic_device); |
313 | d->ioctl_device_name=copystring(ioctl_device); |
314 | |
315 | - d->drive_model=calloc(36,1); |
316 | + d->drive_model=calloc(1, 36); |
317 | strscat(d->drive_model,p+8,8); |
318 | strscat(d->drive_model,p+16,16); |
319 | strscat(d->drive_model,p+32,4); |
320 | @@ -647,6 +795,22 @@ |
321 | return(d); |
322 | |
323 | cdda_identify_scsi_fail: |
324 | + if (d) { |
325 | + if (d->drive_model) |
326 | + free(d->drive_model); |
327 | + if (d->sg) { |
328 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
329 | + |
330 | + if (sgi->cmdp_buffer_len) |
331 | + free(sgi->cmdp); |
332 | + if (sgi->dxferp_buffer_len) |
333 | + free(sgi->dxferp); |
334 | + if (sgi->hdr) |
335 | + free(sgi->hdr); |
336 | + free(d->sg); |
337 | + } |
338 | + free(d); |
339 | + } |
340 | if(generic_device)free((char *)generic_device); |
341 | if(ioctl_device)free((char *)ioctl_device); |
342 | if(i_fd!=-1)close(i_fd); |
343 | --- cdparanoia-III-alpha9.8/interface/scsi_interface.c.sgio 2001-03-23 20:15:46.000000000 -0500 |
344 | +++ cdparanoia-III-alpha9.8/interface/scsi_interface.c 2004-03-30 14:19:29.826011776 -0500 |
345 | @@ -3,6 +3,7 @@ |
346 | * Original interface.c Copyright (C) 1994-1997 |
347 | * Eissfeldt heiko@colossus.escape.de |
348 | * Current blenderization Copyright (C) 1998-1999 Monty xiphmont@mit.edu |
349 | + * Copyright 2004 Peter Jones <pjones@redhat.com> |
350 | * |
351 | * Generic SCSI interface specific code. |
352 | * |
353 | @@ -11,6 +12,7 @@ |
354 | #include "low_interface.h" |
355 | #include "common_interface.h" |
356 | #include "utils.h" |
357 | +#include "scsi_cmds.h" |
358 | |
359 | /* hook */ |
360 | static int Dummy (cdrom_drive *d,int s){ |
361 | @@ -19,7 +21,290 @@ |
362 | |
363 | #include "drive_exceptions.h" |
364 | |
365 | -static void tweak_SG_buffer(cdrom_drive *d){ |
366 | +static void reset_scsi(cdrom_drive *d){ |
367 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
368 | + struct sg_io_hdr *hdr = sgi->hdr; |
369 | + unsigned char key, ASC, ASCQ; |
370 | + int arg, ret, tries; |
371 | + char cmd[6]; |
372 | + |
373 | + d->enable_cdda(d,0); |
374 | + |
375 | + cdmessage(d,"sending SG SCSI reset... "); |
376 | + if(ioctl(d->cdda_fd,SG_SCSI_RESET,&arg)) |
377 | + cdmessage(d,"FAILED: EBUSY\n"); |
378 | + else |
379 | + cdmessage(d,"OK\n"); |
380 | + |
381 | + tries = 0; |
382 | + while(1) { |
383 | + memcpy(cmd, SCSI_TEST_UNIT_READY_6, 6); |
384 | + sgi->setup_scsi_cmd(d, cmd, 6, 0, 56); |
385 | + ret = sgi->handle_scsi_cmd(d); |
386 | + |
387 | + key = hdr->sbp[2] & 0xf; |
388 | + ASC = hdr->sbp[12]; |
389 | + ASCQ = hdr->sbp[13]; |
390 | + |
391 | + if(key == 2 & ASC == 4 & ASCQ == 1 & tries < 10) { |
392 | + tries++; |
393 | + usleep(10); |
394 | + continue; |
395 | + } |
396 | + break; |
397 | + } |
398 | + |
399 | + d->enable_cdda(d,1); |
400 | +} |
401 | + |
402 | +static int check_sbp_error(const char *sbp) { |
403 | + char key = sbp[2] & 0xf; |
404 | + char ASC = sbp[12]; |
405 | + char ASCQ = sbp[13]; |
406 | + |
407 | + if (sbp[0]) { |
408 | + switch (key){ |
409 | + case 0: |
410 | + if (errno==0) |
411 | + errno = EIO; |
412 | + return(TR_UNKNOWN); |
413 | + case 1: |
414 | + break; |
415 | + case 2: |
416 | + if (errno==0) |
417 | + errno = EBUSY; |
418 | + return(TR_BUSY); |
419 | + case 3: |
420 | + if ((ASC==0x0C) & (ASCQ==0x09)) { |
421 | + /* loss of streaming */ |
422 | + if (errno==0) |
423 | + errno = EIO; |
424 | + return(TR_STREAMING); |
425 | + } else { |
426 | + if (errno==0) |
427 | + errno = EIO; |
428 | + return(TR_MEDIUM); |
429 | + } |
430 | + case 4: |
431 | + if (errno==0) |
432 | + errno = EIO; |
433 | + return(TR_FAULT); |
434 | + case 5: |
435 | + if (errno==0) |
436 | + errno = EINVAL; |
437 | + return(TR_ILLEGAL); |
438 | + default: |
439 | + if (errno==0) |
440 | + errno = EIO; |
441 | + return(TR_UNKNOWN); |
442 | + } |
443 | + } |
444 | + return 0; |
445 | +} |
446 | + |
447 | +#ifdef SG_IO |
448 | +int check_fd_sgio(int fd) { |
449 | + struct sg_io_hdr hdr; |
450 | + |
451 | + if (fd < 0) |
452 | + return fd; |
453 | + |
454 | + memset(&hdr, 0, sizeof (struct sg_io_hdr)); |
455 | + /* First try with interface_id = 'A'; for all but the sg case, |
456 | + * that'll get us a -EINVAL if it supports SG_IO, and some other |
457 | + * error for all other cases. */ |
458 | + hdr.interface_id = 'A'; |
459 | + if (ioctl(fd, SG_IO, &hdr)) { |
460 | + switch (errno) { |
461 | + /* sr and ata give us EINVAL when SG_IO is supported |
462 | + * but interface_id is bad. */ |
463 | + case EINVAL: |
464 | + /* sg gives us ENOSYS when SG_IO is supported but |
465 | + * interface_id is bad. IMHO, this is wrong and |
466 | + * needs fixing in the kernel. */ |
467 | + case ENOSYS: |
468 | + return fd; |
469 | + /* everything else gives ENOTTY, I think. I'm just |
470 | + * going to be paranoid and reject everything else. */ |
471 | + default: |
472 | + return -errno; |
473 | + } |
474 | + } |
475 | + /* if we get here, something is dreadfuly wrong. ioctl(fd,SG_IO,&hdr) |
476 | + * handled SG_IO, but took hdr.interface_id = 'A' as valid, and an empty |
477 | + * command as good. Don't trust it. */ |
478 | + return -1; |
479 | +} |
480 | + |
481 | +static void sgio_tweak_SG_buffer(cdrom_drive *d) { |
482 | + int table, reserved, cur, err; |
483 | + char buffer[256]; |
484 | + |
485 | + /* SG_SET_RESERVED_SIZE doesn't actually allocate or reserve anything. |
486 | + * what it _does_ do is give you an error if you ask for a value |
487 | + * larger than q->max_sectors (the length of the device's bio request |
488 | + * queue). So we walk it up from 1 sector until it fails, then get |
489 | + * the value we set it to last. |
490 | + */ |
491 | + /* start with 2 frames, round down to our queue's sector size */ |
492 | + cur = 1; |
493 | + do { |
494 | + cur <<= 1; reserved = cur * (1<<9); |
495 | + err = ioctl(d->cdda_fd, SG_SET_RESERVED_SIZE, &reserved); |
496 | + } while(err >= 0); |
497 | + ioctl(d->cdda_fd, SG_GET_RESERVED_SIZE, &reserved); |
498 | + |
499 | + cur = 0; |
500 | + /* this doesn't currently ever work, but someday somebody might |
501 | + implement working sg lists with SG_IO devices, so who knows... */ |
502 | + table=1; |
503 | + if (ioctl(d->cdda_fd, SG_GET_SG_TABLESIZE, &table) < 0) |
504 | + table=1; |
505 | + |
506 | + sprintf(buffer,"\tDMA scatter/gather table entries: %d\n\t" |
507 | + "table entry size: %d bytes\n\t" |
508 | + "maximum theoretical transfer: %d sectors\n", |
509 | + table, reserved, table*reserved/CD_FRAMESIZE_RAW); |
510 | + cdmessage(d,buffer); |
511 | + |
512 | + cur=table*reserved; |
513 | + |
514 | + ((struct sg_info *)d->sg)->dxferp_max_buffer_len = cur; |
515 | + |
516 | + /* so since we never go above q->max_sectors, we should never get -EIO. |
517 | + * we might still get -ENOMEM, but we back off for that later. Monty |
518 | + * had an old comment: "not too much; new kernels have trouble with DMA |
519 | + * "allocation, so be more conservative: 32kB max until I test more |
520 | + * thoroughly". We're not currently honoring that, because we should |
521 | + * always get -ENOMEM. |
522 | + */ |
523 | +#if 0 |
524 | + cur=(cur>1024*32?1024*32:cur); |
525 | +#endif |
526 | + d->nsectors=cur/CD_FRAMESIZE_RAW; |
527 | + d->bigbuff=cur; |
528 | + |
529 | + sprintf(buffer,"\tSetting default read size to %d sectors (%d bytes).\n\n", |
530 | + d->nsectors,d->nsectors*CD_FRAMESIZE_RAW); |
531 | + cdmessage(d,buffer); |
532 | +} |
533 | + |
534 | +static void sgio_setup_scsi_cmd(cdrom_drive *d, |
535 | + char *cmdp, |
536 | + unsigned int cmd_len, |
537 | + unsigned int in_size, |
538 | + unsigned int out_size) { |
539 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
540 | + struct sg_io_hdr *hdr = sgi->hdr; |
541 | + |
542 | + memset(hdr->cmdp, 0, sgi->cmdp_buffer_len); |
543 | + memset(hdr->dxferp, sgi->bytefill, sgi->dxferp_buffer_len); |
544 | + memcpy(hdr->cmdp, cmdp, cmd_len); |
545 | + |
546 | + hdr->cmd_len = cmd_len; |
547 | + |
548 | + sgi->in_size = in_size; |
549 | + sgi->out_size = out_size; |
550 | +} |
551 | + |
552 | +static int sgio_handle_scsi_cmd(cdrom_drive *d) { |
553 | + int status = 0; |
554 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
555 | + struct sg_io_hdr *hdr = sgi->hdr; |
556 | + |
557 | + if (sgi->in_size) { |
558 | + hdr->dxfer_len = sgi->in_size; |
559 | + hdr->dxfer_direction = SG_DXFER_TO_DEV; |
560 | + |
561 | + errno = 0; |
562 | + status = ioctl(d->cdda_fd, SG_IO, hdr); |
563 | + if (status >= 0) |
564 | + if (hdr->status) |
565 | + status = check_sbp_error(hdr->sbp); |
566 | + if (status < 0) |
567 | + return TR_EWRITE; |
568 | + } |
569 | + if (!sgi->in_size | sgi->out_size) { |
570 | + hdr->dxfer_len = sgi->out_size; |
571 | + hdr->dxfer_direction = sgi->out_size ? SG_DXFER_FROM_DEV : SG_DXFER_NONE; |
572 | + |
573 | + errno = 0; |
574 | + status = ioctl(d->cdda_fd, SG_IO, hdr); |
575 | + if (status < 0) |
576 | + return TR_EREAD; |
577 | + if (status >= 0) |
578 | + if (hdr->status) |
579 | + status = check_sbp_error(hdr->sbp); |
580 | + } |
581 | + if (status) |
582 | + return status; |
583 | + |
584 | + errno = 0; |
585 | + return 0; |
586 | +} |
587 | + |
588 | +void sgio_init_sg_info(cdrom_drive *d) { |
589 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
590 | + struct sg_io_hdr *hdr; |
591 | + |
592 | + hdr = calloc(sizeof (struct sg_io_hdr), 1); |
593 | + |
594 | + sgi->cmdp = hdr->cmdp = calloc(128, 1); |
595 | + sgi->cmdp_buffer_len = 128; |
596 | + |
597 | + hdr->sbp = calloc(SG_MAX_SENSE,1); |
598 | + hdr->mx_sb_len = SG_MAX_SENSE; |
599 | + |
600 | + sgi->bytefill = '\xff'; |
601 | + sgi->bytecheck = 0; |
602 | + |
603 | + hdr->timeout = 5000; |
604 | + hdr->interface_id = 'S'; |
605 | + |
606 | + sgi->hdr = hdr; |
607 | + |
608 | + sgi->setup_scsi_cmd = sgio_setup_scsi_cmd; |
609 | + sgi->handle_scsi_cmd = sgio_handle_scsi_cmd; |
610 | + |
611 | + sgio_tweak_SG_buffer(d); |
612 | + |
613 | + sgi->dxferp = hdr->dxferp = calloc(sgi->dxferp_max_buffer_len, 1); |
614 | + sgi->dxferp_buffer_len = sgi->dxferp_max_buffer_len; |
615 | +} |
616 | +#endif |
617 | + |
618 | +static void sg2_clear_garbage(cdrom_drive *d){ |
619 | + fd_set fdset; |
620 | + struct timeval tv; |
621 | + struct sg_header *sg_hd = (struct sg_header *)((struct sg_info *)d->sg)->hdr; |
622 | + int flag = 0; |
623 | + |
624 | + /* clear out any possibly preexisting garbage */ |
625 | + FD_ZERO(&fdset); |
626 | + FD_SET(d->cdda_fd,&fdset); |
627 | + tv.tv_sec=0; |
628 | + tv.tv_usec=0; |
629 | + |
630 | + /* I like select */ |
631 | + while(select(d->cdda_fd+1,&fdset,NULL,NULL,&tv)==1){ |
632 | + |
633 | + sg_hd->twelve_byte = 0; |
634 | + sg_hd->result = 0; |
635 | + sg_hd->reply_len = SG_OFF; |
636 | + read(d->cdda_fd, sg_hd, 1); |
637 | + |
638 | + /* reset for select */ |
639 | + FD_ZERO(&fdset); |
640 | + FD_SET(d->cdda_fd,&fdset); |
641 | + tv.tv_sec=0; |
642 | + tv.tv_usec=0; |
643 | + if(!flag && d->report_all) |
644 | + cdmessage(d,"Clearing previously returned data from SCSI buffer\n"); |
645 | + flag=1; |
646 | + } |
647 | +} |
648 | + |
649 | +static void sg2_tweak_SG_buffer(cdrom_drive *d){ |
650 | int table,reserved; |
651 | char buffer[256]; |
652 | |
653 | @@ -58,74 +343,47 @@ |
654 | if(ioctl(d->cdda_fd,SG_SET_COMMAND_Q,&reserved)){ |
655 | cdmessage(d,"\tCouldn't disable command queue! Continuing anyway...\n"); |
656 | } |
657 | - |
658 | } |
659 | |
660 | -static void reset_scsi(cdrom_drive *d){ |
661 | - int arg; |
662 | - d->enable_cdda(d,0); |
663 | - |
664 | - cdmessage(d,"sending SG SCSI reset... "); |
665 | - if(ioctl(d->cdda_fd,SG_SCSI_RESET,&arg)) |
666 | - cdmessage(d,"FAILED: EBUSY\n"); |
667 | - else |
668 | - cdmessage(d,"OK\n"); |
669 | - |
670 | - d->enable_cdda(d,1); |
671 | -} |
672 | +/* process a complete scsi command. */ |
673 | |
674 | -static void clear_garbage(cdrom_drive *d){ |
675 | - fd_set fdset; |
676 | - struct timeval tv; |
677 | - struct sg_header *sg_hd=(struct sg_header *)d->sg; |
678 | - int flag=0; |
679 | +static void sg2_setup_scsi_cmd(cdrom_drive *d, |
680 | + char *cmdp, |
681 | + unsigned int cmd_len, |
682 | + unsigned int in_size, |
683 | + unsigned int out_size) { |
684 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
685 | + struct sg_header *hdr = (struct sg_header *)sgi->hdr; |
686 | |
687 | - /* clear out any possibly preexisting garbage */ |
688 | - FD_ZERO(&fdset); |
689 | - FD_SET(d->cdda_fd,&fdset); |
690 | - tv.tv_sec=0; |
691 | - tv.tv_usec=0; |
692 | + sgi->cmdp = (char *)hdr + sizeof (struct sg_header); |
693 | + memcpy(sgi->cmdp, cmdp, cmd_len); |
694 | |
695 | - /* I like select */ |
696 | - while(select(d->cdda_fd+1,&fdset,NULL,NULL,&tv)==1){ |
697 | - |
698 | - sg_hd->twelve_byte = 0; |
699 | - sg_hd->result = 0; |
700 | - sg_hd->reply_len = SG_OFF; |
701 | - read(d->cdda_fd, sg_hd, 1); |
702 | + sgi->dxferp = sgi->cmdp + cmd_len; |
703 | + memset(sgi->dxferp, sgi->bytefill, sgi->dxferp_max_buffer_len - cmd_len); |
704 | |
705 | - /* reset for select */ |
706 | - FD_ZERO(&fdset); |
707 | - FD_SET(d->cdda_fd,&fdset); |
708 | - tv.tv_sec=0; |
709 | - tv.tv_usec=0; |
710 | - if(!flag && d->report_all) |
711 | - cdmessage(d,"Clearing previously returned data from SCSI buffer\n"); |
712 | - flag=1; |
713 | - } |
714 | + sgi->in_size = in_size; |
715 | + sgi->out_size = out_size; |
716 | } |
717 | |
718 | -/* process a complete scsi command. */ |
719 | -static int handle_scsi_cmd(cdrom_drive *d, |
720 | - unsigned int cmd_len, |
721 | - unsigned int in_size, |
722 | - unsigned int out_size, |
723 | - |
724 | - unsigned char bytefill, |
725 | - int bytecheck){ |
726 | +static int sg2_handle_scsi_cmd(cdrom_drive *d) { |
727 | int status = 0; |
728 | - struct sg_header *sg_hd=(struct sg_header *)d->sg; |
729 | - long writebytes=SG_OFF+cmd_len+in_size; |
730 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
731 | + struct sg_header *sg_hd = (struct sg_header *)sgi->hdr; |
732 | + |
733 | + int out_size = sgi->out_size; |
734 | + int in_size = sgi->in_size; |
735 | + |
736 | + long writebytes = (int)(sg_hd) + SG_OFF + sgi->cmd_len + sgi->in_size; |
737 | |
738 | /* generic scsi device services */ |
739 | |
740 | /* clear out any possibly preexisting garbage */ |
741 | - clear_garbage(d); |
742 | + sg2_clear_garbage(d); |
743 | |
744 | - memset(sg_hd,0,sizeof(sg_hd)); |
745 | - sg_hd->twelve_byte = cmd_len == 12; |
746 | + memset(sg_hd,0, SG_OFF); |
747 | + sg_hd->twelve_byte = sgi->cmd_len == 12; |
748 | sg_hd->result = 0; |
749 | - sg_hd->reply_len = SG_OFF + out_size; |
750 | + sg_hd->reply_len = SG_OFF + sgi->out_size; |
751 | |
752 | /* The following is one of the scariest hacks I've ever had to use. |
753 | The idea is this: We want to know if a command fails. The |
754 | @@ -135,8 +393,8 @@ |
755 | length for a command that doesn't take data) such that we can |
756 | tell if the command failed. Scared yet? */ |
757 | |
758 | - if(bytecheck && out_size>in_size){ |
759 | - memset(d->sg_buffer+cmd_len+in_size,bytefill,out_size-in_size); |
760 | + if(sgi->bytecheck && out_size>in_size){ |
761 | + /* the memset for this is done in sg2_setup_scsi_cmd() */ |
762 | /* the size does not remove cmd_len due to the way the kernel |
763 | driver copies buffers */ |
764 | writebytes+=(out_size-in_size); |
765 | @@ -224,40 +482,10 @@ |
766 | if(errno==0)errno=EIO; |
767 | return(TR_EREAD); |
768 | } |
769 | - |
770 | - if(sg_hd->sense_buffer[0]){ |
771 | - char key=sg_hd->sense_buffer[2]&0xf; |
772 | - char ASC=sg_hd->sense_buffer[12]; |
773 | - char ASCQ=sg_hd->sense_buffer[13]; |
774 | - switch(key){ |
775 | - case 0: |
776 | - if(errno==0)errno=EIO; |
777 | - return(TR_UNKNOWN); |
778 | - case 1: |
779 | - break; |
780 | - case 2: |
781 | - if(errno==0)errno=EBUSY; |
782 | - return(TR_BUSY); |
783 | - case 3: |
784 | - if(ASC==0x0C && ASCQ==0x09){ |
785 | - /* loss of streaming */ |
786 | - if(errno==0)errno=EIO; |
787 | - return(TR_STREAMING); |
788 | - }else{ |
789 | - if(errno==0)errno=EIO; |
790 | - return(TR_MEDIUM); |
791 | - } |
792 | - case 4: |
793 | - if(errno==0)errno=EIO; |
794 | - return(TR_FAULT); |
795 | - case 5: |
796 | - if(errno==0)errno=EINVAL; |
797 | - return(TR_ILLEGAL); |
798 | - default: |
799 | - if(errno==0)errno=EIO; |
800 | - return(TR_UNKNOWN); |
801 | - } |
802 | - } |
803 | + |
804 | + status = check_sbp_error(sg_hd->sense_buffer); |
805 | + if (status) |
806 | + return status; |
807 | |
808 | /* still not foolproof; the following doesn't guarantee that we got |
809 | all the data, just that the command was not rejected. */ |
810 | @@ -266,10 +494,11 @@ |
811 | commands still get through. Perhaps no data comes back even |
812 | though the target reports success? */ |
813 | |
814 | - if(bytecheck && in_size+cmd_len<out_size){ |
815 | + if(sgi->bytecheck && sgi->in_size+sgi->cmd_len<sgi->out_size){ |
816 | long i,flag=0; |
817 | - for(i=in_size;i<out_size;i++) |
818 | - if(d->sg_buffer[i]!=bytefill){ |
819 | + for(i=sgi->in_size; i<sgi->out_size; i++) |
820 | + /* XXX check this offset */ |
821 | + if((sgi->dxferp[i])!=(sgi->bytefill)){ |
822 | flag=1; |
823 | break; |
824 | } |
825 | @@ -284,61 +513,67 @@ |
826 | return(0); |
827 | } |
828 | |
829 | -/* Group 1 (10b) command */ |
830 | +void sg2_init_sg_info(cdrom_drive *d) { |
831 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
832 | + struct sg_header *hdr; |
833 | |
834 | -static int mode_sense_atapi(cdrom_drive *d,int size,int page){ |
835 | - memcpy(d->sg_buffer, |
836 | - (char []) {0x5A, /* MODE_SENSE */ |
837 | - 0x00, /* reserved */ |
838 | - 0x00, /* page */ |
839 | - 0, /* reserved */ |
840 | - 0, /* reserved */ |
841 | - 0, /* reserved */ |
842 | - 0, /* reserved */ |
843 | - 0, /* MSB (0) */ |
844 | - 0, /* sizeof(modesense - SG_OFF) */ |
845 | - 0}, /* reserved */ |
846 | - 10); |
847 | - |
848 | - d->sg_buffer[1]=d->lun<<5; |
849 | - d->sg_buffer[2]=0x3F&page; |
850 | - d->sg_buffer[8]=size+4; |
851 | + hdr = calloc(sizeof (struct sg_header)+sgi->dxferp_max_buffer_len, 1); |
852 | |
853 | - if (handle_scsi_cmd (d, 10, 0, size+4,'\377',1)) return(1); |
854 | + sgi->cmdp = (char *)hdr + sizeof (struct sg_header); |
855 | + sgi->cmdp_buffer_len = 0; |
856 | |
857 | - { |
858 | - char *b=d->sg_buffer; |
859 | - if(b[0])return(1); /* Handles only up to 256 bytes */ |
860 | - if(b[6])return(1); /* Handles only up to 256 bytes */ |
861 | - |
862 | - b[0]=b[1]-3; |
863 | - b[1]=b[2]; |
864 | - b[2]=b[3]; |
865 | - b[3]=b[7]; |
866 | + sgi->bytefill = '\xff'; |
867 | + sgi->bytecheck = 1; |
868 | |
869 | - memmove(b+4,b+8,size); |
870 | - } |
871 | - return(0); |
872 | + sgi->setup_scsi_cmd = sg2_setup_scsi_cmd; |
873 | + sgi->handle_scsi_cmd = sg2_handle_scsi_cmd; |
874 | + |
875 | + sg2_tweak_SG_buffer(d); |
876 | + |
877 | + // sgi->dxferp = hdr + sizeof (struct sg_header); |
878 | + sgi->dxferp = NULL; |
879 | + sgi->dxferp_buffer_len = 0; |
880 | +} |
881 | + |
882 | +static int mode_sense_atapi(cdrom_drive *d, int size, int page) { |
883 | + char *buffer; |
884 | + |
885 | + ((struct sg_info *)d->sg)->setup_scsi_cmd(d, SCSI_MODE_SENSE_10(page,size), 10, 0, size); |
886 | + |
887 | + buffer = ((struct sg_info *)d->sg)->dxferp; |
888 | +#if 0 |
889 | + buffer[1]=d->lun<<5; |
890 | +#endif |
891 | + |
892 | + if (((struct sg_info *)d->sg)->handle_scsi_cmd(d)) |
893 | + return 1; |
894 | + |
895 | + if(buffer[0])return(1); /* Handles only up to 256 bytes */ |
896 | + if(buffer[6])return(1); /* Handles only up to 256 bytes */ |
897 | + |
898 | + buffer[0]=buffer[1]-3; |
899 | + buffer[1]=buffer[2]; |
900 | + buffer[2]=buffer[3]; |
901 | + buffer[3]=buffer[7]; |
902 | + |
903 | + memmove(buffer+4,buffer+8,size); |
904 | + return 0; |
905 | } |
906 | |
907 | /* group 0 (6b) command */ |
908 | |
909 | static int mode_sense_scsi(cdrom_drive *d,int size,int page){ |
910 | - memcpy(d->sg_buffer, |
911 | - (char []) {0x1A, /* MODE_SENSE */ |
912 | - 0x00, /* return block descriptor/lun */ |
913 | - 0x00, /* page */ |
914 | - 0, /* reserved */ |
915 | - 0, /* sizeof(modesense - SG_OFF) */ |
916 | - 0}, /* control */ |
917 | - 6); |
918 | + char *buffer; |
919 | + ((struct sg_info *)d->sg)->setup_scsi_cmd(d, SCSI_MODE_SENSE_6(page, size), 6, 0, size); |
920 | |
921 | - d->sg_buffer[1]=d->lun<<5; |
922 | - d->sg_buffer[2]=(0x3F&page); |
923 | - d->sg_buffer[4]=size; |
924 | - |
925 | - if (handle_scsi_cmd (d, 6, 0, size, '\377',1)) return(1); |
926 | - return(0); |
927 | + buffer = ((struct sg_info *)d->sg)->dxferp; |
928 | +#if 0 |
929 | + buffer[1]=d->lun<<5; |
930 | +#endif |
931 | + |
932 | + if (((struct sg_info *)d->sg)->handle_scsi_cmd(d)) |
933 | + return 1; |
934 | + return 0; |
935 | } |
936 | |
937 | static int mode_sense(cdrom_drive *d,int size,int page){ |
938 | @@ -347,80 +582,77 @@ |
939 | return(mode_sense_scsi(d,size,page)); |
940 | } |
941 | |
942 | -static int mode_select(cdrom_drive *d,int density,int secsize){ |
943 | - /* short circut the way Heiko does it; less flexible, but shorter */ |
944 | - if(d->is_atapi){ |
945 | - unsigned char *mode = d->sg_buffer + 18; |
946 | +static int atapi_mode_select(cdrom_drive *d, int density, int secsize) { |
947 | + unsigned char *mode; |
948 | |
949 | - memcpy(d->sg_buffer, |
950 | - (char []) { 0x55, /* MODE_SELECT */ |
951 | - 0x10, /* no save page */ |
952 | - 0, /* reserved */ |
953 | - 0, /* reserved */ |
954 | - 0, /* reserved */ |
955 | - 0, /* reserved */ |
956 | - 0, /* reserved */ |
957 | - 0, /* reserved */ |
958 | - 12, /* sizeof(mode) */ |
959 | - 0, /* reserved */ |
960 | - |
961 | - /* mode parameter header */ |
962 | - 0, 0, 0, 0, 0, 0, 0, |
963 | - 8, /* Block Descriptor Length */ |
964 | - |
965 | - /* descriptor block */ |
966 | - 0, /* Density Code */ |
967 | - 0, 0, 0, /* # of Blocks */ |
968 | - 0, /* reserved */ |
969 | - 0, 0, 0},/* Blocklen */ |
970 | - 26); |
971 | - |
972 | - d->sg_buffer[1]|=d->lun<<5; |
973 | - |
974 | - /* prepare to read cds in the previous mode */ |
975 | - mode [0] = density; |
976 | - mode [6] = secsize >> 8; /* block length "msb" */ |
977 | - mode [7] = secsize & 0xFF; /* block length lsb */ |
978 | + ((struct sg_info *)d->sg)->setup_scsi_cmd(d, SCSI_MODE_SELECT_10, 10, 16, 0); |
979 | + memcpy(((struct sg_info *)d->sg)->dxferp,(char []) { |
980 | + /* mode parameter header */ |
981 | + 0, 0, 0, 0, 0, 0, 0, |
982 | + 8, /* Block Descriptor Length */ |
983 | + /* descriptor block */ |
984 | + 0, /* Density Code */ |
985 | + 0, 0, 0, /* # of Blocks */ |
986 | + 0, /* reserved */ |
987 | + 0, 0, 0},/* Blocklen */ |
988 | + 16); |
989 | + |
990 | + mode = ((struct sg_info *)d->sg)->dxferp; |
991 | +#if 0 |
992 | + mode[1] |= d->lun << 5; |
993 | +#endif |
994 | + /* prepare to read cds in the previous mode */ |
995 | + mode[8] = density; |
996 | + mode[14] = secsize >> 8; /* block length "msb" */ |
997 | + mode[15] = secsize & 0xFF; /* block length lsb */ |
998 | + |
999 | + /* do the scsi cmd */ |
1000 | + return ((struct sg_info *)d->sg)->handle_scsi_cmd(d); |
1001 | +} |
1002 | + |
1003 | +static int scsi_mode_select(cdrom_drive *d, int density, int secsize) { |
1004 | + unsigned char *mode; |
1005 | + |
1006 | + ((struct sg_info *)d->sg)->setup_scsi_cmd(d, SCSI_MODE_SELECT_6, 6, 12, 0); |
1007 | + memcpy(((struct sg_info *)d->sg)->dxferp,(char []) { |
1008 | + /* mode section */ |
1009 | + 0, |
1010 | + 0, 0, |
1011 | + 8, /* Block Descriptor Length */ |
1012 | + 0, /* Density Code */ |
1013 | + 0, 0, 0, /* # of Blocks */ |
1014 | + 0, /* reserved */ |
1015 | + 0, 0, 0},/* Blocklen */ |
1016 | + 12); |
1017 | + |
1018 | + /* prepare to read cds in the previous mode */ |
1019 | + mode = ((struct sg_info *)d->sg)->dxferp; |
1020 | + mode [4] = density; |
1021 | + mode [10] = secsize >> 8; /* block length "msb" */ |
1022 | + mode [11] = secsize & 0xFF; /* block length lsb */ |
1023 | |
1024 | /* do the scsi cmd */ |
1025 | - return(handle_scsi_cmd (d,10, 16, 0,0,0)); |
1026 | - |
1027 | - }else{ |
1028 | - unsigned char *mode = d->sg_buffer + 10; |
1029 | - |
1030 | - memcpy(d->sg_buffer, |
1031 | - (char []) { 0x15, /* MODE_SELECT */ |
1032 | - 0x10, /* no save page */ |
1033 | - 0, /* reserved */ |
1034 | - 0, /* reserved */ |
1035 | - 12, /* sizeof(mode) */ |
1036 | - 0, /* reserved */ |
1037 | - /* mode section */ |
1038 | - 0, |
1039 | - 0, 0, |
1040 | - 8, /* Block Descriptor Length */ |
1041 | - 0, /* Density Code */ |
1042 | - 0, 0, 0, /* # of Blocks */ |
1043 | - 0, /* reserved */ |
1044 | - 0, 0, 0},/* Blocklen */ |
1045 | - 18); |
1046 | - |
1047 | - /* prepare to read cds in the previous mode */ |
1048 | - mode [0] = density; |
1049 | - mode [6] = secsize >> 8; /* block length "msb" */ |
1050 | - mode [7] = secsize & 0xFF; /* block length lsb */ |
1051 | + return ((struct sg_info *)d->sg)->handle_scsi_cmd(d); |
1052 | +} |
1053 | |
1054 | - /* do the scsi cmd */ |
1055 | - return(handle_scsi_cmd (d,6, 12, 0,0,0)); |
1056 | - } |
1057 | +static int mode_select(cdrom_drive *d, int density, int secsize) { |
1058 | + /* short circut the way Heiko does it; less flexible, but shorter */ |
1059 | + if (d->is_atapi) |
1060 | + return atapi_mode_select(d, density, secsize); |
1061 | + return scsi_mode_select(d, density, secsize); |
1062 | } |
1063 | |
1064 | /* get current sector size from SCSI cdrom drive */ |
1065 | static unsigned int get_orig_sectorsize(cdrom_drive *d){ |
1066 | - if(mode_sense(d,12,0x01))return(-1); |
1067 | + if (mode_sense(d,12,0x01)) |
1068 | + return -1; |
1069 | + |
1070 | + d->orgdens = ((struct sg_info *)d->sg)->dxferp[4]; |
1071 | + |
1072 | + d->orgsize = (int)(((struct sg_info *)d->sg)->dxferp[10]<<8); |
1073 | + d->orgsize += (int)((struct sg_info *)d->sg)->dxferp[11]; |
1074 | |
1075 | - d->orgdens = d->sg_buffer[4]; |
1076 | - return(d->orgsize = ((int)(d->sg_buffer[10])<<8)+d->sg_buffer[11]); |
1077 | + return d->orgsize; |
1078 | } |
1079 | |
1080 | /* switch CDROM scsi drives to given sector size */ |
1081 | @@ -463,23 +695,23 @@ |
1082 | fails on at least one Kodak drive. */ |
1083 | |
1084 | static int scsi_read_toc (cdrom_drive *d){ |
1085 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
1086 | int i,first,last; |
1087 | unsigned tracks; |
1088 | - |
1089 | - /* READTOC, MSF format flag, res, res, res, res, Start track, len msb, |
1090 | - len lsb, flags */ |
1091 | + scsi_TOC *toc; |
1092 | |
1093 | /* read the header first */ |
1094 | - memcpy(d->sg_buffer, (char []){ 0x43, 0, 0, 0, 0, 0, 1, 0, 12, 0}, 10); |
1095 | - d->sg_buffer[1]=d->lun<<5; |
1096 | - |
1097 | - if (handle_scsi_cmd (d,10, 0, 12,'\377',1)){ |
1098 | + sgi->setup_scsi_cmd(d, SCSI_READ_TOC(1), 10, 0, 12); |
1099 | +#if 0 |
1100 | + sgi->dxferp[1] = d->lun << 5; |
1101 | +#endif |
1102 | + if (sgi->handle_scsi_cmd(d)) { |
1103 | cderror(d,"004: Unable to read table of contents header\n"); |
1104 | return(-4); |
1105 | } |
1106 | |
1107 | - first=d->sg_buffer[2]; |
1108 | - last=d->sg_buffer[3]; |
1109 | + first = sgi->dxferp[2]; |
1110 | + last = sgi->dxferp[3]; |
1111 | tracks=last-first+1; |
1112 | |
1113 | if (last > MAXTRK || first > MAXTRK || last<0 || first<0) { |
1114 | @@ -488,335 +720,208 @@ |
1115 | } |
1116 | |
1117 | for (i = first; i <= last; i++){ |
1118 | - memcpy(d->sg_buffer, (char []){ 0x43, 0, 0, 0, 0, 0, 0, 0, 12, 0}, 10); |
1119 | - d->sg_buffer[1]=d->lun<<5; |
1120 | - d->sg_buffer[6]=i; |
1121 | + sgi->setup_scsi_cmd(d, SCSI_READ_TOC(i), 10, 0, 12); |
1122 | +#if 0 |
1123 | + sgi->dxferp[1] = d->lun << 5; |
1124 | +#endif |
1125 | |
1126 | - if (handle_scsi_cmd (d,10, 0, 12,'\377',1)){ |
1127 | + if (sgi->handle_scsi_cmd(d)) { |
1128 | cderror(d,"005: Unable to read table of contents entry\n"); |
1129 | return(-5); |
1130 | } |
1131 | - { |
1132 | - scsi_TOC *toc=(scsi_TOC *)(d->sg_buffer+4); |
1133 | - |
1134 | - d->disc_toc[i-first].bFlags=toc->bFlags; |
1135 | - d->disc_toc[i-first].bTrack=i; |
1136 | - d->disc_toc[i-first].dwStartSector= d->adjust_ssize * |
1137 | - (((int)(toc->start_MSB)<<24) | |
1138 | - (toc->start_1<<16)| |
1139 | - (toc->start_2<<8)| |
1140 | - (toc->start_LSB)); |
1141 | - } |
1142 | - } |
1143 | + toc = (scsi_TOC *)(sgi->dxferp+4); |
1144 | + d->disc_toc[i-first].bFlags = toc->bFlags; |
1145 | + d->disc_toc[i-first].bTrack = i; |
1146 | + d->disc_toc[i-first].dwStartSector = |
1147 | + d->adjust_ssize * ( |
1148 | + ((int)(toc->start_MSB)<<24) | (toc->start_1 << 16) | |
1149 | + (toc->start_2 << 8) | (toc->start_LSB) |
1150 | + ); |
1151 | + } |
1152 | + |
1153 | + sgi->setup_scsi_cmd(d, SCSI_READ_TOC(0xAA), 10, 0, 12); |
1154 | +#if 0 |
1155 | + sgi->dxferp[1] = d->lun << 5; |
1156 | +#endif |
1157 | |
1158 | - memcpy(d->sg_buffer, (char []){ 0x43, 0, 0, 0, 0, 0, 0, 0, 12, 0}, 10); |
1159 | - d->sg_buffer[1]=d->lun<<5; |
1160 | - d->sg_buffer[6]=0xAA; |
1161 | - |
1162 | - if (handle_scsi_cmd (d,10, 0, 12,'\377',1)){ |
1163 | + if (sgi->handle_scsi_cmd(d)) { |
1164 | cderror(d,"002: Unable to read table of contents lead-out\n"); |
1165 | return(-2); |
1166 | } |
1167 | - { |
1168 | - scsi_TOC *toc=(scsi_TOC *)(d->sg_buffer+4); |
1169 | - |
1170 | - d->disc_toc[i-first].bFlags=toc->bFlags; |
1171 | - d->disc_toc[i-first].bTrack=0xAA; |
1172 | - d->disc_toc[i-first].dwStartSector= d->adjust_ssize * |
1173 | - (((int)(toc->start_MSB)<<24) | |
1174 | - (toc->start_1<<16)| |
1175 | - (toc->start_2<<8)| |
1176 | - (toc->start_LSB)); |
1177 | - } |
1178 | + |
1179 | + toc = (scsi_TOC *)(sgi->dxferp+4); |
1180 | + d->disc_toc[i-first].bFlags = toc->bFlags; |
1181 | + d->disc_toc[i-first].bTrack = 0xAA; |
1182 | + d->disc_toc[i-first].dwStartSector = |
1183 | + d->adjust_ssize * ( |
1184 | + ((int)(toc->start_MSB)<<24) | (toc->start_1 << 16) | |
1185 | + (toc->start_2 << 8) | (toc->start_LSB) |
1186 | + ); |
1187 | |
1188 | d->cd_extra = FixupTOC(d,tracks+1); /* include lead-out */ |
1189 | - return(tracks); |
1190 | + return tracks; |
1191 | } |
1192 | |
1193 | /* a contribution from Boris for IMS cdd 522 */ |
1194 | /* check this for ACER/Creative/Foo 525,620E,622E, etc? */ |
1195 | static int scsi_read_toc2 (cdrom_drive *d){ |
1196 | - u_int32_t foo,bar; |
1197 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
1198 | + u_int32_t msb,lsb; |
1199 | |
1200 | int i; |
1201 | unsigned tracks; |
1202 | |
1203 | - memcpy(d->sg_buffer, (char[]){ 0xe5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10); |
1204 | - d->sg_buffer[5]=1; |
1205 | - d->sg_buffer[8]=255; |
1206 | - |
1207 | - if (handle_scsi_cmd (d,10, 0, 256,'\377',1)){ |
1208 | + sgi->setup_scsi_cmd(d, CDD522_READ_TOC(1), 10, 0, 256); |
1209 | + if (sgi->handle_scsi_cmd(d)) { |
1210 | cderror(d,"004: Unable to read table of contents header\n"); |
1211 | return(-4); |
1212 | } |
1213 | |
1214 | /* copy to our structure and convert start sector */ |
1215 | - tracks = d->sg_buffer[1]; |
1216 | + tracks = sgi->dxferp[1]; |
1217 | if (tracks > MAXTRK) { |
1218 | cderror(d,"003: CDROM reporting illegal number of tracks\n"); |
1219 | return(-3); |
1220 | } |
1221 | |
1222 | for (i = 0; i < tracks; i++){ |
1223 | - memcpy(d->sg_buffer, (char[]){ 0xe5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10); |
1224 | - d->sg_buffer[5]=i+1; |
1225 | - d->sg_buffer[8]=255; |
1226 | + sgi->setup_scsi_cmd(d, CDD522_READ_TOC(i+1), 10, 0, 256); |
1227 | |
1228 | - if (handle_scsi_cmd (d,10, 0, 256,'\377',1)){ |
1229 | + if (sgi->handle_scsi_cmd(d)) { |
1230 | cderror(d,"005: Unable to read table of contents entry\n"); |
1231 | return(-5); |
1232 | } |
1233 | |
1234 | - d->disc_toc[i].bFlags = d->sg_buffer[10]; |
1235 | + d->disc_toc[i].bFlags = sgi->dxferp[10]; |
1236 | d->disc_toc[i].bTrack = i + 1; |
1237 | |
1238 | - d->disc_toc[i].dwStartSector= d->adjust_ssize * |
1239 | - (((signed char)(d->sg_buffer[2])<<24) | |
1240 | - (d->sg_buffer[3]<<16)| |
1241 | - (d->sg_buffer[4]<<8)| |
1242 | - (d->sg_buffer[5])); |
1243 | + d->disc_toc[i].dwStartSector = d->adjust_ssize * ( |
1244 | + ((signed char)(sgi->dxferp[2])<<24) | |
1245 | + (sgi->dxferp[3]<<16) | |
1246 | + (sgi->dxferp[4]<<8) | |
1247 | + (sgi->dxferp[5]) |
1248 | + ); |
1249 | } |
1250 | |
1251 | d->disc_toc[i].bFlags = 0; |
1252 | d->disc_toc[i].bTrack = i + 1; |
1253 | - memcpy (&foo, d->sg_buffer+2, 4); |
1254 | - memcpy (&bar, d->sg_buffer+6, 4); |
1255 | - d->disc_toc[i].dwStartSector = d->adjust_ssize * (be32_to_cpu(foo) + |
1256 | - be32_to_cpu(bar)); |
1257 | - |
1258 | - d->disc_toc[i].dwStartSector= d->adjust_ssize * |
1259 | - ((((signed char)(d->sg_buffer[2])<<24) | |
1260 | - (d->sg_buffer[3]<<16)| |
1261 | - (d->sg_buffer[4]<<8)| |
1262 | - (d->sg_buffer[5]))+ |
1263 | - |
1264 | - ((((signed char)(d->sg_buffer[6])<<24) | |
1265 | - (d->sg_buffer[7]<<16)| |
1266 | - (d->sg_buffer[8]<<8)| |
1267 | - (d->sg_buffer[9])))); |
1268 | - |
1269 | + memcpy (&msb, sgi->dxferp+2, 4); |
1270 | + memcpy (&lsb, sgi->dxferp+6, 4); |
1271 | + d->disc_toc[i].dwStartSector = d->adjust_ssize * |
1272 | + (be32_to_cpu(msb) + be32_to_cpu(lsb)); |
1273 | + |
1274 | + d->disc_toc[i].dwStartSector= d->adjust_ssize * ( |
1275 | + ((((signed char)(sgi->dxferp[2])<<24) | |
1276 | + (sgi->dxferp[3]<<16) | |
1277 | + (sgi->dxferp[4]<<8) | |
1278 | + (sgi->dxferp[5]) |
1279 | + ) + ( |
1280 | + ((signed char)(sgi->dxferp[6])<<24) | |
1281 | + (sgi->dxferp[7]<<16) | |
1282 | + (sgi->dxferp[8]<<8) | |
1283 | + (sgi->dxferp[9]))) |
1284 | + ); |
1285 | |
1286 | d->cd_extra = FixupTOC(d,tracks+1); |
1287 | - return(tracks); |
1288 | + return tracks; |
1289 | } |
1290 | |
1291 | /* These do one 'extra' copy in the name of clean code */ |
1292 | |
1293 | -static int i_read_28 (cdrom_drive *d, void *p, long begin, long sectors){ |
1294 | +static int generic_scsi_read(cdrom_drive *d, void *p, long begin, long sectors, |
1295 | + char *read_cmd, int len, int in_size, int out_size) { |
1296 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
1297 | int ret; |
1298 | - memcpy(d->sg_buffer,(char []){0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0},10); |
1299 | - |
1300 | - if(d->fua) |
1301 | - d->sg_buffer[1]=0x08; |
1302 | |
1303 | - d->sg_buffer[1]|=d->lun<<5; |
1304 | + sgi->setup_scsi_cmd(d, read_cmd, len, in_size, out_size); |
1305 | +#if 0 |
1306 | + sgi->dxferp[1] = d->lun << 5; |
1307 | +#endif |
1308 | |
1309 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1310 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1311 | - d->sg_buffer[5] = begin & 0xFF; |
1312 | - d->sg_buffer[8] = sectors; |
1313 | - if((ret=handle_scsi_cmd(d,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1314 | - return(ret); |
1315 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1316 | - return(0); |
1317 | + ret = sgi->handle_scsi_cmd(d); |
1318 | + if (ret) |
1319 | + return ret; |
1320 | + if (p) |
1321 | + memcpy(p, sgi->dxferp, sectors * CD_FRAMESIZE_RAW); |
1322 | + return 0; |
1323 | } |
1324 | |
1325 | -static int i_read_A8 (cdrom_drive *d, void *p, long begin, long sectors){ |
1326 | - int ret; |
1327 | - memcpy(d->sg_buffer,(char []){0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},12); |
1328 | - |
1329 | - if(d->fua) |
1330 | - d->sg_buffer[1]=0x08; |
1331 | - |
1332 | - d->sg_buffer[1]|=d->lun<<5; |
1333 | - |
1334 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1335 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1336 | - d->sg_buffer[5] = begin & 0xFF; |
1337 | - d->sg_buffer[9] = sectors; |
1338 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1339 | - return(ret); |
1340 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1341 | - return(0); |
1342 | +static int i_read_28(cdrom_drive *d, void *p, long begin, long sectors){ |
1343 | + return generic_scsi_read(d, p, begin, sectors, |
1344 | + SCSI_READ_10(d->fua, begin, sectors), 10, 0, sectors * CD_FRAMESIZE_RAW); |
1345 | } |
1346 | |
1347 | -static int i_read_D4_10 (cdrom_drive *d, void *p, long begin, long sectors){ |
1348 | - int ret; |
1349 | - memcpy(d->sg_buffer,(char []){0xd4, 0, 0, 0, 0, 0, 0, 0, 0, 0},10); |
1350 | - |
1351 | - if(d->fua) |
1352 | - d->sg_buffer[1]=0x08; |
1353 | - |
1354 | - d->sg_buffer[1]|=d->lun<<5; |
1355 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1356 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1357 | - d->sg_buffer[5] = begin & 0xFF; |
1358 | - d->sg_buffer[8] = sectors; |
1359 | - if((ret=handle_scsi_cmd(d,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1360 | - return(ret); |
1361 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1362 | - return(0); |
1363 | +static int i_read_A8(cdrom_drive *d, void *p, long begin, long sectors){ |
1364 | + return generic_scsi_read(d, p, begin, sectors, |
1365 | + SCSI_READ_12(d->fua, begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); |
1366 | } |
1367 | |
1368 | -static int i_read_D4_12 (cdrom_drive *d, void *p, long begin, long sectors){ |
1369 | - int ret; |
1370 | - memcpy(d->sg_buffer,(char []){0xd4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},12); |
1371 | - |
1372 | - if(d->fua) |
1373 | - d->sg_buffer[1]=0x08; |
1374 | - |
1375 | - d->sg_buffer[1]|=d->lun<<5; |
1376 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1377 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1378 | - d->sg_buffer[5] = begin & 0xFF; |
1379 | - d->sg_buffer[9] = sectors; |
1380 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1381 | - return(ret); |
1382 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1383 | - return(0); |
1384 | +static int i_read_D4_10(cdrom_drive *d, void *p, long begin, long sectors){ |
1385 | + return generic_scsi_read(d, p, begin, sectors, |
1386 | + D4_READ_10(begin, sectors), 10, 0, sectors * CD_FRAMESIZE_RAW); |
1387 | } |
1388 | |
1389 | -static int i_read_D5 (cdrom_drive *d, void *p, long begin, long sectors){ |
1390 | - int ret; |
1391 | - memcpy(d->sg_buffer,(char []){0xd5, 0, 0, 0, 0, 0, 0, 0, 0, 0},10); |
1392 | - |
1393 | - if(d->fua) |
1394 | - d->sg_buffer[1]=0x08; |
1395 | - |
1396 | - d->sg_buffer[1]|=d->lun<<5; |
1397 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1398 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1399 | - d->sg_buffer[5] = begin & 0xFF; |
1400 | - d->sg_buffer[8] = sectors; |
1401 | - if((ret=handle_scsi_cmd(d,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1402 | - return(ret); |
1403 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1404 | - return(0); |
1405 | +static int i_read_D4_12(cdrom_drive *d, void *p, long begin, long sectors){ |
1406 | + return generic_scsi_read(d, p, begin, sectors, |
1407 | + D4_READ_12(begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); |
1408 | } |
1409 | |
1410 | -static int i_read_D8 (cdrom_drive *d, void *p, long begin, long sectors){ |
1411 | - int ret; |
1412 | - memcpy(d->sg_buffer,(char []){0xd8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},12); |
1413 | - |
1414 | - if(d->fua) |
1415 | - d->sg_buffer[1]=0x08; |
1416 | - |
1417 | - d->sg_buffer[1]|=d->lun<<5; |
1418 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1419 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1420 | - d->sg_buffer[5] = begin & 0xFF; |
1421 | - d->sg_buffer[9] = sectors; |
1422 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1423 | - return(ret); |
1424 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1425 | - return(0); |
1426 | +static int i_read_D5(cdrom_drive *d, void *p, long begin, long sectors){ |
1427 | + return generic_scsi_read(d, p, begin, sectors, |
1428 | + D5_READ_10(begin, sectors), 10, 0, sectors * CD_FRAMESIZE_RAW); |
1429 | } |
1430 | |
1431 | -static int i_read_mmc (cdrom_drive *d, void *p, long begin, long sectors){ |
1432 | - int ret; |
1433 | - /* if(begin<=12007 && begin+sectors>12000){ |
1434 | - errno=EIO; |
1435 | - return(TR_ILLEGAL); |
1436 | - }*/ |
1437 | - |
1438 | - memcpy(d->sg_buffer,(char []){0xbe, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0},12); |
1439 | - |
1440 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1441 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1442 | - d->sg_buffer[5] = begin & 0xFF; |
1443 | - d->sg_buffer[8] = sectors; |
1444 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1445 | - return(ret); |
1446 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1447 | - return(0); |
1448 | +static int i_read_D8(cdrom_drive *d, void *p, long begin, long sectors){ |
1449 | + return generic_scsi_read(d, p, begin, sectors, |
1450 | + D8_READ_12(begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); |
1451 | } |
1452 | |
1453 | -static int i_read_mmc2 (cdrom_drive *d, void *p, long begin, long sectors){ |
1454 | - int ret; |
1455 | - memcpy(d->sg_buffer,(char []){0xbe, 0, 0, 0, 0, 0, 0, 0, 0, 0xf8, 0, 0},12); |
1456 | - |
1457 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1458 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1459 | - d->sg_buffer[5] = begin & 0xFF; |
1460 | - d->sg_buffer[8] = sectors; |
1461 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1462 | - return(ret); |
1463 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1464 | - return(0); |
1465 | +static int i_read_mmc(cdrom_drive *d, void *p, long begin, long sectors){ |
1466 | + return generic_scsi_read(d, p, begin, sectors, |
1467 | + READ_CD_12(begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); |
1468 | } |
1469 | |
1470 | -static int i_read_mmc3 (cdrom_drive *d, void *p, long begin, long sectors){ |
1471 | - int ret; |
1472 | - memcpy(d->sg_buffer,(char []){0xbe, 4, 0, 0, 0, 0, 0, 0, 0, 0xf8, 0, 0},12); |
1473 | +static int i_read_mmc2(cdrom_drive *d, void *p, long begin, long sectors){ |
1474 | + char cmd[12]; |
1475 | |
1476 | - d->sg_buffer[3] = (begin >> 16) & 0xFF; |
1477 | - d->sg_buffer[4] = (begin >> 8) & 0xFF; |
1478 | - d->sg_buffer[5] = begin & 0xFF; |
1479 | - d->sg_buffer[8] = sectors; |
1480 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1481 | - return(ret); |
1482 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1483 | - return(0); |
1484 | + memcpy(cmd, READ_CD_12(begin, sectors), 12); |
1485 | + cmd[9] = 0xf8; |
1486 | + return generic_scsi_read(d, p, begin, sectors, |
1487 | + cmd, 12, 0, sectors * CD_FRAMESIZE_RAW); |
1488 | } |
1489 | |
1490 | -/* straight from the MMC3 spec */ |
1491 | -static inline void LBA_to_MSF(long lba, |
1492 | - unsigned char *M, |
1493 | - unsigned char *S, |
1494 | - unsigned char *F){ |
1495 | - if(lba>=-150){ |
1496 | - *M=(lba+150)/(60*75); |
1497 | - lba-=(*M)*60*75; |
1498 | - *S=(lba+150)/75; |
1499 | - lba-=(*S)*75; |
1500 | - *F=(lba+150); |
1501 | - }else{ |
1502 | - *M=(lba+450150)/(60*75); |
1503 | - lba-=(*M)*60*75; |
1504 | - *S=(lba+450150)/75; |
1505 | - lba-=(*S)*75; |
1506 | - *F=(lba+450150); |
1507 | - } |
1508 | -} |
1509 | - |
1510 | - |
1511 | -static int i_read_msf (cdrom_drive *d, void *p, long begin, long sectors){ |
1512 | - int ret; |
1513 | - memcpy(d->sg_buffer,(char []){0xb9, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0},12); |
1514 | +static int i_read_mmc3(cdrom_drive *d, void *p, long begin, long sectors){ |
1515 | + char cmd[12]; |
1516 | |
1517 | - LBA_to_MSF(begin,d->sg_buffer+3,d->sg_buffer+4,d->sg_buffer+5); |
1518 | - LBA_to_MSF(begin+sectors,d->sg_buffer+6,d->sg_buffer+7,d->sg_buffer+8); |
1519 | + memcpy(cmd, READ_CD_12(begin, sectors), 12); |
1520 | + cmd[1] = 4; |
1521 | + cmd[9] = 0xf8; |
1522 | + return generic_scsi_read(d, p, begin, sectors, |
1523 | + cmd, 12, 0, sectors * CD_FRAMESIZE_RAW); |
1524 | +} |
1525 | |
1526 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1527 | - return(ret); |
1528 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1529 | - return(0); |
1530 | +static int i_read_msf(cdrom_drive *d, void *p, long begin, long sectors){ |
1531 | + return generic_scsi_read(d, p, begin, sectors, |
1532 | + READ_CD_MSF_12(begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); |
1533 | } |
1534 | |
1535 | static int i_read_msf2 (cdrom_drive *d, void *p, long begin, long sectors){ |
1536 | - int ret; |
1537 | - memcpy(d->sg_buffer,(char []){0xb9, 0, 0, 0, 0, 0, 0, 0, 0, 0xf8, 0, 0},12); |
1538 | + char cmd[12]; |
1539 | |
1540 | - LBA_to_MSF(begin,d->sg_buffer+3,d->sg_buffer+4,d->sg_buffer+5); |
1541 | - LBA_to_MSF(begin+sectors,d->sg_buffer+6,d->sg_buffer+7,d->sg_buffer+8); |
1542 | - |
1543 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1544 | - return(ret); |
1545 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1546 | - return(0); |
1547 | + memcpy(cmd, READ_CD_MSF_12(begin, sectors), 12); |
1548 | + cmd[9] = 0xf8; |
1549 | + return generic_scsi_read(d, p, begin, sectors, |
1550 | + cmd, 12, 0, sectors * CD_FRAMESIZE_RAW); |
1551 | } |
1552 | |
1553 | static int i_read_msf3 (cdrom_drive *d, void *p, long begin, long sectors){ |
1554 | - int ret; |
1555 | - memcpy(d->sg_buffer,(char []){0xb9, 4, 0, 0, 0, 0, 0, 0, 0, 0xf8, 0, 0},12); |
1556 | + char cmd[12]; |
1557 | |
1558 | - LBA_to_MSF(begin,d->sg_buffer+3,d->sg_buffer+4,d->sg_buffer+5); |
1559 | - LBA_to_MSF(begin+sectors,d->sg_buffer+6,d->sg_buffer+7,d->sg_buffer+8); |
1560 | - |
1561 | - if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) |
1562 | - return(ret); |
1563 | - if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); |
1564 | - return(0); |
1565 | + memcpy(cmd, READ_CD_MSF_12(begin, sectors), 12); |
1566 | + cmd[1] = 4; |
1567 | + cmd[9] = 0xf8; |
1568 | + return generic_scsi_read(d, p, begin, sectors, |
1569 | + cmd, 12, 0, sectors * CD_FRAMESIZE_RAW); |
1570 | } |
1571 | |
1572 | static long scsi_read_map (cdrom_drive *d, void *p, long begin, long sectors, |
1573 | @@ -824,6 +929,10 @@ |
1574 | int retry_count,err; |
1575 | char *buffer=(char *)p; |
1576 | |
1577 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
1578 | + struct sg_io_hdr *hdr = sgi->hdr; |
1579 | + unsigned char key, ASC, ASCQ; |
1580 | + |
1581 | /* read d->nsectors at a time, max. */ |
1582 | sectors=(sectors>d->nsectors?d->nsectors:sectors); |
1583 | sectors=(sectors<1?1:sectors); |
1584 | @@ -832,17 +941,32 @@ |
1585 | |
1586 | while(1) { |
1587 | if((err=map(d,(p?buffer:NULL),begin,sectors))){ |
1588 | + /* Dunno if we even need this now that scsi_reset does it, |
1589 | + * but try to take "device is becoming ready" into account */ |
1590 | + key = hdr->sbp[2] & 0xf; |
1591 | + ASC = hdr->sbp[12]; |
1592 | + ASCQ = hdr->sbp[13]; |
1593 | + |
1594 | + if(key == 2 & ASC == 4 & ASCQ == 1) { |
1595 | + if(retry_count > MAX_RETRIES-1) { |
1596 | + char b[256]; |
1597 | + sprintf(b,"010: Unable to access sector %ld\n", |
1598 | + begin); |
1599 | + cderror(d,b); |
1600 | + return(-10); |
1601 | + } else { |
1602 | + retry_count++; |
1603 | + usleep(100); |
1604 | + continue; |
1605 | + } |
1606 | + } |
1607 | if(d->report_all){ |
1608 | - struct sg_header *sg_hd=(struct sg_header *)d->sg; |
1609 | char b[256]; |
1610 | - |
1611 | sprintf(b,"scsi_read error: sector=%ld length=%ld retry=%d\n", |
1612 | begin,sectors,retry_count); |
1613 | cdmessage(d,b); |
1614 | sprintf(b," Sense key: %x ASC: %x ASCQ: %x\n", |
1615 | - (int)(sg_hd->sense_buffer[2]&0xf), |
1616 | - (int)(sg_hd->sense_buffer[12]), |
1617 | - (int)(sg_hd->sense_buffer[13])); |
1618 | + key, ASC, ASCQ); |
1619 | cdmessage(d,b); |
1620 | sprintf(b," Transport error: %s\n",strerror_tr[err]); |
1621 | cdmessage(d,b); |
1622 | @@ -852,9 +976,7 @@ |
1623 | fprintf(stderr,"scsi_read error: sector=%ld length=%ld retry=%d\n", |
1624 | begin,sectors,retry_count); |
1625 | fprintf(stderr," Sense key: %x ASC: %x ASCQ: %x\n", |
1626 | - (int)(sg_hd->sense_buffer[2]&0xf), |
1627 | - (int)(sg_hd->sense_buffer[12]), |
1628 | - (int)(sg_hd->sense_buffer[13])); |
1629 | + key, ASC, ASCQ); |
1630 | fprintf(stderr," Transport error: %s\n",strerror_tr[err]); |
1631 | fprintf(stderr," System error: %s\n",strerror(errno)); |
1632 | } |
1633 | @@ -1014,7 +1136,7 @@ |
1634 | static int count_2352_bytes(cdrom_drive *d){ |
1635 | long i; |
1636 | for(i=2351;i>=0;i--) |
1637 | - if(d->sg_buffer[i]!=(unsigned char)'\177') |
1638 | + if(((struct sg_info *)d->sg)->dxferp[i]!=(unsigned char)'\177') |
1639 | return(((i+3)>>2)<<2); |
1640 | |
1641 | return(0); |
1642 | @@ -1023,7 +1145,7 @@ |
1643 | static int verify_nonzero(cdrom_drive *d){ |
1644 | long i,flag=0; |
1645 | for(i=0;i<2352;i++) |
1646 | - if(d->sg_buffer[i]!=0){ |
1647 | + if(((struct sg_info *)d->sg)->dxferp[i]!=0){ |
1648 | flag=1; |
1649 | break; |
1650 | } |
1651 | @@ -1307,7 +1429,17 @@ |
1652 | return; |
1653 | } |
1654 | |
1655 | -static int check_atapi(cdrom_drive *d){ |
1656 | +static int check_sgio(cdrom_drive *d) { |
1657 | + int fd = d->cdda_fd; |
1658 | + |
1659 | +#ifdef SG_IO |
1660 | + if (fd == check_fd_sgio(fd)) |
1661 | + return 1; |
1662 | +#endif |
1663 | + return 0; |
1664 | +} |
1665 | + |
1666 | +static int check_atapi(cdrom_drive *d, int using_sgio){ |
1667 | int atapiret=-1; |
1668 | int fd = d->cdda_fd; /* this is the correct fd (not ioctl_fd), as the |
1669 | generic device is the device we need to check */ |
1670 | @@ -1321,7 +1453,7 @@ |
1671 | if(atapiret==1){ |
1672 | cdmessage(d,"\tDrive is ATAPI (using SCSI host adaptor emulation)\n"); |
1673 | /* Disable kernel SCSI command translation layer for access through sg */ |
1674 | - if (ioctl(fd,SG_SET_TRANSFORM,0)) |
1675 | + if (!using_sgio && ioctl(fd,SG_SET_TRANSFORM,0)) |
1676 | cderror(d,"\tCouldn't disable kernel command translation layer\n"); |
1677 | d->is_atapi=1; |
1678 | }else{ |
1679 | @@ -1340,7 +1472,7 @@ |
1680 | d->is_mmc=0; |
1681 | if(mode_sense(d,22,0x2A)==0){ |
1682 | |
1683 | - b=d->sg_buffer; |
1684 | + b=((struct sg_info *)d->sg)->dxferp; |
1685 | b+=b[3]+4; |
1686 | |
1687 | if((b[0]&0x3F)==0x2A){ |
1688 | @@ -1380,21 +1512,27 @@ |
1689 | } |
1690 | |
1691 | /* request vendor brand and model */ |
1692 | -unsigned char *scsi_inquiry(cdrom_drive *d){ |
1693 | - memcpy(d->sg_buffer,(char[]){ 0x12,0,0,0,56,0},6); |
1694 | +unsigned char *scsi_inquiry(cdrom_drive *d) { |
1695 | + static char ret[56]; |
1696 | + struct sg_info *sgi = (struct sg_info *)d->sg; |
1697 | |
1698 | - if(handle_scsi_cmd(d,6, 0, 56,'\377',1)) { |
1699 | + if (sgi->hdr == NULL) |
1700 | + scsi_init_drive(d); |
1701 | + |
1702 | + sgi->setup_scsi_cmd(d, SCSI_INQUIRY_6(56), 6, 0, 56); |
1703 | + if (sgi->handle_scsi_cmd(d)) { |
1704 | cderror(d,"008: Unable to identify CDROM model\n"); |
1705 | - return(NULL); |
1706 | + return NULL; |
1707 | } |
1708 | - return (d->sg_buffer); |
1709 | + memcpy(ret, ((struct sg_info *)d->sg)->dxferp, 56); |
1710 | + return ret; |
1711 | } |
1712 | |
1713 | - |
1714 | int scsi_init_drive(cdrom_drive *d){ |
1715 | - int ret; |
1716 | + int ret, is_sgio; |
1717 | |
1718 | - check_atapi(d); |
1719 | + is_sgio = check_sgio(d); |
1720 | + check_atapi(d, is_sgio); |
1721 | check_mmc(d); |
1722 | |
1723 | /* generic Sony type defaults; specialize from here */ |
1724 | @@ -1451,15 +1589,16 @@ |
1725 | if(d->tracks<1) |
1726 | return(d->tracks); |
1727 | |
1728 | - tweak_SG_buffer(d); |
1729 | d->opened=1; |
1730 | |
1731 | if((ret=verify_read_command(d)))return(ret); |
1732 | check_fua_bit(d); |
1733 | |
1734 | d->error_retry=1; |
1735 | - d->sg=realloc(d->sg,d->nsectors*CD_FRAMESIZE_RAW + SG_OFF + 128); |
1736 | - d->sg_buffer=d->sg+SG_OFF; |
1737 | +#if 0 |
1738 | + ((struct sg_info *)d->sg)=realloc(((struct sg_info *)d->sg),d->nsectors*CD_FRAMESIZE_RAW + SG_OFF + 128); |
1739 | + ((struct sg_info *)d->sg)_buffer=((struct sg_info *)d->sg)+SG_OFF; |
1740 | +#endif |
1741 | d->report_all=1; |
1742 | return(0); |
1743 | } |
1744 | --- cdparanoia-III-alpha9.8/interface/scsi_cmds.h.sgio 2004-03-30 12:46:03.306332320 -0500 |
1745 | +++ cdparanoia-III-alpha9.8/interface/scsi_cmds.h 2004-03-30 14:09:53.760587032 -0500 |
1746 | @@ -0,0 +1,197 @@ |
1747 | +/****************************************************************** |
1748 | + * CopyPolicy: GNU General Public License version 2 |
1749 | + * Copyright 2004 Peter Jones <pjones@redhat.com> |
1750 | + * |
1751 | + * macros to generate scsi commands. |
1752 | + * |
1753 | + ******************************************************************/ |
1754 | + |
1755 | +#ifndef _SCSI_CMDS_H |
1756 | +#define _SCSI_CMDS_H 1 |
1757 | +#include <scsi/scsi.h> |
1758 | + |
1759 | +/* from the MMC3 spec, rewritten as seperate macros */ |
1760 | +#define LBA_to_M(lba) (lba>=-150?((lba+150)/(60*75)):((lba+450150)/(60*75))) |
1761 | +#define LBA_to_S(lba) (lba>=-150?((lba+150)/75):((lba+450150)/75)) |
1762 | +#define LBA_to_F(lba) (lba>=-150?(lba+150):(lba+450150)) |
1763 | + |
1764 | +/* Group 1 (10b) command */ |
1765 | +#define SCSI_TWELVE_BYTE(a,b,c,d,e,f,g,h,i,j,k,l) ((char []) {a,b,c,d,e,f,g,h,i,j,k,l}) |
1766 | +#define SCSI_READ_12(fua, a, l) SCSI_TWELVE_BYTE( \ |
1767 | + READ_12, /* READ_10 */ \ |
1768 | + (fua & 1) << 3, /* force unit access */ \ |
1769 | + (a >> 24) & 0xff, /* lba byte 3 */ \ |
1770 | + (a >> 16) & 0xff, /* lba byte 2 */ \ |
1771 | + (a >> 8) & 0xff, /* lba byte 1 */ \ |
1772 | + a & 0xff, /* lba byte 0 */ \ |
1773 | + 0, /* reserved */ \ |
1774 | + (l >> 24) & 0xff, /* len byte 3 */ \ |
1775 | + (l >> 16) & 0xff, /* len byte 2 */ \ |
1776 | + (l >> 8) & 0xff, /* len byte 1 */ \ |
1777 | + l & 0xff, /* len byte 0 */ \ |
1778 | + 0 /* control */ \ |
1779 | +) |
1780 | +#define D4_READ_12(a, l) SCSI_TWELVE_BYTE( \ |
1781 | + 0xD4, /* 0xD4 */ \ |
1782 | + 0, /* lun */ \ |
1783 | + 0, /* ? */ \ |
1784 | + (a >> 16) & 0xff, /* lba byte 2 */ \ |
1785 | + (a >> 8) & 0xff, /* lba byte 1 */ \ |
1786 | + a & 0xff, /* lba byte 0 */ \ |
1787 | + 0, /* reserved */ \ |
1788 | + 0, /* ? */ \ |
1789 | + 0, /* ? */ \ |
1790 | + l & 0xff, /* len byte 0 */ \ |
1791 | + 0, 0 /* ? */ \ |
1792 | +) |
1793 | +#define D8_READ_12(a, l) SCSI_TWELVE_BYTE( \ |
1794 | + 0xD8, /* 0xD4 */ \ |
1795 | + 0, /* lun */ \ |
1796 | + 0, /* ? */ \ |
1797 | + (a >> 16) & 0xff, /* lba byte 2 */ \ |
1798 | + (a >> 8) & 0xff, /* lba byte 1 */ \ |
1799 | + a & 0xff, /* lba byte 0 */ \ |
1800 | + 0, /* reserved */ \ |
1801 | + 0, /* ? */ \ |
1802 | + 0, /* ? */ \ |
1803 | + l & 0xff, /* len byte 0 */ \ |
1804 | + 0, 0 /* ? */ \ |
1805 | +) |
1806 | +#define READ_CD_12(a, l) SCSI_TWELVE_BYTE( \ |
1807 | + 0xBE, /* 0xD4 */ \ |
1808 | + 0, /* ? */ \ |
1809 | + (a >> 24) & 0xff, /* lba byte 3 */ \ |
1810 | + (a >> 16) & 0xff, /* lba byte 2 */ \ |
1811 | + (a >> 8) & 0xff, /* lba byte 1 */ \ |
1812 | + a & 0xff, /* lba byte 0 */ \ |
1813 | + (l >> 16) & 0xff, /* len byte 2 */ \ |
1814 | + (l >> 8) & 0xff, /* len byte 1 */ \ |
1815 | + l & 0xff, /* len byte 0 */ \ |
1816 | + 10, /* ecc */ \ |
1817 | + 0, 0 /* ? */ \ |
1818 | +) |
1819 | +#define READ_CD_MSF_12(a, l) SCSI_TWELVE_BYTE( \ |
1820 | + 0xB9, /* 0xD4 */ \ |
1821 | + 0, /* ? */ \ |
1822 | + 0, /* ? */ \ |
1823 | + LBA_to_M((a)), /* start M */ \ |
1824 | + LBA_to_S((a)), /* start S */ \ |
1825 | + LBA_to_F((a)), /* start F */ \ |
1826 | + LBA_to_M((a)+(l)), /* start M */ \ |
1827 | + LBA_to_S((a)+(l)), /* start S */ \ |
1828 | + LBA_to_F((a)+(l)), /* start F */ \ |
1829 | + 10, /* ecc */ \ |
1830 | + 0, 0 /* ? */ \ |
1831 | +) |
1832 | + |
1833 | +#define SCSI_TEN_BYTE(a,b,c,d,e,f,g,h,i,j) ((char []) {a,b,c,d,e,f,g,h,i,j}) |
1834 | +#define SCSI_MODE_SENSE_10(page, size) SCSI_TEN_BYTE( \ |
1835 | + MODE_SENSE_10, /* MODE_SENSE */ \ |
1836 | + 0x00, /* reserved */ \ |
1837 | + page & 0x3F, /* page */ \ |
1838 | + 0, /* reserved */ \ |
1839 | + 0, /* reserved */ \ |
1840 | + 0, /* reserved */ \ |
1841 | + 0, /* reserved */ \ |
1842 | + 0, /* MSB (0) */ \ |
1843 | + size, /* sizeof(modesense - SG_OFF) */ \ |
1844 | + 0 /* reserved */ \ |
1845 | +) |
1846 | +#define SCSI_MODE_SELECT_10 SCSI_TEN_BYTE( \ |
1847 | + MODE_SELECT_10, /* MODE_SELECT */ \ |
1848 | + 0x10, /* no save page */ \ |
1849 | + 0, /* reserved */ \ |
1850 | + 0, /* reserved */ \ |
1851 | + 0, /* reserved */ \ |
1852 | + 0, /* reserved */ \ |
1853 | + 0, /* reserved */ \ |
1854 | + 0, /* reserved */ \ |
1855 | + 12, /* sizeof(mode) */ \ |
1856 | + 0 /* reserved */ \ |
1857 | +) |
1858 | +#define SCSI_READ_TOC(track_number) SCSI_TEN_BYTE( \ |
1859 | + READ_TOC, /* READ_TOC */ \ |
1860 | + 0, /* MSF format */ \ |
1861 | + 0, \ |
1862 | + 0, \ |
1863 | + 0, \ |
1864 | + 0, \ |
1865 | + track_number, /* start track */ \ |
1866 | + 0, /* len msb */ \ |
1867 | + 12, /* len lsb */ \ |
1868 | + 0 /* flags */ \ |
1869 | +) |
1870 | +/* a contribution from Boris for IMS cdd 522 */ |
1871 | +/* check this for ACER/Creative/Foo 525,620E,622E, etc? */ |
1872 | +#define CDD522_READ_TOC(track_number) SCSI_TEN_BYTE( \ |
1873 | + 0xE5, /* CDD522_READ_TOC */ \ |
1874 | + 0, 0, 0, 0, /* res */ \ |
1875 | + track_number, /* start track */ \ |
1876 | + 0, 0, 0, 0 /* ? */ \ |
1877 | +) |
1878 | +#define SCSI_READ_10(fua, a, l) SCSI_TEN_BYTE( \ |
1879 | + READ_10, /* READ_10 */ \ |
1880 | + (fua?8:0), /* force unit access */ \ |
1881 | + (a >> 24) & 0xff, /* lba byte 3 */ \ |
1882 | + (a >> 16) & 0xff, /* lba byte 2 */ \ |
1883 | + (a >> 8) & 0xff, /* lba byte 1 */ \ |
1884 | + a & 0xff, /* lba byte 0 */ \ |
1885 | + 0, /* reserved */ \ |
1886 | + (l >> 8) & 0xff, /* len byte 1 */ \ |
1887 | + l & 0xff, /* len byte 0 */ \ |
1888 | + 0 /* control */ \ |
1889 | +) |
1890 | +#define D4_READ_10(a, l) SCSI_TEN_BYTE( \ |
1891 | + 0xD4, /* 0xD4 */ \ |
1892 | + 0, /* ? */ \ |
1893 | + 0, /* ? */ \ |
1894 | + (a >> 16) & 0xff, /* lba byte 2 */ \ |
1895 | + (a >> 8) & 0xff, /* lba byte 1 */ \ |
1896 | + a & 0xff, /* lba byte 0 */ \ |
1897 | + 0, /* reserved */ \ |
1898 | + 0, /* ? */ \ |
1899 | + l & 0xff, /* len byte 0 */ \ |
1900 | + 0 /* control */ \ |
1901 | +) |
1902 | +#define D5_READ_10(a, l) SCSI_TEN_BYTE( \ |
1903 | + 0xD5, /* 0xD5 */ \ |
1904 | + 0, /* lun */ \ |
1905 | + 0, /* ? */ \ |
1906 | + (a >> 16) & 0xff, /* lba byte 2 */ \ |
1907 | + (a >> 8) & 0xff, /* lba byte 1 */ \ |
1908 | + a & 0xff, /* lba byte 0 */ \ |
1909 | + 0, /* reserved */ \ |
1910 | + 0, /* ? */ \ |
1911 | + l & 0xff, /* len byte 0 */ \ |
1912 | + 0 /* control */ \ |
1913 | +) |
1914 | + |
1915 | + |
1916 | +#define SCSI_SIX_BYTE(a,b,c,d,e,f) ((char []) {a,b,c,d,e,f}) |
1917 | +#define SCSI_MODE_SENSE_6(page, size) SCSI_SIX_BYTE( \ |
1918 | + MODE_SENSE, /* MODE_SENSE */ \ |
1919 | + 0x00, /* return block descriptor/lun */ \ |
1920 | + page & 0x3F, /* page */ \ |
1921 | + 0, /* reserved */ \ |
1922 | + size, /* sizeof(modesense - SG_OFF) */ \ |
1923 | + 0 /* control */ \ |
1924 | +) |
1925 | +#define SCSI_MODE_SELECT_6 SCSI_SIX_BYTE( \ |
1926 | + MODE_SELECT, /* MODE_SELECT */ \ |
1927 | + 0x10, /* no save page */ \ |
1928 | + 0, /* reserved */ \ |
1929 | + 0, /* reserved */ \ |
1930 | + 12, /* sizeof(mode) */ \ |
1931 | + 0 /* reserved */ \ |
1932 | +) |
1933 | +#define SCSI_INQUIRY_6(len) SCSI_SIX_BYTE( \ |
1934 | + INQUIRY, /* INQUIRY */ \ |
1935 | + 0, 0, 0, /* ? */ \ |
1936 | + len, 0 /* len, ? */ \ |
1937 | +) |
1938 | +#define SCSI_TEST_UNIT_READY_6 SCSI_SIX_BYTE( \ |
1939 | + TEST_UNIT_READY,/* TEST_UNIT_READY */ \ |
1940 | + 0, 0, 0, 0, /* reserved */ \ |
1941 | + 0 /* control */ \ |
1942 | +) |
1943 | +#endif |