1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 1996, 1997 David Mosberger-Tang
3 Copyright (C) 2003 Frank Zago
4 This file is part of the SANE package.
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19 As a special exception, the authors of SANE give permission for
20 additional uses of the libraries contained in this release of SANE.
21
22 The exception is that, if you link a SANE library with other files
23 to produce an executable, this does not by itself cause the
24 resulting executable to be covered by the GNU General Public
25 License. Your use of that executable is in no way restricted on
26 account of linking the SANE library code into it.
27
28 This exception does not, however, invalidate any other reasons why
29 the executable file might be covered by the GNU General Public
30 License.
31
32 If you submit changes to SANE to the maintainers to be included in
33 a subsequent release, you agree by submitting the changes that
34 those changes may be distributed with this exception intact.
35
36 If you write modifications of your own for SANE, it is your choice
37 whether to permit this exception to apply to your modifications.
38 If you do not wish that, delete this exception notice.
39
40 This file provides a generic SCSI interface. */
41
42 #ifdef _AIX
43 # include "../include/lalloca.h" /* MUST come first for AIX! */
44 #endif
45
46 #include "../include/sane/config.h"
47 #include "../include/lalloca.h"
48 #include "../include/lassert.h"
49
50 #include <ctype.h>
51 #include <errno.h>
52 #include <fcntl.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <unistd.h>
56
57 #ifdef HAVE_SYS_IOCTL_H
58 #include <sys/ioctl.h>
59 #endif
60 #include <sys/param.h>
61 #include <sys/types.h>
62
63 #if defined (HAVE_WINDOWS_H)
64 # include <windows.h>
65 #endif
66
67 #define STUBBED_INTERFACE 0
68 #define LINUX_INTERFACE 1
69 #define BSD_INTERFACE 2
70 #define HPUX_INTERFACE 3
71 #define OPENSTEP_INTERFACE 4
72 #define DECUNIX_INTERFACE 5
73 #define SCO_OS5_INTERFACE 6
74 #define IRIX_INTERFACE 7
75 #define SOLARIS_INTERFACE 8
76 #define SOLARIS_SG_INTERFACE 9
77 #define OS2_INTERFACE 10
78 #define AIX_GSC_INTERFACE 11
79 #define DOMAINOS_INTERFACE 12
80 #define FREEBSD_CAM_INTERFACE 13
81 #define SYSVR4_INTERFACE 14
82 #define SCO_UW71_INTERFACE 15
83 #define SOLARIS_USCSI_INTERFACE 16
84 #define MACOSX_INTERFACE 17
85 #define WIN32_INTERFACE 18
86
87 #ifdef HAVE_RESMGR
88 # include <resmgr.h>
89 #endif
90
91 #if defined (HAVE_SCSI_SG_H)
92 # define USE LINUX_INTERFACE
93 # include <scsi/sg.h>
94 #elif defined (HAVE__USR_SRC_LINUX_INCLUDE_SCSI_SG_H)
95 # define USE LINUX_INTERFACE
96 # include "/usr/src/linux/include/scsi/sg.h"
97 #elif defined (HAVE_SYS_SCSICMD_H)
98 # define USE SCSO_OS5_INTERFACE
99 # include <sys/scsi.h>
100 # include <sys/scsicmd.h>
101 #elif defined (HAVE_CAMLIB_H)
102 # define USE FREEBSD_CAM_INTERFACE
103 # include <stdio.h> /* there is a bug in scsi_all.h */
104 # ifdef __DragonFly__
105 # include <bus/cam/cam.h>
106 # include <bus/cam/cam_ccb.h>
107 # include <bus/cam/scsi/scsi_message.h>
108 # include <bus/cam/scsi/scsi_pass.h>
109 # else
110 # include <cam/cam.h>
111 # include <cam/cam_ccb.h>
112 # include <cam/scsi/scsi_message.h>
113 # include <cam/scsi/scsi_pass.h>
114 # endif
115 # include <camlib.h>
116 #elif defined (HAVE_SYS_SCSIIO_H)
117 # define USE BSD_INTERFACE
118 # include <sys/scsiio.h>
119 # ifdef HAVE_SCSI_H
120 # include <scsi.h>
121 # endif
122 #elif defined (HAVE_BSD_DEV_SCSIREG_H)
123 # define USE OPENSTEP_INTERFACE
124 # include <bsd/dev/scsireg.h>
125 #elif defined (HAVE_IO_CAM_CAM_H)
126 # define USE DECUNIX_INTERFACE
127 # include <io/common/iotypes.h>
128 # include <io/cam/cam.h>
129 # include <io/cam/dec_cam.h>
130 # include <io/cam/uagt.h>
131 # include <io/cam/scsi_all.h>
132 #elif defined (HAVE_SYS_DSREQ_H)
133 # define USE IRIX_INTERFACE
134 # include <sys/dsreq.h>
135 # include <invent.h>
136 #elif defined (HAVE_SYS_SCSI_H)
137 # include <sys/scsi.h>
138 # ifdef HAVE_SYS_SDI_COMM_H
139 # ifdef HAVE_SYS_PASSTHRUDEF_H
140 # define USE SCO_UW71_INTERFACE
141 # include <sys/scsi.h>
142 # include <sys/sdi_edt.h>
143 # include <sys/sdi.h>
144 # include <sys/passthrudef.h>
145 # else
146 # define USE SYSVR4_INTERFACE /* Unixware 2.x tested */
147 # define HAVE_SYSV_DRIVER
148 # include <sys/sdi_edt.h>
149 # include <sys/sdi_comm.h>
150 # endif
151 # else
152 # ifdef SCTL_READ
153 # define USE HPUX_INTERFACE
154 # else
155 # ifdef HAVE_GSCDDS_H
156 # define USE AIX_GSC_INTERFACE
157 # include <gscdds.h>
158 # else
159 /* This happens for AIX without gsc and possibly other platforms... */
160 # endif
161 # endif
162 # endif
163 #elif defined (HAVE_OS2_H)
164 # define USE OS2_INTERFACE
165 # define INCL_DOSFILEMGR
166 # define INCL_DOS
167 # define INCL_DOSDEVICES
168 # define INCL_DOSDEVIOCTL
169 # define INCL_DOSMEMMGR
170 # include <os2.h>
171 # include "os2_srb.h"
172 #elif defined (HAVE_SYS_SCSI_SGDEFS_H)
173 # define USE SOLARIS_SG_INTERFACE
174 # include <sys/scsi/sgdefs.h>
175 #elif defined (HAVE_SYS_SCSI_TARGETS_SCGIO_H)
176 # define USE SOLARIS_INTERFACE
177 # define SOL2
178 # include <sys/scsi/targets/scgio.h>
179 #elif defined (HAVE_SYS_SCSI_SCSI_H)
180 /*
181 * the "official" solaris uscsi(7I) interface; comes last, so that users
182 * installing the SCG/SG driver can still use these generic scsi interfaces
183 */
184 # define USE SOLARIS_USCSI_INTERFACE
185 # define SOL2
186 # include <sys/scsi/scsi.h>
187 #elif defined (HAVE_APOLLO_SCSI_H)
188 # define USE DOMAINOS_INTERFACE
189 # include <signal.h> /* Only used for signal name for KillDomainServer */
190 # include <apollo/base.h>
191 # include <apollo/ec2.h>
192 # include <apollo/error.h>
193 # include <apollo/ms.h>
194 # include <apollo/mutex.h>
195 # include <apollo/scsi.h>
196 # include <apollo/time.h>
197 # include "sanei_DomainOS.h"
198 #elif defined (HAVE_IOKIT_CDB_IOSCSILIB_H) || \
199 defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \
200 defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H)
201 # define USE MACOSX_INTERFACE
202 # include <CoreFoundation/CoreFoundation.h>
203 # include <IOKit/IOKitLib.h>
204 # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H
205 # include <IOKit/IOCFPlugIn.h>
206 # include <IOKit/cdb/IOSCSILib.h>
207 # endif
208 # ifdef HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H
209 /* The def of VERSION causes problems in the following include files */
210 # undef VERSION
211 # include <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h>
212 # include <IOKit/scsi/SCSICommandOperationCodes.h>
213 # include <IOKit/scsi/SCSITaskLib.h>
214 # else
215 # ifdef HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H
216 /* The def of VERSION causes problems in the following include files */
217 # undef VERSION
218 # include <IOKit/scsi-commands/SCSICmds_INQUIRY_Definitions.h>
219 # include <IOKit/scsi-commands/SCSICommandOperationCodes.h>
220 # include <IOKit/scsi-commands/SCSITaskLib.h>
221 # endif
222 # endif
223 #elif defined (HAVE_DDK_NTDDSCSI_H)
224 # define USE WIN32_INTERFACE
225 # include <ddk/scsi.h>
226 # include <ddk/ntddscsi.h>
227 #elif defined (HAVE_NTDDSCSI_H)
228 # define USE WIN32_INTERFACE
229 # include <ntddscsi.h>
230 #endif
231
232 #ifndef USE
233 # define USE STUBBED_INTERFACE
234 #endif
235
236 #if USE == LINUX_INTERFACE
237 # include <dirent.h>
238 #endif
239
240 #include "../include/sane/sanei.h"
241 #include "../include/sane/sanei_config.h"
242 #include "../include/sane/sanei_scsi.h"
243
244 #define BACKEND_NAME sanei_scsi
245 #include "../include/sane/sanei_debug.h"
246
247 #if USE == DECUNIX_INTERFACE
248 static int cam_fd = -1; /* used for SCSI CAM based interfaces */
249 #endif
250
251 #if USE == SOLARIS_INTERFACE || USE == SOLARIS_USCSI_INTERFACE
252 static int unit_ready (int fd);
253 #endif
254
255 #ifdef SG_BIG_BUFF
256 # define MAX_DATA SG_BIG_BUFF
257 #endif
258
259 #if USE == SYSVR4_INTERFACE
260 # define MAX_DATA 56*1024 /* don't increase or kernel will dump
261 * tested with adsl, adsa and umax backend
262 * it depends on the lowend scsi
263 * drivers . But the most restriction
264 * is in the UNIXWARE KERNEL witch do
265 * not allow more then 64kB DMA transfers */
266 static char lastrcmd[16]; /* hold command block of last read command */
267 #endif
268
269 #if USE == OPENSTEP_INTERFACE
270 # define MAX_DATA (120*1024)
271 #endif
272
273 #if USE == IRIX_INTERFACE
274 # define MAX_DATA (256*1024)
275 #endif
276
277 #if USE == FREEBSD_CAM_INTERFACE
278 # define MAX_DATA (DFLTPHYS - PAGE_SIZE)
279 #endif
280
281 #if USE == SOLARIS_INTERFACE
282 # define MAX_DATA (128*1024)
283 #endif
284
285 #if USE == SOLARIS_SG_INTERFACE
286 # define MAX_DATA (128*1024)
287 #endif
288
289 #if USE == SOLARIS_USCSI_INTERFACE
290 # define MAX_DATA (64*1024)
291 #endif
292
293 #if USE == OS2_INTERFACE
294 # define MAX_DATA (64*1024)
295 #endif
296
297 #if USE == MACOSX_INTERFACE
298 # define MAX_DATA (128*1024)
299 #endif
300
301
302 #ifndef MAX_DATA
303 # define MAX_DATA (32*1024)
304 #endif
305
306 #ifdef SG_SET_TIMEOUT
307 # ifdef _SC_CLK_TCK
308 # define GNU_HZ sysconf(_SC_CLK_TCK)
309 # else
310 # ifdef HZ
311 # define GNU_HZ HZ
312 # else
313 # ifdef CLOCKS_PER_SEC
314 # define GNU_HZ CLOCKS_PER_SEC
315 # endif
316 # endif
317 # endif
318 #endif
319
320 /* default timeout value: 120 seconds */
321 static int sane_scsicmd_timeout = 120;
322 int sanei_scsi_max_request_size = MAX_DATA;
323 #if USE == LINUX_INTERFACE
324 /* the following #defines follow Douglas Gilbert's sample code
325 to maintain run time compatibility with the old and the
326 new SG driver for Linux
327 */
328 #include "linux_sg3_err.h" /* contains several definitions of error codes */
329 #ifndef SG_SET_COMMAND_Q
330 #define SG_SET_COMMAND_Q 0x2271
331 #endif
332 #ifndef SG_SET_RESERVED_SIZE
333 #define SG_SET_RESERVED_SIZE 0x2275
334 #endif
335 #ifndef SG_GET_RESERVED_SIZE
336 #define SG_GET_RESERVED_SIZE 0x2272
337 #endif
338 #ifndef SG_GET_SCSI_ID
339 #define SG_GET_SCSI_ID 0x2276
340 #else
341 #define SG_GET_SCSI_ID_FOUND
342 #endif
343 #ifndef SG_GET_VERSION_NUM
344 #define SG_GET_VERSION_NUM 0x2282
345 #endif
346 #ifndef SG_NEXT_CMD_LEN
347 #define SG_NEXT_CMD_LEN 0x2283
348 #endif
349
350 #ifndef SCSIBUFFERSIZE
351 #define SCSIBUFFERSIZE (128 * 1024)
352 #endif
353
354 /* the struct returned by the SG ioctl call SG_GET_SCSI_ID changed
355 from version 2.1.34 to 2.1.35, and we need the information from
356 the field s_queue_depth, which was introduced in 2.1.35.
357 To get this file compiling also with older versions of sg.h, the
358 struct is re-defined here.
359 */
360 typedef struct xsg_scsi_id
361 {
362 int host_no; /* as in "scsi<n>" where 'n' is one of 0, 1, 2 etc */
363 int channel;
364 int scsi_id; /* scsi id of target device */
365 int lun;
366 int scsi_type; /* TYPE_... defined in scsi/scsi.h */
367 short h_cmd_per_lun; /* host (adapter) maximum commands per lun */
368 short d_queue_depth; /* device (or adapter) maximum queue length */
369 int unused1; /* probably find a good use, set 0 for now */
370 int unused2; /* ditto */
371 }
372 SG_scsi_id;
373
374 typedef struct req
375 {
376 struct req *next;
377 int fd;
378 u_int running:1, done:1;
379 SANE_Status status;
380 size_t *dst_len;
381 void *dst;
382 /* take the definition of the ioctl parameter SG_IO as a
383 compiler flag if the new SG driver is available
384 */
385 union
386 {
387 struct
388 {
389 struct sg_header hdr;
390 /* Make sure this is the last element, the real size is
391 SG_BIG_BUFF and machine dependent */
392 u_int8_t data[1];
393 }
394 cdb;
395 #ifdef SG_IO
396 /* at present, Linux's SCSI system limits the sense buffer to 16 bytes
397 which is definitely too small. Hoping that this will change at some time,
398 let's set the sense buffer size to 64.
399 */
400 #define SENSE_MAX 64
401 #define MAX_CDB 12
402 struct
403 {
404 struct sg_io_hdr hdr;
405 u_char sense_buffer[SENSE_MAX];
406 u_int8_t data[1];
407 }
408 sg3;
409 #endif
410 }
411 sgdata;
412 }
413 req;
414
415 typedef struct Fdparms
416 {
417 int sg_queue_used, sg_queue_max;
418 size_t buffersize;
419 req *sane_qhead, *sane_qtail, *sane_free_list;
420 }
421 fdparms;
422
423 #endif
424
425 #if USE == FREEBSD_CAM_INTERFACE
426 # define CAM_MAXDEVS 128
427 struct cam_device *cam_devices[CAM_MAXDEVS] = { NULL };
428 #endif
429
430 static struct
431 {
432 u_int in_use:1; /* is this fd_info in use? */
433 u_int fake_fd:1; /* is this a fake file descriptor? */
434 u_int bus, target, lun; /* nexus info; used for some interfaces only */
435 SANEI_SCSI_Sense_Handler sense_handler;
436 void *sense_handler_arg;
437 void *pdata; /* platform-specific data */
438 }
439 *fd_info;
440
441 static u_char cdb_sizes[8] = {
442 6, 10, 10, 12, 12, 12, 10, 10
443 };
444 #define CDB_SIZE(opcode) cdb_sizes[(((opcode) >> 5) & 7)]
445
446
447 #if USE == DOMAINOS_INTERFACE
448
449 /*
450 This includes the server code. Most of these routines are private to the
451 actual server. The only public ones are:
452 sanei_DomainOS_init Used to initialize the server
453 DomainErrorCheck A common error handling routine
454 */
455
456 #include "sanei_DomainOS.c"
457
458 int ServerInitialized = 0;
459 pid_t ServerPID;
460 struct DomainServerCommon *com;
461 long CommandTriggerValue[2];
462 ec2_$ptr_t CommandAcceptedPtr[2];
463 long ResultTriggerValue[2];
464 ec2_$ptr_t ResultReadyPtr[2];
465 time_$clock_t Wait16S = { 64, 0 }; /* Delay of about 16 Seconds */
466
467
468 /* This function is registered as an exit function. It's purpose is
469 to make sure that the Domain SANE Server is stopped. It tries to
470 send an Exit command, and if that fails, it will send SIGQUIT to
471 the server. It will also unmap the common area before it
472 returns. */
473 static void
KillDomainServer(void)474 KillDomainServer (void)
475 {
476 static boolean GotTheLock;
477 static status_$t status;
478 static pinteger index;
479
480 DBG (1, "Asking Domain SANE Server to exit\n");
481 /* First, try to send a command to exit */
482 if (GotTheLock = mutex_$lock (&com->CommandLock, Wait16S))
483 {
484 /* Set the wait time to 16 Seconds (units are 4uS) */
485 com->opcode = Exit;
486 CommandTriggerValue[0] = ec2_$read (com->CommandAccepted) + 1;
487 ec2_$advance (&com->CommandAvailable, &status);
488 DomainErrorCheck (status, "Can't advance CommandAvailable EC");
489 /* For this wait, we want to allow a timeout as well */
490 CommandTriggerValue[1] = (ec2_$read (*CommandAcceptedPtr[1])
491 + DomainECWaitConstant);
492 index = ec2_$wait_svc (CommandAcceptedPtr, CommandTriggerValue, 2,
493 &status);
494 DomainErrorCheck (status,
495 "Error waiting on Exit command acceptance EC");
496 /* Release the lock */
497 mutex_$unlock (&com->CommandLock);
498 if (index == 1)
499 DBG (1, "Domain SANE Server responded to exit request\n");
500 else
501 DBG (1, "Domain SANE Server did not respond to exit request\n");
502 }
503 else
504 DBG (0, "Could not get mutex lock for killing server\n");
505 if ((!GotTheLock) || (index != 1))
506 {
507 /* If we get here, then we never got the mutex lock, or we timed out
508 waiting for an Exit command ack. */
509 /* It's now time to be brutal with the server */
510 DBG (1, "Sending QUIT signal to Domain SANE Server\n");
511 kill (ServerPID, SIGQUIT);
512 }
513 /* unmap the common area */
514 ms_$unmap (com, sizeof (struct DomainServerCommon), &status);
515 DomainErrorCheck (status, "Error unmapping common area");
516 }
517 #endif /* USE == DOMAINOS_INTERFACE */
518
519
520 #if USE == OS2_INTERFACE
521
522 /* Driver info: */
523 static HFILE driver_handle = 0; /* file handle for device driver */
524 static PVOID aspi_buf = 0; /* Big data buffer locked by driver. */
525 static int aspi_ref_count = 0; /* # of fds using ASPI */
526 static SRB *PSRBlock = 0; /* SCSI Request Block */
527 static char tmpAspi[MAXPATHLEN]; /* scsi chain scan */
528 #define INQUIRY 0x12
529 #define set_inquiry_return_size(icb,val) icb[0x04]=val
530 #define IN_periph_devtype_cpu 0x03
531 #define IN_periph_devtype_scanner 0x06
532 #define get_inquiry_vendor(in, buf) strncpy(buf, in + 0x08, 0x08)
533 #define get_inquiry_product(in, buf) strncpy(buf, in + 0x10, 0x010)
534 #define get_inquiry_version(in, buf) strncpy(buf, in + 0x20, 0x04)
535 #define get_inquiry_periph_devtype(in) (in[0] & 0x1f)
536 #define get_inquiry_additional_length(in) in[0x04]
537 #define set_inquiry_length(out,n) out[0x04]=n-5
538
539 /* Open OS2 ASPI driver.
540
541 Output: 0 if error, which is reported. */
542 static int
open_aspi(void)543 open_aspi (void)
544 {
545 ULONG rc;
546 ULONG ActionTaken;
547 USHORT lockSegmentReturn;
548 unsigned long cbreturn = 0;
549 unsigned long cbParam = 0;
550 int i, num_adapters; /* no. of scsi adapters installed */
551
552 char *devtypes[] = {
553 "disk", "tape", "printer", "processor", "CD-writer",
554 "CD-drive", "scanner", "optical-drive", "jukebox",
555 "communicator"
556 };
557 FILE *tmp;
558
559 if (driver_handle)
560 {
561 aspi_ref_count++; /* increment internal usage counter */
562 return 1; /* Already open. */
563 }
564 aspi_buf = _tcalloc (sanei_scsi_max_request_size, 1);
565 if (aspi_buf == NULL)
566 {
567 DBG (1, "sanei_scsi_open_aspi: _tcalloc aspi_buf failed");
568 return 0;
569 }
570
571 PSRBlock = _tcalloc (sizeof (SRB), 1);
572 if (PSRBlock == NULL)
573 {
574 DBG (1, "sanei_scsi_open_aspi: _tcalloc PSRBlock failed");
575 return 0;
576 }
577
578 rc = DosOpen ((PSZ) "aspirou$", /* open driver */
579 &driver_handle,
580 &ActionTaken,
581 0,
582 0,
583 FILE_OPEN,
584 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, NULL);
585 if (rc)
586 {
587 /* opening failed -> return false */
588 DBG (1, "open_aspi: opening failed.\n");
589 return 0;
590 }
591
592 /* Lock aspi_buf. */
593 rc = DosDevIOCtl (driver_handle, 0x92, 0x04, /* pass aspi_buf pointer */
594 (void *) aspi_buf, sizeof (PVOID), /* to driver */
595 &cbParam, (void *) &lockSegmentReturn,
596 sizeof (USHORT), &cbreturn);
597 if (rc || lockSegmentReturn)
598 {
599 /* DosDevIOCtl failed */
600 DBG (1, "sanei_scsi_open_aspi: Can't lock buffer. rc= %lu \n", rc);
601 return 0;
602 }
603
604 /* query number of installed adapters */
605 memset (PSRBlock, 0, sizeof (SRB));
606 PSRBlock->cmd = SRB_Inquiry; /* host adapter inquiry */
607
608 PSRBlock->ha_num = 0; /* host adapter number */
609
610 PSRBlock->flags = 0; /* no flags set */
611
612 rc = DosDevIOCtl (driver_handle, 0x92, 0x02,
613 (void *) PSRBlock, sizeof (SRB), &cbParam,
614 (void *) PSRBlock, sizeof (SRB), &cbreturn);
615 num_adapters = PSRBlock->u.inq.num_ha;
616
617 DBG (1, "OS/2: installed adapters %d\n", num_adapters);
618 DBG (1, "OS/2: ASPI manager is '%s'\n", PSRBlock->u.inq.aspimgr_id);
619 DBG (1, "OS/2: host adapter is '%s'\n", PSRBlock->u.inq.host_id);
620 DBG (1, "OS/2: unique id is '%s'\n", PSRBlock->u.inq.unique_id);
621
622 strcpy (tmpAspi, "asXXXXXX");
623 mkstemp (tmpAspi);
624 DBG (2, "open_aspi: open temporary file '%s'\n", tmpAspi);
625 tmp = fopen (tmpAspi, "w");
626 if (!tmp)
627 { /* can't open tmp file */
628
629 DBG (1, "open_aspi: Can't open temporary file.\n");
630 return 0;
631 }
632
633 /* scan all installed adapters */
634 for (i = 0; i < num_adapters; i++)
635 {
636 int id;
637 /* query adapter name */
638 memset (PSRBlock, 0, sizeof (SRB));
639 PSRBlock->cmd = SRB_Inquiry; /* host adapter inquiry */
640
641 PSRBlock->ha_num = i; /* host adapter number */
642
643 PSRBlock->flags = 0; /* no flags set */
644
645 rc = DosDevIOCtl (driver_handle, 0x92, 0x02,
646 (void *) PSRBlock, sizeof (SRB), &cbParam,
647 (void *) PSRBlock, sizeof (SRB), &cbreturn);
648 DBG (1, "OS/2: adapter#%02d '%s'\n", i, PSRBlock->u.inq.host_id);
649
650 /* scan scsi chain (need 15 for wide?) */
651 for (id = 0; id < 7; id++)
652 {
653 unsigned char len;
654 char vendor[9];
655 char product[17];
656 char version[5];
657 char *pp;
658
659 memset (PSRBlock, 0, sizeof (SRB));
660 PSRBlock->cmd = SRB_Device; /* get device type */
661
662 PSRBlock->ha_num = i; /* host adapter number */
663
664 PSRBlock->flags = 0; /* no flags set */
665
666 PSRBlock->u.dev.target = id; /* target id */
667
668 PSRBlock->u.dev.lun = 0; /* target LUN */
669
670 rc = DosDevIOCtl (driver_handle, 0x92, 0x02,
671 (void *) PSRBlock, sizeof (SRB), &cbParam,
672 (void *) PSRBlock, sizeof (SRB), &cbreturn);
673 DBG (1, "OS/2: id#%02d status=%02xh\n",
674 id, PSRBlock->status);
675
676 /* skip if device not connected */
677 if (PSRBlock->status == SRB_BadDevice)
678 continue;
679
680 DBG (1, "OS/2: type is '%s'\n",
681 PSRBlock->u.dev.devtype < sizeof (devtypes) / sizeof (char *)?
682 devtypes[PSRBlock->u.dev.devtype] : "unknown device");
683
684 /* query adapter string id */
685 memset (PSRBlock, 0, sizeof (SRB));
686 PSRBlock->cmd = SRB_Command; /* execute SCSI command */
687
688 PSRBlock->ha_num = i; /* host adapter number */
689 PSRBlock->flags = SRB_Read | SRB_Post; /* data transfer, posting */
690 PSRBlock->u.cmd.target = id; /* Target SCSI ID */
691 PSRBlock->u.cmd.lun = 0; /* Target SCSI LUN */
692 PSRBlock->u.cmd.data_len = 5; /* # of bytes transferred */
693 PSRBlock->u.cmd.sense_len = 32; /* length of sense buffer */
694 PSRBlock->u.cmd.data_ptr = NULL; /* pointer to data buffer */
695 PSRBlock->u.cmd.link_ptr = NULL; /* pointer to next SRB */
696 PSRBlock->u.cmd.cdb_len = 6; /* SCSI command length */
697 PSRBlock->u.cmd.cdb_st[0] = INQUIRY; /* inquiry command */
698 PSRBlock->u.cmd.cdb_st[1] = 0; /* ?? length */
699 PSRBlock->u.cmd.cdb_st[2] = 0; /* transfer length MSB */
700 PSRBlock->u.cmd.cdb_st[3] = 0; /* transfer length */
701 PSRBlock->u.cmd.cdb_st[4] = 5; /* transfer length LSB */
702 PSRBlock->u.cmd.cdb_st[5] = 0;
703 rc = DosDevIOCtl (driver_handle, 0x92, 0x02,
704 (void *) PSRBlock, sizeof (SRB), &cbParam,
705 (void *) PSRBlock, sizeof (SRB), &cbreturn);
706 len = ((char *) aspi_buf)[4]; /* additional length */
707
708 /* query id string */
709 memset (PSRBlock, 0, sizeof (SRB));
710 PSRBlock->cmd = SRB_Command; /* execute SCSI command */
711 PSRBlock->ha_num = i; /* host adapter number */
712 PSRBlock->flags = SRB_Read | SRB_Post; /* data transfer, posting */
713 PSRBlock->u.cmd.target = id; /* Target SCSI ID */
714 PSRBlock->u.cmd.lun = 0; /* Target SCSI LUN */
715 PSRBlock->u.cmd.data_len = 5 + len; /* # of bytes transferred */
716 PSRBlock->u.cmd.sense_len = 32; /* length of sense buffer */
717 PSRBlock->u.cmd.data_ptr = NULL; /* pointer to data buffer */
718 PSRBlock->u.cmd.link_ptr = NULL; /* pointer to next SRB */
719 PSRBlock->u.cmd.cdb_len = 6; /* SCSI command length */
720 PSRBlock->u.cmd.cdb_st[0] = 0x12; /* inquiry command */
721 PSRBlock->u.cmd.cdb_st[1] = 0; /* ?? length */
722 PSRBlock->u.cmd.cdb_st[2] = 0; /* transfer length MSB */
723 PSRBlock->u.cmd.cdb_st[3] = 0; /* transfer length */
724 PSRBlock->u.cmd.cdb_st[4] = 5 + len; /* transfer length LSB */
725 PSRBlock->u.cmd.cdb_st[5] = 0;
726 rc = DosDevIOCtl (driver_handle, 0x92, 0x02,
727 (void *) PSRBlock, sizeof (SRB), &cbParam,
728 (void *) PSRBlock, sizeof (SRB), &cbreturn);
729 DBG (1, "OS/2 '%s'\n", (char *) aspi_buf + 8);
730 /* write data */
731 get_inquiry_vendor ((char *) aspi_buf, vendor);
732 get_inquiry_product ((char *) aspi_buf, product);
733 get_inquiry_version ((char *) aspi_buf, version);
734
735 pp = &vendor[7];
736 vendor[8] = '\0';
737 while (pp >= vendor && (*pp == ' ' || *pp >= 127))
738 *pp-- = '\0';
739
740 pp = &product[15];
741 product[16] = '\0';
742 while (pp >= product && (*pp == ' ' || *pp >= 127))
743 *pp-- = '\0';
744
745 pp = product;
746 do
747 {
748 if (isspace ((int) *pp))
749 *pp = '_';
750 }
751 while (*++pp);
752
753 pp = &version[3];
754 version[4] = '\0';
755 while (pp >= version && (*pp == ' ' || *(pp - 1) >= 127))
756 *pp-- = '\0';
757 fprintf (tmp, "Vendor: %s ", vendor);
758 fprintf (tmp, "Model: %s ", product);
759 fprintf (tmp, "Rev: %s ", version);
760 fprintf (tmp, "scsi %d Channel: 0 Id: %d Lun: 0\n", i, id);
761 }
762 }
763 DBG (2, "open_aspi: close temporary file '%s'\n", tmpAspi);
764 fclose (tmp);
765
766 aspi_ref_count++; /* increment internal usage counter */
767
768 return 1;
769 }
770
771 /* Close driver and free everything. */
772
773 static void
close_aspi(void)774 close_aspi (void)
775 {
776 aspi_ref_count--; /* decrement internal usage counter */
777
778 if (aspi_ref_count)
779 return; /* wait for usage==0 */
780
781 if (driver_handle) /* Close driver. */
782 DosClose (driver_handle);
783 driver_handle = 0;
784 if (aspi_buf) /* Free buffer. */
785 _tfree (aspi_buf);
786 aspi_buf = 0;
787
788 if (PSRBlock)
789 _tfree (PSRBlock);
790 PSRBlock = 0;
791
792 errno = 0;
793 if (unlink (tmpAspi)) /* remove scsi descriptions */
794 DBG (2, "OS/2: error#%d while removing temporary '%s'\n", errno, tmpAspi);
795 strcpy (tmpAspi, "");
796
797 DBG (1, "OS/2: ASPI closed\n");
798 }
799
800 #endif /* USE_OS2_INTERFACE */
801
802 static int num_alloced = 0;
803
804 #if USE == LINUX_INTERFACE
805
806 static int sg_version = 0;
807
808 static SANE_Status
get_max_buffer_size(const char * file)809 get_max_buffer_size (const char *file)
810 {
811 int fd = -1;
812 int buffersize = SCSIBUFFERSIZE, i;
813 size_t len;
814 char *cc, *cc1, buf[32];
815
816 #ifdef HAVE_RESMGR
817 fd = rsm_open_device(file, O_RDWR);
818 #endif
819
820 if (fd == -1)
821 fd = open (file, O_RDWR);
822
823 if (fd > 0)
824 {
825 cc = getenv ("SANE_SG_BUFFERSIZE");
826 if (cc)
827 {
828 i = strtol (cc, &cc1, 10);
829 if (cc != cc1 && i >= 32768)
830 buffersize = i;
831 }
832
833 ioctl (fd, SG_SET_RESERVED_SIZE, &buffersize);
834 if (0 == ioctl (fd, SG_GET_RESERVED_SIZE, &buffersize))
835 {
836 if (buffersize < sanei_scsi_max_request_size)
837 sanei_scsi_max_request_size = buffersize;
838 close (fd);
839 DBG (4, "get_max_buffer_size for %s: %i\n", file,
840 sanei_scsi_max_request_size);
841 return SANE_STATUS_GOOD;
842 }
843 else
844 {
845 close (fd);
846 /* ioctl not available: we have the old SG driver */
847 fd = open ("/proc/sys/kernel/sg-big-buff", O_RDONLY);
848 if (fd > 0 && (len = read (fd, buf, sizeof (buf) - 1)) > 0)
849 {
850 buf[len] = '\0';
851 sanei_scsi_max_request_size = atoi (buf);
852 close (fd);
853 }
854 else
855 sanei_scsi_max_request_size = buffersize < SG_BIG_BUFF ?
856 buffersize : SG_BIG_BUFF;
857 return SANE_STATUS_IO_ERROR;
858 }
859 }
860 else
861 return SANE_STATUS_GOOD;
862 }
863
864
865 SANE_Status
sanei_scsi_open_extended(const char * dev,int * fdp,SANEI_SCSI_Sense_Handler handler,void * handler_arg,int * buffersize)866 sanei_scsi_open_extended (const char *dev, int *fdp,
867 SANEI_SCSI_Sense_Handler handler,
868 void *handler_arg, int *buffersize)
869 #else
870
871 SANE_Status
872 sanei_scsi_open (const char *dev, int *fdp,
873 SANEI_SCSI_Sense_Handler handler, void *handler_arg)
874 #endif
875 {
876 u_int bus = 0, target = 0, lun = 0, fake_fd = 0;
877 char *real_dev = 0;
878 void *pdata = 0;
879 char *cc, *cc1;
880 int fd, i;
881 #if USE == LINUX_INTERFACE
882 static int first_time = 1;
883 #elif USE == MACOSX_INTERFACE
884 UInt8 *guid;
885 int len;
886 u_int d;
887 #endif
888
889 cc = getenv ("SANE_SCSICMD_TIMEOUT");
890 if (cc)
891 {
892 i = strtol (cc, &cc1, 10);
893 /* 20 minutes are hopefully enough as a timeout value ;) */
894 if (cc != cc1 && i > 0 && i <= 1200)
895 {
896 sane_scsicmd_timeout = i;
897 }
898 else
899 {
900 DBG (1,
901 "sanei_scsi_open: timeout value must be between 1 and 1200 seconds\n");
902 }
903 }
904
905 DBG_INIT ();
906
907 #if USE == LINUX_INTERFACE
908 if (first_time)
909 {
910 first_time = 0;
911
912 /* Try to determine a reliable value for sanei_scsi_max_request_size:
913
914 With newer versions of the SG driver, check the available buffer
915 size by opening all SG device files belonging to a scanner,
916 issue the ioctl calls for setting and reading the reserved
917 buffer size, and take the smallest value.
918
919 For older version of the SG driver, which don't support variable
920 buffer size, try to read /proc/sys/kernel/sg-big-biff ; if
921 this fails (SG driver too old, or loaded as a module), use
922 SG_BIG_BUFF
923 */
924
925 sanei_scsi_max_request_size = SCSIBUFFERSIZE;
926 cc = getenv ("SANE_SG_BUFFERSIZE");
927 if (cc)
928 {
929 i = strtol (cc, &cc1, 10);
930 if (cc != cc1 && i >= 32768)
931 sanei_scsi_max_request_size = i;
932 }
933 sanei_scsi_find_devices (0, 0, "Scanner", -1, -1, -1, -1,
934 get_max_buffer_size);
935 sanei_scsi_find_devices (0, 0, "Processor", -1, -1, -1, -1,
936 get_max_buffer_size);
937 DBG (4, "sanei_scsi_open: sanei_scsi_max_request_size=%d bytes\n",
938 sanei_scsi_max_request_size);
939 }
940 #endif
941
942 #if USE == OS2_INTERFACE
943 if (sscanf (dev, "b%ut%ul%u", &bus, &target, &lun) != 3)
944 {
945 DBG (1, "sanei_scsi_open: device name %s is not valid\n", dev);
946 return SANE_STATUS_INVAL;
947 }
948 if (!open_aspi ())
949 {
950 /* Open driver if necessary. */
951 close_aspi ();
952 return SANE_STATUS_INVAL;
953 }
954
955 /* Find fake fd. */
956 for (fd = 0; fd < num_alloced; ++fd)
957 if (!fd_info[fd].in_use)
958 break;
959 fake_fd = 1;
960 #elif USE == DECUNIX_INTERFACE
961 {
962 UAGT_CAM_SCAN cam_scan;
963
964 if (sscanf (dev, "b%dt%dl%d", &bus, &target, &lun) != 3)
965 {
966 DBG (1, "sanei_scsi_open: device name `%s´ is not valid: %s\n",
967 dev, strerror (errno));
968 return SANE_STATUS_INVAL;
969 }
970
971 if (cam_fd < 0)
972 {
973 cam_fd = open ("/dev/cam", O_RDWR);
974 if (cam_fd < 0)
975 {
976 DBG (1, "sanei_scsi_open: open(/dev/cam) failed: %s\n",
977 strerror (errno));
978 return SANE_STATUS_INVAL;
979 }
980 }
981 cam_scan.ucs_bus = bus;
982 cam_scan.ucs_target = target;
983 cam_scan.ucs_lun = lun;
984 if (ioctl (cam_fd, UAGT_CAM_SINGLE_SCAN, &cam_scan) < 0)
985 {
986 DBG (1, "sanei_scsi_open: ioctl(UAGT_CAM_SINGLE_SCAN) failed: %s\n",
987 strerror (errno));
988 return SANE_STATUS_INVAL;
989 }
990
991 for (fd = 0; fd < num_alloced; ++fd)
992 if (!fd_info[fd].in_use)
993 break;
994 fake_fd = 1;
995 }
996 #elif USE == DOMAINOS_INTERFACE
997 {
998 static int index;
999 static status_$t status;
1000 static unsigned long length_mapped;
1001
1002 DBG (1, "sanei_scsi_open: (dev='%s', int * fdp=%p, "
1003 "SANEI_SCSI_Sense_Handler handler=%p)\n", dev, fdp, handler);
1004
1005 /* See if the server process has started yet */
1006 if (!ServerInitialized)
1007 {
1008 static char *CommonAreaPath;
1009
1010 /* Initialize the server */
1011 DBG (2, "Initializing Domain Server\n");
1012
1013 /* Map the area */
1014 CommonAreaPath = tmpnam (NULL);
1015 DBG (2, "Domain Server Common area name is '%s'\n", CommonAreaPath);
1016 com = ms_$crmapl (CommonAreaPath, strlen (CommonAreaPath), 0,
1017 sizeof (struct DomainServerCommon), ms_$cowriters,
1018 &status);
1019 DomainErrorCheck (status, "Can't open common area");
1020 DBG (2, "Domain Server common area mapped\n");
1021
1022 /* Initialize the eventcounts */
1023 ec2_$init (&com->CommandAvailable);
1024 ec2_$init (&com->CommandAccepted);
1025 ec2_$init (&com->ResultReady);
1026 ec2_$init (&com->ResultAccepted);
1027 DBG (2, "Domain Server EC's initialized\n");
1028 /* Initialize the mutex locks */
1029 mutex_$init (&com->CommandLock);
1030 mutex_$init (&com->ResultLock);
1031 DBG (2, "Domain Server MutexLock's initialized\n");
1032
1033 /* Initialize pointers to ECs */
1034 CommandAcceptedPtr[0] = &com->CommandAccepted;
1035 ResultReadyPtr[0] = &com->ResultReady;
1036 time_$get_ec (time_$clockh_key, &CommandAcceptedPtr[1], &status);
1037 DomainErrorCheck (status, "Can't get time EC");
1038 ResultReadyPtr[1] = CommandAcceptedPtr[1];
1039
1040 /* Read the ResultReady EC value, to avoid race with the server */
1041 ResultTriggerValue[0] = ec2_$read (com->ResultReady) + 1;
1042
1043 /* Now invoke the server */
1044 ServerPID = fork ();
1045 if (!ServerPID)
1046 {
1047 /* I am the child, call the initialization routine */
1048 sanei_DomainOS_init (CommonAreaPath);
1049 /* We get here when the server is done, so we just exit. */
1050 exit (EXIT_SUCCESS);
1051 }
1052
1053 /* The communication area is open, wait for the initial response */
1054 ResultTriggerValue[1] = (ec2_$read (*ResultReadyPtr[1])
1055 + DomainECWaitConstant);
1056 index =
1057 ec2_$wait_svc (ResultReadyPtr, ResultTriggerValue, 2, &status);
1058 DomainErrorCheck (status, "Error waiting on initial open EC");
1059 if (index != 1)
1060 {
1061 DBG (0, "Domain SANE Server never responded on startup\n");
1062 /* Send a quit signal to the server */
1063 kill (ServerPID, SIGQUIT);
1064 return SANE_STATUS_INVAL;
1065 }
1066 /* Register a function to kill the server when we are done */
1067 assert (!atexit (KillDomainServer));
1068 ServerInitialized = 1;
1069 }
1070
1071 /* Find fake fd. */
1072 for (fd = 0; fd < num_alloced; ++fd)
1073 if (!fd_info[fd].in_use)
1074 break;
1075 fake_fd = 1;
1076
1077 /* Send the command open to the server */
1078 if (!mutex_$lock (&com->CommandLock, Wait16S))
1079 {
1080 DBG (0, "Could not obtain mutex lock for Open\n");
1081 return SANE_STATUS_INVAL;
1082 }
1083 com->opcode = Open;
1084 strcpy (com->open_path, dev);
1085 CommandTriggerValue[0] = ec2_$read (com->CommandAccepted) + 1;
1086 ec2_$advance (&com->CommandAvailable, &status);
1087 DomainErrorCheck (status, "Can't advance CommandAvailable EC");
1088 CommandTriggerValue[1] = (ec2_$read (*CommandAcceptedPtr[1])
1089 + DomainECWaitConstant);
1090 index = ec2_$wait_svc (CommandAcceptedPtr, CommandTriggerValue, 2,
1091 &status);
1092 DomainErrorCheck (status, "Error waiting on Open command acceptance EC");
1093 if (index != 1)
1094 {
1095 DBG (0, "Domain SANE Server never accepted Open Command\n");
1096 return SANE_STATUS_INVAL;
1097 }
1098
1099 /* Read the result */
1100 status = com->CommandStatus;
1101 DomainErrorCheck (status, "Opening device in server");
1102
1103 /* Now map the data area, and make it temporary */
1104 DBG (2, "Mapping server's data block, name is '%s'\n", com->open_path);
1105 pdata = ms_$mapl (com->open_path, strlen (com->open_path), 0,
1106 DomainMaxDataSize + DomainSenseSize, ms_$cowriters,
1107 ms_$wr, true, &length_mapped, &status);
1108 DomainErrorCheck (status, "Mapping Server Data block");
1109 assert (length_mapped >= DomainMaxDataSize + DomainSenseSize);
1110 ms_$mk_temporary (pdata, &status);
1111 DomainErrorCheck (status, "Can't make data block temporary");
1112
1113 /* Release the lock */
1114 mutex_$unlock (&com->CommandLock);
1115
1116 if (status.all != status_$ok)
1117 {
1118 /* we have a failure, return an error code, and generate debug
1119 output */
1120 DBG (1, "sanei_scsi_open: acquire failed, Domain/OS status is %08x\n",
1121 status.all);
1122 error_$print (status);
1123 return SANE_STATUS_INVAL;
1124 }
1125 else
1126 {
1127 /* device acquired, what else to do? */
1128 fd = com->fd;
1129 }
1130 }
1131 #elif USE == FREEBSD_CAM_INTERFACE
1132 if (1)
1133 { /* 'if(1) {' makes my emacs c-mode indent better than
1134 just '{' unfortunately, this only works if all of
1135 the '{' are that way. */
1136
1137 struct cam_device *curdev;
1138
1139 fake_fd = 1;
1140 fd = -1;
1141
1142 if ((curdev = cam_open_pass (dev, O_RDWR, NULL)) != NULL)
1143 {
1144 for (fd = 0; fd < CAM_MAXDEVS && cam_devices[fd] != NULL; fd++)
1145 ;
1146
1147 if (fd == CAM_MAXDEVS)
1148 {
1149 DBG (1, "sanei_scsi_open: too many CAM devices (%d)\n", fd);
1150 cam_close_device (curdev);
1151 return SANE_STATUS_INVAL;
1152 }
1153 cam_devices[fd] = curdev;
1154 }
1155 else
1156 {
1157 DBG (1, "sanei_scsi_open: can't open device `%s´: %s\n", dev,
1158 strerror (errno));
1159 return SANE_STATUS_INVAL;
1160 }
1161 }
1162 #elif USE == SCO_UW71_INTERFACE
1163 {
1164 pt_scsi_address_t dev_addr;
1165 pt_handle_t pt_handle;
1166 int bus, cnt, id, lun;
1167
1168 if (4 !=
1169 sscanf (dev, "/dev/passthru0:%d,%d,%d,%d", &bus, &cnt, &id, &lun))
1170 {
1171 DBG (1, "sanei_scsi_open: device name `%s´ is not valid: %s\n",
1172 dev, strerror (errno));
1173 return SANE_STATUS_INVAL;
1174 }
1175 dev_addr.psa_bus = bus;
1176 dev_addr.psa_controller = cnt;
1177 dev_addr.psa_target = id;
1178 dev_addr.psa_lun = lun;
1179
1180 if (0 != pt_open (PASSTHRU_SCSI_ADDRESS, &dev_addr, PT_EXCLUSIVE,
1181 &pt_handle))
1182 {
1183 DBG (1, "sanei_scsi_open: pt_open failed: %s!\n", strerror (errno));
1184 return SANE_STATUS_INVAL;
1185 }
1186 else
1187 fd = (int) pt_handle;
1188 }
1189 #elif USE == MACOSX_INTERFACE
1190 {
1191 # if defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \
1192 defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H)
1193 len = strlen (dev);
1194 if (len > 2 && len % 2 == 0 && dev [0] == '<' && dev [len - 1] == '>')
1195 {
1196 len = (len - 2) / 2;
1197 guid = (UInt8 *) malloc (len);
1198 for (i = 0; i < len; i++)
1199 {
1200 if (sscanf (&dev [2 * i + 1], "%02x", &d) != 1)
1201 break;
1202 guid [i] = d;
1203 }
1204 if (i == len)
1205 pdata = (void *) CFDataCreate (kCFAllocatorDefault, guid, len);
1206 free (guid);
1207 }
1208 # endif
1209 # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H
1210 if ((pdata == NULL) &&
1211 (sscanf (dev, "u%ut%ul%u", &bus, &target, &lun) != 3))
1212 # else
1213 if (pdata == NULL)
1214 # endif
1215 {
1216 DBG (1, "sanei_scsi_open: device name %s is not valid\n", dev);
1217 return SANE_STATUS_INVAL;
1218 }
1219
1220 /* Find fake fd. */
1221 for (fd = 0; fd < num_alloced; ++fd)
1222 if (!fd_info[fd].in_use)
1223 break;
1224 fake_fd = 1;
1225 }
1226 #elif USE == WIN32_INTERFACE
1227 {
1228 char scsi_hca_name[20];
1229 u_int hca = 0;
1230
1231 if (sscanf (dev, "h%ub%ut%ul%u", &hca, &bus, &target, &lun) != 4)
1232 {
1233 DBG (1, "sanei_scsi_open: device name %s is not valid\n", dev);
1234 return SANE_STATUS_INVAL;
1235 }
1236
1237 snprintf(scsi_hca_name, 19, "\\\\.\\Scsi%d:", hca);
1238 scsi_hca_name[19] = 0;
1239
1240 fd = CreateFile(scsi_hca_name, GENERIC_READ | GENERIC_WRITE,
1241 FILE_SHARE_READ | FILE_SHARE_WRITE,
1242 NULL, OPEN_EXISTING,
1243 FILE_FLAG_RANDOM_ACCESS, NULL );
1244
1245 if (fd == INVALID_HANDLE_VALUE) fd = -1;
1246 }
1247 #else
1248 #if defined(SGIOCSTL) || (USE == SOLARIS_INTERFACE)
1249 {
1250 size_t len;
1251
1252 /* OpenStep and the Solaris SCG driver are a bit broken in that
1253 the device name refers to a scsi _bus_, not an individual scsi
1254 device. Hence, SANE has to fudge with the device name so we
1255 know which target to connect to. For this purpose, we use the
1256 last character in the device name as the target index. 'a' is
1257 target 0, 'b', target 1, and so on... */
1258
1259 len = strlen (dev);
1260 if (len <= 1)
1261 {
1262 DBG (1, "sanei_scsi_open: devicename `%s' too short\n", dev);
1263 return SANE_STATUS_INVAL;
1264 }
1265
1266 real_dev = strdup (dev);
1267 real_dev[len - 1] = '\0';
1268
1269 target = dev[len - 1] - 'a';
1270 if (target > 7)
1271 {
1272 DBG (1, "sanei_scsi_open: `%c' is not a valid target id\n",
1273 dev[len - 1]);
1274 return SANE_STATUS_INVAL;
1275 }
1276 dev = real_dev;
1277 }
1278 #endif /* defined(SGIOCSTL) || (USE == SOLARIS_INTERFACE) */
1279
1280 fd = -1;
1281 #ifdef HAVE_RESMGR
1282 fd = rsm_open_device(dev, O_RDWR | O_EXCL | O_NONBLOCK);
1283 #endif
1284
1285 if (fd == -1)
1286 fd = open (dev, O_RDWR | O_EXCL
1287 #if USE == LINUX_INTERFACE
1288 | O_NONBLOCK
1289 #endif
1290 );
1291 if (fd < 0)
1292 {
1293 SANE_Status status = SANE_STATUS_INVAL;
1294
1295 if (errno == EACCES)
1296 status = SANE_STATUS_ACCESS_DENIED;
1297 else if (errno == EBUSY)
1298 status = SANE_STATUS_DEVICE_BUSY;
1299
1300 DBG (1, "sanei_scsi_open: open of `%s' failed: %s\n",
1301 dev, strerror (errno));
1302 return status;
1303 }
1304
1305 if (real_dev)
1306 free (real_dev);
1307
1308 #ifdef SG_SET_TIMEOUT
1309 /* Set large timeout since some scanners are slow but do not
1310 disconnect... ;-( */
1311 {
1312 int timeout;
1313 timeout = sane_scsicmd_timeout * GNU_HZ;
1314 ioctl (fd, SG_SET_TIMEOUT, &timeout);
1315 }
1316 #endif
1317
1318 #ifdef SGIOCSTL
1319 {
1320 struct scsi_adr sa;
1321
1322 sa.sa_target = target;
1323 sa.sa_lun = 0;
1324 if (ioctl (fd, SGIOCSTL, &sa) == -1)
1325 {
1326 DBG (1, "sanei_scsi_open: failed to attach to target: %u (%s)\n",
1327 sa.sa_target, strerror (errno));
1328 return SANE_STATUS_INVAL;
1329 }
1330 }
1331 #endif /* SGIOCSTL */
1332 #if USE == LINUX_INTERFACE
1333 {
1334 SG_scsi_id sid;
1335 int ioctl_val;
1336 int real_buffersize;
1337 fdparms *fdpa = 0;
1338 SG_scsi_id devinfo;
1339
1340 pdata = fdpa = malloc (sizeof (fdparms));
1341 if (!pdata)
1342 {
1343 close (fd);
1344 return SANE_STATUS_NO_MEM;
1345 }
1346 memset (fdpa, 0, sizeof (fdparms));
1347 /* default: allow only one command to be sent to the SG driver
1348 */
1349 fdpa->sg_queue_max = 1;
1350
1351 /* Try to read the SG version. If the ioctl call is successful,
1352 we have the new SG driver, and we can increase the buffer size
1353 using another ioctl call.
1354 If we have SG version 2.1.35 or above, we can additionally enable
1355 command queueing.
1356 */
1357 if (0 == ioctl (fd, SG_GET_VERSION_NUM, &sg_version))
1358 {
1359 DBG (1, "sanei_scsi_open: SG driver version: %i\n", sg_version);
1360
1361 ioctl_val = ioctl (fd, SG_GET_SCSI_ID, &devinfo);
1362 if (ioctl_val == EINVAL || ioctl_val == ENOTTY)
1363 {
1364 DBG (1, "sanei_scsi_open: The file %s is not an SG device file\n",
1365 dev);
1366 close (fd);
1367 return SANE_STATUS_INVAL;
1368 }
1369
1370 if (devinfo.scsi_type != 6 && devinfo.scsi_type != 3)
1371 {
1372 DBG (1,
1373 "sanei_scsi_open: The device found for %s does not look like a scanner\n",
1374 dev);
1375 close (fd);
1376 return SANE_STATUS_INVAL;
1377 }
1378
1379 /* try to reserve a SG buffer of the size specified by *buffersize
1380 */
1381 ioctl (fd, SG_SET_RESERVED_SIZE, buffersize);
1382
1383 /* the set call may not be able to allocate as much memory
1384 as requested, thus we read the actual buffer size.
1385 */
1386 if (0 == ioctl (fd, SG_GET_RESERVED_SIZE, &real_buffersize))
1387 {
1388 /* if we got more memory than requested, we stick with
1389 with the requested value, in order to allow
1390 sanei_scsi_open to check the buffer size exactly.
1391 */
1392 if (real_buffersize < *buffersize)
1393 *buffersize = real_buffersize;
1394 fdpa->buffersize = *buffersize;
1395 }
1396 else
1397 {
1398 DBG (1, "sanei_scsi_open: cannot read SG buffer size - %s\n",
1399 strerror (errno));
1400 close (fd);
1401 return SANE_STATUS_NO_MEM;
1402 }
1403 DBG (1, "sanei_scsi_open_extended: using %i bytes as SCSI buffer\n",
1404 *buffersize);
1405
1406 if (sg_version >= 20135)
1407 {
1408 DBG (1, "trying to enable low level command queueing\n");
1409
1410 if (0 == ioctl (fd, SG_GET_SCSI_ID, &sid))
1411 {
1412 DBG (1, "sanei_scsi_open: Host adapter queue depth: %i\n",
1413 sid.d_queue_depth);
1414
1415 ioctl_val = 1;
1416 if (0 == ioctl (fd, SG_SET_COMMAND_Q, &ioctl_val))
1417 {
1418 fdpa->sg_queue_max = sid.d_queue_depth;
1419 if (fdpa->sg_queue_max <= 0)
1420 fdpa->sg_queue_max = 1;
1421 }
1422 }
1423 }
1424 }
1425 else
1426 {
1427 /* we have a really old SG driver version, or we're not opening
1428 an SG device file
1429 */
1430 if (ioctl (fd, SG_GET_TIMEOUT, &ioctl_val) < 0)
1431 {
1432 DBG (1, "sanei_scsi_open: The file %s is not an SG device file\n",
1433 dev);
1434 close (fd);
1435 return SANE_STATUS_INVAL;
1436 }
1437 if (sanei_scsi_max_request_size < *buffersize)
1438 *buffersize = sanei_scsi_max_request_size;
1439 fdpa->buffersize = *buffersize;
1440 }
1441 if (sg_version == 0)
1442 {
1443 DBG (1, "sanei_scsi_open: using old SG driver logic\n");
1444 }
1445 else
1446 {
1447 DBG (1,
1448 "sanei_scsi_open: SG driver can change buffer size at run time\n");
1449 if (fdpa->sg_queue_max > 1)
1450 DBG (1, "sanei_scsi_open: low level command queueing enabled\n");
1451 #ifdef SG_IO
1452 if (sg_version >= 30000)
1453 {
1454 DBG (1, "sanei_scsi_open: using new SG header structure\n");
1455 }
1456 #endif
1457 }
1458 }
1459 #endif /* LINUX_INTERFACE */
1460 #endif /* !DECUNIX_INTERFACE */
1461
1462 /* Note: this really relies on fd to start small. Windows starts a little higher than 3. */
1463
1464 if (fd >= num_alloced)
1465 {
1466 size_t new_size, old_size;
1467
1468 old_size = num_alloced * sizeof (fd_info[0]);
1469 num_alloced = fd + 8;
1470 new_size = num_alloced * sizeof (fd_info[0]);
1471 if (fd_info)
1472 fd_info = realloc (fd_info, new_size);
1473 else
1474 fd_info = malloc (new_size);
1475 memset ((char *) fd_info + old_size, 0, new_size - old_size);
1476 if (!fd_info)
1477 {
1478 if (!fake_fd)
1479 close (fd);
1480 return SANE_STATUS_NO_MEM;
1481 }
1482 }
1483 fd_info[fd].in_use = 1;
1484 fd_info[fd].sense_handler = handler;
1485 fd_info[fd].sense_handler_arg = handler_arg;
1486 fd_info[fd].fake_fd = fake_fd;
1487 fd_info[fd].bus = bus;
1488 fd_info[fd].target = target;
1489 fd_info[fd].lun = lun;
1490 fd_info[fd].pdata = pdata;
1491
1492 #if USE == SOLARIS_INTERFACE || USE == SOLARIS_USCSI_INTERFACE
1493 /* verify that the device really exists: */
1494 if (!unit_ready (fd))
1495 {
1496 sanei_scsi_close (fd);
1497 return SANE_STATUS_INVAL;
1498 }
1499 #endif
1500 #if USE == SYSVR4_INTERFACE
1501 memset (lastrcmd, 0, 16); /* reinitialize last read command block */
1502 #endif
1503
1504 if (fdp)
1505 *fdp = fd;
1506
1507 return SANE_STATUS_GOOD;
1508 }
1509
1510 #if USE == LINUX_INTERFACE
1511 /* The "wrapper" for the old open call */
1512 SANE_Status
sanei_scsi_open(const char * dev,int * fdp,SANEI_SCSI_Sense_Handler handler,void * handler_arg)1513 sanei_scsi_open (const char *dev, int *fdp,
1514 SANEI_SCSI_Sense_Handler handler, void *handler_arg)
1515 {
1516 int i = 0;
1517 int wanted_buffersize = SCSIBUFFERSIZE, real_buffersize;
1518 SANE_Status res;
1519 char *cc, *cc1;
1520 static int first_time = 1;
1521
1522 if (first_time)
1523 {
1524 cc = getenv ("SANE_SG_BUFFERSIZE");
1525 if (cc)
1526 {
1527 i = strtol (cc, &cc1, 10);
1528 if (cc != cc1 && i >= 32768)
1529 wanted_buffersize = i;
1530 }
1531 }
1532 else
1533 wanted_buffersize = sanei_scsi_max_request_size;
1534
1535 real_buffersize = wanted_buffersize;
1536 res = sanei_scsi_open_extended (dev, fdp, handler, handler_arg,
1537 &real_buffersize);
1538
1539 /* make sure that we got as much memory as we wanted, otherwise
1540 the backend might be confused
1541 */
1542 if (!first_time && real_buffersize != wanted_buffersize)
1543 {
1544 DBG (1, "sanei_scsi_open: could not allocate SG buffer memory "
1545 "wanted: %i got: %i\n", wanted_buffersize, real_buffersize);
1546 sanei_scsi_close (*fdp);
1547 return SANE_STATUS_NO_MEM;
1548 }
1549
1550 first_time = 0;
1551 return res;
1552 }
1553 #else
1554 /* dummy for the proposed new open call */
1555 SANE_Status
sanei_scsi_open_extended(const char * dev,int * fdp,SANEI_SCSI_Sense_Handler handler,void * handler_arg,int * buffersize)1556 sanei_scsi_open_extended (const char *dev, int *fdp,
1557 SANEI_SCSI_Sense_Handler handler,
1558 void *handler_arg, int *buffersize)
1559 {
1560 SANE_Status res;
1561 res = sanei_scsi_open (dev, fdp, handler, handler_arg);
1562 if (sanei_scsi_max_request_size < *buffersize)
1563 *buffersize = sanei_scsi_max_request_size;
1564 return res;
1565 }
1566 #endif
1567
1568 void
sanei_scsi_close(int fd)1569 sanei_scsi_close (int fd)
1570 {
1571 #if USE == LINUX_INTERFACE
1572 if (fd_info[fd].pdata)
1573 {
1574 req *req, *next_req;
1575
1576 /* make sure that there are no pending SCSI calls */
1577 sanei_scsi_req_flush_all_extended (fd);
1578
1579 req = ((fdparms *) fd_info[fd].pdata)->sane_free_list;
1580 while (req)
1581 {
1582 next_req = req->next;
1583 free (req);
1584 req = next_req;
1585 }
1586 free (fd_info[fd].pdata);
1587 }
1588 #endif
1589
1590 fd_info[fd].in_use = 0;
1591 fd_info[fd].sense_handler = 0;
1592 fd_info[fd].sense_handler_arg = 0;
1593
1594 #ifdef WIN32
1595 CloseHandle(fd);
1596 #else
1597 if (!fd_info[fd].fake_fd)
1598 close (fd);
1599 #endif
1600
1601 #if USE == FREEBSD_CAM_INTERFACE
1602 cam_close_device (cam_devices[fd]);
1603 cam_devices[fd] = NULL;
1604 #elif USE == DOMAINOS_INTERFACE
1605 {
1606 static int index;
1607 static status_$t status;
1608
1609 DBG (1, "sanei_scsi_close: fd=%d\n", fd);
1610
1611 /* Send the command to the server */
1612 if (!mutex_$lock (&com->CommandLock, Wait16S))
1613 {
1614 DBG (0, "Could not obtain mutex lock for Close command\n");
1615 }
1616 else
1617 {
1618 com->opcode = Close;
1619 com->fd = fd;
1620 CommandTriggerValue[0] = ec2_$read (com->CommandAccepted) + 1;
1621 ec2_$advance (&com->CommandAvailable, &status);
1622 DomainErrorCheck (status, "Can't advance CommandAvailable EC");
1623 CommandTriggerValue[1] = (ec2_$read (*CommandAcceptedPtr[1])
1624 + DomainECWaitConstant);
1625 index = ec2_$wait_svc (CommandAcceptedPtr, CommandTriggerValue, 2,
1626 &status);
1627 DomainErrorCheck (status,
1628 "Error waiting on Close command acceptance EC");
1629 if (index != 1)
1630 {
1631 DBG (0, "Domain SANE Server never accepted Close Command\n");
1632 }
1633
1634 /* Read the result */
1635 status = com->CommandStatus;
1636 /* Release the lock */
1637 mutex_$unlock (&com->CommandLock);
1638 }
1639
1640 /* Unmap the data area */
1641 ms_$unmap (fd_info[com->fd].pdata, DomainMaxDataSize + DomainSenseSize,
1642 &status);
1643 DomainErrorCheck (status, "Error unmapping device data area");
1644 }
1645 #endif /* USE == DOMAINOS_INTERFACE */
1646
1647 #if USE == OS2_INTERFACE
1648 close_aspi ();
1649 #endif /* USE == OS2_INTERFACE */
1650
1651 #if USE == MACOSX_INTERFACE
1652 if (fd_info[fd].pdata)
1653 CFRelease (fd_info[fd].pdata);
1654 #endif /* USE == MACOSX_INTERFACE */
1655 }
1656
1657
1658 #if USE == DOMAINOS_INTERFACE
1659 # define WE_HAVE_ASYNC_SCSI
1660
1661 void
sanei_scsi_req_flush_all(void)1662 sanei_scsi_req_flush_all (void)
1663 {
1664 status_$t status;
1665
1666 DBG (1, "sanei_scsi_req_flush_all: ()\n");
1667 /* I have never seen this called, and I'm not sure what to do with it,
1668 so I guarantee that it will generate a fault, and I can add support
1669 for it. */
1670 assert (1 == 0);
1671 }
1672
1673
1674 SANE_Status
sanei_scsi_req_enter2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size,void ** idp)1675 sanei_scsi_req_enter2 (int fd,
1676 const void *cmd, size_t cmd_size,
1677 const void *src, size_t src_size,
1678 void *dst, size_t * dst_size, void **idp)
1679 {
1680 SANEI_SCSI_Sense_Handler handler;
1681 static int index;
1682 static SANE_Status sane_status;
1683 static status_$t status;
1684 static scsi_$status_t SCSIStatus;
1685 static void *buf_ptr;
1686
1687 if (dst_size)
1688 DBG (1, "sanei_scsi_req_enter2: (fd=%x, cmd=%p, cmd_size=%x, "
1689 "src=%p, src_size=%x, dst=%p, dst_size=%x, *idp=%p)\n",
1690 fd, cmd, cmd_size, src, src_size, dst, *dst_size, idp);
1691 else
1692 DBG (1, "sanei_scsi_req_enter2: (fd=%x, cmd=%p, cmd_size=%x, "
1693 "src=%p, src_size=%x, dst=%p, dst_size=NULL, *idp=%p)\n",
1694 fd, src, src_size, dst, idp);
1695
1696 /* Lock the command structure */
1697 if (!mutex_$lock (&com->CommandLock, mutex_$wait_forever))
1698 {
1699 DBG (0, "Could not obtain mutex lock for Enter Command\n");
1700 return SANE_STATUS_INVAL;
1701 }
1702
1703 /* Fill in the command structure */
1704 com->opcode = Enter;
1705 com->fd = fd;
1706 com->cdb_size = cmd_size;
1707 if (dst_size)
1708 com->dst_size = *dst_size;
1709 memcpy (&com->cdb, cmd, com->cdb_size);
1710
1711 /* figure out if this is a read or a write */
1712 if (dst_size && *dst_size)
1713 {
1714 /* dest buffer specified, must be a read */
1715 /* assert (com->cdb_size == src_size); */
1716 com->direction = scsi_read;
1717 buf_ptr = dst;
1718 com->buf_size = *dst_size;
1719 }
1720 else
1721 {
1722 /* no dest buffer, must be a write */
1723 /* assert (com->cdb_size <= src_size); */
1724 com->direction = scsi_write;
1725 buf_ptr = (char *) src;
1726 com->buf_size = src_size;
1727 if (com->buf_size)
1728 memcpy (fd_info[fd].pdata, buf_ptr, com->buf_size);
1729 }
1730
1731 CommandTriggerValue[0] = ec2_$read (com->CommandAccepted) + 1;
1732 ec2_$advance (&com->CommandAvailable, &status);
1733 DomainErrorCheck (status, "Can't advance CommandAvailable EC");
1734 CommandTriggerValue[1] = (ec2_$read (*CommandAcceptedPtr[1])
1735 + DomainECWaitConstant);
1736 index = ec2_$wait_svc (CommandAcceptedPtr, CommandTriggerValue, 2, &status);
1737 DomainErrorCheck (status, "Error waiting on Enter command acceptance EC");
1738 if (index != 1)
1739 {
1740 DBG (0, "Domain SANE Server never accepted Enter Command\n");
1741 return SANE_STATUS_INVAL;
1742 }
1743
1744 /* Read the result */
1745 status = com->CommandStatus;
1746 SCSIStatus = com->SCSIStatus;
1747
1748 /* Release the lock */
1749 mutex_$unlock (&com->CommandLock);
1750
1751 /* Now decode the return status */
1752 if (status.all)
1753 DBG (1, "Server returned status %08x from Enter command\n", status.all);
1754 switch (status.all)
1755 {
1756 case status_$ok:
1757 sane_status = SANE_STATUS_GOOD;
1758 break;
1759 case scsi_$dma_underrun:
1760 sane_status = SANE_STATUS_IO_ERROR;
1761 /* This error is generated by the HP and UMAX backends. They
1762 ask for too much data. For now, the error is ignored :-( */
1763 sane_status = SANE_STATUS_GOOD;
1764 break;
1765 case scsi_$operation_timeout:
1766 sane_status = SANE_STATUS_DEVICE_BUSY;
1767 break;
1768 case scsi_$hdwr_failure: /* received when both scanners were active */
1769 sane_status = SANE_STATUS_IO_ERROR;
1770 break;
1771 case (status_$ok | 0x80000000):
1772 /* Special - no Domain/OS error, but fail bit set means to check
1773 SCSI operation status. */
1774 DBG (1, "Server returned SCSI status of %08x\n", SCSIStatus);
1775 switch (SCSIStatus)
1776 {
1777 case scsi_check_condition:
1778 /* Call the sense handler, if defined */
1779 handler = fd_info[com->fd].sense_handler;
1780 if (handler)
1781 (*handler) (fd, ((u_char *) fd_info[fd].pdata
1782 + DomainMaxDataSize),
1783 fd_info[com->fd].sense_handler_arg);
1784 sane_status = SANE_STATUS_IO_ERROR;
1785 break;
1786 case scsi_busy:
1787 sane_status = SANE_STATUS_DEVICE_BUSY;
1788 break;
1789 default:
1790 DBG (0, "Error - Unrecognized SCSI status %08x returned from "
1791 "Enter command\n", SCSIStatus);
1792 sane_status = SANE_STATUS_IO_ERROR;
1793 exit (EXIT_FAILURE);
1794 }
1795 break;
1796 default:
1797 DBG (0, "Unmapped status (%08x) returned from Domain SANE Server\n",
1798 status.all);
1799 sane_status = SANE_STATUS_IO_ERROR;
1800 }
1801
1802 /* If a read, copy the data into the destination buffer */
1803 if ((com->direction == scsi_read) && com->dst_size)
1804 memcpy (buf_ptr, fd_info[fd].pdata, com->dst_size);
1805
1806 return sane_status;
1807 }
1808
1809
1810 SANE_Status
sanei_scsi_req_wait(void * id)1811 sanei_scsi_req_wait (void *id)
1812 {
1813 SANE_Status status;
1814 DBG (1, "sanei_scsi_req_wait: (id=%p)\n", id);
1815 status = SANE_STATUS_GOOD;
1816 return status;
1817 }
1818
1819
1820 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)1821 sanei_scsi_cmd2 (int fd,
1822 const void *cmd, size_t cmd_size,
1823 const void *src, size_t src_size,
1824 void *dst, size_t * dst_size)
1825 {
1826 SANE_Status status;
1827 void *id;
1828
1829 DBG (1, "sanei_scsi_cmd2: (fd=%d)\n", fd);
1830 status =
1831 sanei_scsi_req_enter2 (fd, cmd, cmd_size, src, src_size, dst, dst_size,
1832 &id);
1833 if (status != SANE_STATUS_GOOD)
1834 return status;
1835 return sanei_scsi_req_wait (id);
1836 }
1837
1838 #endif /* USE == DOMAINOS_INTERFACE */
1839
1840
1841 #if USE == LINUX_INTERFACE
1842
1843 #include <ctype.h>
1844 #include <signal.h>
1845
1846 #include <sys/time.h>
1847
1848 #define WE_HAVE_ASYNC_SCSI
1849 #define WE_HAVE_FIND_DEVICES
1850
1851 static int pack_id = 0;
1852 static int need_init = 1;
1853 static sigset_t all_signals;
1854
1855 #define ATOMIC(s) \
1856 do \
1857 { \
1858 sigset_t old_mask; \
1859 \
1860 if (need_init) \
1861 { \
1862 need_init = 0; \
1863 sigfillset (&all_signals); \
1864 } \
1865 sigprocmask (SIG_BLOCK, &all_signals, &old_mask); \
1866 {s;} \
1867 sigprocmask (SIG_SETMASK, &old_mask, 0); \
1868 } \
1869 while (0)
1870
1871 static void
issue(struct req * req)1872 issue (struct req *req)
1873 {
1874 ssize_t nwritten;
1875 fdparms *fdp;
1876 struct req *rp;
1877 int retries;
1878 int ret;
1879
1880 if (!req)
1881 return;
1882
1883 fdp = (fdparms *) fd_info[req->fd].pdata;
1884 DBG (4, "sanei_scsi.issue: %p\n", (void *) req);
1885
1886 rp = fdp->sane_qhead;
1887 while (rp && rp->running)
1888 rp = rp->next;
1889
1890 while (rp && fdp->sg_queue_used < fdp->sg_queue_max)
1891 {
1892 retries = 20;
1893 while (retries)
1894 {
1895 errno = 0;
1896 #ifdef SG_IO
1897 if (sg_version < 30000)
1898 {
1899 #endif
1900 ATOMIC (rp->running = 1;
1901 nwritten = write (rp->fd, &rp->sgdata.cdb,
1902 rp->sgdata.cdb.hdr.pack_len);
1903 ret = 0;
1904 if (nwritten != rp->sgdata.cdb.hdr.pack_len)
1905 {
1906 /* ENOMEM can easily happen, if both command queueing
1907 inside the SG driver and large buffers are used.
1908 Therefore, if ENOMEM does not occur for the first
1909 command in the queue, we simply try to issue
1910 it later again.
1911 */
1912 if (errno == EAGAIN
1913 || (errno == ENOMEM && rp != fdp->sane_qhead))
1914 {
1915 /* don't try to send the data again, but
1916 wait for the next call to issue()
1917 */
1918 rp->running = 0;}
1919 }
1920 );
1921 #ifdef SG_IO
1922 }
1923 else
1924 {
1925 ATOMIC (rp->running = 1;
1926 ret = ioctl(rp->fd, SG_IO, &rp->sgdata.sg3.hdr);
1927 nwritten = 0;
1928 if (ret < 0)
1929 {
1930 /* ENOMEM can easily happen, if both command queuein
1931 inside the SG driver and large buffers are used.
1932 Therefore, if ENOMEM does not occur for the first
1933 command in the queue, we simply try to issue
1934 it later again.
1935 */
1936 if (errno == EAGAIN
1937 || (errno == ENOMEM && rp != fdp->sane_qhead))
1938 {
1939 /* don't try to send the data again, but
1940 wait for the next call to issue()
1941 */
1942 rp->running = 0;
1943 }
1944 else /* game over */
1945 {
1946 rp->running = 0;
1947 rp->done = 1;
1948 rp->status = SANE_STATUS_IO_ERROR;
1949 }
1950 }
1951 );
1952 IF_DBG (if (DBG_LEVEL >= 255)
1953 system ("cat /proc/scsi/sg/debug 1>&2");)
1954 }
1955 #endif
1956 if (rp == fdp->sane_qhead && errno == EAGAIN)
1957 {
1958 retries--;
1959 usleep (10000);
1960 }
1961 else
1962 retries = 0;
1963 }
1964
1965 #ifndef SG_IO
1966 if (nwritten != rp->sgdata.cdb.hdr.pack_len)
1967 #else
1968 if ((sg_version < 30000 && nwritten != rp->sgdata.cdb.hdr.pack_len)
1969 || (sg_version >= 30000 && ret < 0))
1970 #endif
1971 {
1972 if (rp->running)
1973 {
1974 #ifdef SG_IO
1975 if (sg_version < 30000)
1976 #endif
1977 DBG (1, "sanei_scsi.issue: bad write (errno=%i) %s %li\n",
1978 errno, strerror (errno), (long)nwritten);
1979 #ifdef SG_IO
1980 else if (sg_version > 30000)
1981 DBG (1, "sanei_scsi.issue: SG_IO ioctl error (errno=%i, ret=%d) %s\n",
1982 errno, ret, strerror (errno));
1983 #endif
1984 rp->done = 1;
1985 if (errno == ENOMEM)
1986 {
1987 DBG (1, "sanei_scsi.issue: SG_BIG_BUF inconsistency? "
1988 "Check file PROBLEMS.\n");
1989 rp->status = SANE_STATUS_NO_MEM;
1990 }
1991 else
1992 rp->status = SANE_STATUS_IO_ERROR;
1993 }
1994 else
1995 {
1996 if (errno == ENOMEM)
1997 DBG (1, "issue: ENOMEM - cannot queue SCSI command. "
1998 "Trying again later.\n");
1999 else
2000 DBG (1, "issue: EAGAIN - cannot queue SCSI command. "
2001 "Trying again later.\n");
2002 }
2003 break; /* in case of an error don't try to queue more commands */
2004 }
2005 else
2006 {
2007 #ifdef SG_IO
2008 if (sg_version < 30000)
2009 #endif
2010 req->status = SANE_STATUS_IO_ERROR;
2011 #ifdef SG_IO
2012 else if (sg_version > 30000) /* SG_IO is synchronous, we're all set */
2013 req->status = SANE_STATUS_GOOD;
2014 #endif
2015 }
2016 fdp->sg_queue_used++;
2017 rp = rp->next;
2018 }
2019 }
2020
sanei_scsi_req_flush_all_extended(int fd)2021 void sanei_scsi_req_flush_all_extended (int fd)
2022 {
2023 fdparms *fdp;
2024 struct req *req, *next_req;
2025 int len, count;
2026
2027 fdp = (fdparms *) fd_info[fd].pdata;
2028 for (req = fdp->sane_qhead; req; req = next_req)
2029 {
2030 if (req->running && !req->done)
2031 {
2032 count = sane_scsicmd_timeout * 10;
2033 while (count)
2034 {
2035 errno = 0;
2036 #ifdef SG_IO
2037 if (sg_version < 30000)
2038 #endif
2039 len =
2040 read (fd, &req->sgdata.cdb,
2041 req->sgdata.cdb.hdr.reply_len);
2042 #ifdef SG_IO
2043 else
2044 len = read (fd, &req->sgdata.sg3.hdr, sizeof (Sg_io_hdr));
2045 #endif
2046 if (len >= 0 || (len < 0 && errno != EAGAIN))
2047 break;
2048 usleep (100000);
2049 count--;
2050 }
2051 ((fdparms *) fd_info[req->fd].pdata)->sg_queue_used--;
2052 }
2053 next_req = req->next;
2054
2055 req->next = fdp->sane_free_list;
2056 fdp->sane_free_list = req;
2057 }
2058
2059 fdp->sane_qhead = fdp->sane_qtail = 0;
2060 }
2061
sanei_scsi_req_flush_all()2062 void sanei_scsi_req_flush_all ()
2063 {
2064 int fd, i, j = 0;
2065
2066 /* sanei_scsi_open allows only one open file handle, so we
2067 can simply look for the first entry where in_use is set
2068 */
2069
2070 fd = num_alloced;
2071 for (i = 0; i < num_alloced; i++)
2072 if (fd_info[i].in_use)
2073 {
2074 j++;
2075 fd = i;
2076 }
2077
2078 assert (j < 2);
2079
2080 if (fd < num_alloced)
2081 sanei_scsi_req_flush_all_extended (fd);
2082 }
2083
2084 SANE_Status
sanei_scsi_req_enter2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size,void ** idp)2085 sanei_scsi_req_enter2 (int fd,
2086 const void *cmd, size_t cmd_size,
2087 const void *src, size_t src_size,
2088 void *dst, size_t * dst_size, void **idp)
2089 {
2090 struct req *req;
2091 size_t size;
2092 fdparms *fdp;
2093
2094 fdp = (fdparms *) fd_info[fd].pdata;
2095
2096 if (fdp->sane_free_list)
2097 {
2098 req = fdp->sane_free_list;
2099 fdp->sane_free_list = req->next;
2100 req->next = 0;
2101 }
2102 else
2103 {
2104 #ifdef SG_IO
2105 if (sg_version < 30000)
2106 #endif
2107 size = (sizeof (*req) - sizeof (req->sgdata.cdb.data)
2108 + fdp->buffersize);
2109 #ifdef SG_IO
2110 else
2111 size = sizeof (*req) + MAX_CDB + fdp->buffersize
2112 - sizeof (req->sgdata.sg3.data);
2113 #endif
2114 req = malloc (size);
2115 if (!req)
2116 {
2117 DBG (1, "sanei_scsi_req_enter: failed to malloc %lu bytes\n",
2118 (u_long) size);
2119 return SANE_STATUS_NO_MEM;
2120 }
2121 }
2122 req->fd = fd;
2123 req->running = 0;
2124 req->done = 0;
2125 req->status = SANE_STATUS_GOOD;
2126 req->dst = dst;
2127 req->dst_len = dst_size;
2128 #ifdef SG_IO
2129 if (sg_version < 30000)
2130 {
2131 #endif
2132 memset (&req->sgdata.cdb.hdr, 0, sizeof (req->sgdata.cdb.hdr));
2133 req->sgdata.cdb.hdr.pack_id = pack_id++;
2134 req->sgdata.cdb.hdr.pack_len = cmd_size + src_size
2135 + sizeof (req->sgdata.cdb.hdr);
2136 req->sgdata.cdb.hdr.reply_len = (dst_size ? *dst_size : 0)
2137 + sizeof (req->sgdata.cdb.hdr);
2138 memcpy (&req->sgdata.cdb.data, cmd, cmd_size);
2139 memcpy (&req->sgdata.cdb.data[cmd_size], src, src_size);
2140 if (CDB_SIZE (*(const u_char *) cmd) != cmd_size)
2141 {
2142 if (ioctl (fd, SG_NEXT_CMD_LEN, &cmd_size))
2143 {
2144 DBG (1,
2145 "sanei_scsi_req_enter2: ioctl to set command length failed\n");
2146 }
2147 }
2148 #ifdef SG_IO
2149 }
2150 else
2151 {
2152 memset (&req->sgdata.sg3.hdr, 0, sizeof (req->sgdata.sg3.hdr));
2153 req->sgdata.sg3.hdr.interface_id = 'S';
2154 req->sgdata.sg3.hdr.cmd_len = cmd_size;
2155 req->sgdata.sg3.hdr.iovec_count = 0;
2156 req->sgdata.sg3.hdr.mx_sb_len = SENSE_MAX;
2157 /* read or write? */
2158 if (dst_size && *dst_size)
2159 {
2160 req->sgdata.sg3.hdr.dxfer_direction = SG_DXFER_FROM_DEV;
2161 req->sgdata.sg3.hdr.dxfer_len = *dst_size;
2162 req->sgdata.sg3.hdr.dxferp = dst;
2163 }
2164 else if (src_size)
2165 {
2166 req->sgdata.sg3.hdr.dxfer_direction = SG_DXFER_TO_DEV;
2167 if (src_size > fdp->buffersize)
2168 {
2169 DBG (1,
2170 "sanei_scsi_req_enter2 warning: truncating write data "
2171 "from requested %li bytes to allowed %li bytes\n",
2172 (long)src_size, (long)fdp->buffersize);
2173 src_size = fdp->buffersize;
2174 }
2175 req->sgdata.sg3.hdr.dxfer_len = src_size;
2176 memcpy (&req->sgdata.sg3.data[MAX_CDB], src, src_size);
2177 req->sgdata.sg3.hdr.dxferp = &req->sgdata.sg3.data[MAX_CDB];
2178 }
2179 else
2180 {
2181 req->sgdata.sg3.hdr.dxfer_direction = SG_DXFER_NONE;
2182 }
2183 if (cmd_size > MAX_CDB)
2184 {
2185 DBG (1, "sanei_scsi_req_enter2 warning: truncating write data "
2186 "from requested %li bytes to allowed %i bytes\n",
2187 (long)cmd_size, MAX_CDB);
2188 cmd_size = MAX_CDB;
2189 }
2190 memcpy (req->sgdata.sg3.data, cmd, cmd_size);
2191 req->sgdata.sg3.hdr.cmdp = req->sgdata.sg3.data;
2192 req->sgdata.sg3.hdr.sbp = &(req->sgdata.sg3.sense_buffer[0]);
2193 req->sgdata.sg3.hdr.timeout = 1000 * sane_scsicmd_timeout;
2194 #ifdef ENABLE_SCSI_DIRECTIO
2195 /* for the adventurous: If direct IO is used,
2196 the kernel locks the buffer. This can lead to conflicts,
2197 if a backend uses shared memory.
2198 OTOH, direct IO may be faster, and it reduces memory usage
2199 */
2200 req->sgdata.sg3.hdr.flags = SG_FLAG_DIRECT_IO;
2201 #else
2202 req->sgdata.sg3.hdr.flags = 0;
2203 #endif
2204 req->sgdata.sg3.hdr.pack_id = pack_id++;
2205 req->sgdata.sg3.hdr.usr_ptr = 0;
2206 }
2207 #endif
2208
2209 req->next = 0;
2210 ATOMIC (if (fdp->sane_qtail)
2211 {
2212 fdp->sane_qtail->next = req; fdp->sane_qtail = req;}
2213 else
2214 fdp->sane_qhead = fdp->sane_qtail = req);
2215
2216 DBG (4, "scsi_req_enter: entered %p\n", (void *) req);
2217
2218 *idp = req;
2219 issue (req);
2220
2221 DBG (10, "scsi_req_enter: queue_used: %i, queue_max: %i\n",
2222 ((fdparms *) fd_info[fd].pdata)->sg_queue_used,
2223 ((fdparms *) fd_info[fd].pdata)->sg_queue_max);
2224
2225 return SANE_STATUS_GOOD;
2226 }
2227
sanei_scsi_req_wait(void * id)2228 SANE_Status sanei_scsi_req_wait (void *id)
2229 {
2230 SANE_Status status = SANE_STATUS_GOOD;
2231 struct req *req = id;
2232 ssize_t nread = 0;
2233
2234 /* we don't support out-of-order completion */
2235 assert (req == ((fdparms *) fd_info[req->fd].pdata)->sane_qhead);
2236
2237 DBG (4, "sanei_scsi_req_wait: waiting for %p\n", (void *) req);
2238
2239 issue (req); /* ensure the command is running */
2240 if (req->done)
2241 {
2242 issue (req->next); /* issue next command, if any */
2243 status = req->status;
2244 }
2245 else
2246 {
2247 #ifdef SG_IO
2248 if (sg_version < 30000)
2249 {
2250 #endif
2251 fd_set readable;
2252
2253 /* wait for command completion: */
2254 FD_ZERO (&readable);
2255 FD_SET (req->fd, &readable);
2256 select (req->fd + 1, &readable, 0, 0, 0);
2257
2258 /* now atomically read result and set DONE: */
2259 ATOMIC (nread = read (req->fd, &req->sgdata.cdb,
2260 req->sgdata.cdb.hdr.reply_len);
2261 req->done = 1);
2262 #ifdef SG_IO
2263 }
2264 else
2265 {
2266 IF_DBG (if (DBG_LEVEL >= 255)
2267 system ("cat /proc/scsi/sg/debug 1>&2");)
2268
2269 /* set DONE: */
2270 nread = 0; /* unused in this code path */
2271 req->done = 1;
2272 }
2273 #endif
2274
2275 if (fd_info[req->fd].pdata)
2276 ((fdparms *) fd_info[req->fd].pdata)->sg_queue_used--;
2277
2278 /* Now issue next command asap, if any. We can't do this
2279 earlier since the Linux kernel has space for just one big
2280 buffer. */
2281 issue (req->next);
2282
2283 DBG (4, "sanei_scsi_req_wait: read %ld bytes\n", (long) nread);
2284
2285 if (nread < 0)
2286 {
2287 DBG (1, "sanei_scsi_req_wait: read returned %ld (errno=%d)\n",
2288 (long) nread, errno);
2289 status = SANE_STATUS_IO_ERROR;
2290 }
2291 else
2292 {
2293 #ifdef SG_IO
2294 if (sg_version < 30000)
2295 {
2296 #endif
2297 nread -= sizeof (req->sgdata.cdb.hdr);
2298
2299 /* check for errors, but let the sense_handler decide.... */
2300 if ((req->sgdata.cdb.hdr.result != 0) ||
2301 (((req->sgdata.cdb.hdr.sense_buffer[0] & 0x7f) != 0)
2302 #ifdef HAVE_SG_TARGET_STATUS
2303 /* this is messy... Sometimes it happens that we have
2304 a valid looking sense buffer, but the DRIVER_SENSE
2305 bit is not set. Moreover, we can check this only for
2306 not too old SG drivers
2307 */
2308 && (req->sgdata.cdb.hdr.driver_status & DRIVER_SENSE)
2309 #endif
2310 ))
2311 {
2312 SANEI_SCSI_Sense_Handler handler
2313 = fd_info[req->fd].sense_handler;
2314 void *arg = fd_info[req->fd].sense_handler_arg;
2315
2316 DBG (1,
2317 "sanei_scsi_req_wait: SCSI command complained: %s\n",
2318 strerror (req->sgdata.cdb.hdr.result));
2319 DBG (10,
2320 "sense buffer: %02x %02x %02x %02x %02x %02x %02x %02x"
2321 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
2322 req->sgdata.cdb.hdr.sense_buffer[0],
2323 req->sgdata.cdb.hdr.sense_buffer[1],
2324 req->sgdata.cdb.hdr.sense_buffer[2],
2325 req->sgdata.cdb.hdr.sense_buffer[3],
2326 req->sgdata.cdb.hdr.sense_buffer[4],
2327 req->sgdata.cdb.hdr.sense_buffer[5],
2328 req->sgdata.cdb.hdr.sense_buffer[6],
2329 req->sgdata.cdb.hdr.sense_buffer[7],
2330 req->sgdata.cdb.hdr.sense_buffer[8],
2331 req->sgdata.cdb.hdr.sense_buffer[9],
2332 req->sgdata.cdb.hdr.sense_buffer[10],
2333 req->sgdata.cdb.hdr.sense_buffer[11],
2334 req->sgdata.cdb.hdr.sense_buffer[12],
2335 req->sgdata.cdb.hdr.sense_buffer[13],
2336 req->sgdata.cdb.hdr.sense_buffer[14],
2337 req->sgdata.cdb.hdr.sense_buffer[15]);
2338 #ifdef HAVE_SG_TARGET_STATUS
2339 /* really old SG header do not define target_status,
2340 host_status and driver_status
2341 */
2342 DBG (10, "target status: %02x host status: %02x"
2343 " driver status: %02x\n",
2344 req->sgdata.cdb.hdr.target_status,
2345 req->sgdata.cdb.hdr.host_status,
2346 req->sgdata.cdb.hdr.driver_status);
2347
2348 if (req->sgdata.cdb.hdr.host_status == DID_NO_CONNECT || req->sgdata.cdb.hdr.host_status == DID_BUS_BUSY || req->sgdata.cdb.hdr.host_status == DID_TIME_OUT || req->sgdata.cdb.hdr.driver_status == DRIVER_BUSY || req->sgdata.cdb.hdr.target_status == 0x04) /* BUSY */
2349 #else
2350 if (req->sgdata.cdb.hdr.result == EBUSY)
2351 #endif
2352 status = SANE_STATUS_DEVICE_BUSY;
2353 else if (handler)
2354 /* sense handler should return SANE_STATUS_GOOD if it
2355 decided all was ok after all */
2356 status =
2357 (*handler) (req->fd, req->sgdata.cdb.hdr.sense_buffer,
2358 arg);
2359 else
2360 status = SANE_STATUS_IO_ERROR;
2361 }
2362
2363 /* if we are ok so far, copy over the return data */
2364 if (status == SANE_STATUS_GOOD)
2365 {
2366 if (req->dst)
2367 memcpy (req->dst, req->sgdata.cdb.data, nread);
2368
2369 if (req->dst_len)
2370 *req->dst_len = nread;
2371 }
2372 #ifdef SG_IO
2373 }
2374 else
2375 {
2376 /* check for errors, but let the sense_handler decide.... */
2377 if (((req->sgdata.sg3.hdr.info & SG_INFO_CHECK) != 0)
2378 || ((req->sgdata.sg3.hdr.sb_len_wr > 0)
2379 && ((req->sgdata.sg3.sense_buffer[0] & 0x7f) != 0)
2380 && (req->sgdata.sg3.hdr.
2381 driver_status & DRIVER_SENSE)))
2382 {
2383 SANEI_SCSI_Sense_Handler handler
2384 = fd_info[req->fd].sense_handler;
2385 void *arg = fd_info[req->fd].sense_handler_arg;
2386
2387 DBG (1,
2388 "sanei_scsi_req_wait: SCSI command complained: %s\n",
2389 strerror (errno));
2390 DBG (10,
2391 "sense buffer: %02x %02x %02x %02x %02x %02x %02x %02x"
2392 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
2393 req->sgdata.sg3.sense_buffer[0],
2394 req->sgdata.sg3.sense_buffer[1],
2395 req->sgdata.sg3.sense_buffer[2],
2396 req->sgdata.sg3.sense_buffer[3],
2397 req->sgdata.sg3.sense_buffer[4],
2398 req->sgdata.sg3.sense_buffer[5],
2399 req->sgdata.sg3.sense_buffer[6],
2400 req->sgdata.sg3.sense_buffer[7],
2401 req->sgdata.sg3.sense_buffer[8],
2402 req->sgdata.sg3.sense_buffer[9],
2403 req->sgdata.sg3.sense_buffer[10],
2404 req->sgdata.sg3.sense_buffer[11],
2405 req->sgdata.sg3.sense_buffer[12],
2406 req->sgdata.sg3.sense_buffer[13],
2407 req->sgdata.sg3.sense_buffer[14],
2408 req->sgdata.sg3.sense_buffer[15]);
2409 DBG (10,
2410 "target status: %02x host status: %04x"
2411 " driver status: %04x\n", req->sgdata.sg3.hdr.status,
2412 req->sgdata.sg3.hdr.host_status,
2413 req->sgdata.sg3.hdr.driver_status);
2414
2415 /* the first three tests below are an replacement of the
2416 error "classification" as it was with the old SG driver,
2417 the fourth test is new.
2418 */
2419 if (req->sgdata.sg3.hdr.host_status == SG_ERR_DID_NO_CONNECT || req->sgdata.sg3.hdr.host_status == SG_ERR_DID_BUS_BUSY || req->sgdata.sg3.hdr.host_status == SG_ERR_DID_TIME_OUT || req->sgdata.sg3.hdr.driver_status == DRIVER_BUSY || req->sgdata.sg3.hdr.masked_status == 0x04) /* BUSY */
2420 status = SANE_STATUS_DEVICE_BUSY;
2421 else if (handler && req->sgdata.sg3.hdr.sb_len_wr)
2422 /* sense handler should return SANE_STATUS_GOOD if it
2423 decided all was ok after all */
2424 status =
2425 (*handler) (req->fd, req->sgdata.sg3.sense_buffer,
2426 arg);
2427
2428 /* status bits INTERMEDIATE and CONDITION MET should not
2429 result in an error; neither should reserved bits
2430 */
2431 else if (((req->sgdata.sg3.hdr.status & 0x2a) == 0)
2432 && (req->sgdata.sg3.hdr.host_status ==
2433 SG_ERR_DID_OK)
2434 &&
2435 ((req->sgdata.sg3.hdr.
2436 driver_status & ~SG_ERR_DRIVER_SENSE) ==
2437 SG_ERR_DRIVER_OK))
2438 status = SANE_STATUS_GOOD;
2439 else
2440 status = SANE_STATUS_IO_ERROR;
2441 }
2442
2443 #if 0
2444 /* Sometimes the Linux SCSI system reports bogus resid values.
2445 Observed with lk 2.4.5, 2.4.13, aic7xxx and sym53c8xx drivers,
2446 if command queueing is used. So we better issue only a warning
2447 */
2448 if (status == SANE_STATUS_GOOD)
2449 {
2450 if (req->dst_len)
2451 {
2452 *req->dst_len -= req->sgdata.sg3.hdr.resid;
2453 }
2454 }
2455 #endif
2456 if (req->sgdata.sg3.hdr.resid)
2457 {
2458 DBG (1,
2459 "sanei_scsi_req_wait: SG driver returned resid %i\n",
2460 req->sgdata.sg3.hdr.resid);
2461 DBG (1,
2462 " NOTE: This value may be bogus\n");
2463 }
2464 }
2465 #endif
2466 }
2467 }
2468
2469 /* dequeue and release processed request: */
2470 ATOMIC (((fdparms *) fd_info[req->fd].pdata)->sane_qhead
2471 = ((fdparms *) fd_info[req->fd].pdata)->sane_qhead->next;
2472 if (!((fdparms *) fd_info[req->fd].pdata)->sane_qhead)
2473 ((fdparms *) fd_info[req->fd].pdata)->sane_qtail = 0;
2474 req->next = ((fdparms *) fd_info[req->fd].pdata)->sane_free_list;
2475 ((fdparms *) fd_info[req->fd].pdata)->sane_free_list = req);
2476 return status;
2477 }
2478
2479 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)2480 sanei_scsi_cmd2 (int fd,
2481 const void *cmd, size_t cmd_size,
2482 const void *src, size_t src_size,
2483 void *dst, size_t * dst_size)
2484 {
2485 SANE_Status status;
2486 void *id;
2487
2488 status =
2489 sanei_scsi_req_enter2 (fd, cmd, cmd_size, src, src_size, dst, dst_size,
2490 &id);
2491 if (status != SANE_STATUS_GOOD)
2492 return status;
2493 return sanei_scsi_req_wait (id);
2494 }
2495
2496 /* The following code (up to and including sanei_scsi_find_devices() )
2497 is trying to match device/manufacturer names and/or SCSI addressing
2498 numbers (i.e. <host,bus,id,lun>) with a sg device file name
2499 (e.g. /dev/sg3).
2500 */
2501 #define PROCFILE "/proc/scsi/scsi"
2502 #define DEVFS_MSK "/dev/scsi/host%d/bus%d/target%d/lun%d/generic"
2503 #define SCAN_MISSES 5
2504
2505 /* Some <scsi/scsi.h> headers don't have the following define */
2506 #ifndef SCSI_IOCTL_GET_IDLUN
2507 #define SCSI_IOCTL_GET_IDLUN 0x5382
2508 #endif
2509
2510 static int lx_sg_dev_base = -1;
2511 static int lx_devfs = -1;
2512
2513 static const struct lx_device_name_list_tag
2514 {
2515 const char *prefix;
2516 char base;
2517 }
2518 lx_dnl[] =
2519 {
2520 {
2521 "/dev/sg", 0}
2522 ,
2523 {
2524 "/dev/sg", 'a'}
2525 ,
2526 {
2527 "/dev/uk", 0}
2528 ,
2529 {
2530 "/dev/gsc", 0}
2531 };
2532
2533 static int /* Returns open sg file descriptor, or -1 for no access,
2534 or -2 for not found (or other error) */
lx_mk_devicename(int guess_devnum,char * name,size_t name_len)2535 lx_mk_devicename (int guess_devnum, char *name, size_t name_len)
2536 {
2537 int dev_fd, k, dnl_len;
2538 const struct lx_device_name_list_tag *dnp;
2539
2540 dnl_len = NELEMS (lx_dnl);
2541 k = ((-1 == lx_sg_dev_base) ? 0 : lx_sg_dev_base);
2542 for (; k < dnl_len; ++k)
2543 {
2544 dnp = &lx_dnl[k];
2545 if (dnp->base)
2546 snprintf (name, name_len, "%s%c", dnp->prefix,
2547 dnp->base + guess_devnum);
2548 else
2549 snprintf (name, name_len, "%s%d", dnp->prefix, guess_devnum);
2550 dev_fd = -1;
2551 #ifdef HAVE_RESMGR
2552 dev_fd = rsm_open_device (name, O_RDWR | O_NONBLOCK);
2553 #endif
2554 if (dev_fd == -1)
2555 dev_fd = open (name, O_RDWR | O_NONBLOCK);
2556 if (dev_fd >= 0)
2557 {
2558 lx_sg_dev_base = k;
2559 return dev_fd;
2560 }
2561 else if ((EACCES == errno) || (EBUSY == errno))
2562 {
2563 lx_sg_dev_base = k;
2564 return -1;
2565 }
2566 if (-1 != lx_sg_dev_base)
2567 return -2;
2568 }
2569 return -2;
2570 }
2571
2572 static int /* Returns 1 for match, else 0 */
lx_chk_id(int dev_fd,int host,int channel,int id,int lun)2573 lx_chk_id (int dev_fd, int host, int channel, int id, int lun)
2574 {
2575 #ifdef SG_GET_SCSI_ID_FOUND
2576 struct sg_scsi_id ssid;
2577
2578 if ((ioctl (dev_fd, SG_GET_SCSI_ID, &ssid) >= 0))
2579 {
2580 DBG (2, "lx_chk_id: %d,%d %d,%d %d,%d %d,%d\n", host, ssid.host_no,
2581 channel, ssid.channel, id, ssid.scsi_id, lun, ssid.lun);
2582 if ((host == ssid.host_no) &&
2583 (channel == ssid.channel) &&
2584 (id == ssid.scsi_id) && (lun == ssid.lun))
2585 return 1;
2586 else
2587 return 0;
2588 }
2589 #endif
2590 {
2591 struct my_scsi_idlun
2592 {
2593 int dev_id;
2594 int host_unique_id;
2595 }
2596 my_idlun;
2597 if (ioctl (dev_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun) >= 0)
2598 {
2599 if (((my_idlun.dev_id & 0xff) == id) &&
2600 (((my_idlun.dev_id >> 8) & 0xff) == lun) &&
2601 (((my_idlun.dev_id >> 16) & 0xff) == channel))
2602 return 1; /* cheating, assume 'host' number matches */
2603 }
2604 }
2605 return 0;
2606 }
2607
2608 static int /* Returns 1 if match with 'name' set, else 0 */
2609
lx_scan_sg(int exclude_devnum,char * name,size_t name_len,int host,int channel,int id,int lun)2610 lx_scan_sg (int exclude_devnum, char *name, size_t name_len,
2611 int host, int channel, int id, int lun)
2612 {
2613 int dev_fd, k, missed;
2614
2615 if (-1 == lx_sg_dev_base)
2616 return 0;
2617 for (k = 0, missed = 0; (missed < SCAN_MISSES) && (k < 255);
2618 ++k, ++missed)
2619 {
2620 DBG (2, "lx_scan_sg: k=%d, exclude=%d, missed=%d\n", k,
2621 exclude_devnum, missed);
2622 if (k == exclude_devnum)
2623 {
2624 missed = 0;
2625 continue; /* assumed this one has been checked already */
2626 }
2627 if ((dev_fd = lx_mk_devicename (k, name, name_len)) >= 0)
2628 {
2629 missed = 0;
2630 if (lx_chk_id (dev_fd, host, channel, id, lun))
2631 {
2632 close (dev_fd);
2633 return 1;
2634 }
2635 close (dev_fd);
2636 }
2637 else if (-1 == dev_fd)
2638 missed = 0; /* no permissions but something found */
2639 }
2640 return 0;
2641 }
2642
2643 static int /* Returns 1 if match, else 0 */
2644
lx_chk_devicename(int guess_devnum,char * name,size_t name_len,int host,int channel,int id,int lun)2645 lx_chk_devicename (int guess_devnum, char *name, size_t name_len,
2646 int host, int channel, int id, int lun)
2647 {
2648 int dev_fd;
2649
2650 if (host < 0)
2651 return 0;
2652 if (0 != lx_devfs)
2653 { /* simple mapping if we have devfs */
2654 if (-1 == lx_devfs)
2655 {
2656 if ((dev_fd =
2657 lx_mk_devicename (guess_devnum, name, name_len)) >= 0)
2658 close (dev_fd); /* hack to load sg driver module */
2659 }
2660 snprintf (name, name_len, DEVFS_MSK, host, channel, id, lun);
2661 dev_fd = open (name, O_RDWR | O_NONBLOCK);
2662 if (dev_fd >= 0)
2663 {
2664 close (dev_fd);
2665 lx_devfs = 1;
2666 DBG (1, "lx_chk_devicename: matched device(devfs): %s\n", name);
2667 return 1;
2668 }
2669 else if (ENOENT == errno)
2670 lx_devfs = 0;
2671 }
2672
2673 if ((dev_fd = lx_mk_devicename (guess_devnum, name, name_len)) < -1)
2674 { /* no candidate sg device file name found, try /dev/sg0,1 */
2675 if ((dev_fd = lx_mk_devicename (0, name, name_len)) < -1)
2676 {
2677 if ((dev_fd = lx_mk_devicename (1, name, name_len)) < -1)
2678 return 0; /* no luck finding sg fd to open */
2679 }
2680 }
2681 if (dev_fd >= 0)
2682 {
2683 /* now check this fd for match on <host, channel, id, lun> */
2684 if (lx_chk_id (dev_fd, host, channel, id, lun))
2685 {
2686 close (dev_fd);
2687 DBG (1, "lx_chk_devicename: matched device(direct): %s\n", name);
2688 return 1;
2689 }
2690 close (dev_fd);
2691 }
2692 /* if mismatch then call scan algorithm */
2693 if (lx_scan_sg (guess_devnum, name, name_len, host, channel, id, lun))
2694 {
2695 DBG (1, "lx_chk_devicename: matched device(scan): %s\n", name);
2696 return 1;
2697 }
2698 return 0;
2699 }
2700
2701 /* Legacy /proc/scsi/scsi */
2702 static void /* calls 'attach' function pointer with sg device file name iff match */
sanei_proc_scsi_find_devices(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))2703 sanei_proc_scsi_find_devices (const char *findvendor, const char *findmodel,
2704 const char *findtype,
2705 int findbus, int findchannel, int findid,
2706 int findlun,
2707 SANE_Status (*attach) (const char *dev))
2708 {
2709 #define FOUND_VENDOR 1
2710 #define FOUND_MODEL 2
2711 #define FOUND_TYPE 4
2712 #define FOUND_REV 8
2713 #define FOUND_HOST 16
2714 #define FOUND_CHANNEL 32
2715 #define FOUND_ID 64
2716 #define FOUND_LUN 128
2717 #define FOUND_ALL 255
2718
2719 char *me = "sanei_proc_scsi_find_devices";
2720
2721 size_t findvendor_len = 0, findmodel_len = 0, findtype_len = 0;
2722 char vendor[32], model[32], type[32], revision[32];
2723 int bus, channel, id, lun;
2724
2725 int number, i, j, definedd;
2726 char line[256], dev_name[128], *c1, *c2, ctmp;
2727 char *string;
2728 FILE *proc_fp;
2729 char *end;
2730 struct
2731 {
2732 const char *name;
2733 size_t name_len;
2734 int is_int; /* integer valued? (not a string) */
2735 union
2736 {
2737 void *v; /* avoids compiler warnings... */
2738 char *str;
2739 int *i;
2740 }
2741 u;
2742 }
2743 param[] =
2744 {
2745 {
2746 "Vendor:", 7, 0,
2747 {
2748 0}
2749 }
2750 ,
2751 {
2752 "Model:", 6, 0,
2753 {
2754 0}
2755 }
2756 ,
2757 {
2758 "Type:", 5, 0,
2759 {
2760 0}
2761 }
2762 ,
2763 {
2764 "Rev:", 4, 0,
2765 {
2766 0}
2767 }
2768 ,
2769 {
2770 "scsi", 4, 1,
2771 {
2772 0}
2773 }
2774 ,
2775 {
2776 "Channel:", 8, 1,
2777 {
2778 0}
2779 }
2780 ,
2781 {
2782 "Id:", 3, 1,
2783 {
2784 0}
2785 }
2786 ,
2787 {
2788 "Lun:", 4, 1,
2789 {
2790 0}
2791 }
2792 };
2793
2794 param[0].u.str = vendor;
2795 param[1].u.str = model;
2796 param[2].u.str = type;
2797 param[3].u.str = revision;
2798 param[4].u.i = &bus;
2799 param[5].u.i = &channel;
2800 param[6].u.i = &id;
2801 param[7].u.i = &lun;
2802
2803 DBG_INIT ();
2804
2805 proc_fp = fopen (PROCFILE, "r");
2806 if (!proc_fp)
2807 {
2808 DBG (1, "%s: could not open %s for reading\n", me, PROCFILE);
2809 return;
2810 }
2811
2812 number = bus = channel = id = lun = -1;
2813
2814 vendor[0] = model[0] = type[0] = '\0';
2815 if (findvendor)
2816 findvendor_len = strlen (findvendor);
2817 if (findmodel)
2818 findmodel_len = strlen (findmodel);
2819 if (findtype)
2820 findtype_len = strlen (findtype);
2821
2822 definedd = 0;
2823 while (!feof (proc_fp))
2824 {
2825 fgets (line, sizeof (line), proc_fp);
2826 string = (char *) sanei_config_skip_whitespace (line);
2827
2828 while (*string)
2829 {
2830 for (i = 0; i < NELEMS (param); ++i)
2831 {
2832 if (strncmp (string, param[i].name, param[i].name_len) == 0)
2833 {
2834 string += param[i].name_len;
2835 /* Make sure that we don't read the next parameter name
2836 as a value, if the real value consists only of spaces
2837 */
2838 c2 = string + strlen (string);
2839 for (j = 0; j < NELEMS (param); ++j)
2840 {
2841 c1 = strstr (string, param[j].name);
2842 if ((j != i) && c1 && (c1 < c2))
2843 c2 = c1;
2844 }
2845 ctmp = *c2;
2846 *c2 = 0;
2847 string = (char *) sanei_config_skip_whitespace (string);
2848
2849 if (param[i].is_int)
2850 {
2851 if (*string)
2852 {
2853 *param[i].u.i = strtol (string, &end, 10);
2854 string = (char *) end;
2855 }
2856 else
2857 *param[i].u.i = 0;
2858 }
2859 else
2860 {
2861 strncpy (param[i].u.str, string, 32);
2862 param[i].u.str[31] = '\0';
2863 /* while (*string && !isspace (*string))
2864 ++string;
2865 */
2866 }
2867 /* string = sanei_config_skip_whitespace (string); */
2868 *c2 = ctmp;
2869 string = c2;
2870 definedd |= 1 << i;
2871
2872 if (param[i].u.v == &bus)
2873 {
2874 ++number;
2875 definedd = FOUND_HOST;
2876 }
2877 break;
2878 }
2879 }
2880 if (i >= NELEMS (param))
2881 ++string; /* no match */
2882 }
2883
2884 if (FOUND_ALL != definedd)
2885 /* some info is still missing */
2886 continue;
2887
2888 definedd = 0;
2889 if ((!findvendor || strncmp (vendor, findvendor, findvendor_len) == 0)
2890 && (!findmodel || strncmp (model, findmodel, findmodel_len) == 0)
2891 && (!findtype || strncmp (type, findtype, findtype_len) == 0)
2892 && (findbus == -1 || bus == findbus)
2893 && (findchannel == -1 || channel == findchannel)
2894 && (findid == -1 || id == findid)
2895 && (findlun == -1 || lun == findlun))
2896 {
2897 DBG (2, "%s: found: vendor=%s model=%s type=%s\n\t"
2898 "bus=%d chan=%d id=%d lun=%d num=%d\n",
2899 me, findvendor, findmodel, findtype,
2900 bus, channel, id, lun, number);
2901 if (lx_chk_devicename (number, dev_name, sizeof (dev_name), bus,
2902 channel, id, lun)
2903 && ((*attach) (dev_name) != SANE_STATUS_GOOD))
2904 {
2905 DBG(1,"sanei_scsi_find_devices: bad attach\n");
2906 }
2907 }
2908 else
2909 {
2910 DBG (2, "%s: no match\n", me);
2911 }
2912 vendor[0] = model[0] = type[0] = 0;
2913 bus = channel = id = lun = -1;
2914 }
2915 fclose (proc_fp);
2916 }
2917
2918 #define SYSFS_SCSI_DEVICES "/sys/bus/scsi/devices"
2919
2920 /* From linux/drivers/scsi/scsi.c */
2921 static char *lnxscsi_device_types[] = {
2922 "Direct-Access ",
2923 "Sequential-Access",
2924 "Printer ",
2925 "Processor ",
2926 "WORM ",
2927 "CD-ROM ",
2928 "Scanner ",
2929 "Optical Device ",
2930 "Medium Changer ",
2931 "Communications ",
2932 "ASC IT8 ",
2933 "ASC IT8 ",
2934 "RAID ",
2935 "Enclosure ",
2936 "Direct-Access-RBC",
2937 "Optical card ",
2938 "Bridge controller",
2939 "Object storage ",
2940 "Automation/Drive "
2941 };
2942
2943 void /* calls 'attach' function pointer with sg device file name iff match */
sanei_scsi_find_devices(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))2944 sanei_scsi_find_devices (const char *findvendor, const char *findmodel,
2945 const char *findtype,
2946 int findbus, int findchannel, int findid,
2947 int findlun,
2948 SANE_Status (*attach) (const char *dev))
2949 {
2950 char *me = "sanei_scsi_find_devices";
2951 char path[PATH_MAX];
2952 char dev_name[128];
2953 struct dirent *buf;
2954 DIR *scsidevs;
2955 FILE *fp;
2956 char *ptr;
2957 char *end;
2958 int bcil[4]; /* bus, channel, id, lun */
2959 char vmt[3][33]; /* vendor, model, type */
2960 int vmt_len[3];
2961 char *vmtfiles[3] = { "vendor", "model", "type" };
2962 int lastbus;
2963 int number;
2964 int i;
2965 long val;
2966 int ret;
2967
2968 DBG_INIT ();
2969
2970 DBG (2, "%s: looking for: v=%s m=%s t=%s b=%d c=%d i=%d l=%d\n",
2971 me, findvendor, findmodel, findtype,
2972 findbus, findchannel, findid, findlun);
2973
2974 scsidevs = opendir (SYSFS_SCSI_DEVICES);
2975 if (!scsidevs)
2976 {
2977 DBG (1, "%s: could not open %s; falling back to /proc\n",
2978 me, SYSFS_SCSI_DEVICES);
2979
2980 sanei_proc_scsi_find_devices (findvendor, findmodel, findtype,
2981 findbus, findchannel, findid, findlun,
2982 attach);
2983 return;
2984 }
2985
2986 vmt_len[0] = (findvendor) ? strlen(findvendor) : 0;
2987 vmt_len[1] = (findmodel) ? strlen(findmodel) : 0;
2988 vmt_len[2] = (findtype) ? strlen(findtype) : 0;
2989
2990 lastbus = -1;
2991 number = -1;
2992 for (;;)
2993 {
2994 errno = 0;
2995 buf = readdir (scsidevs);
2996 if (errno != 0)
2997 {
2998 DBG (1, "%s: could not read directory %s: %s\n",
2999 me, SYSFS_SCSI_DEVICES, strerror(errno));
3000
3001 break;
3002 }
3003
3004 if (buf == NULL)
3005 break;
3006
3007 if (buf->d_name[0] == '.')
3008 continue;
3009
3010 /* Extract bus, channel, id, lun from directory name b:c:i:l */
3011 ptr = buf->d_name;
3012 for (i = 0; i < 4; i++)
3013 {
3014 errno = 0;
3015 val = strtol (ptr, &end, 10);
3016 if (((errno == ERANGE) && ((val == LONG_MAX) || (val == LONG_MIN)))
3017 || ((errno != 0) && (val == 0)))
3018 {
3019 DBG (1, "%s: invalid integer in string (%s): %s\n",
3020 me, ptr, strerror(errno));
3021
3022 i = 12; /* Skip */
3023 break;
3024 }
3025
3026 if (end == ptr)
3027 {
3028 DBG (1, "%s: no integer found in string: %s (%d)\n", me, ptr, i);
3029
3030 i = 12; /* Skip */
3031 break;
3032 }
3033
3034 if (*end && (*end != ':'))
3035 {
3036 DBG (1, "%s: parse error on string %s (%d)\n", me, buf->d_name, i);
3037
3038 i = 12; /* Skip */
3039 break;
3040 }
3041
3042 if (val > INT_MAX)
3043 {
3044 DBG (1, "%s: integer value too large (%s)\n", me, buf->d_name);
3045
3046 i = 12; /* Skip */
3047 break;
3048 }
3049
3050 bcil[i] = (int) val;
3051 ptr = end + 1;
3052 }
3053
3054 /* Skip this one */
3055 if (i == 12)
3056 continue;
3057
3058 if (bcil[0] != lastbus)
3059 {
3060 lastbus = bcil[0];
3061 number++;
3062 }
3063
3064 for (i = 0; i < 3; i++)
3065 {
3066 ret = snprintf (path, PATH_MAX, "%s/%s/%s",
3067 SYSFS_SCSI_DEVICES, buf->d_name, vmtfiles[i]);
3068 if ((ret < 0) || (ret >= PATH_MAX))
3069 {
3070 DBG (1, "%s: skipping %s/%s, PATH_MAX exceeded on %s\n",
3071 me, SYSFS_SCSI_DEVICES, buf->d_name, vmtfiles[i]);
3072
3073 i = 12; /* Skip */
3074 break;
3075 }
3076
3077 memset (vmt[i], 0, sizeof(vmt[i]));
3078
3079 fp = fopen(path, "r");
3080 if (!fp)
3081 {
3082 DBG (1, "%s: could not open %s: %s\n", me, path, strerror(errno));
3083
3084 i = 12; /* Skip */
3085 break;
3086 }
3087
3088 ret = fread (vmt[i], 1, sizeof(vmt[i]) - 1, fp);
3089 if (ret <= 0)
3090 {
3091 if (ferror(fp))
3092 {
3093 DBG (1, "%s: error reading %s\n", me, path);
3094
3095 i = 12; /* Skip */
3096 break;
3097 }
3098 }
3099
3100 if (vmt[i][ret - 1] == '\n')
3101 vmt[i][ret - 1] = '\0';
3102
3103 fclose (fp);
3104 }
3105
3106 /* Skip this one */
3107 if (i == 12)
3108 continue;
3109
3110 /* Type is a numeric string and must be converted back to a well-known string */
3111 errno = 0;
3112 val = strtol (vmt[2], &end, 10);
3113 if (((errno == ERANGE) && ((val == LONG_MAX) || (val == LONG_MIN)))
3114 || ((errno != 0) && (val == 0)))
3115 {
3116 DBG (1, "%s: invalid integer in type string (%s): %s\n",
3117 me, vmt[2], strerror(errno));
3118 continue;
3119 }
3120
3121 if (end == vmt[2])
3122 {
3123 DBG (1, "%s: no integer found in type string: %s\n", me, vmt[2]);
3124 continue;
3125 }
3126
3127 if ((val < 0) || (val >= (int)(sizeof(lnxscsi_device_types) / sizeof(lnxscsi_device_types[0]))))
3128 {
3129 DBG (1, "%s: invalid type %ld\n", me, val);
3130 continue;
3131 }
3132
3133 strncpy(vmt[2], lnxscsi_device_types[val], sizeof(vmt[2]) - 1);
3134
3135 if ((!findvendor || strncmp (vmt[0], findvendor, vmt_len[0]) == 0)
3136 && (!findmodel || strncmp (vmt[1], findmodel, vmt_len[1]) == 0)
3137 && (!findtype || strncmp (vmt[2], findtype, vmt_len[2]) == 0)
3138 && (findbus == -1 || bcil[0] == findbus)
3139 && (findchannel == -1 || bcil[1] == findchannel)
3140 && (findid == -1 || bcil[2] == findid)
3141 && (findlun == -1 || bcil[3] == findlun))
3142 {
3143 DBG (2, "%s: found: vendor=%s model=%s type=%s\n\t"
3144 "bus=%d chan=%d id=%d lun=%d num=%d\n",
3145 me, vmt[0], vmt[1], vmt[2],
3146 bcil[0], bcil[1], bcil[2], bcil[3], number);
3147
3148 if (lx_chk_devicename (number, dev_name, sizeof (dev_name),
3149 bcil[0], bcil[1], bcil[2], bcil[3])
3150 && ((*attach) (dev_name) != SANE_STATUS_GOOD))
3151 {
3152 DBG (1, "%s: bad attach\n", me);
3153 }
3154 }
3155 else
3156 {
3157 DBG (2, "%s: no match\n", me);
3158 }
3159 }
3160
3161 closedir(scsidevs);
3162 }
3163
3164 #endif /* USE == LINUX_INTERFACE */
3165
3166
3167 #if USE == BSD_INTERFACE
3168
3169 #ifndef HAVE_SCSIREQ_ENTER
scsireq_enter(int fd,scsireq_t * hdr)3170 static int scsireq_enter (int fd, scsireq_t * hdr)
3171 {
3172 return ioctl (fd, SCIOCCOMMAND, hdr);
3173 }
3174 #endif /* !HAVE_SCSIREQ_ENTER */
3175
3176 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)3177 sanei_scsi_cmd2 (int fd,
3178 const void *cmd, size_t cmd_size,
3179 const void *src, size_t src_size,
3180 void *dst, size_t * dst_size)
3181 {
3182 /* xxx obsolete: size_t cdb_size;
3183 */
3184 scsireq_t hdr;
3185 int result;
3186
3187 /* xxx obsolete:
3188 cdb_size = CDB_SIZE (*(u_char *) src);
3189 */
3190
3191 memset (&hdr, 0, sizeof (hdr));
3192 memcpy (hdr.cmd, cmd, cmd_size);
3193 if (dst_size && *dst_size)
3194 {
3195 /* xxx obsolete: assert (cdb_size == src_size);
3196 */
3197 hdr.flags = SCCMD_READ;
3198 hdr.databuf = dst;
3199 hdr.datalen = *dst_size;
3200 }
3201 else
3202 {
3203 /* xxx obsolete: assert (cdb_size <= src_size);
3204 */
3205 hdr.flags = SCCMD_WRITE;
3206 /* The old variant:
3207 hdr.databuf = (char *) src + cdb_size;
3208 hdr.datalen = src_size;
3209 xxxxxx huh? Shouldn´t the above line have been src_size - cdb_size)
3210 */
3211 hdr.databuf = (char *) src;
3212 hdr.datalen = src_size;
3213 }
3214 hdr.timeout = sane_scsicmd_timeout * 1000;
3215 hdr.cmdlen = cmd_size;
3216 hdr.senselen = sizeof (hdr.sense);
3217
3218 result = scsireq_enter (fd, &hdr);
3219 if (result < 0)
3220 {
3221 DBG (1, "sanei_scsi_cmd: scsi_reqenter() failed: %s\n",
3222 strerror (errno));
3223 return SANE_STATUS_IO_ERROR;
3224 }
3225 if (hdr.retsts != SCCMD_OK)
3226 {
3227 SANEI_SCSI_Sense_Handler handler;
3228
3229 DBG (1, "sanei_scsi_cmd: scsi returned with status %d\n", hdr.retsts);
3230 switch (hdr.retsts)
3231 {
3232 case SCCMD_TIMEOUT:
3233 case SCCMD_BUSY:
3234 return SANE_STATUS_DEVICE_BUSY;
3235
3236 case SCCMD_SENSE:
3237 handler = fd_info[fd].sense_handler;
3238 if (handler)
3239 return (*handler) (fd, &hdr.sense[0],
3240 fd_info[fd].sense_handler_arg);
3241 /* fall through */
3242 default:
3243 return SANE_STATUS_IO_ERROR;
3244 }
3245 }
3246
3247 if (dst_size)
3248 *dst_size = hdr.datalen_used;
3249
3250 return SANE_STATUS_GOOD;
3251 }
3252 #endif /* USE == BSD_INTERFACE */
3253
3254 #if USE == FREEBSD_CAM_INTERFACE
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)3255 SANE_Status sanei_scsi_cmd2 (int fd,
3256 const void *cmd, size_t cmd_size,
3257 const void *src, size_t src_size,
3258 void *dst, size_t * dst_size)
3259 {
3260
3261 struct cam_device *dev;
3262 union ccb *ccb;
3263 int rv;
3264 u_int32_t ccb_flags;
3265 char *data_buf;
3266 size_t data_len;
3267 SANE_Status status;
3268
3269 if (fd < 0 || fd > CAM_MAXDEVS || cam_devices[fd] == NULL)
3270 {
3271 fprintf (stderr, "attempt to reference invalid unit %d\n", fd);
3272 return SANE_STATUS_INVAL;
3273 }
3274
3275 dev = cam_devices[fd];
3276 ccb = cam_getccb (dev);
3277
3278 /* Build the CCB */
3279 memset (&(&ccb->ccb_h)[1], 0, sizeof (struct ccb_scsiio));
3280 memcpy (&ccb->csio.cdb_io.cdb_bytes, cmd, cmd_size);
3281
3282 /*
3283 * Set the data direction flags.
3284 */
3285 if (dst_size && *dst_size)
3286 {
3287 /* xxx obsolete: assert (cdb_size == src_size);
3288 */
3289 ccb_flags = CAM_DIR_IN;
3290 data_buf = ((char *) (dst));
3291 data_len = *dst_size;
3292 }
3293 else if (src_size > 0)
3294 {
3295 ccb_flags = CAM_DIR_OUT;
3296 data_buf = ((char *) (src));
3297 data_len = src_size;
3298 }
3299 else
3300 {
3301 ccb_flags = CAM_DIR_NONE;
3302 data_buf = NULL;
3303 data_len = 0;
3304 }
3305
3306 cam_fill_csio (&ccb->csio,
3307 /* retries */ 1,
3308 /* cbfncp */ NULL,
3309 /* flags */ ccb_flags,
3310 /* tag_action */ MSG_SIMPLE_Q_TAG,
3311 /* data_ptr */ (u_int8_t *) data_buf,
3312 /* dxfer_len */ data_len,
3313 /* sense_len */ SSD_FULL_SIZE,
3314 /* cdb_len */ cmd_size,
3315 /* timeout */ sane_scsicmd_timeout * 1000);
3316
3317 /* Run the command */
3318 errno = 0;
3319 if ((rv = cam_send_ccb (dev, ccb)) == -1)
3320 {
3321 cam_freeccb (ccb);
3322 return (SANE_STATUS_IO_ERROR);
3323 }
3324
3325 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
3326 {
3327 SANEI_SCSI_Sense_Handler handler;
3328
3329 DBG (1, "sanei_scsi_cmd: scsi returned with status %d\n",
3330 (ccb->ccb_h.status & CAM_STATUS_MASK));
3331
3332 switch (ccb->ccb_h.status & CAM_STATUS_MASK)
3333 {
3334 case CAM_BUSY:
3335 case CAM_SEL_TIMEOUT:
3336 case CAM_SCSI_BUSY:
3337 status = SANE_STATUS_DEVICE_BUSY;
3338 break;
3339 default:
3340 status = SANE_STATUS_IO_ERROR;
3341 }
3342
3343 handler = fd_info[fd].sense_handler;
3344 if (handler && (ccb->ccb_h.status & CAM_AUTOSNS_VALID))
3345 {
3346 SANE_Status st = (*handler)
3347 (fd, ((u_char *) (&ccb->csio.sense_data)),
3348 fd_info[fd].sense_handler_arg);
3349 cam_freeccb (ccb);
3350 return st;
3351 }
3352 else
3353 {
3354 cam_freeccb (ccb);
3355 return status;
3356 }
3357 }
3358 cam_freeccb (ccb);
3359 return SANE_STATUS_GOOD;
3360 }
3361
3362 #define WE_HAVE_FIND_DEVICES
3363
3364 int
cam_compare_inquiry(int fd,path_id_t path_id,target_id_t target_id,lun_id_t target_lun,const char * vendor,const char * product,const char * type)3365 cam_compare_inquiry (int fd, path_id_t path_id,
3366 target_id_t target_id, lun_id_t target_lun,
3367 const char *vendor, const char *product,
3368 const char *type)
3369 {
3370 struct ccb_dev_match cdm;
3371 struct device_match_pattern *pattern;
3372 struct scsi_inquiry_data *inq;
3373 int retval = 0;
3374
3375 /* build ccb for device match */
3376 memset (&cdm, 0, sizeof (cdm));
3377 cdm.ccb_h.func_code = XPT_DEV_MATCH;
3378
3379 /* result buffer */
3380 cdm.match_buf_len = sizeof (struct dev_match_result);
3381 cdm.matches = (struct dev_match_result *) malloc (cdm.match_buf_len);
3382 cdm.num_matches = 0;
3383
3384 /* pattern buffer */
3385 cdm.num_patterns = 1;
3386 cdm.pattern_buf_len = sizeof (struct dev_match_pattern);
3387 cdm.patterns = (struct dev_match_pattern *) malloc (cdm.pattern_buf_len);
3388
3389 /* assemble conditions */
3390 cdm.patterns[0].type = DEV_MATCH_DEVICE;
3391 pattern = &cdm.patterns[0].pattern.device_pattern;
3392 pattern->flags = DEV_MATCH_PATH | DEV_MATCH_TARGET | DEV_MATCH_LUN;
3393 pattern->path_id = path_id;
3394 pattern->target_id = target_id;
3395 pattern->target_lun = target_lun;
3396
3397 if (ioctl (fd, CAMIOCOMMAND, &cdm) == -1)
3398 {
3399 DBG (1, "error sending CAMIOCOMMAND ioctl");
3400 retval = -1;
3401 goto ret;
3402 }
3403
3404 if ((cdm.ccb_h.status != CAM_REQ_CMP)
3405 || ((cdm.status != CAM_DEV_MATCH_LAST)
3406 && (cdm.status != CAM_DEV_MATCH_MORE)))
3407 {
3408 DBG (1, "got CAM error %#x, CDM error %d\n",
3409 cdm.ccb_h.status, cdm.status);
3410 retval = -1;
3411 goto ret;
3412 }
3413
3414 if (cdm.num_matches == 0)
3415 {
3416 DBG (1, "not found\n");
3417 retval = -1;
3418 goto ret;
3419 }
3420
3421 if (cdm.matches[0].type != DEV_MATCH_DEVICE)
3422 {
3423 DBG (1, "no device match\n");
3424 retval = -1;
3425 goto ret;
3426 }
3427
3428 inq = &cdm.matches[0].result.device_result.inq_data;
3429 if ((vendor && cam_strmatch (inq->vendor, vendor, SID_VENDOR_SIZE)) ||
3430 (product && cam_strmatch (inq->product, product, SID_PRODUCT_SIZE)))
3431 retval = 1;
3432
3433 ret:
3434 free (cdm.patterns);
3435 free (cdm.matches);
3436 return (retval);
3437 }
3438
3439 void
sanei_scsi_find_devices(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))3440 sanei_scsi_find_devices (const char *findvendor, const char *findmodel,
3441 const char *findtype,
3442 int findbus, int findchannel, int findid,
3443 int findlun,
3444 SANE_Status (*attach) (const char *dev))
3445 {
3446 int fd;
3447 struct ccb_dev_match cdm;
3448 struct periph_match_pattern *pattern;
3449 struct periph_match_result *result;
3450 int i;
3451 char devname[16];
3452
3453 DBG_INIT ();
3454
3455 if ((fd = open (XPT_DEVICE, O_RDWR)) == -1)
3456 {
3457 DBG (1, "could not open %s\n", XPT_DEVICE);
3458 return;
3459 }
3460
3461 /* build ccb for device match */
3462 memset (&cdm, 0, sizeof (cdm));
3463 cdm.ccb_h.func_code = XPT_DEV_MATCH;
3464
3465 /* result buffer */
3466 cdm.match_buf_len = sizeof (struct dev_match_result) * 100;
3467 cdm.matches = (struct dev_match_result *) malloc (cdm.match_buf_len);
3468 cdm.num_matches = 0;
3469
3470 /* pattern buffer */
3471 cdm.num_patterns = 1;
3472 cdm.pattern_buf_len = sizeof (struct dev_match_pattern);
3473 cdm.patterns = (struct dev_match_pattern *) malloc (cdm.pattern_buf_len);
3474
3475 /* assemble conditions ... findchannel is ignored */
3476 cdm.patterns[0].type = DEV_MATCH_PERIPH;
3477 pattern = &cdm.patterns[0].pattern.periph_pattern;
3478 pattern->flags = PERIPH_MATCH_NAME;
3479 strcpy (pattern->periph_name, "pass");
3480 if (findbus != -1)
3481 {
3482 pattern->path_id = findbus;
3483 pattern->flags |= PERIPH_MATCH_PATH;
3484 }
3485 if (findid != -1)
3486 {
3487 pattern->target_id = findid;
3488 pattern->flags |= PERIPH_MATCH_TARGET;
3489 }
3490 if (findlun != -1)
3491 {
3492 pattern->target_lun = findlun;
3493 pattern->flags |= PERIPH_MATCH_LUN;
3494 }
3495
3496 /* result loop */
3497 do
3498 {
3499 if (ioctl (fd, CAMIOCOMMAND, &cdm) == -1)
3500 {
3501 DBG (1, "error sending CAMIOCOMMAND ioctl");
3502 break;
3503 }
3504
3505 if ((cdm.ccb_h.status != CAM_REQ_CMP)
3506 || ((cdm.status != CAM_DEV_MATCH_LAST)
3507 && (cdm.status != CAM_DEV_MATCH_MORE)))
3508 {
3509 DBG (1, "got CAM error %#x, CDM error %d\n",
3510 cdm.ccb_h.status, cdm.status);
3511 break;
3512 }
3513
3514 for (i = 0; i < cdm.num_matches; i++)
3515 {
3516 if (cdm.matches[i].type != DEV_MATCH_PERIPH)
3517 continue;
3518 result = &cdm.matches[i].result.periph_result;
3519 DBG (4, "%s%d on scbus%d %d:%d\n",
3520 result->periph_name, result->unit_number,
3521 result->path_id, result->target_id, result->target_lun);
3522 if (cam_compare_inquiry (fd, result->path_id,
3523 result->target_id, result->target_lun,
3524 findvendor, findmodel, findtype) == 0)
3525 {
3526 sprintf (devname, "/dev/%s%d", result->periph_name,
3527 result->unit_number);
3528 (*attach) (devname);
3529 }
3530 }
3531 }
3532 while ((cdm.ccb_h.status == CAM_REQ_CMP)
3533 && (cdm.status == CAM_DEV_MATCH_MORE));
3534
3535 free (cdm.patterns);
3536 free (cdm.matches);
3537 close (fd);
3538 return;
3539 }
3540
3541 #endif
3542
3543
3544
3545 #if USE == HPUX_INTERFACE
3546 /* XXX untested code! */
3547 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)3548 sanei_scsi_cmd2 (int fd,
3549 const void *cmd, size_t cmd_size,
3550 const void *src, size_t src_size,
3551 void *dst, size_t * dst_size)
3552 {
3553 struct sctl_io hdr;
3554 /* xxx obsolete size_t cdb_size;
3555
3556 cdb_size = CDB_SIZE (*(u_char *) src);
3557 */
3558
3559 memset (&hdr, 0, sizeof (hdr));
3560 memcpy (hdr.cdb, cmd, cmd_size);
3561 if (dst_size && *dst_size)
3562 {
3563 /* xxx obsolete assert (cdb_size == src_size);
3564 */
3565 hdr.flags = SCTL_READ;
3566 hdr.data = dst;
3567 hdr.data_length = *dst_size;
3568 }
3569 else
3570 {
3571 /* xxx obsolete assert (cdb_size <= src_size);
3572 */
3573 hdr.data = (char *) src;
3574 hdr.data_length = src_size;
3575 }
3576 hdr.cdb_length = cmd_size;
3577 hdr.max_msecs = sane_scsicmd_timeout * 1000;
3578 if (ioctl (fd, SIOC_IO, &hdr) < 0)
3579 {
3580 DBG (1, "sanei_scsi_cmd: ioctl(SIOC_IO) failed: %s\n",
3581 strerror (errno));
3582 return SANE_STATUS_IO_ERROR;
3583 }
3584 if (hdr.cdb_status)
3585 DBG (1, "sanei_scsi_cmd: SCSI completed with cdb_status=%d\n",
3586 hdr.cdb_status);
3587 if (dst_size)
3588 *dst_size = hdr.data_xfer;
3589
3590 if (hdr.sense_xfer > 0 && (hdr.sense[0] & 0x80)
3591 && fd_info[fd].sense_handler)
3592 return (*fd_info[fd].sense_handler) (fd, hdr.sense,
3593 fd_info[fd].sense_handler_arg);
3594 return SANE_STATUS_GOOD;
3595 }
3596 #endif /* USE == HPUX_INTERFACE */
3597
3598
3599 #if USE == OPENSTEP_INTERFACE
3600 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)3601 sanei_scsi_cmd2 (int fd,
3602 const void *cmd, size_t cmd_size,
3603 const void *src, size_t src_size,
3604 void *dst, size_t * dst_size)
3605 {
3606 struct scsi_req hdr;
3607 /* xxx obsolete size_t cdb_size;
3608
3609 cdb_size = CDB_SIZE (*(u_char *) src);
3610 */
3611
3612 memset (&hdr, 0, sizeof (hdr));
3613 memcpy (&hdr.sr_cdb, cmd, cmd_size);
3614 hdr.sr_cdb_length = cmd_size;
3615
3616 if (dst_size && *dst_size)
3617 {
3618 /* xxx obsolete assert (cdb_size == src_size);
3619 */
3620 hdr.sr_dma_dir = SR_DMA_RD;
3621 hdr.sr_addr = dst;
3622 hdr.sr_dma_max = *dst_size;
3623 }
3624 else
3625 {
3626 /* xxx obsolete assert (cdb_size <= src_size);
3627 */
3628 hdr.sr_dma_dir = SR_DMA_WR;
3629 hdr.sr_addr = (char *) src;
3630 hdr.sr_dma_max = src_size;
3631 }
3632 hdr.sr_ioto = sane_scsicmd_timeout;
3633
3634 if (ioctl (fd, SGIOCREQ, &hdr) == -1)
3635 {
3636 DBG (1, "sanei_scsi_cmd: ioctl(SGIOCREQ) failed: %s\n",
3637 strerror (errno));
3638 return SANE_STATUS_IO_ERROR;
3639 }
3640 if (hdr.sr_io_status != 1)
3641 DBG (1, "sanei_scsi_cmd: SGIOCREQ completed with sr_io_status=%d\n",
3642 hdr.sr_io_status);
3643
3644 if (hdr.sr_io_status == SR_IOST_CHKSNV)
3645 {
3646 struct scsi_req sr;
3647 struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
3648 struct esense_reply sense_reply;
3649 int i;
3650 char *p;
3651
3652 /* clear struct */
3653 p = (char *) cdbp;
3654 for (i = 0; i < sizeof (union cdb); i++)
3655 *p++ = 0;
3656 memset (&sr, 0, sizeof (struct scsi_req));
3657
3658 cdbp->c6_opcode = C6OP_REQSENSE;
3659 cdbp->c6_lun = 0; /* where do I get the lun from? */
3660 cdbp->c6_len = 0x20;
3661 cdbp->c6_ctrl = 0;
3662
3663 sr.sr_dma_dir = SR_DMA_RD;
3664 sr.sr_addr = (char *) &sense_reply;
3665 sr.sr_dma_max = sizeof (struct esense_reply);
3666 sr.sr_ioto = sane_scsicmd_timeout;
3667 sr.sr_cdb_length = 6;
3668
3669 ioctl (fd, SGIOCREQ, &sr);
3670 if (sense_reply.er_ibvalid)
3671 {
3672 sr.sr_esense = sense_reply;
3673 if (fd_info[fd].sense_handler)
3674 return (*fd_info[fd].sense_handler)
3675 (fd, (u_char *) & sr.sr_esense,
3676 fd_info[fd].sense_handler_arg);
3677 }
3678
3679 /* sense reply is invalid */
3680 return SANE_STATUS_INVAL;
3681 }
3682
3683 if (hdr.sr_scsi_status == SR_IOST_CHKSV && fd_info[fd].sense_handler)
3684 return (*fd_info[fd].sense_handler) (fd, (u_char *) & hdr.sr_esense,
3685 fd_info[fd].sense_handler_arg);
3686 if (dst_size)
3687 *dst_size = hdr.sr_dma_xfr;
3688 return SANE_STATUS_GOOD;
3689 }
3690 #endif /* USE == OPENSTEP_INTERFACE */
3691
3692
3693 #if USE == DECUNIX_INTERFACE
3694 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)3695 sanei_scsi_cmd2 (int fd,
3696 const void *cmd, size_t cmd_size,
3697 const void *src, size_t src_size,
3698 void *dst, size_t * dst_size)
3699 {
3700 u_char sense[64];
3701 UAGT_CAM_CCB hdr;
3702 CCB_SCSIIO ccb;
3703 /* xxx obsolete size_t cdb_size;
3704
3705 cdb_size = CDB_SIZE (*(u_char *) src);
3706 */
3707
3708 memset (&ccb, 0, sizeof (ccb));
3709 ccb.cam_ch.my_addr = (CCB_HEADER *) & ccb;
3710 ccb.cam_ch.cam_ccb_len = sizeof (ccb);
3711 ccb.cam_ch.cam_func_code = XPT_SCSI_IO;
3712 ccb.cam_ch.cam_path_id = fd_info[fd].bus;
3713 ccb.cam_ch.cam_target_id = fd_info[fd].target;
3714 ccb.cam_ch.cam_target_lun = fd_info[fd].lun;
3715 ccb.cam_ch.cam_flags = 0;
3716
3717 if (dst_size && *dst_size)
3718 {
3719 /* xxx obsolete assert (cdb_size == src_size);
3720 */
3721 ccb.cam_ch.cam_flags |= CAM_DIR_IN;
3722 ccb.cam_data_ptr = (u_char *) dst;
3723 ccb.cam_dxfer_len = *dst_size;
3724 }
3725 else
3726 {
3727 /* xxx obsolete assert (cdb_size <= src_size);
3728 */
3729 if (0 == src_size)
3730 ccb.cam_ch.cam_flags |= CAM_DIR_NONE;
3731 else
3732 ccb.cam_ch.cam_flags |= CAM_DIR_OUT;
3733 ccb.cam_data_ptr = (u_char *) src;
3734 ccb.cam_dxfer_len = src_size;
3735 }
3736 ccb.cam_timeout = sane_scsicmd_timeout;
3737 ccb.cam_cdb_len = cmd_size;
3738 memcpy (&ccb.cam_cdb_io.cam_cdb_bytes[0], cmd, cmd_size);
3739
3740 memset (&hdr, 0, sizeof (hdr));
3741 hdr.uagt_ccb = (CCB_HEADER *) & ccb;
3742 hdr.uagt_ccblen = sizeof (ccb);
3743 hdr.uagt_buffer = ccb.cam_data_ptr;
3744 hdr.uagt_buflen = ccb.cam_dxfer_len;
3745 hdr.uagt_snsbuf = sense;
3746 hdr.uagt_snslen = sizeof (sense);
3747 hdr.uagt_cdb = 0; /* indicate that CDB is in CCB */
3748 hdr.uagt_cdblen = 0;
3749
3750 if (ioctl (cam_fd, UAGT_CAM_IO, &hdr) < 0)
3751 {
3752 DBG (1, "sanei_scsi_cmd: ioctl(UAGT_CAM_IO) failed: %s\n",
3753 strerror (errno));
3754 return SANE_STATUS_IO_ERROR;
3755 }
3756 if (ccb.cam_ch.cam_status != CAM_REQ_CMP)
3757 {
3758 DBG (1, "sanei_scsi_cmd: UAGT_CAM_IO completed with cam_status=%d\n",
3759 ccb.cam_ch.cam_status);
3760
3761 if (ccb.cam_ch.cam_status == CAM_AUTOSNS_VALID
3762 && fd_info[fd].sense_handler)
3763 return (*fd_info[fd].sense_handler) (fd, sense,
3764 fd_info[fd].sense_handler_arg);
3765 else
3766 return SANE_STATUS_INVAL;
3767 }
3768 if (dst_size)
3769 *dst_size = ccb.cam_dxfer_len;
3770 return SANE_STATUS_GOOD;
3771 }
3772 #endif /* USE == DECUNIX_INTERFACE */
3773
3774
3775 #if USE == SCO_OS5_INTERFACE
3776 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)3777 sanei_scsi_cmd2 (int fd,
3778 const void *cmd, size_t cmd_size,
3779 const void *src, size_t src_size,
3780 void *dst, size_t * dst_size)
3781 {
3782 static u_char sense_buffer[256];
3783 struct scsicmd2 sc2;
3784 struct scsicmd *sc;
3785 /* xxx obsolete int cdb_size;
3786 */
3787 int opcode;
3788 int i;
3789
3790 if (fd < 0)
3791 return SANE_STATUS_IO_ERROR;
3792
3793 memset (&sc2, 0, sizeof (sc2));
3794 sc = &sc2.cmd;
3795 sc2.sense_len = sizeof (sense_buffer);
3796 sc2.sense_ptr = sense_buffer;
3797
3798 /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src);
3799 */
3800 if (dst_size && *dst_size)
3801 {
3802 sc->is_write = 0;
3803 sc->data_ptr = dst;
3804 sc->data_len = *dst_size;
3805 }
3806 else
3807 {
3808 sc->data_len = src_size;
3809 sc->data_ptr = (char *) src;
3810 sc->is_write = 1;
3811 }
3812 memcpy (sc->cdb, cmd, cmd_size);
3813 sc->cdb_len = cmd_size;
3814
3815 /* Send the command down via the "pass-through" interface */
3816 if (ioctl (fd, SCSIUSERCMD2, &sc2) < 0)
3817 {
3818 DBG (1, "sanei_scsi_cmd: ioctl(SCSIUSERCMD2) failed: %s\n",
3819 strerror (errno));
3820 return SANE_STATUS_IO_ERROR;
3821 }
3822 if (sc->host_sts || sc->target_sts)
3823 {
3824 DBG (1, "sanei_scsi_cmd: SCSIUSERCMD2 completed with "
3825 "host_sts=%x, target_sts=%x\n", sc->host_sts, sc->target_sts);
3826 if (fd_info[fd].sense_handler)
3827 return (*fd_info[fd].sense_handler) (fd, sense_buffer,
3828 fd_info[fd].sense_handler_arg);
3829 return SANE_STATUS_IO_ERROR;
3830 }
3831 return SANE_STATUS_GOOD;
3832 }
3833 #endif /* USE == SCO_OS5_INTERFACE */
3834 #if USE == SYSVR4_INTERFACE
3835
3836 /*
3837 * UNIXWARE 2.x interface
3838 * (c) R=I+S Rapp Informatik System Germany
3839 * Email: wolfgang@rapp-informatik.de
3840 *
3841 * The driver version should run with other scsi components like disk
3842 * attached to the same controller at the same time.
3843 *
3844 * Attention : This port needs a sane kernel driver for Unixware 2.x
3845 * The driver is available in binary pkgadd format
3846 * Please mail me.
3847 *
3848 */
3849 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)3850 sanei_scsi_cmd2 (int fd,
3851 const void *cmd, size_t cmd_size,
3852 const void *src, size_t src_size,
3853 void *dst, size_t * dst_size)
3854 {
3855 struct sb sb, *sb_ptr; /* Command block and pointer */
3856 struct scs *scs; /* group 6 command pointer */
3857 struct scm *scm; /* group 10 command pointer */
3858 struct scv *scv; /* group 12 command pointer */
3859 char sense[32]; /* for call of sens req */
3860 char cmd[16]; /* global for right alignment */
3861 char *cp;
3862
3863 /* xxx obsolete size_t cdb_size;
3864
3865 cdb_size = CDB_SIZE (*(u_char *) src);
3866 */
3867 memset (&cmd, 0, 16);
3868 sb_ptr = &sb;
3869 sb_ptr->sb_type = ISCB_TYPE;
3870 cp = (char *) cmd;
3871 DBG (1,
3872 "cdb_size = %d src = {0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x ...}\n",
3873 cmd_size, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7],
3874 cp[8], cp[9]);
3875 switch (cmd_size)
3876 {
3877 default:
3878 return SANE_STATUS_IO_ERROR;
3879 case 6:
3880 scs = (struct scs *) cmd;
3881 memcpy (SCS_AD (scs), cmd, SCS_SZ);
3882 scs->ss_lun = 0;
3883 sb_ptr->SCB.sc_cmdpt = SCS_AD (scs);
3884 sb_ptr->SCB.sc_cmdsz = SCS_SZ;
3885 break;
3886 case 10:
3887 scm = (struct scm *) cmd;
3888 memcpy (SCM_AD (scm), cmd, SCM_SZ);
3889 scm->sm_lun = 0;
3890 sb_ptr->SCB.sc_cmdpt = SCM_AD (scm);
3891 sb_ptr->SCB.sc_cmdsz = SCM_SZ;
3892 break;
3893 case 12:
3894 scv = (struct scv *) cmd;
3895 memcpy (SCV_AD (scv), cmd, SCV_SZ);
3896 scv->sv_lun = 0;
3897 sb_ptr->SCB.sc_cmdpt = SCV_AD (scv);
3898 sb_ptr->SCB.sc_cmdsz = SCV_SZ;
3899 break;
3900 }
3901 if (dst_size && *dst_size)
3902 {
3903 assert (0 == src_size);
3904 sb_ptr->SCB.sc_mode = SCB_READ;
3905 sb_ptr->SCB.sc_datapt = dst;
3906 sb_ptr->SCB.sc_datasz = *dst_size;
3907 }
3908 else
3909 {
3910 assert (0 <= src_size);
3911 sb_ptr->SCB.sc_mode = SCB_WRITE;
3912 sb_ptr->SCB.sc_datapt = (char *) src;
3913 if ((sb_ptr->SCB.sc_datasz = src_size) > 0)
3914 {
3915 sb_ptr->SCB.sc_mode = SCB_WRITE;
3916 }
3917 else
3918 {
3919 /* also use READ mode if the backends have write with length 0 */
3920 sb_ptr->SCB.sc_mode = SCB_READ;
3921 }
3922 }
3923 sb_ptr->SCB.sc_time = sane_scsicmd_timeout * 1000;
3924 DBG (1, "sanei_scsi_cmd: sc_mode = %d, sc_cmdsz = %d, sc_datasz = %d\n",
3925 sb_ptr->SCB.sc_mode, sb_ptr->SCB.sc_cmdsz, sb_ptr->SCB.sc_datasz);
3926 {
3927 /* do read write by normal read or write system calls */
3928 /* the driver will lock process in momory and do optimized transfer */
3929 cp = (char *) cmd;
3930 switch (*cp)
3931 {
3932 case 0x0: /* test unit ready */
3933 if (ioctl (fd, SS_TEST, NULL) < 0)
3934 {
3935 return SANE_STATUS_DEVICE_BUSY;
3936 }
3937 break;
3938 case SS_READ:
3939 case SM_READ:
3940 if (*dst_size > 0x2048)
3941 {
3942 sb_ptr->SCB.sc_datapt = NULL;
3943 sb_ptr->SCB.sc_datasz = 0;
3944 if (memcmp
3945 (sb_ptr->SCB.sc_cmdpt, lastrcmd, sb_ptr->SCB.sc_cmdsz))
3946 {
3947 /* set the command block for the next read or write */
3948 memcpy (lastrcmd, sb_ptr->SCB.sc_cmdpt,
3949 sb_ptr->SCB.sc_cmdsz);
3950 if (!ioctl (fd, SDI_SEND, sb_ptr))
3951 {
3952 *dst_size = read (fd, dst, *dst_size);
3953 if (*dst_size == -1)
3954 {
3955 perror ("sanei-scsi:UW-driver read ");
3956 return SANE_STATUS_IO_ERROR;
3957 }
3958 break;
3959 }
3960 }
3961 else
3962 {
3963 *dst_size = read (fd, dst, *dst_size);
3964 if (*dst_size == -1)
3965 {
3966 perror ("sanei-scsi:UW-driver read ");
3967 return SANE_STATUS_IO_ERROR;
3968 }
3969 break;
3970 }
3971 return SANE_STATUS_IO_ERROR;
3972 }
3973 /* fall through for small read */
3974 default:
3975 if (ioctl (fd, SDI_SEND, sb_ptr) < 0)
3976 {
3977 DBG (1, "sanei_scsi_cmd: ioctl(SDI_SEND) FAILED: %s\n",
3978 strerror (errno));
3979 return SANE_STATUS_IO_ERROR;
3980 }
3981 if (dst_size)
3982 *dst_size = sb_ptr->SCB.sc_datasz;
3983 #ifdef UWSUPPORTED /* at this time not supported by driver */
3984 if (sb_ptr->SCB.sc_comp_code != SDI_ASW)
3985 {
3986 DBG (1, "sanei_scsi_cmd: scsi_cmd failure %x\n",
3987 sb_ptr->SCB.sc_comp_code);
3988 if (sb_ptr->SCB.sc_comp_code == SDI_CKSTAT
3989 && sb_ptr->SCB.sc_status == S_CKCON)
3990 if (fd_info[fd].sense_handler)
3991 {
3992 void *arg = fd_info[fd].sense_handler_arg;
3993 return (*fd_info[fd].sense_handler) (fd,
3994 (u_char *) & sb_ptr->
3995 SCB.sc_link, arg);
3996 }
3997 return SANE_STATUS_IO_ERROR;
3998 }
3999 #endif
4000 break;
4001 }
4002 return SANE_STATUS_GOOD;
4003 }
4004 }
4005 #endif /* USE == SYSVR4_INTERFACE */
4006 #if USE == SCO_UW71_INTERFACE
4007 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)4008 sanei_scsi_cmd2 (int fd,
4009 const void *cmd, size_t cmd_size,
4010 const void *src, size_t src_size,
4011 void *dst, size_t * dst_size)
4012 {
4013 static u_char sense_buffer[24];
4014 struct scb cmdblk;
4015 time_t elapsed;
4016 uint_t compcode, status;
4017 /* xxx obsolete int cdb_size, mode;
4018 */
4019 int mode;
4020 int i;
4021
4022 if (fd < 0)
4023 return SANE_STATUS_IO_ERROR;
4024
4025 cmdblk.sc_cmdpt = (caddr_t) cmd;
4026 /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src);
4027 */
4028 cmdblk.sc_cmdsz = cmd_size;
4029 cmdblk.sc_time = 60000; /* 60 secs */
4030
4031 if (dst_size && *dst_size)
4032 {
4033 /* xxx obsolete assert (cdb_size == src_size);
4034 */
4035 cmdblk.sc_datapt = (caddr_t) dst;
4036 cmdblk.sc_datasz = *dst_size;
4037 mode = SCB_READ;
4038 }
4039 else
4040 {
4041 /* xxx obsolete assert (cdb_size <= src_size);
4042 */
4043 cmdblk.sc_datapt = (char *) src;
4044 cmdblk.sc_datasz = src_size;
4045 mode = SCB_WRITE;
4046 }
4047
4048 if (pt_send (fd, cmdblk.sc_cmdpt, cmdblk.sc_cmdsz, cmdblk.sc_datapt,
4049 cmdblk.sc_datasz, mode, cmdblk.sc_time, &elapsed, &compcode,
4050 &status, sense_buffer, sizeof (sense_buffer)) != 0)
4051 {
4052 DBG (1, "sanei_scsi_cmd: pt_send failed: %s!\n", strerror (errno));
4053 }
4054 else
4055 {
4056 DBG (2, "sanei_scsi_cmd completed with: compcode = %x, status = %x\n",
4057 compcode, status);
4058
4059 switch (compcode)
4060 {
4061 case SDI_ASW: /* All seems well */
4062 return SANE_STATUS_GOOD;
4063 case SDI_CKSTAT:
4064 DBG (2, "Sense Data:\n");
4065 for (i = 0; i < sizeof (sense_buffer); i++)
4066 DBG (2, "%.2X ", sense_buffer[i]);
4067 DBG (2, "\n");
4068 if (fd_info[fd].sense_handler)
4069 return (*fd_info[fd].sense_handler) (fd, sense_buffer,
4070 fd_info[fd].
4071 sense_handler_arg);
4072 /* fall through */
4073 default:
4074 return SANE_STATUS_IO_ERROR;
4075 }
4076 }
4077 }
4078 #endif /* USE == SCO_UW71_INTERFACE */
4079
4080 #if USE == OS2_INTERFACE
4081
4082 #define WE_HAVE_FIND_DEVICES
4083
4084 static int
get_devicename(int bus,int target,int lun,char * name,size_t name_len)4085 get_devicename (int bus, int target, int lun, char *name, size_t name_len)
4086 {
4087 snprintf (name, name_len, "b%dt%dl%d", bus, target, lun);
4088 DBG (1, "OS/2 searched device is %s\n", name);
4089 return 0;
4090 }
4091
4092 void
sanei_scsi_find_devices(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))4093 sanei_scsi_find_devices (const char *findvendor, const char *findmodel,
4094 const char *findtype,
4095 int findbus, int findchannel, int findid,
4096 int findlun,
4097 SANE_Status (*attach) (const char *dev))
4098 {
4099 size_t findvendor_len = 0, findmodel_len = 0, findtype_len = 0;
4100 char vendor[32], model[32], type[32], revision[32];
4101 int bus, channel, id, lun, number, i;
4102 char line[256], dev_name[128];
4103 const char *string;
4104 FILE *proc_fp;
4105 char *end;
4106 struct
4107 {
4108 const char *name;
4109 size_t name_len;
4110 int is_int; /* integer valued? (not a string) */
4111 union
4112 {
4113 void *v; /* avoids compiler warnings... */
4114 char *str;
4115 int *i;
4116 }
4117 u;
4118 }
4119 param[] =
4120 {
4121 {
4122 "Vendor:", 7, 0,
4123 {
4124 0}
4125 }
4126 ,
4127 {
4128 "Model:", 6, 0,
4129 {
4130 0}
4131 }
4132 ,
4133 {
4134 "Type:", 5, 0,
4135 {
4136 0}
4137 }
4138 ,
4139 {
4140 "Rev:", 4, 0,
4141 {
4142 0}
4143 }
4144 ,
4145 {
4146 "scsi", 4, 1,
4147 {
4148 0}
4149 }
4150 ,
4151 {
4152 "Channel:", 8, 1,
4153 {
4154 0}
4155 }
4156 ,
4157 {
4158 "Id:", 3, 1,
4159 {
4160 0}
4161 }
4162 ,
4163 {
4164 "Lun:", 4, 1,
4165 {
4166 0}
4167 }
4168 };
4169
4170 param[0].u.str = vendor;
4171 param[1].u.str = model;
4172 param[2].u.str = type;
4173 param[3].u.str = revision;
4174 param[4].u.i = &bus;
4175 param[5].u.i = &channel;
4176 param[6].u.i = &id;
4177 param[7].u.i = &lun;
4178
4179 DBG_INIT ();
4180
4181 open_aspi (); /* open aspi manager if not already done */
4182
4183 DBG (2, "find_devices: open temporary file '%s'\n", tmpAspi);
4184 proc_fp = fopen (tmpAspi, "r");
4185 if (!proc_fp)
4186 {
4187 DBG (1, "could not open %s for reading\n", tmpAspi);
4188 return;
4189 }
4190
4191 number = bus = channel = id = lun = -1;
4192
4193 vendor[0] = model[0] = type[0] = '\0';
4194 if (findvendor)
4195 findvendor_len = strlen (findvendor);
4196 if (findmodel)
4197 findmodel_len = strlen (findmodel);
4198 if (findtype)
4199 findtype_len = strlen (findtype);
4200
4201 while (!feof (proc_fp))
4202 {
4203 if (!fgets (line, sizeof (line), proc_fp))
4204 break; /* at eof exit */
4205
4206 string = sanei_config_skip_whitespace (line);
4207
4208 while (*string)
4209 {
4210 for (i = 0; i < NELEMS (param); ++i)
4211 {
4212 if (strncmp (string, param[i].name, param[i].name_len) == 0)
4213 {
4214 string += param[i].name_len;
4215 string = sanei_config_skip_whitespace (string);
4216 if (param[i].is_int)
4217 {
4218 *param[i].u.i = strtol (string, &end, 10);
4219 string = (char *) end;
4220 }
4221 else
4222 {
4223 strncpy (param[i].u.str, string, 32);
4224 param[i].u.str[31] = '\0';
4225 while (*string && !isspace ((int) *string))
4226 ++string;
4227 }
4228 string = sanei_config_skip_whitespace (string);
4229
4230 if (param[i].u.v == &bus)
4231 ++number;
4232 break;
4233 }
4234 }
4235 if (i >= NELEMS (param))
4236 ++string; /* no match */
4237 }
4238
4239 if ((findvendor && !vendor[0]) || (findmodel && !model[0])
4240 || (findtype && !type[0])
4241 || (findbus >= 0 && bus == -1) || (findchannel >= 0
4242 && channel == -1)
4243 || (findlun >= 0 && lun == -1))
4244 /* some info is still missing */
4245 continue;
4246
4247 if ((!findvendor || strncmp (vendor, findvendor, findvendor_len) == 0)
4248 && (!findmodel || strncmp (model, findmodel, findmodel_len) == 0)
4249 && (!findtype || strncmp (type, findtype, findtype_len) == 0)
4250 && (findbus == -1 || bus == findbus)
4251 && (findchannel == -1 || channel == findchannel)
4252 && (findid == -1 || id == findid)
4253 && (findlun == -1 || lun == findlun)
4254 && get_devicename (bus, id, lun, dev_name, sizeof (dev_name)) >= 0
4255 && (*attach) (dev_name) != SANE_STATUS_GOOD)
4256 return;
4257
4258 vendor[0] = model[0] = type[0] = 0;
4259 bus = channel = id = lun = -1;
4260 }
4261
4262 DBG (2, "find_devices: close temporary file '%s'\n", tmpAspi);
4263 fclose (proc_fp);
4264
4265 close_aspi (); /* close aspi manager */
4266 }
4267
4268 /* XXX untested code! */
4269 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)4270 sanei_scsi_cmd2 (int fd,
4271 const void *cmd, size_t cmd_size,
4272 const void *src, size_t src_size,
4273 void *dst, size_t * dst_size)
4274 {
4275 ULONG rc; /* Returns. */
4276 unsigned long cbreturn;
4277 unsigned long cbParam;
4278 if (aspi_buf == NULL) /* avoid SIGSEGV in memcpy() when calling
4279 sanei_scsi_cmd2() while aspi-driver is closed */
4280 {
4281 DBG (1, "sanei_scsi_cmd: Error no device (aspi_buf == NULL)\n");
4282 return SANE_STATUS_INVAL;
4283 }
4284
4285 if (PSRBlock == NULL) /* avoid SIGSEGV in memcpy() when calling
4286 sanei_scsi_cmd2() while aspi-driver is closed */
4287 {
4288 DBG (1, "sanei_scsi_cmd: Error no device (PSRBlock == NULL)\n");
4289 return SANE_STATUS_INVAL;
4290 }
4291
4292 memset (PSRBlock, 0, sizeof (SRB)); /* Okay, I'm paranoid. */
4293 PSRBlock->cmd = SRB_Command; /* execute SCSI cmd */
4294 PSRBlock->ha_num = fd_info[fd].bus; /* host adapter number */
4295 PSRBlock->u.cmd.target = fd_info[fd].target; /* Target SCSI ID */
4296 PSRBlock->u.cmd.lun = fd_info[fd].lun; /* Target SCSI LUN */
4297 PSRBlock->flags = SRB_Post; /* posting enabled */
4298 if (dst_size && *dst_size)
4299 {
4300 /* Reading. */
4301 assert (*dst_size <= (size_t) sanei_scsi_max_request_size);
4302 PSRBlock->u.cmd.data_len = *dst_size;
4303 DBG (1, "sanei_scsi_cmd: Reading PSRBlock->u.cmd.data_len= %lu\n",
4304 PSRBlock->u.cmd.data_len);
4305 PSRBlock->flags |= SRB_Read;
4306 }
4307 else
4308 {
4309 /* Writing. */
4310 PSRBlock->u.cmd.data_len = src_size;
4311 DBG (1, "sanei_scsi_cmd: Writing PSRBlock->u.cmd.data_len= %lu\n",
4312 PSRBlock->u.cmd.data_len);
4313 assert (PSRBlock->u.cmd.data_len <=
4314 (unsigned long) sanei_scsi_max_request_size);
4315 if (PSRBlock->u.cmd.data_len)
4316 PSRBlock->flags |= SRB_Write;
4317 else
4318 PSRBlock->flags |= SRB_NoTransfer;
4319 memcpy (aspi_buf, src, PSRBlock->u.cmd.data_len);
4320 }
4321 PSRBlock->u.cmd.sense_len = 32; /* length of sense buffer */
4322 PSRBlock->u.cmd.data_ptr = NULL; /* pointer to data buffer already registered */
4323 PSRBlock->u.cmd.link_ptr = NULL; /* pointer to next SRB */
4324 PSRBlock->u.cmd.cdb_len = cmd_size; /* SCSI command length */
4325 memcpy (PSRBlock->u.cmd.cdb_st, cmd, cmd_size);
4326
4327 /* Do the command. */
4328 rc = DosDevIOCtl (driver_handle, 0x92, 0x02,
4329 (void *) PSRBlock, sizeof (SRB), &cbParam,
4330 (void *) PSRBlock, sizeof (SRB), &cbreturn);
4331
4332 if (rc)
4333 {
4334 DBG (1, "sanei_scsi_cmd: DosDevIOCtl failed. rc= %lu \n", rc);
4335 return SANE_STATUS_IO_ERROR;
4336 }
4337
4338 /* Get sense data if available. */
4339 if ((PSRBlock->status == SRB_Aborted || PSRBlock->status == SRB_Error) &&
4340 PSRBlock->u.cmd.target_status == SRB_CheckStatus
4341 && fd_info[fd].sense_handler != 0)
4342 {
4343 SANEI_SCSI_Sense_Handler s_handler = fd_info[fd].sense_handler;
4344 return (*s_handler) (fd, &PSRBlock->u.cmd.cdb_st[cmd_size],
4345 fd_info[fd].sense_handler_arg);
4346 }
4347 if (PSRBlock->status != SRB_Done ||
4348 PSRBlock->u.cmd.ha_status != SRB_NoError ||
4349 PSRBlock->u.cmd.target_status != SRB_NoStatus)
4350 {
4351 DBG (1, "sanei_scsi_cmd: command 0x%02x failed.\n"
4352 "PSRBlock->status= 0x%02x\n"
4353 "PSRBlock->u.chm.ha_status= 0x%02x\n"
4354 "PSRBlock->u.cmd.target_status= 0x%02x\n",
4355 PSRBlock->u.cmd.cdb_st[0],
4356 PSRBlock->status,
4357 PSRBlock->u.cmd.ha_status, PSRBlock->u.cmd.target_status);
4358 return SANE_STATUS_IO_ERROR;
4359 }
4360
4361 if (dst_size && *dst_size) /* Reading? */
4362 memcpy ((char *) dst, aspi_buf, *dst_size);
4363 return SANE_STATUS_GOOD;
4364 }
4365 #endif /* USE == OS2_INTERFACE */
4366
4367 #if USE == STUBBED_INTERFACE
4368 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)4369 sanei_scsi_cmd2 (int fd,
4370 const void *cmd, size_t cmd_size,
4371 const void *src, size_t src_size,
4372 void *dst, size_t * dst_size)
4373 {
4374 return SANE_STATUS_UNSUPPORTED;
4375 }
4376 #endif /* USE == STUBBED_INTERFACE */
4377
4378 #if USE == IRIX_INTERFACE
4379
4380 #define WE_HAVE_FIND_DEVICES
4381
4382 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)4383 sanei_scsi_cmd2 (int fd,
4384 const void *cmd, size_t cmd_size,
4385 const void *src, size_t src_size,
4386 void *dst, size_t * dst_size)
4387 {
4388 dsreq_t scsi_req; /* SCSI request */
4389 /* xxx obsolete size_t cdb_size; *//* Size of SCSI command */
4390 static u_char *cmdbuf = NULL, /* Command buffer */
4391 *sensebuf = NULL, /* Request sense buffer */
4392 *databuf = NULL; /* Data buffer */
4393
4394 /*
4395 * Allocate the sense and command data buffers as necessary; we have
4396 * to do this to avoid buffer alignment problems, since some
4397 * hardware requires these buffers to be 32-bit aligned.
4398 */
4399 if (cmdbuf == NULL)
4400 {
4401 cmdbuf = malloc (64);
4402 sensebuf = malloc (1024); /* may be can reduced to 128 */
4403 databuf = malloc (MAX_DATA);
4404
4405 if (cmdbuf == NULL || sensebuf == NULL || databuf == NULL)
4406 return SANE_STATUS_NO_MEM;
4407 }
4408
4409 /*
4410 * Build the SCSI request...
4411 */
4412 /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src);
4413 */
4414
4415 DBG (1, "sanei_scsi_cmd: cmd_size = %d\n", cmd_size);
4416
4417 if (dst != NULL)
4418 {
4419 /*
4420 * SCSI command returning/reading data...
4421 */
4422 scsi_req.ds_flags = DSRQ_READ | DSRQ_SENSE;
4423 scsi_req.ds_time = 120 * 1000;
4424 scsi_req.ds_cmdbuf = (caddr_t) cmdbuf;
4425 scsi_req.ds_cmdlen = cmd_size;
4426 scsi_req.ds_databuf = (caddr_t) databuf;
4427 scsi_req.ds_datalen = *dst_size;
4428 scsi_req.ds_sensebuf = (caddr_t) sensebuf;
4429 scsi_req.ds_senselen = 128; /* 1024 does not work, 128 is tested (O.Rauch) */
4430
4431 /*
4432 * Copy command to cmdbuf to assure 32-bit alignment.
4433 */
4434 memcpy (cmdbuf, cmd, cmd_size);
4435 }
4436 else
4437 {
4438 /*
4439 * SCSI command sending/writing data...
4440 */
4441 scsi_req.ds_flags = DSRQ_WRITE | DSRQ_SENSE;
4442 scsi_req.ds_time = 120 * 1000;
4443 scsi_req.ds_cmdbuf = (caddr_t) cmdbuf;
4444 scsi_req.ds_cmdlen = cmd_size;
4445 scsi_req.ds_databuf = (caddr_t) databuf;
4446 scsi_req.ds_datalen = src_size;
4447 scsi_req.ds_sensebuf = (caddr_t) sensebuf;
4448 scsi_req.ds_senselen = 128;
4449
4450 /*
4451 * Copy command and data to local buffers to ensure 32-bit alignment...
4452 */
4453 memcpy (cmdbuf, (u_char *) cmd, cmd_size);
4454 memcpy (databuf, (u_char *) src, src_size);
4455 }
4456
4457 memset (sensebuf, 0, 128);
4458
4459 /*
4460 * Do SCSI request...
4461 */
4462 if (ioctl (fd, DS_ENTER, &scsi_req) < 0)
4463 {
4464 DBG (1, "sanei_scsi_cmd: ioctl failed - %s\n", strerror (errno));
4465 return SANE_STATUS_IO_ERROR;
4466 }
4467
4468 DBG (1, "sanei_scsi_cmd: status = %d\n", scsi_req.ds_status);
4469
4470 /*
4471 * Set the incoming data size and copy the destination data as needed...
4472 */
4473 if (dst != NULL)
4474 {
4475 *dst_size = scsi_req.ds_datasent;
4476
4477 DBG (1, "sanei_scsi_cmd: read %d bytes\n", scsi_req.ds_datasent);
4478
4479 if (scsi_req.ds_datasent > 0)
4480 memcpy (dst, databuf, scsi_req.ds_datasent);
4481 }
4482
4483 /*
4484 * Return the appropriate status code...
4485 */
4486 if (scsi_req.ds_status != 0)
4487 {
4488 if (scsi_req.ds_status == STA_BUSY)
4489 return SANE_STATUS_DEVICE_BUSY;
4490 else if (fd_info[fd].sense_handler)
4491 return (*fd_info[fd].sense_handler) (fd, sensebuf,
4492 fd_info[fd].sense_handler_arg);
4493 else
4494 return SANE_STATUS_IO_ERROR;
4495 }
4496 return SANE_STATUS_GOOD;
4497 }
4498
4499 void
sanei_scsi_find_devices(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))4500 sanei_scsi_find_devices (const char *findvendor, const char *findmodel,
4501 const char *findtype,
4502 int findbus, int findchannel, int findid,
4503 int findlun,
4504 SANE_Status (*attach) (const char *dev))
4505 {
4506 size_t findvendor_len = 0, findmodel_len = 0;
4507 /* Lengths of search strings */
4508 inventory_t *inv; /* Current hardware inventory entry */
4509 int bus, id, lun; /* Current Bus, ID, and LUN */
4510 char dev_name[128]; /* SCSI device name */
4511 int fd; /* SCSI file */
4512 size_t inqsize; /* Size of returned inquiry data */
4513 char vendor[9], /* Vendor name */
4514 model[17]; /* Model/product name */
4515 u_char inqdata[128], /* Inquiry data buffer */
4516 inqcommand[6]; /* Inquiry command (0x12) buffer */
4517
4518 DBG_INIT ();
4519
4520 vendor[0] = model[0] = '\0';
4521 if (findvendor)
4522 findvendor_len = strlen (findvendor);
4523 if (findmodel)
4524 findmodel_len = strlen (findmodel);
4525
4526 if (findvendor != NULL)
4527 DBG (1, "sanei_scsi_find_devices: looking for vendors starting "
4528 "with \"%s\".\n", findvendor);
4529
4530 if (findmodel != NULL)
4531 DBG (1, "sanei_scsi_find_devices: looking for models starting "
4532 "with \"%s\".\n", findmodel);
4533
4534 setinvent ();
4535
4536 while ((inv = getinvent ()) != NULL)
4537 {
4538 if (inv->inv_class != INV_SCSI ||
4539 (inv->inv_type != INV_SCANNER && inv->inv_type != INV_CPU))
4540 continue;
4541
4542 bus = inv->inv_controller;
4543 id = inv->inv_unit;
4544 lun = inv->inv_state >> 8;
4545
4546 DBG (1, "sanei_scsi_find_devices: found %s on controller %d, "
4547 "ID %d, LUN %d.\n",
4548 inv->inv_type == INV_SCANNER ? "scanner" : "processor",
4549 bus, id, lun);
4550
4551 if ((findbus >= 0 && bus != findbus) ||
4552 (findid >= 0 && id != findid) || (findlun >= 0 && lun != findlun))
4553 {
4554 DBG (1, "sanei_scsi_find_devices: ignoring this device.\n");
4555 continue;
4556 }
4557
4558 sprintf (dev_name, "/dev/scsi/sc%dd%dl%d", bus, id, lun);
4559 DBG (1, "sanei_scsi_find_devices: device name is \"%s\".\n",
4560 dev_name);
4561
4562 /*
4563 * Open the SCSI device and get the inquiry data...
4564 */
4565
4566 if (sanei_scsi_open (dev_name, &fd, NULL, NULL) != SANE_STATUS_GOOD)
4567 {
4568 DBG (1,
4569 "sanei_scsi_find_devices: unable to open device file - %s.\n",
4570 strerror (errno));
4571 continue;
4572 }
4573
4574 DBG (1, "sanei_scsi_find_devices: device fd = %d.\n", fd);
4575
4576 inqsize = sizeof (inqdata);
4577
4578 inqcommand[0] = 0x12;
4579 inqcommand[1] = 0;
4580 inqcommand[2] = 0;
4581 inqcommand[3] = sizeof (inqdata) >> 8;
4582 inqcommand[4] = sizeof (inqdata);
4583 inqcommand[5] = 0;
4584
4585 if (sanei_scsi_cmd (fd, inqcommand, sizeof (inqcommand), inqdata,
4586 &inqsize) != SANE_STATUS_GOOD)
4587 {
4588 DBG (1,
4589 "sanei_scsi_find_devices: unable to get inquiry data - %s.\n",
4590 strerror (errno));
4591 continue;
4592 }
4593
4594 sanei_scsi_close (fd);
4595
4596 strncpy (vendor, (char *) inqdata + 8, 8);
4597 vendor[8] = '\0';
4598 strncpy (model, (char *) inqdata + 16, 16);
4599 model[16] = '\0';
4600
4601 DBG (1, "sanei_scsi_find_devices: vendor = \'%s\', model = \'%s'.\n",
4602 vendor, model);
4603
4604 /*
4605 * Compare as necessary...
4606 */
4607
4608 if ((findvendor != NULL
4609 && strncmp (findvendor, vendor, findvendor_len))
4610 || (findmodel != NULL
4611 && strncmp (findmodel, model, findmodel_len)))
4612 {
4613 DBG (1, "sanei_scsi_find_devices: ignoring this device.\n");
4614 continue;
4615 }
4616
4617 /*
4618 * OK, this one matches, so use it!
4619 */
4620
4621 DBG (1, "sanei_scsi_find_devices: attaching this device.\n");
4622
4623 (*attach) (dev_name);
4624 }
4625 }
4626 #endif /* USE == IRIX_INTERFACE */
4627
4628 #if USE == AIX_GSC_INTERFACE
4629 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)4630 sanei_scsi_cmd2 (int fd,
4631 const void *cmd, size_t cmd_size,
4632 const void *src, size_t src_size,
4633 void *dst, size_t * dst_size)
4634 {
4635 scmd_t scmd;
4636 /* xxx obsolete size_t cdb_size;
4637 */
4638 char sense_buf[32];
4639 char status;
4640
4641 /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src);
4642 */
4643
4644 memset (&scmd, 0, sizeof (scmd));
4645 if (dst_size && *dst_size)
4646 {
4647 /* xxx obsolete assert (cdb_size == src_size);
4648 */
4649 scmd.rw = 1;
4650 scmd.data_buf = dst;
4651 scmd.datalen = *dst_size;
4652 }
4653 else
4654 {
4655 /* assert (cdb_size <= src_size);
4656 */
4657 scmd.data_buf = (char *) src;
4658 scmd.datalen = src_size;
4659 }
4660 scmd.cdb = (char *) cmd;
4661 scmd.cdblen = cmd_size;
4662 scmd.timeval = sane_scsicmd_timeout;
4663 scmd.sense_buf = sense_buf;
4664 scmd.senselen = sizeof (sense_buf);
4665 scmd.statusp = &status;
4666 DBG (1, "sanei_scsi_cmd: scmd.rw = %d, scmd.cdblen = %d, ",
4667 scmd.rw, scmd.cdblen);
4668 DBG (1, "scmd.cdb = {0x%x,0x%x,0x%x,0x%x,0x%x,0x%x, ...}\n",
4669 scmd.cdb[0], scmd.cdb[1], scmd.cdb[2],
4670 scmd.cdb[3], scmd.cdb[4], scmd.cdb[5]);
4671 if (ioctl (fd, GSC_CMD, &scmd) < 0)
4672 {
4673 DBG (1, "sanei_scsi_cmd: ioctl(SIOC_IO) failed: %s\n",
4674 strerror (errno));
4675 return SANE_STATUS_IO_ERROR;
4676 }
4677 if (*scmd.statusp)
4678 DBG (1, "sanei_scsi_cmd: SCSI completed with status=%d\n",
4679 *scmd.statusp);
4680
4681 DBG (1, "sanei_scsi_cmd: dst = {0x%x,0x%x,0x%x,0x%x,0x%x,0x%x, ...}\n",
4682 *((char *) dst + 0), *((char *) dst + 1), *((char *) dst + 2),
4683 *((char *) dst + 3), *((char *) dst + 4), *((char *) dst + 5));
4684
4685 if (dst_size)
4686 *dst_size = scmd.datalen;
4687
4688 if (scmd.senselen > 0
4689 && (scmd.sense_buf[0] & 0x80) && fd_info[fd].sense_handler)
4690 return (*fd_info[fd].sense_handler) (fd, (u_char *) scmd.sense_buf,
4691 fd_info[fd].sense_handler_arg);
4692 return SANE_STATUS_GOOD;
4693 }
4694 #endif /* USE == AIX_GSC_INTERFACE */
4695
4696 #if USE == SOLARIS_SG_INTERFACE
4697
4698 #ifndef CCS_SENSE_LEN
4699 # define CCS_SENSE_LEN 18
4700 #endif
4701
4702 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)4703 sanei_scsi_cmd2 (int fd,
4704 const void *cmd, size_t cmd_size,
4705 const void *src, size_t src_size,
4706 void *dst, size_t * dst_size)
4707 {
4708 struct user_scsi us;
4709 /* xxx obsolete size_t cdb_size;
4710 */
4711 char sensebf[CCS_SENSE_LEN];
4712
4713 /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src);
4714 */
4715
4716 /* first put the user scsi structure together. */
4717 memset (&us, 0, sizeof (us));
4718 us.us_cdbp = (caddr_t) cmd;
4719 us.us_cdblen = cmd_size;
4720 us.us_sensep = sensebf;
4721 us.us_senselen = CCS_SENSE_LEN;
4722 if (dst && dst_size && *dst_size)
4723 {
4724 us.us_bufp = (caddr_t) dst;
4725 us.us_buflen = *dst_size;
4726 us.us_flags = USER_SCSI_READ;
4727 }
4728 else
4729 {
4730 us.us_bufp = (caddr_t) src;
4731 us.us_buflen = src_size;
4732 us.us_flags = USER_SCSI_WRITE;
4733 }
4734 /* now run it */
4735 if (ioctl (fd, USER_SCSI, &us) < 0)
4736 return SANE_STATUS_IO_ERROR;
4737 if (dst_size)
4738 *dst_size -= us.us_resid;
4739
4740 return SANE_STATUS_GOOD;
4741 }
4742 #endif /* USE == SOLARIS_SG_INTERFACE */
4743
4744 #if USE == SOLARIS_INTERFACE
4745
4746 #ifndef SC_NOT_READ
4747 # define SC_NOT_READY 0x02
4748 #endif
4749
4750 #ifndef SC_BUSY
4751 # define SC_BUSY 0x08
4752 #endif
4753 #define DEF_TIMEOUT sane_scsicmd_timeout;
4754
4755 /* Choosing one of the following DEF_SCG_FLG's SCG_DISRE_ENA allows
4756 the SCSI driver to disconnect/reconnect. SCG_CMD_RETRY allows a
4757 retry if a retryable error occurs.
4758
4759 Disallowing SCG_DISRE_ENA slows down the operation of the SCSI bus
4760 while the scanner is working. If you have severe problems try to
4761 set it to 0.
4762
4763 SCG_CMD_RETRY allows the driver to retry some commands. It should
4764 normally be set. For some kinds of odd problems, it may cause the
4765 machine to hang for some time. */
4766
4767 #define DEF_SCG_FLG SCG_DISRE_ENA
4768 /* #define DEF_SCG_FLG 0 */
4769 /* #define DEF_SCG_FLG SCG_DISRE_ENA | SCG_CMD_RETRY */
4770 /* #define DEF_SCG_FLG SCG_CMD_RETRY */
4771
4772 static int d_errs = 100;
4773
4774 static SANE_Status
scsi_cmd(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size,int probing)4775 scsi_cmd (int fd,
4776 const void *cmd, size_t cmd_size,
4777 const void *src, size_t src_size,
4778 void *dst, size_t * dst_size, int probing)
4779 {
4780 struct scg_cmd scmd;
4781 /* xxx obsolete size_t cdb_size;
4782 */
4783 SANEI_SCSI_Sense_Handler handler;
4784
4785 /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src);
4786 */
4787
4788 memset (&scmd, 0, sizeof (scmd));
4789 scmd.flags = DEF_SCG_FLG | (probing ? SCG_SILENT : 0);
4790 if (dst && dst_size && *dst_size)
4791 {
4792 /* xxx obsolete assert (cdb_size == src_size);
4793 */
4794 scmd.flags |= SCG_RECV_DATA;
4795 scmd.addr = dst;
4796 scmd.size = *dst_size;
4797 }
4798 else
4799 {
4800 /* xxx obsolete assert (cdb_size <= src_size);
4801 */
4802 scmd.addr = (caddr_t) src;
4803 scmd.size = src_size;
4804 }
4805 scmd.cdb_len = cmd_size;
4806 scmd.sense_len = CCS_SENSE_LEN;
4807 scmd.target = fd_info[fd].target;
4808 /* use 2 second timeout when probing, 60 seconds otherwise: */
4809 scmd.timeout = probing ? 2 : DEF_TIMEOUT;
4810 memcpy (&scmd.cdb.g0_cdb.cmd, cmd, cmd_size);
4811 scmd.cdb.cmd_cdb[1] |= fd_info[fd].lun << 5;
4812 if (ioctl (fd, SCGIO_CMD, &scmd) < 0)
4813 return SANE_STATUS_IO_ERROR;
4814 if (dst_size)
4815 *dst_size = scmd.size - scmd.resid;
4816 if (scmd.error == 0 && scmd.errno == 0 && *(u_char *) & scmd.scb == 0)
4817 return SANE_STATUS_GOOD;
4818
4819 if (scmd.error == SCG_TIMEOUT)
4820 DBG (0, "sanei_scsi_cmd %x: timeout\n", scmd.cdb.g0_cdb.cmd);
4821 else if (probing)
4822 {
4823 struct scsi_ext_sense *ext_sense =
4824 (struct scsi_ext_sense *) &scmd.sense;
4825
4826 if (scmd.error < SCG_FATAL
4827 && ((scmd.sense.code < 0x70 && scmd.sense.code != 0x04)
4828 || (scmd.sense.code >= 0x70
4829 && ext_sense->key != SC_NOT_READY)))
4830 return SANE_STATUS_GOOD;
4831 }
4832 else
4833 {
4834 char errbf[128];
4835 int i, rv, lifes;
4836
4837 handler = fd_info[fd].sense_handler;
4838 DBG (3, "cmd=%x, error=%d:%s, bsiz=%d, stat=%x,%x,%x, slen=%d\n",
4839 scmd.cdb.g0_cdb.cmd, scmd.error, strerror (scmd.errno),
4840 ((dst_size != NULL) ? (*dst_size) : 0), scmd.u_scb.cmd_scb[0],
4841 scmd.u_scb.cmd_scb[1], scmd.u_scb.cmd_scb[2], scmd.sense_count);
4842 *errbf = '\0';
4843 for (i = 0; i < scmd.sense_count; i++)
4844 sprintf (errbf + strlen (errbf), "%x,", scmd.u_sense.cmd_sense[i]);
4845 DBG (3, "sense=%s\n", errbf);
4846
4847 /* test_unit_ready on a busy unit returns error = 0 or 2 with
4848 errno=EIO. I've seen 0 on a CDrom without a CD, and 2 on a
4849 scanner just busy.
4850
4851 If (SANE_DEBUG_SANEI_SCSI > 100) lifes =
4852 SANE_DEBUG_SANEI_SCSI - 100 use up one life for every
4853 scmd.error abort and dump core when no lifes left
4854 test_unit_ready commands are not counted. */
4855 if (scmd.error)
4856 {
4857 if (sanei_debug_sanei_scsi > 100 &&
4858 scmd.cdb.g0_cdb.cmd != SC_TEST_UNIT_READY)
4859 {
4860 lifes = sanei_debug_sanei_scsi - ++d_errs;
4861 DBG (1, "sanei_scsi_cmd: %d lifes left\n", lifes);
4862 assert (lifes > 0);
4863 }
4864 return SANE_STATUS_IO_ERROR;
4865 }
4866 if (scmd.u_scb.cmd_scb[0] == SC_BUSY)
4867 return SANE_STATUS_DEVICE_BUSY;
4868 if (*(u_char *) & scmd.sense && handler)
4869 {
4870 rv = (*handler) (fd, scmd.u_sense.cmd_sense,
4871 fd_info[fd].sense_handler_arg);
4872 DBG (2, "sanei_scsi_cmd: sense-handler returns %d\n", rv);
4873 return rv;
4874 }
4875 }
4876 return SANE_STATUS_IO_ERROR;
4877 }
4878
4879 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)4880 sanei_scsi_cmd2 (int fd,
4881 const void *cmd, size_t cmd_size,
4882 const void *src, size_t src_size,
4883 void *dst, size_t * dst_size)
4884 {
4885 return scsi_cmd (fd, cmd, cmd_size, src, src_size, dst, dst_size, 0);
4886 }
4887
unit_ready(int fd)4888 static int unit_ready (int fd)
4889 {
4890 static const u_char test_unit_ready[] = { 0, 0, 0, 0, 0, 0 };
4891 int status;
4892
4893 status = scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready),
4894 0, 0, 0, 0, 1);
4895 return (status == SANE_STATUS_GOOD);
4896 }
4897
4898 #endif /* USE == SOLARIS_INTERFACE */
4899
4900
4901 #if USE == SOLARIS_USCSI_INTERFACE
4902
4903 #define DEF_TIMEOUT sane_scsicmd_timeout;
4904
4905 static int d_errs = 100;
4906 typedef struct scsi_extended_sense extended_sense_t;
4907 typedef struct scsi_inquiry scsi_inquiry_t;
4908
4909 static SANE_Status
scsi_cmd(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size,int probing)4910 scsi_cmd (int fd,
4911 const void *cmd, size_t cmd_size,
4912 const void *src, size_t src_size,
4913 void *dst, size_t * dst_size, int probing)
4914 {
4915 struct uscsi_cmd us;
4916 scsi_inquiry_t inquiry, *iq = &inquiry;
4917 extended_sense_t sense, *sp = &sense;
4918 SANEI_SCSI_Sense_Handler handler;
4919
4920 memset (&us, 0, sizeof (us));
4921 memset (sp, 0, sizeof (*sp));
4922
4923 us.uscsi_flags = USCSI_SILENT | USCSI_RQENABLE | USCSI_DIAGNOSE;
4924 us.uscsi_timeout = probing ? 2 : DEF_TIMEOUT;
4925 us.uscsi_rqbuf = (caddr_t) sp; /* sense data address */
4926 us.uscsi_rqlen = sizeof (extended_sense_t); /* length of sense data */
4927
4928 if (dst && dst_size && *dst_size)
4929 {
4930 us.uscsi_flags |= USCSI_READ;
4931 us.uscsi_bufaddr = (caddr_t) dst;
4932 us.uscsi_buflen = *dst_size;
4933 }
4934 else
4935 {
4936 us.uscsi_flags |= USCSI_WRITE;
4937 us.uscsi_bufaddr = (caddr_t) src;
4938 us.uscsi_buflen = src_size;
4939 }
4940
4941 us.uscsi_cdblen = cmd_size;
4942 us.uscsi_cdb = (caddr_t) cmd;
4943
4944 if (ioctl (fd, USCSICMD, &us) < 0)
4945 return SANE_STATUS_IO_ERROR;
4946
4947 if (dst_size)
4948 *dst_size = us.uscsi_buflen - us.uscsi_resid;
4949
4950 if ((us.uscsi_status & STATUS_MASK) == STATUS_GOOD)
4951 return SANE_STATUS_GOOD;
4952
4953 if (sp->es_key == SUN_KEY_TIMEOUT)
4954 DBG (0, "sanei_scsi_cmd %x: timeout\n", *(char *) cmd);
4955 else
4956 {
4957 char errbf[128];
4958 int i, rv, lifes;
4959
4960 handler = fd_info[fd].sense_handler;
4961 DBG (3, "cmd=%x, scsi_status=%x\n", *(char *) cmd, us.uscsi_status);
4962 *errbf = '\0';
4963
4964 for (i = 0; i < us.uscsi_rqlen; i++)
4965 sprintf (errbf + strlen (errbf), "%x,", *(sp + i));
4966
4967 DBG (3, "sense=%s\n", errbf);
4968
4969 #if 0
4970 if (us.error)
4971 {
4972 if (sanei_debug_sanei_scsi > 100 &&
4973 scmd.cdb.g0_cdb.cmd != SC_TEST_UNIT_READY)
4974 {
4975 lifes = sanei_debug_sanei_scsi - ++d_errs;
4976 DBG (1, "sanei_scsi_cmd: %d lifes left\n", lifes);
4977 assert (lifes > 0);
4978 }
4979 return SANE_STATUS_IO_ERROR;
4980 }
4981
4982 if (scmd.u_scb.cmd_scb[0] == SC_BUSY)
4983 return SANE_STATUS_DEVICE_BUSY;
4984 #endif
4985
4986 if (handler)
4987 {
4988 rv = (*handler) (fd, (unsigned char *) sp,
4989 fd_info[fd].sense_handler_arg);
4990 DBG (2, "sanei_scsi_cmd: sense-handler returns %d\n", rv);
4991 return rv;
4992 }
4993 }
4994
4995 return SANE_STATUS_IO_ERROR;
4996 }
4997
4998 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)4999 sanei_scsi_cmd2 (int fd,
5000 const void *cmd, size_t cmd_size,
5001 const void *src, size_t src_size,
5002 void *dst, size_t * dst_size)
5003 {
5004 return scsi_cmd (fd, cmd, cmd_size, src, src_size, dst, dst_size, 0);
5005 }
5006
unit_ready(int fd)5007 static int unit_ready (int fd)
5008 {
5009 static const u_char test_unit_ready[] = { 0, 0, 0, 0, 0, 0 };
5010 int status;
5011
5012 status = scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready),
5013 0, 0, 0, 0, 1);
5014 return (status == SANE_STATUS_GOOD);
5015 }
5016 #endif /* USE == SOLARIS_USCSI_INTERFACE */
5017
5018 #if USE == WIN32_INTERFACE
5019
5020 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)5021 sanei_scsi_cmd2 (int fd,
5022 const void *cmd, size_t cmd_size,
5023 const void *src, size_t src_size,
5024 void *dst, size_t * dst_size)
5025 {
5026 struct pkt {
5027 SCSI_PASS_THROUGH_DIRECT sptd;
5028 unsigned char sense[255];
5029 } pkt;
5030 DWORD BytesReturned;
5031 BOOL ret;
5032
5033 memset(&pkt, 0, sizeof( pkt ));
5034 pkt.sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT );
5035
5036 pkt.sptd.PathId = fd_info[fd].bus;
5037 pkt.sptd.TargetId = fd_info[fd].target;
5038 pkt.sptd.Lun = fd_info[fd].lun;
5039
5040 assert(cmd_size == 6 || cmd_size == 10 || cmd_size == 12 || cmd_size == 16);
5041 memcpy(pkt.sptd.Cdb, cmd, cmd_size);
5042 pkt.sptd.CdbLength = cmd_size;
5043
5044 if (dst_size && *dst_size)
5045 {
5046 pkt.sptd.DataIn = SCSI_IOCTL_DATA_IN;
5047 pkt.sptd.DataTransferLength = *dst_size;
5048 pkt.sptd.DataBuffer = dst;
5049 }
5050 else if (src_size)
5051 {
5052 pkt.sptd.DataIn = SCSI_IOCTL_DATA_OUT;
5053 pkt.sptd.DataTransferLength = src_size;
5054 pkt.sptd.DataBuffer = src;
5055 }
5056 else {
5057 pkt.sptd.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
5058 }
5059
5060 pkt.sptd.TimeOutValue = sane_scsicmd_timeout;
5061
5062 pkt.sptd.SenseInfoOffset = (void *)pkt.sense - (void *)&pkt;
5063 pkt.sptd.SenseInfoLength = sizeof(pkt.sense);
5064
5065 ret = DeviceIoControl(fd,
5066 IOCTL_SCSI_PASS_THROUGH_DIRECT,
5067 &pkt.sptd, sizeof( pkt ),
5068 &pkt.sptd, sizeof( pkt ),
5069 &BytesReturned, NULL );
5070
5071 if (ret == 0)
5072 {
5073 DBG (1, "sanei_scsi_cmd2: DeviceIoControl() failed: %ld\n",
5074 GetLastError());
5075 return SANE_STATUS_IO_ERROR;
5076 }
5077
5078 if (pkt.sptd.ScsiStatus == 2){
5079 /* Check condition. */
5080 SANEI_SCSI_Sense_Handler handler;
5081
5082 handler = fd_info[fd].sense_handler;
5083 if (handler) {
5084 return handler(fd, pkt.sense, fd_info[fd].sense_handler_arg);
5085 }
5086 else {
5087 return SANE_STATUS_IO_ERROR;
5088 }
5089 }
5090 else if (pkt.sptd.ScsiStatus != 0) {
5091 DBG (1, "sanei_scsi_cmd2: ScsiStatus is %d\n",
5092 pkt.sptd.ScsiStatus);
5093 return SANE_STATUS_IO_ERROR;
5094 }
5095
5096 if (dst_size) {
5097 *dst_size = pkt.sptd.DataTransferLength;
5098 }
5099
5100 return SANE_STATUS_GOOD;
5101 }
5102
5103 #define WE_HAVE_FIND_DEVICES
5104
5105 /* This is almost the same algorithm used in sane-find-scanner. */
5106 void
sanei_scsi_find_devices(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))5107 sanei_scsi_find_devices (const char *findvendor, const char *findmodel,
5108 const char *findtype,
5109 int findbus, int findchannel, int findid, int findlun,
5110 SANE_Status (*attach) (const char *dev))
5111 {
5112 int hca;
5113 HANDLE fd;
5114 char scsi_hca_name[20];
5115 char buffer[4096];
5116 DWORD BytesReturned;
5117 BOOL ret;
5118 PSCSI_ADAPTER_BUS_INFO adapter;
5119 PSCSI_INQUIRY_DATA inquiry;
5120 int i;
5121
5122 DBG_INIT();
5123
5124 hca = 0;
5125
5126 for(hca = 0; ; hca++) {
5127
5128 /* Open the adapter */
5129 snprintf(scsi_hca_name, 20, "\\\\.\\Scsi%d:", hca);
5130 fd = CreateFile(scsi_hca_name, GENERIC_READ | GENERIC_WRITE,
5131 FILE_SHARE_READ | FILE_SHARE_WRITE,
5132 NULL, OPEN_EXISTING,
5133 FILE_FLAG_RANDOM_ACCESS, NULL );
5134
5135 if (fd == INVALID_HANDLE_VALUE) {
5136 /* Assume there is no more adapter. This is wrong in the case
5137 * of hot-plug stuff, but I have yet to see it on a user
5138 * machine. */
5139 break;
5140 }
5141
5142 /* Get the inquiry info for the devices on that hca. */
5143 ret = DeviceIoControl(fd,
5144 IOCTL_SCSI_GET_INQUIRY_DATA,
5145 NULL,
5146 0,
5147 buffer,
5148 sizeof(buffer),
5149 &BytesReturned,
5150 FALSE);
5151
5152 if(ret == 0)
5153 {
5154 CloseHandle(fd);
5155 continue;
5156 }
5157
5158 adapter = (PSCSI_ADAPTER_BUS_INFO)buffer;
5159
5160 for(i = 0; i < adapter->NumberOfBuses; i++) {
5161
5162 if (adapter->BusData[i].InquiryDataOffset == 0) {
5163 /* No device here */
5164 continue;
5165 }
5166
5167 inquiry = (PSCSI_INQUIRY_DATA) (buffer +
5168 adapter->BusData[i].InquiryDataOffset);
5169
5170 while(1) {
5171
5172 if ((findvendor == NULL || strncmp(findvendor, (char *)&inquiry->InquiryData[8], 8) == 0)) {
5173 DBG(1, "OK1\n");
5174 } else {
5175 DBG(1, "failed for [%s] and [%s]\n",findvendor, (char *)&inquiry->InquiryData[8] );
5176 }
5177
5178
5179 /* Check if this device fits the criteria. */
5180 if ((findvendor == NULL || strncmp(findvendor, (char *)&inquiry->InquiryData[8], strlen(findvendor)) == 0) &&
5181 (findmodel == NULL || strncmp(findmodel, (char *)&inquiry->InquiryData[16], strlen(findmodel)) == 0) &&
5182 (findbus == -1 || findbus == hca) &&
5183 (findchannel == -1 || findchannel == inquiry->PathId) &&
5184 (findid == -1 || findid == inquiry->TargetId) &&
5185 (findlun == -1 || findlun == inquiry->Lun)) {
5186
5187 char device_name[20];
5188 sprintf(device_name, "h%db%dt%dl%d", hca, inquiry->PathId, inquiry->TargetId, inquiry->Lun);
5189 attach(device_name);
5190 }
5191 if (inquiry->NextInquiryDataOffset == 0) {
5192 /* No device here */
5193 break;
5194 } else {
5195 inquiry = (PSCSI_INQUIRY_DATA) (buffer +
5196 inquiry->NextInquiryDataOffset);
5197 }
5198 }
5199 }
5200 CloseHandle(fd);
5201
5202 }
5203 }
5204 #endif /* USE == WIN32_INTERFACE */
5205
5206 #if USE == MACOSX_INTERFACE
5207
5208 # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H
5209
5210 static SANE_Status
sanei_scsi_cmd2_old_api(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)5211 sanei_scsi_cmd2_old_api (int fd,
5212 const void *cmd, size_t cmd_size,
5213 const void *src, size_t src_size,
5214 void *dst, size_t * dst_size)
5215 {
5216 mach_port_t masterPort;
5217 IOReturn ioReturnValue;
5218 io_object_t scsiDevice;
5219 int i;
5220 CFMutableDictionaryRef scsiMatchDictionary;
5221 int deviceTypeNumber;
5222 CFNumberRef deviceTypeRef;
5223 io_iterator_t scsiObjectIterator;
5224 io_object_t device;
5225 CFNumberRef IOUnitRef;
5226 int iounit;
5227 CFNumberRef scsiTargetRef;
5228 int scsitarget;
5229 CFNumberRef scsiLunRef;
5230 int scsilun;
5231 IOCFPlugInInterface **plugInInterface;
5232 SInt32 score;
5233 HRESULT plugInResult;
5234 IOSCSIDeviceInterface **scsiDeviceInterface;
5235 IOCDBCommandInterface **cdbCommandInterface;
5236 CDBInfo cdb;
5237 IOVirtualRange range;
5238 UInt32 transferCount;
5239 Boolean isWrite;
5240 SCSIResults results;
5241 UInt32 seqNumber;
5242
5243 masterPort = 0;
5244 ioReturnValue = IOMasterPort (MACH_PORT_NULL, &masterPort);
5245 if (ioReturnValue != kIOReturnSuccess || masterPort == 0)
5246 {
5247 DBG (5, "Could not get I/O master port (0x%08x)\n", ioReturnValue);
5248 return SANE_STATUS_IO_ERROR;
5249 }
5250
5251 scsiDevice = 0;
5252 for (i = 0; !scsiDevice && i < 2; i++)
5253 {
5254 scsiMatchDictionary = IOServiceMatching (kIOSCSIDeviceClassName);
5255 if (scsiMatchDictionary == NULL)
5256 {
5257 DBG (5, "Could not create SCSI matching dictionary\n");
5258 return SANE_STATUS_NO_MEM;
5259 }
5260
5261 deviceTypeNumber =
5262 (i == 0 ? kSCSIDevTypeScanner : kSCSIDevTypeProcessor);
5263 deviceTypeRef = CFNumberCreate (NULL, kCFNumberIntType,
5264 &deviceTypeNumber);
5265 CFDictionarySetValue (scsiMatchDictionary,
5266 CFSTR (kSCSIPropertyDeviceTypeID),
5267 deviceTypeRef);
5268 CFRelease (deviceTypeRef);
5269
5270 scsiObjectIterator = 0;
5271 ioReturnValue = IOServiceGetMatchingServices (masterPort,
5272 scsiMatchDictionary,
5273 &scsiObjectIterator);
5274 if (ioReturnValue != kIOReturnSuccess)
5275 {
5276 DBG (5, "Could not match services (0x%08x)\n", ioReturnValue);
5277 return SANE_STATUS_NO_MEM;
5278 }
5279
5280 while ((device = IOIteratorNext (scsiObjectIterator)))
5281 {
5282 IOUnitRef =
5283 IORegistryEntryCreateCFProperty (device,
5284 CFSTR (kSCSIPropertyIOUnit),
5285 NULL, 0);
5286 CFNumberGetValue (IOUnitRef, kCFNumberIntType, &iounit);
5287 CFRelease (IOUnitRef);
5288 scsiTargetRef =
5289 IORegistryEntryCreateCFProperty (device,
5290 CFSTR (kSCSIPropertyTarget),
5291 NULL, 0);
5292 CFNumberGetValue (scsiTargetRef, kCFNumberIntType, &scsitarget);
5293 CFRelease (scsiTargetRef);
5294 scsiLunRef =
5295 IORegistryEntryCreateCFProperty (device,
5296 CFSTR (kSCSIPropertyLun),
5297 NULL, 0);
5298 CFNumberGetValue (scsiLunRef, kCFNumberIntType, &scsilun);
5299 CFRelease (scsiLunRef);
5300
5301 if (fd_info[fd].bus == iounit &&
5302 fd_info[fd].target == scsitarget &&
5303 fd_info[fd].lun == scsilun)
5304 scsiDevice = device;
5305 else
5306 IOObjectRelease (device);
5307 }
5308 IOObjectRelease (scsiObjectIterator);
5309 }
5310 if (!scsiDevice)
5311 {
5312 DBG (5, "Device not found (unit %i, target %i, lun %i)\n",
5313 fd_info[fd].bus, fd_info[fd].target, fd_info[fd].lun);
5314 return SANE_STATUS_INVAL;
5315 }
5316
5317 plugInInterface = NULL;
5318 score = 0;
5319 ioReturnValue = IOCreatePlugInInterfaceForService (scsiDevice,
5320 kIOSCSIUserClientTypeID,
5321 kIOCFPlugInInterfaceID,
5322 &plugInInterface,
5323 &score);
5324 if (ioReturnValue != kIOReturnSuccess || plugInInterface == NULL)
5325 {
5326 DBG (5, "Error creating plugin interface (0x%08x)\n", ioReturnValue);
5327 return SANE_STATUS_NO_MEM;
5328 }
5329
5330 scsiDeviceInterface = NULL;
5331 plugInResult = (*plugInInterface)->
5332 QueryInterface (plugInInterface,
5333 CFUUIDGetUUIDBytes (kIOSCSIDeviceInterfaceID),
5334 (LPVOID) & scsiDeviceInterface);
5335 if (plugInResult != S_OK || scsiDeviceInterface == NULL)
5336 {
5337 DBG (5, "Couldn't create SCSI device interface (%ld)\n", plugInResult);
5338 return SANE_STATUS_NO_MEM;
5339 }
5340
5341 (*plugInInterface)->Release (plugInInterface);
5342 IOObjectRelease (scsiDevice);
5343
5344 ioReturnValue = (*scsiDeviceInterface)->open (scsiDeviceInterface);
5345 if (ioReturnValue != kIOReturnSuccess)
5346 {
5347 DBG (5, "Error opening SCSI interface (0x%08x)\n", ioReturnValue);
5348 return SANE_STATUS_IO_ERROR;
5349 }
5350
5351 cdbCommandInterface = NULL;
5352 plugInResult = (*scsiDeviceInterface)->
5353 QueryInterface (scsiDeviceInterface,
5354 CFUUIDGetUUIDBytes (kIOCDBCommandInterfaceID),
5355 (LPVOID) & cdbCommandInterface);
5356 if (plugInResult != S_OK || cdbCommandInterface == NULL)
5357 {
5358 DBG (5, "Error creating CDB interface (%ld)\n", plugInResult);
5359 return SANE_STATUS_NO_MEM;
5360 }
5361
5362 cdb.cdbLength = cmd_size;
5363 memcpy (&cdb.cdb, cmd, cmd_size);
5364 if (dst && dst_size)
5365 {
5366 memset (dst, 0, *dst_size);
5367 range.address = (IOVirtualAddress) dst;
5368 range.length = *dst_size;
5369 transferCount = *dst_size;
5370 isWrite = false;
5371 }
5372 else
5373 {
5374 range.address = (IOVirtualAddress) src;
5375 range.length = src_size;
5376 transferCount = src_size;
5377 isWrite = true;
5378 }
5379
5380 seqNumber = 0;
5381 ioReturnValue = (*cdbCommandInterface)->
5382 setAndExecuteCommand (cdbCommandInterface, &cdb, transferCount,
5383 &range, 1, isWrite, sane_scsicmd_timeout * 1000,
5384 0, 0, 0, &seqNumber);
5385 if (ioReturnValue != kIOReturnSuccess &&
5386 ioReturnValue != kIOReturnUnderrun)
5387 {
5388 DBG (5, "Error executing CDB command (0x%08x)\n", ioReturnValue);
5389 return SANE_STATUS_IO_ERROR;
5390 }
5391
5392 ioReturnValue = (*cdbCommandInterface)->getResults (cdbCommandInterface,
5393 &results);
5394 if (ioReturnValue != kIOReturnSuccess &&
5395 ioReturnValue != kIOReturnUnderrun)
5396 {
5397 DBG (5, "Error getting results from CDB Interface (0x%08x)\n",
5398 ioReturnValue);
5399 return SANE_STATUS_IO_ERROR;
5400 }
5401
5402 if (dst && dst_size)
5403 *dst_size = results.bytesTransferred;
5404
5405 (*cdbCommandInterface)->Release (cdbCommandInterface);
5406 (*scsiDeviceInterface)->close (scsiDeviceInterface);
5407 (*scsiDeviceInterface)->Release (scsiDeviceInterface);
5408
5409 return SANE_STATUS_GOOD;
5410 }
5411
5412
5413 static void
sanei_scsi_find_devices_old_api(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))5414 sanei_scsi_find_devices_old_api (const char *findvendor,
5415 const char *findmodel,
5416 const char *findtype, int findbus,
5417 int findchannel, int findid, int findlun,
5418 SANE_Status (*attach) (const char *dev))
5419 {
5420 mach_port_t masterPort;
5421 IOReturn ioReturnValue;
5422 int i;
5423 CFMutableDictionaryRef scsiMatchDictionary;
5424 int deviceTypeNumber;
5425 CFNumberRef deviceTypeRef;
5426 io_iterator_t scsiObjectIterator;
5427 io_object_t scsiDevice;
5428 CFNumberRef IOUnitRef;
5429 int iounit;
5430 CFNumberRef scsiTargetRef;
5431 int scsitarget;
5432 CFNumberRef scsiLunRef;
5433 int scsilun;
5434 IOCFPlugInInterface **plugInInterface;
5435 SInt32 score;
5436 HRESULT plugInResult;
5437 IOSCSIDeviceInterface **scsiDeviceInterface;
5438 SCSIInquiry inquiry;
5439 UInt32 inquirySize;
5440 char devname[16];
5441
5442 masterPort = 0;
5443 ioReturnValue = IOMasterPort (MACH_PORT_NULL, &masterPort);
5444 if (ioReturnValue != kIOReturnSuccess || masterPort == 0)
5445 {
5446 DBG (5, "Could not get I/O master port (0x%08x)\n", ioReturnValue);
5447 return;
5448 }
5449
5450 for (i = 0; i < 2; i++)
5451 {
5452 scsiMatchDictionary = IOServiceMatching (kIOSCSIDeviceClassName);
5453 if (scsiMatchDictionary == NULL)
5454 {
5455 DBG (5, "Could not create SCSI matching dictionary\n");
5456 return;
5457 }
5458 deviceTypeNumber =
5459 (i == 0 ? kSCSIDevTypeScanner : kSCSIDevTypeProcessor);
5460 deviceTypeRef = CFNumberCreate (NULL, kCFNumberIntType,
5461 &deviceTypeNumber);
5462 CFDictionarySetValue (scsiMatchDictionary,
5463 CFSTR (kSCSIPropertyDeviceTypeID),
5464 deviceTypeRef);
5465 CFRelease (deviceTypeRef);
5466
5467 scsiObjectIterator = 0;
5468 ioReturnValue = IOServiceGetMatchingServices (masterPort,
5469 scsiMatchDictionary,
5470 &scsiObjectIterator);
5471 if (ioReturnValue != kIOReturnSuccess)
5472 {
5473 DBG (5, "Could not match services (0x%08x)\n", ioReturnValue);
5474 return;
5475 }
5476
5477 while ((scsiDevice = IOIteratorNext (scsiObjectIterator)))
5478 {
5479 IOUnitRef =
5480 IORegistryEntryCreateCFProperty (scsiDevice,
5481 CFSTR (kSCSIPropertyIOUnit),
5482 NULL, 0);
5483 CFNumberGetValue (IOUnitRef, kCFNumberIntType, &iounit);
5484 CFRelease (IOUnitRef);
5485 scsiTargetRef =
5486 IORegistryEntryCreateCFProperty (scsiDevice,
5487 CFSTR (kSCSIPropertyTarget),
5488 NULL, 0);
5489 CFNumberGetValue (scsiTargetRef, kCFNumberIntType, &scsitarget);
5490 CFRelease (scsiTargetRef);
5491 scsiLunRef =
5492 IORegistryEntryCreateCFProperty (scsiDevice,
5493 CFSTR (kSCSIPropertyLun),
5494 NULL, 0);
5495 CFNumberGetValue (scsiLunRef, kCFNumberIntType, &scsilun);
5496 CFRelease (scsiLunRef);
5497
5498 plugInInterface = NULL;
5499 score = 0;
5500 ioReturnValue =
5501 IOCreatePlugInInterfaceForService (scsiDevice,
5502 kIOSCSIUserClientTypeID,
5503 kIOCFPlugInInterfaceID,
5504 &plugInInterface, &score);
5505 if (ioReturnValue != kIOReturnSuccess || plugInInterface == NULL)
5506 {
5507 DBG (5, "Error creating plugin interface (0x%08x)\n",
5508 ioReturnValue);
5509 return;
5510 }
5511
5512 scsiDeviceInterface = NULL;
5513 plugInResult = (*plugInInterface)->
5514 QueryInterface (plugInInterface,
5515 CFUUIDGetUUIDBytes (kIOSCSIDeviceInterfaceID),
5516 (LPVOID) & scsiDeviceInterface);
5517 if (plugInResult != S_OK || scsiDeviceInterface == NULL)
5518 {
5519 DBG (5, "Couldn't create SCSI device interface (%ld)\n",
5520 plugInResult);
5521 return;
5522 }
5523
5524 (*plugInInterface)->Release (plugInInterface);
5525 IOObjectRelease (scsiDevice);
5526
5527 ioReturnValue = (*scsiDeviceInterface)->
5528 getInquiryData (scsiDeviceInterface, &inquiry,
5529 sizeof (SCSIInquiry), &inquirySize);
5530
5531 (*scsiDeviceInterface)->Release (scsiDeviceInterface);
5532
5533 if ((findlun < 0 || findlun == scsilun) &&
5534 (findvendor == NULL || strncmp (findvendor,
5535 inquiry.vendorName,
5536 strlen (findvendor)) == 0) &&
5537 (findmodel == NULL || strncmp (findmodel,
5538 inquiry.productName,
5539 strlen (findmodel)) == 0))
5540 {
5541 sprintf (devname, "u%dt%dl%d", iounit, scsitarget, scsilun);
5542 (*attach) (devname);
5543 }
5544 }
5545 IOObjectRelease (scsiObjectIterator);
5546 }
5547 }
5548
5549 # endif /* ifdef HAVE_IOKIT_CDB_IOSCSILIB_H */
5550
5551 # if defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \
5552 defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H)
5553
5554 static
CreateMatchingDictionaryForSTUC(SInt32 peripheralDeviceType,const char * findvendor,const char * findmodel,const CFDataRef scsiguid,CFMutableDictionaryRef * matchingDict)5555 void CreateMatchingDictionaryForSTUC (SInt32 peripheralDeviceType,
5556 const char *findvendor,
5557 const char *findmodel,
5558 const CFDataRef scsiguid,
5559 CFMutableDictionaryRef * matchingDict)
5560 {
5561 CFMutableDictionaryRef subDict;
5562 CFNumberRef deviceTypeRef;
5563 CFStringRef str;
5564
5565 /* Create the dictionaries */
5566 *matchingDict =
5567 CFDictionaryCreateMutable (kCFAllocatorDefault, 0,
5568 &kCFTypeDictionaryKeyCallBacks,
5569 &kCFTypeDictionaryValueCallBacks);
5570 if (*matchingDict == NULL)
5571 {
5572 return;
5573 }
5574
5575 subDict =
5576 CFDictionaryCreateMutable (kCFAllocatorDefault, 0,
5577 &kCFTypeDictionaryKeyCallBacks,
5578 &kCFTypeDictionaryValueCallBacks);
5579 if (subDict == NULL)
5580 {
5581 CFRelease (*matchingDict);
5582 *matchingDict = NULL;
5583 return;
5584 }
5585
5586 /* Create a dictionary with the "SCSITaskDeviceCategory" key with the
5587 appropriate value for the device type we're interested in.*/
5588
5589 CFDictionarySetValue (subDict,
5590 CFSTR (kIOPropertySCSITaskDeviceCategory),
5591 CFSTR (kIOPropertySCSITaskUserClientDevice));
5592
5593 deviceTypeRef = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType,
5594 &peripheralDeviceType);
5595 CFDictionarySetValue (subDict,
5596 CFSTR (kIOPropertySCSIPeripheralDeviceType),
5597 deviceTypeRef);
5598 CFRelease (deviceTypeRef);
5599
5600 /* Add search for a vendor or model */
5601
5602 if (findvendor)
5603 {
5604 str = CFStringCreateWithCString (kCFAllocatorDefault, findvendor,
5605 kCFStringEncodingUTF8);
5606 CFDictionarySetValue (subDict,
5607 CFSTR (kIOPropertySCSIVendorIdentification),
5608 str);
5609 CFRelease (str);
5610 }
5611 if (findmodel)
5612 {
5613 str = CFStringCreateWithCString (kCFAllocatorDefault, findmodel,
5614 kCFStringEncodingUTF8);
5615 CFDictionarySetValue (subDict,
5616 CFSTR (kIOPropertySCSIProductIdentification),
5617 str);
5618 CFRelease (str);
5619 }
5620 if (scsiguid)
5621 {
5622 CFDictionarySetValue (subDict,
5623 CFSTR
5624 (kIOPropertySCSITaskUserClientInstanceGUID),
5625 scsiguid);
5626 }
5627
5628 /* Add the dictionary to the main dictionary with the key "IOPropertyMatch"
5629 to narrow the search to the above dictionary. */
5630
5631 CFDictionarySetValue (*matchingDict, CFSTR (kIOPropertyMatchKey), subDict);
5632 CFRelease (subDict);
5633 }
5634
5635 static
CreateDeviceInterfaceUsingSTUC(io_object_t scsiDevice,IOCFPlugInInterface *** thePlugInInterface,SCSITaskDeviceInterface *** theInterface)5636 void CreateDeviceInterfaceUsingSTUC (io_object_t scsiDevice,
5637 IOCFPlugInInterface ***
5638 thePlugInInterface,
5639 SCSITaskDeviceInterface ***
5640 theInterface)
5641 {
5642 IOReturn ioReturnValue;
5643 IOCFPlugInInterface **plugInInterface = NULL;
5644 SInt32 score = 0;
5645 HRESULT plugInResult;
5646 SCSITaskDeviceInterface **interface = NULL;
5647
5648 /* Create the base interface of type IOCFPlugInInterface.
5649 This object will be used to create the SCSI device interface object. */
5650
5651 ioReturnValue =
5652 IOCreatePlugInInterfaceForService (scsiDevice,
5653 kIOSCSITaskDeviceUserClientTypeID,
5654 kIOCFPlugInInterfaceID,
5655 &plugInInterface, &score);
5656 if (ioReturnValue != kIOReturnSuccess)
5657 {
5658 DBG (5, "Error creating plugin interface (0x%08x)\n", ioReturnValue);
5659 return;
5660 }
5661
5662 /* Query the base plugin interface for an instance of the specific
5663 SCSI device interface object. */
5664
5665 plugInResult =
5666 (*plugInInterface)->QueryInterface (plugInInterface,
5667 CFUUIDGetUUIDBytes
5668 (kIOSCSITaskDeviceInterfaceID),
5669 (LPVOID) & interface);
5670 if (plugInResult != S_OK)
5671 {
5672 DBG (5, "Couldn't create SCSI device interface (%ld)\n",
5673 (long) plugInResult);
5674 return;
5675 }
5676
5677 /* Set the return values. */
5678
5679 *thePlugInInterface = plugInInterface;
5680 *theInterface = interface;
5681 }
5682
5683 static SANE_Status
ExecuteSCSITask(SCSITaskInterface ** task,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)5684 ExecuteSCSITask (SCSITaskInterface ** task,
5685 const void *cmd, size_t cmd_size,
5686 const void *src, size_t src_size,
5687 void *dst, size_t * dst_size)
5688 {
5689 SCSITaskStatus taskStatus;
5690 SCSI_Sense_Data senseData;
5691 SCSICommandDescriptorBlock cdb;
5692 IOReturn ioReturnValue;
5693 #ifdef HAVE_SCSITASKSGELEMENT
5694 SCSITaskSGElement range;
5695 #else
5696 IOVirtualRange range;
5697 #endif
5698 UInt64 transferCount = 0;
5699 UInt64 data_length = 0;
5700 UInt8 transferType = 0;
5701
5702 if (dst && dst_size) /* isRead */
5703 {
5704 DBG (6, "isRead dst_size:%ld\n", *dst_size);
5705
5706 /* Zero the buffer. */
5707 memset (dst, 0, *dst_size);
5708
5709 /* Configure the virtual range for the buffer. */
5710 range.address = (long) dst;
5711 range.length = *dst_size;
5712
5713 data_length = *dst_size;
5714 transferType = kSCSIDataTransfer_FromTargetToInitiator;
5715 }
5716 else
5717 {
5718 DBG (6, "isWrite src_size:%ld\n", src_size);
5719
5720 /* Configure the virtual range for the buffer. */
5721 range.address = (long) src;
5722 range.length = src_size;
5723
5724 data_length = src_size;
5725 transferType = kSCSIDataTransfer_FromInitiatorToTarget;
5726 }
5727
5728
5729 /* zero the senseData and CDB */
5730 memset (&senseData, 0, sizeof (senseData));
5731 memset (cdb, 0, sizeof (cdb));
5732
5733 /* copy the command data */
5734 memcpy (cdb, cmd, cmd_size);
5735
5736 /* Set the actual cdb in the task */
5737 ioReturnValue = (*task)->SetCommandDescriptorBlock (task, cdb, cmd_size);
5738 if (ioReturnValue != kIOReturnSuccess)
5739 {
5740 DBG (5, "Error setting CDB (0x%08x)\n", ioReturnValue);
5741 return SANE_STATUS_IO_ERROR;
5742 }
5743
5744 /* Set the scatter-gather entry in the task */
5745 ioReturnValue = (*task)->SetScatterGatherEntries (task, &range, 1,
5746 data_length,
5747 transferType);
5748 if (ioReturnValue != kIOReturnSuccess)
5749 {
5750 DBG (5, "Error setting scatter-gather entries (0x%08x)\n",
5751 ioReturnValue);
5752 return SANE_STATUS_IO_ERROR;
5753 }
5754
5755 /* Set the timeout in the task */
5756 ioReturnValue = (*task)->SetTimeoutDuration (task,
5757 sane_scsicmd_timeout * 1000);
5758 if (ioReturnValue != kIOReturnSuccess)
5759 {
5760 DBG (5, "Error setting timeout (0x%08x)\n", ioReturnValue);
5761 return SANE_STATUS_IO_ERROR;
5762 }
5763
5764 DBG (5, "Executing command\n");
5765
5766 /* Send it! */
5767 ioReturnValue = (*task)->ExecuteTaskSync (task, &senseData, &taskStatus,
5768 &transferCount);
5769 if (ioReturnValue != kIOReturnSuccess)
5770 {
5771 DBG (5, "Error executing task (0x%08x)\n", ioReturnValue);
5772 return SANE_STATUS_IO_ERROR;
5773 }
5774
5775 DBG (5, "ExecuteTaskSync OK Transferred %lld bytes\n", transferCount);
5776
5777 if (taskStatus != kSCSITaskStatus_GOOD)
5778 {
5779 DBG (5, "taskStatus = 0x%08x\n", taskStatus);
5780 return SANE_STATUS_IO_ERROR;
5781 }
5782
5783 /* Task worked correctly */
5784 if (dst && dst_size)
5785 *dst_size = transferCount;
5786
5787 return SANE_STATUS_GOOD;
5788 }
5789
5790 static SANE_Status
ExecuteCommandUsingSTUC(SCSITaskDeviceInterface ** interface,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)5791 ExecuteCommandUsingSTUC (SCSITaskDeviceInterface ** interface,
5792 const void *cmd, size_t cmd_size,
5793 const void *src, size_t src_size,
5794 void *dst, size_t * dst_size)
5795 {
5796 SCSITaskInterface **task;
5797 IOReturn ioReturnValue;
5798 SANE_Status returnValue;
5799
5800 /* Get exclusive access for the device if we can. This must be done
5801 before any SCSITasks can be created and sent to the device. */
5802 ioReturnValue = (*interface)->ObtainExclusiveAccess (interface);
5803
5804 if (ioReturnValue != kIOReturnSuccess)
5805 {
5806 DBG (5, "ObtainExclusiveAccess failed (0x%08x)\n", ioReturnValue);
5807 return SANE_STATUS_NO_MEM;
5808 }
5809
5810 /* Create a task now that we have exclusive access */
5811 task = (*interface)->CreateSCSITask (interface);
5812
5813 if (task == NULL)
5814 {
5815 DBG (5, "CreateSCSITask returned NULL\n");
5816 (*interface)->ReleaseExclusiveAccess (interface);
5817 return SANE_STATUS_NO_MEM;
5818 }
5819
5820 returnValue = ExecuteSCSITask (task, cmd, cmd_size,
5821 src, src_size, dst, dst_size);
5822
5823 /* Release the task interface */
5824 (*task)->Release (task);
5825
5826 /* Release exclusive access */
5827 (*interface)->ReleaseExclusiveAccess (interface);
5828
5829 return returnValue;
5830 }
5831
5832 static SANE_Status
sanei_scsi_cmd2_stuc_api(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)5833 sanei_scsi_cmd2_stuc_api (int fd,
5834 const void *cmd, size_t cmd_size,
5835 const void *src, size_t src_size,
5836 void *dst, size_t * dst_size)
5837 {
5838 CFDataRef guid;
5839 mach_port_t masterPort;
5840 int i;
5841 io_object_t scsiDevice;
5842 SInt32 peripheralDeviceType;
5843 CFMutableDictionaryRef matchingDict;
5844 io_iterator_t iokIterator;
5845 IOReturn ioReturnValue;
5846 IOCFPlugInInterface **plugInInterface = NULL;
5847 SCSITaskDeviceInterface **interface = NULL;
5848 io_object_t nextDevice;
5849 SANE_Status returnValue;
5850
5851 guid = fd_info[fd].pdata;
5852 if (!guid)
5853 {
5854 DBG (5, "No GUID\n");
5855 return SANE_STATUS_INVAL;
5856 }
5857
5858 DBG (2, "cmd2: cmd_size:%ld src_size:%ld dst_size:%ld isWrite:%d\n",
5859 cmd_size, src_size, (!dst_size) ? 0 : *dst_size, (!dst_size) ? 1 : 0);
5860
5861 /* Use default master port */
5862 masterPort = 0;
5863 ioReturnValue = IOMasterPort (MACH_PORT_NULL, &masterPort);
5864 if (ioReturnValue != kIOReturnSuccess || masterPort == 0)
5865 {
5866 DBG (5, "Could not get I/O master port (0x%08x)\n", ioReturnValue);
5867 return SANE_STATUS_IO_ERROR;
5868 }
5869
5870 /* Search for both Scanner type and Processor type devices */
5871 /* GB TDB This should only be needed for find */
5872 scsiDevice = 0;
5873 for (i = 0; !scsiDevice && i < 2; i++)
5874 {
5875 peripheralDeviceType =
5876 (i == 0 ? kINQUIRY_PERIPHERAL_TYPE_ScannerSCSI2Device :
5877 kINQUIRY_PERIPHERAL_TYPE_ProcessorSPCDevice);
5878
5879 /* Set up a matching dictionary to search the I/O Registry for
5880 the SCSI device */
5881 /* we are interested in, specifying the SCSITaskUserClient GUID. */
5882 matchingDict = NULL;
5883 CreateMatchingDictionaryForSTUC (peripheralDeviceType, NULL, NULL,
5884 guid, &matchingDict);
5885 if (matchingDict == NULL)
5886 {
5887 DBG (5, "CreateMatchingDictionaryForSTUC Failed\n");
5888 return SANE_STATUS_NO_MEM;
5889 }
5890
5891 /* Now search I/O Registry for the matching device */
5892 iokIterator = 0;
5893 ioReturnValue =
5894 IOServiceGetMatchingServices (masterPort, matchingDict,
5895 &iokIterator);
5896 if (ioReturnValue != kIOReturnSuccess)
5897 {
5898 DBG (5, "IOServiceGetMatchingServices Failed\n");
5899 return SANE_STATUS_NO_MEM;
5900 }
5901
5902 scsiDevice = IOIteratorNext (iokIterator);
5903
5904 while ((nextDevice = IOIteratorNext (iokIterator)))
5905 {
5906 IOObjectRelease (nextDevice);
5907 }
5908
5909 IOObjectRelease (iokIterator);
5910 }
5911
5912 if (!scsiDevice)
5913 {
5914 DBG (5, "Device not found\n");
5915 return SANE_STATUS_INVAL;
5916 }
5917
5918 /* Found Device */
5919 /* Create interface */
5920
5921 CreateDeviceInterfaceUsingSTUC (scsiDevice, &plugInInterface, &interface);
5922
5923 /* Done with SCSI object from I/O Registry. */
5924 ioReturnValue = IOObjectRelease (scsiDevice);
5925
5926 returnValue = SANE_STATUS_IO_ERROR;
5927
5928 if (ioReturnValue != kIOReturnSuccess)
5929 {
5930 DBG (5, "Error releasing SCSI device. (0x%08x)\n", ioReturnValue);
5931 }
5932 else if (interface != NULL)
5933 {
5934 /* Execute the command */
5935 returnValue =
5936 ExecuteCommandUsingSTUC (interface, cmd, cmd_size, src, src_size,
5937 dst, dst_size);
5938 }
5939
5940 if (interface != NULL)
5941 {
5942 (*interface)->Release (interface);
5943 }
5944
5945 if (plugInInterface != NULL)
5946 {
5947 IODestroyPlugInInterface (plugInInterface);
5948 }
5949
5950 return returnValue;
5951 }
5952
5953 static void
sanei_scsi_find_devices_stuc_api(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))5954 sanei_scsi_find_devices_stuc_api (const char *findvendor,
5955 const char *findmodel,
5956 const char *findtype, int findbus,
5957 int findchannel, int findid, int findlun,
5958 SANE_Status (*attach) (const char *dev))
5959 {
5960 mach_port_t masterPort;
5961 IOReturn ioReturnValue;
5962 int i;
5963 SInt32 peripheralDeviceType;
5964 CFMutableDictionaryRef matchingDict;
5965 io_iterator_t iokIterator;
5966 io_object_t scsiDevice;
5967 CFDataRef GUIDRef;
5968 char *devname;
5969 int len;
5970 const unsigned char *p;
5971 CFDictionaryRef protocolCharacteristics;
5972 CFNumberRef scsiLunRef;
5973 int scsilun;
5974
5975 masterPort = 0;
5976 ioReturnValue = IOMasterPort (MACH_PORT_NULL, &masterPort);
5977 if (ioReturnValue != kIOReturnSuccess || masterPort == 0)
5978 return;
5979
5980 DBG (5, "Search for Vendor: %s Model: %s\n",
5981 (findvendor) ? findvendor : "(none)",
5982 (findmodel) ? findmodel : "(none)");
5983
5984 /* Search for both Scanner type and Processor type devices */
5985
5986 for (i = 0; i < 2; i++)
5987 {
5988 peripheralDeviceType =
5989 (i == 0 ? kINQUIRY_PERIPHERAL_TYPE_ScannerSCSI2Device :
5990 kINQUIRY_PERIPHERAL_TYPE_ProcessorSPCDevice);
5991
5992 /* Set up a matching dictionary to search the I/O Registry for SCSI
5993 devices we are interested in. */
5994
5995 matchingDict = NULL;
5996 CreateMatchingDictionaryForSTUC (peripheralDeviceType, findvendor,
5997 findmodel, NULL, &matchingDict);
5998 if (matchingDict == NULL)
5999 {
6000 DBG (5, "CreateMatchingDictionaryForSTUC Failed\n");
6001 return;
6002 }
6003
6004 /* Now search I/O Registry for matching devices. */
6005
6006 iokIterator = 0;
6007 ioReturnValue =
6008 IOServiceGetMatchingServices (masterPort, matchingDict,
6009 &iokIterator);
6010 if (ioReturnValue != kIOReturnSuccess)
6011 {
6012 DBG (5, "IOServiceGetMatchingServices Failed\n");
6013 return;
6014 }
6015
6016 /* Check devices */
6017
6018 while ((scsiDevice = IOIteratorNext (iokIterator)))
6019 {
6020 scsilun = 0;
6021 protocolCharacteristics = IORegistryEntryCreateCFProperty
6022 (scsiDevice, CFSTR ("Protocol Characteristics"), NULL, 0);
6023 if (protocolCharacteristics)
6024 {
6025 scsiLunRef = CFDictionaryGetValue
6026 (protocolCharacteristics,
6027 CFSTR ("SCSI Logical Unit Number"));
6028 if (scsiLunRef)
6029 CFNumberGetValue (scsiLunRef, kCFNumberIntType, &scsilun);
6030 CFRelease (protocolCharacteristics);
6031 }
6032
6033 if (findlun < 0 || findlun == scsilun)
6034 {
6035 /* Create device name from the SCSITaskUserClient GUID */
6036
6037 GUIDRef = IORegistryEntryCreateCFProperty
6038 (scsiDevice,
6039 CFSTR (kIOPropertySCSITaskUserClientInstanceGUID),
6040 NULL, 0);
6041
6042 if (GUIDRef)
6043 {
6044 len = CFDataGetLength (GUIDRef);
6045 p = CFDataGetBytePtr (GUIDRef);
6046
6047 devname = (char *) malloc (2 * len + 3);
6048 devname [0] = '<';
6049 for (i = 0; i < len; i++)
6050 sprintf (&devname [2 * i + 1], "%02x", p [i]);
6051 devname [2 * len + 1] = '>';
6052 devname [2 * len + 2] = '\0';
6053
6054 CFRelease (GUIDRef);
6055
6056 DBG (1, "Found: %s\n", devname);
6057
6058 /* Attach to the device */
6059 (*attach) (devname);
6060 free (devname);
6061 }
6062 else
6063 DBG (1, "Can't find SCSITaskUserClient GUID\n");
6064 }
6065 }
6066 IOObjectRelease (iokIterator);
6067 }
6068 }
6069
6070 # endif /* HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H */
6071
6072 SANE_Status
sanei_scsi_cmd2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)6073 sanei_scsi_cmd2 (int fd,
6074 const void *cmd, size_t cmd_size,
6075 const void *src, size_t src_size,
6076 void *dst, size_t * dst_size)
6077 {
6078 if (fd_info[fd].pdata)
6079 # if defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \
6080 defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H)
6081 return sanei_scsi_cmd2_stuc_api (fd, cmd, cmd_size, src, src_size,
6082 dst, dst_size);
6083 # else
6084 return SANE_STATUS_INVAL;
6085 # endif
6086 else
6087 # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H
6088 return sanei_scsi_cmd2_old_api (fd, cmd, cmd_size, src, src_size,
6089 dst, dst_size);
6090 # else
6091 return SANE_STATUS_INVAL;
6092 # endif
6093 }
6094
6095 void
sanei_scsi_find_devices(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))6096 sanei_scsi_find_devices (const char *findvendor, const char *findmodel,
6097 const char *findtype,
6098 int findbus, int findchannel, int findid,
6099 int findlun,
6100 SANE_Status (*attach) (const char *dev))
6101 {
6102 # if defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \
6103 defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H)
6104 sanei_scsi_find_devices_stuc_api (findvendor, findmodel, findtype,
6105 findbus, findchannel, findid,
6106 findlun, attach);
6107 # endif
6108 # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H
6109 sanei_scsi_find_devices_old_api (findvendor, findmodel, findtype,
6110 findbus, findchannel, findid,
6111 findlun, attach);
6112 # endif
6113 }
6114
6115 #define WE_HAVE_FIND_DEVICES
6116
6117 #endif /* USE == MACOSX_INTERFACE */
6118
6119
6120 #ifndef WE_HAVE_ASYNC_SCSI
6121
6122 SANE_Status
sanei_scsi_req_enter2(int fd,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size,void ** idp)6123 sanei_scsi_req_enter2 (int fd, const void *cmd, size_t cmd_size,
6124 const void *src, size_t src_size,
6125 void *dst, size_t * dst_size, void **idp)
6126 {
6127 return sanei_scsi_cmd2 (fd, cmd, cmd_size, src, src_size, dst, dst_size);
6128 }
6129
sanei_scsi_req_wait(void * id)6130 SANE_Status sanei_scsi_req_wait (void *id)
6131 {
6132 return SANE_STATUS_GOOD;
6133 }
6134
sanei_scsi_req_flush_all(void)6135 void sanei_scsi_req_flush_all (void)
6136 {
6137 }
6138
sanei_scsi_req_flush_all_extended(int fd)6139 void sanei_scsi_req_flush_all_extended (int fd)
6140 {
6141 }
6142
6143 #endif /* WE_HAVE_ASYNC_SCSI */
6144
sanei_scsi_req_enter(int fd,const void * src,size_t src_size,void * dst,size_t * dst_size,void ** idp)6145 SANE_Status sanei_scsi_req_enter (int fd,
6146 const void *src, size_t src_size,
6147 void *dst, size_t * dst_size, void **idp)
6148 {
6149 size_t cmd_size = CDB_SIZE (*(const char *) src);
6150
6151 if (dst_size && *dst_size)
6152 assert (src_size == cmd_size);
6153 else
6154 assert (src_size >= cmd_size);
6155
6156 return sanei_scsi_req_enter2 (fd, src, cmd_size,
6157 (const char *) src + cmd_size,
6158 src_size - cmd_size, dst, dst_size, idp);
6159 }
6160
6161 SANE_Status
sanei_scsi_cmd(int fd,const void * src,size_t src_size,void * dst,size_t * dst_size)6162 sanei_scsi_cmd (int fd, const void *src, size_t src_size,
6163 void *dst, size_t * dst_size)
6164 {
6165 size_t cmd_size = CDB_SIZE (*(const char *) src);
6166
6167 if (dst_size && *dst_size)
6168 assert (src_size == cmd_size);
6169 else
6170 assert (src_size >= cmd_size);
6171
6172 return sanei_scsi_cmd2 (fd, src, cmd_size,
6173 (const char *) src + cmd_size,
6174 src_size - cmd_size, dst, dst_size);
6175 }
6176
6177
6178
6179 #ifndef WE_HAVE_FIND_DEVICES
6180
6181 void
sanei_scsi_find_devices(const char * findvendor,const char * findmodel,const char * findtype,int findbus,int findchannel,int findid,int findlun,SANE_Status (* attach)(const char * dev))6182 sanei_scsi_find_devices (const char *findvendor, const char *findmodel,
6183 const char *findtype,
6184 int findbus, int findchannel, int findid,
6185 int findlun,
6186 SANE_Status (*attach) (const char *dev))
6187 {
6188 DBG_INIT ();
6189 DBG (1, "sanei_scsi_find_devices: not implemented for this platform\n");
6190 }
6191
6192 #endif /* WE_HAVE_FIND_DEVICES */
6193