Annotation of /trunk/cdparanoia/patches/cdparanoia-3.9.8-sgio.patch
Parent Directory | Revision Log
Revision 144 -
(hide 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 | niro | 144 | 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 |