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