Notes on Linux's SG driver version 2.1.30 ----------------------------------------- 990328 Introduction ============ These are notes on the Linux SCSI generic packet device driver (sg) describing version 2.1.30 . The original driver was written by Lawrence Foard and has remained in place with minimal changes since circa 1992. Version 2 of this driver remains backward compatible (binary and source **) with the original. It adds scatter gather, command queuing, per file descriptor sequencing, asynchronous notification and better error reporting. Sg is one of the four "high level" SCSI device drivers along with sd, st and sr (disk, tape and CDROM respectively). Sg is more generalized (but lower level) than its sibling and tends to be used on SCSI devices that don't fit into the already serviced categories. Thus sg is used for scanners, cd writers and reading audio cds amongst other things. The interface and usage of the original sg driver has been documented by Heiko Eissfeldt in a HOWTO called SCSI-Programming-HOWTO. My copy of the document is version 1.5 dated 7th May 1996. It can found at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/SCSI-Programming-HOWTO . Amongst other things it has a lot of tables from the SCSI-2 standard that are very useful for programming this interface. ** It is possible to write applications that perform differently depending on whether they are using the original or this version of the sg device driver. The author is not aware of any useful applications that have problems with version 2 (yet). Architecture ============ The SCSI generic packet device driver (sg) is a character based device. It is one of the four high level device driver in the SCSI sub-system; the others are sd (for direct-access devices - disks), st (for tapes) and sr (for data cdroms). The other three devices are block devices. The unifying layer of the SCSI sub-system in the so-called mid-level. Below that are all the drivers for the various adapters supported by Linux. Since sg is a character device it supports the traditional Unix system calls of open(), close(), read(), write() and ioctl(). Two other related system calls: poll() and fcntl() are added to this list and how they interact with the sg device driver is documented later. An SG device is accessed by write()ing SCSI commands plus any associated outgoing data to it; the resulting status codes and any incoming data are then obtained by a read() call. The device can be opened O_NONBLOCK (non-blocking) and poll() used to monitor its progress. The device may be opened O_EXCL which excludes other "sg" users from this device (but not "sd", "st" or "sr" users). The buffer given to the write() call is made up as follows: - struct sg_header image (see below) - scsi command (6, 10 or 12 bytes long) - data to be written to the device (if any) The buffer received from the corresponding read() call contains: - struct sg_header image (check status/errors + sense_buffer) - data read back from device (if any) The given SCSI command has its LUN field overwritten by the LUN value of the associated sg device that has been open()ed. sg_header ========= This is the name of the control structure that conveys information about the length of data to be read/written by the associated SCSI command. It also conveys error and status information from the read() call. An instance of this structure is the first thing that is placed in the data buffers of both write() and read(). In its original form it looked like this: struct sg_header { int pack_len; int reply_len; int pack_id; int result; unsigned int twelve_byte:1; unsigned int other_flags:31; unsigned char sense_buffer[16]; }; /* this structure is 36 bytes long */ The 'pack_len' is bizzare and ends up having the 'reply_len' put in it (perhaps it had a use at some stage). The 'reply_len' is the length of the data the corresponding read() will/should request (including the sg_header). The 'pack_id' is not acted upon by the sg device driver but is conveyed back to the corresponding read() so it can be used for sequencing by an application. The 'result' is also bizzare, turning certain types of host codes it 0 (no error), EBUSY or EIO. With better error reporting now available, the 'result' is best ignored. The 'twelve_byte' field overrides the internal SCSI command length "guessing" algorithm for group 6 and 7 commands (ie when 1st byte >= 0xc0) and forces a command lenth of 12 bytes. The command length "guessing" algorithm is as follows: Group: 0 1 2 3 4 5 6 7 Length: 6 10 10 12 12 12 10 10 'other_flags' was originally documented as "not used" but some current applications assume it has 0 placed in it. The 'sense_buffer' is the first 16 bytes of SCSI sense buffer that is returned when the target returns a SCSI status code of CHECK_CONDITION or COMMAND_TERMINATED [or (driver_status & DRIVER_SENSE) is true]. This buffer should be at least 18 bytes long and arguably 32 bytes; unfortunately this is unlikely to happen in the 2.2.x series of kernels. The new sg_header offered in this driver is: #define SG_MAX_SENSE 16 struct sg_header { int pack_len; /* [o] reply_len (ie useless) ignored as input */ int reply_len; /* [i] max length of expected reply (inc. sg_header) */ int pack_id; /* [io] id number of packet (use ints >= 0) */ int result; /* [o] 0==ok, else (+ve) Unix errno code (e.g. EIO) */ unsigned int twelve_byte:1; /* [i] Force 12 byte command length for group 6 & 7 commands */ unsigned int target_status:5; /* [o] scsi status from target */ unsigned int host_status:8; /* [o] host status (see "DID" codes) */ unsigned int driver_status:8; /* [o] driver status+suggestion */ unsigned int other_flags:10; /* unused */ unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] when target_status is CHECK_CONDITION or COMMAND_TERMINATED this is output. */ }; /* This structure is 36 bytes long on i386 */ Firstly the new header is binary compatible with the original. This is important for keeping existing apps working without recompilation. Only those elements (or fields) that are new or in some way different from the original are documented below. 'pack_id' becomes input to a read() when ioctl(sg_fd, SG_SET_FORCE_PACK_ID, &one) is active. A 'pack_id' of -1 is interpreted as fetch the oldest waiting packet; any other value will cause the read() to wait (or yield EAGAIN) until a packet with that 'pack_id' becomes available. In all cases the value of 'pack_id' available after a read() is the value given to that variable in the prior, corresponding write(). The 'target_status' field is always output and is the (masked and shifted 1 bit right) SCSI status code from the target device. The allowable values are (found in ): /* N.B. 1 bit offset from usual SCSI status values */ #define GOOD 0x00 #define CHECK_CONDITION 0x01 #define CONDITION_GOOD 0x02 #define BUSY 0x04 #define INTERMEDIATE_GOOD 0x08 #define INTERMEDIATE_C_GOOD 0x0a #define RESERVATION_CONFLICT 0x0c #define COMMAND_TERMINATED 0x11 #define QUEUE_FULL 0x14 When the 'target_status' is CHECK_CONDITION or COMMAND_TERMINATED the 'sense_buffer' is output. Note that when (driver_status & DRIVER_SENSE) is true then the 'sense_buffer' is also output (this seems to occur when the scsi ide emulation is used). When the 'sense_buffer' is output the SCSI Sense Key can be found at (sense_buffer[2] & 0x0f) . The 'host_status' field is always output and has the following values whose "defines" are not visible outside the kernel (unfortunately): #define DID_OK 0x00 /* NO error */ #define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */ #define DID_BUS_BUSY 0x02 /* BUS stayed busy through time out period */ #define DID_TIME_OUT 0x03 /* TIMED OUT for other reason */ #define DID_BAD_TARGET 0x04 /* BAD target. */ #define DID_ABORT 0x05 /* Told to abort for some other reason */ #define DID_PARITY 0x06 /* Parity error */ #define DID_ERROR 0x07 /* Internal error */ #define DID_RESET 0x08 /* Reset by somebody. */ #define DID_BAD_INTR 0x09 /* Got an interrupt we weren't expecting. */ #define DID_PASSTHROUGH 0x0a /* Force command past mid-layer */ #define DID_SOFT_ERROR 0x0b /* The low level driver just wish a retry */ The 'driver_status' field is always output. When ('driver_status' & DRIVER_SENSE) is true the 'sense_buffer' is also output. The following values whose "defines" are not visible outside the kernel (unfortunately) can occur: #define DRIVER_OK 0x00 /* Typically no suggestion */ #define DRIVER_BUSY 0x01 #define DRIVER_SOFT 0x02 #define DRIVER_MEDIA 0x03 #define DRIVER_ERROR 0x04 #define DRIVER_INVALID 0x05 #define DRIVER_TIMEOUT 0x06 #define DRIVER_HARD 0x07 #define DRIVER_SENSE 0x08 /* above status 'or'ed with one of the following suggestions */ #define SUGGEST_RETRY 0x10 #define SUGGEST_ABORT 0x20 #define SUGGEST_REMAP 0x30 #define SUGGEST_DIE 0x40 #define SUGGEST_SENSE 0x80 'other_flags' still remains as a 10 bit field, so code that places 0 in it will still be happy. It is not used. memory ====== Memory is a scarce resource in any computer. Sg needs to reserve memory suitable for DMA roughly equal in size to the maximum of the write and read data buffers for each packet. This DMA memory is obtained at the time of a write() and released when the corresponding read() is called (although if memory is tight it may be using the buffer reserved by the open() ). Linux obtaining memory a challenge for several reasons. The memory pool that sg uses is in common with all other device drivers and all user processes. In this environment the only way to 99.9% guarantee a driver will have memory in Linux is to build it into the kernel (ie not as a module) and then reserve it on initialization before user processes get a chance. [Of course, another driver initialized before sg could take all available memory ...] Another problem is the biggest contiguous chunk of memory that can be obtained from the kernel is 32 * PAGE_SIZE (which is 128KBytes on i386). As memory gets "splintered" there is a good chance that buffers won't be available (my machine has 64 MBytes of RAM and has 3 available at the moment). The original sg driver used the following technique: grab a SG_BIG_BUFF sized buffer at driver initialization and use it for all requests greater than PAGE_SIZE (4096 bytes on i386). By default SG_BIG_BUFF is set to 32 KBytes in the origianl driver but many applications suggest that the user increases this number. Linux limits the biggest single buffer of this type to 32 * PAGE_SIZE (128KBytes on i386). Unfortunately if the sg driver is a module then there is a high chance a contiguous block of that large size will not be available at module initialization. The author has found no "silver bullet" solution but uses multiple techniques hoping that at least one is able provide memory at the critical time. Listed below are some of these techniques: - use scatter gather: then instead of one large buffer needing to be found, multiple smaller buffer can be used - use memory above the 16MByte level: the original driver limited itself to obtaining memory below the 16MByte level (on the i386) due to the shortcomings of DMA on ISA adapters. Yet more and more people use PCI adapters that don't have this problem. So make the decision based on the capabilities of the host adpater associated with the current SCSI device - reserve some memory at open() for emergencies but otherwise fetch and release it on a per packet basis - if the kernel is short of memory then dip into the SCSI DMA pool (maintained by the mid-level driver) to a limited amount System Calls ============ What follows are descriptions of the characteristics of the standard Unix operating system calls when applied to a SCSI generic device using this version of the device driver. open ---- The filename should be an 'sg' device such as /dev/sg[a-z] /dev/sg[0,1,2,...] or a symbolic link to one of these. [Devfs has its own sub-directory for sg devices.] It seems as though SCSI devices are allocated to sg minor numbers in the same order as they appear in 'cat /proc/scsi/scsi'. Sg is a "character" based Linux device driver. This means it has an open/close/read/write/ioctl type interface. Flags can be either O_RDONLY or O_RDWR or-ed with either O_EXCL waits for other opens on sg device to be closed before proceeding. If O_NONBLOCK is set then yields EBUSY when someone else has the sg device open. The combination of O_RDONLY and O_EXCL is disallowed. O_NONBLOCK Sets non-blocking mode. Calls that would otherwise block yield EAGAIN (eg read() ) or EBUSY (eg open() ). The original version of sg did not allow the O_RDONLY (yielding a EACCES error). This version allows it for accessing ioctls (e.g. doing an sg device scan with the SG_GET_SCSI_ID ioctl) but write()s will not be allowed. By default, sequencing is per file descriptor in this version of sg. This means, for example that 2 processes can independently manipulate the same sg device at the same time. This may or may not make sense depending on the application: 2 processes (logically) reading from the same direct access device (ie a disk) is ok while running 2 instances of cd writing software on the same device at the same time probably wouldn't be a good idea. The previous version of sg supported only per device sequencing and this can still be selected with the SG_SET_MERGE_FD,1 ioctl(). The driver will attempt to reserve SG_SCATTER_SZ bytes (32KBytes in the current sg.h) on open() for "emergency" situations. If this is unavailable it will halve its request and try again. It gives up if PAGE_SIZE bytes (4096 bytes on i386) cannot be obtained so no memory is reserved. In this case open() will still return successfully. The actual amount of memory reserved can be found with the SG_GET_RESERVED_SIZE ioctl(). Returns a file descriptor if >= 0 , otherwise -1 implies an error. Error codes (value in 'errno' after -1 returned): ENODEV sg not compiled into kernel or the kernel cannot find the sg module (or it can't initialize itself (low memory??)) ENXIO either scsi sub-system is currently processing some error (eg doing a device reset) or the sg driver/module removed or corrupted EBUSY O_NONBLOCK set and some user of this sg device has O_EXCL set while someone is already using this device EINTR while waiting for an "exclusive" lock to clear, a signal is received, just try again ... ENOMEM An attempt to get memory to store this open's context failed (this was _not_ a request to reserve DMA memory) EACCES An attempt to use both O_RDONLY and O_EXCL write ----- Even though sg is a character-based device driver it sends and receives packets to/from the associated scsi device. Write() is used to send a packet containing 2 mandatory parts and 1 optional part. The mandatory parts are: - a control block (an instance of struct sg_header) - a SCSI command (6, 10 or 12 bytes long) The optional part is: - outgoing data (eg if a SCSI write command is being sent) These should appear as one contiguous string in the buffer given to write() in the above order with no pad characters. If a write() accepts this packet then at some later time the user should call a read() to get the result of the SCSI command. The previous sg driver enforced a strict write()/read()/write()/read() regime so that a second write() would block until first read() was finished. This sg driver relaxes that condition and thereby allows command queuing (limit is SG_MAX_QUEUE (16) outstanding packets per file descriptor). However, for backward compatibility, command queuing is turned off by default (#define SG_DEF_COMMAND_Q 0 in sg.h). This can be changed via the the SG_SET_COMMAND_Q ioctl() [or by recompiling after changing the above define to 1]. In this sg driver a write() should return more or less immediately. Returns number of bytes written if > 0 , otherwise -1 implies an error. Error codes (value in 'errno' after -1 returned): ENXIO either scsi sub-system is currently processing some error (eg doing a device reset) or the sg driver/module removed or corrupted EACCES opened with RD_ONLY flag EIO incoming buffer too short. It should be at least (6 + sizeof(struct sg_header))==42 bytes long EDOM a) command queuing off: a packet is already queued b) command queuing on: too many packets queued (SG_MAX_QUEUE exceeded) EAGAIN SCSI mid-level out of command blocks (rare), try again. This is more likely to happen when queuing commands, so wait a bit (eg usleep(10000) ) before trying again ENOMEM can't get memory for DMA. Take evasive action ... (see section on memory) read ---- Read() is used to receive a packet containing 1 mandatory part and 1 optional part. The mandatory part is: - a control block (an instance of struct sg_header) The optional part is: - incoming data (eg if a SCSI read command was sent by earlier write() ) The buffer given to a read() and its corresponding count should be sufficient to accommodate this packet to avoid truncation. Truncation has occurred if count < sg_header::replylen . By default, read() will return the oldest packet queued up. If the SG_SET_FORCE_PACK_ID,1 ioctl() is active then read() will attempt to fetch the packet whose pack_id (given earlier to write()) matches the sg_header::pack_id given to this read(). If not available it will either wait or yield EAGAIN. As a special case, -1 in sg_header::pack_id given to read() will match the oldest packet. Returns number of bytes read if > 0 , otherwise -1 implies an error. Unfortunately the return value in the non-error case is simply the same as the count argument. It is not the actual number of bytes DMA-ed by the SCSI device. This driver is currently unable to provide such an underrun indication. Error codes (value in 'errno' after -1 returned): ENXIO either scsi sub-system is currently processing some error (eg doing a device reset) or the sg driver/module removed or corrupted EAGAIN either no waiting packet or requested packet is not available while O_NONBLOCK flag was set EINTR while waiting for a packet, a signal is received, just try again ... EIO if the 'count' given to read() is < sizeof(struct sg_header) and the 'result' element in sg_header is non-zero. Not a recommended error reporting technique close ----- Preferably a close() should be done after all issued write()s have had their corresponding read() calls completed. Unfortunately this is not always possible. The semantics of close() in Unix are to return more or less immediately (ie not wait on any event) so the driver needs to arrange to an orderly cleanup of those packets that are still "in flight". A process that has an open file descriptor to an sg device may be aborted (eg by a kill signal). In this case, the kernel automatically calls close (which is called 'sg_release()' in the version 2 driver) to facilitate the cleanup mentioned above. A problem persists in version 2.1.8 if the sg driver is a module and is removed while packets are still "in flight". Hopefully this will be soon fixed. Returns 0 if successful, otherwise -1 implies an error. Error codes (value in 'errno' after -1 returned): ENXIO sg driver/module removed or corrupted ioctl (sg specific) ------------------- Ken Thompson (or perhaps some other Unix luminary) described ioctl() as the "garbage bin of Unix". This driver compounds the situation by adding around 18 more commands. These commands either yield state information (10 of them), change the driver's characteristics (8 of them) or allow direct communication with the common SCSI mid-level driver. Those commands with an appended "+" are new in version 2. Those commands with an appended "W" are only accessible from file descriptors opened with O_RDWR. They will yield EACCES otherwise. SG_GET_TIMEOUT: Ignores its 3rd argument and _returns_ the timeout value (which will be >= 0 ). The unit of this timeout is "jiffies" which are currently 10 millisecond intervals on i386 (less on an alpha). Linux supplies a manifest constant HZ which is the number of "jiffies" in 1 second. SG_SET_TIMEOUT: Assumes 3rd argument points to an int containing the new timeout value for this file descriptor. The unit is a "jiffy". Packets that are already "in flight" will not be effected. The default value is set on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h). SG_EMULATED_HOST: Assumes 3rd argument points to an int and outputs a flag indicating whether the host (adapter) is connected to a real SCSI bus or is emulated one (eg ide-scsi device driver). A value of 1 means emulated while 0 is not. SG_SET_FORCE_LOW_DMA +: Assumes 3rd argument points to an int containing 0 or 1. 0 (default) means sg decides whether to use memory above 16 Mbyte level (on i386) based on the host adapter being used by this SCSI device. Typically PCI SCSI adapters will indicate they can DMA to the whole 32 bit address space. If 1 is given then the host adapter is overridden and only memory below the 16MB level is used for DMA. A requirement for this should be extremely rare. If the "reserve" buffer allocated on open() is not in use then it will be de-allocated and re-allocated under the 16MB level (and the latter operation could fail yielding ENOMEM). Only the current file descriptor is effected. SG_GET_LOW_DMA +: Assumes 3rd argument points to an int and places 0 or 1 in it. 0 indicates the whole 32 bit address space is being used for DMA transfers on this file descriptor. 1 indicates the memory below the 16MB level (on i386) is being used (and this may be the case because the host adapters setting has been overridden by SG_SET_FORCE_LOW_DMA,1 . SG_GET_SCSI_ID +: Assumes 3rd argument is pointing to an object of type Sg_scsi_id and populates it. That structure contains ints for host_no, channel, scsi_id, lun and scsi_type. Most of this information is available from other sources (eg SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER) but tends to be awkward to collect. SG_SET_FORCE_PACK_ID +: Assumes 3rd argument is pointing to an int. 0 (default) instructs read() to return the oldest (written) packet if multiple packets are waiting to be read (when command queuing is being used). 1 instructs read() to view the sg_header::pack_id as input and return the oldest packet matching that pack_id or wait until it arrives (or yield EAGAIN if O_NONBLOCK is in force). As a special case the pack_id of -1 given to read() in the mode will match the oldest packet. Only the current file descriptor is effected by this command. SG_GET_LOW_DMA +: Assumes 3rd argument points to an int and places the pack_id of the oldest (written) packet in it. If no packet is waiting to be read then yields -1. SG_GET_NUM_WAITING +: Assumes 3rd argument points to an int and places the number of packets waiting to be read in it. SG_GET_SG_TABLESIZE +: Assumes 3rd argument points to an int and places the maximum number of scatter gather elements supported by the host adapter. 0 indicates that the adapter does support scatter gather. SG_SET_RESERVED_SIZE +W: This is not currently implemented. It is intended for reserving either a large buffer or scatter gather list that will be available until the current file descriptor is closed. The requested amount of memory may not be available so SG_GET_RESERVED_SIZE should be used after this call to see how much was reserved. (EBUSY error possible) SG_GET_RESERVED_SIZE +: Assumes 3rd argument points to an int and places the size in bytes of the DMA buffer reserved on open() for emergencies. If this is 0 then it is probably not wise to attempt on operation like burning a CD on this file descriptor. SG_SET_MERGE_FD +W: Assumes 3rd argument is pointing to an int. 0 (the default) causes all subsequent sequencing to be per file descriptor. 1 causes all subsequent sequencing to be per device. If this command tries to change the current state and the is one or more _other_ file descriptors using this sg device then an EBUSY error occurs. Also if this file descriptor was not open()ed with the O_RDWR flag then an EACCES error occurs. Per device sequencing was the original semantics and allowed, for example different processes to "share" the device, one perhaps write()ing with the other one read()ing. This command is supplied if anyone needs those semantics. Per file descriptor sequencing, perhaps with the usage of the O_EXCL flag, seems more sensible. SG_GET_MERGE_FD +: Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies sequencing is per file descriptor. 1 implies sequencing is per device (original sg driver's semantics). SG_SET_COMMAND_Q +: Assumes 3rd argument is pointing to an int. 0 (current default, set by SG_DEF_COMMAND_Q in sg.h) disables command queuing. Attempts to write() a packet while one is already queued will result in a EDOM error. 1 turns command queuing on. Changing the queuing state only effects write()s done after the change. Only the current file descriptor is effected by this command. SG_GET_COMMAND_Q +: Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies that command queuing is off on this file descriptor. 1 implies command queuing is on. SG_SET_DEBUG +: Assumes 3rd argument is pointing to an int. 0 (default) turns debugging off. Values > 0 cause the SCSI sense buffer to be decoded and output to the console/log when a SCSI device error occurs. Values > 8 cause the current sg device driver's state to be output to the console/log (this is a "one off" effect). If you need a _lot_ of the SCSI sub-system debug information (mainly from the mid-level) then try 'echo "scsi dump 0" > /proc/scsi/scsi' and lots of debug will appear in your console/log. ioctl (in common with sd, st + sr) ---------------------------------- The following ioctl()s can be called from any high-level scsi device driver (ie sd, st, sr + sg). Access permissions may differ a bit from one device to another, the access information given below is specific to the sg device driver. SCSI_IOCTL_GET_IDLUN: SCSI_IOCTL_GET_BUS_NUMBER: SCSI_IOCTL_SEND_COMMAND: W If open()ed O_RDONLY yields an EACCESS error. Otherwise is forwarded onto the SCSI mid-level driver for processing. Don't know much about this one but it looks pretty powerful and dangerous. Some comments says it is also deprecated. : W If open()ed O_RDONLY yields an EACCESS error. Otherwise is forwarded onto the SCSI mid-level driver for processing. poll ---- This is a native call in Linux 2.2 but most of its capabilities are available through the older select() call. Given a choice poll() should probably be used. Typically poll() is used when a sg scsi device is open()ed O_NONBLOCK for polling; or alternatively with asynchronous notification using the fcntl() system call (below) and the SIGPOLL (aka SIGIO) signal. Only if something drastically is wrong (eg file handle gone stale) will POLLERR ever be set. POLLPRI, POLLHUP and POLLNVAL are never set. POLLIN is set when there is one or more packets waiting to be read. When POLLIN is set it implies that a read() will not block (or yield EAGAIN in non-blocking mode) but return a packet immediately. POLLOUT (aka POLLWRNORM) is set when write() is able to accept a packet (ie will _not_ yield an EDOM error). The setting of POLLOUT is effected by the SG_SET_COMMAND_Q state: if the state is on then POLLOUT will remain set until the number of queued packets reaches SG_MAX_QUEUE, if the state is off then POLLOUT is only set when no packets are queued. Note that a packet can be queued after write()ing but not available to be read(); this typically happens when a SCSI read command is issued while the data is being retreaved. Poll() is per file descriptor unless SG_SET_MERGE_FD is set in which case it is per device. fcntl ----- There are several uses for this system call in association with a sg file descriptor. The first pseudo code shows code that is useful for scanning the sg devices, taking care not to be caught in a wait for an O_EXCL lock by another process, and when the appropriate device is found switching to normal blocked io. A working example of this logic is in the sg_scan.c utility program. open("/dev/sga", O_RDONLY | O_NONBLOCK) /* check device, EBUSY means some other process has O_EXCL lock on it */ /* one the device you want is found then ... */ flags = fcntl(sg_fd, F_GETFL) fcntl(sg_fd, F_SETFL, flags & (~ O_NONBLOCK)) /* for simple apps is is easier to use normal blocked io */ Some work has to be done in Linux to set up for asynchronous notification. This is a non-blocking mode of operation in which when the driver receives data back from a device so that a read() can be done, it sends a SIGPOLL (aka SIGIO) signal to the owning process. A working example of this logic is in the sg_poll.c test program. sigemptyset(&sig_set) sigaddset(&sig_set, SIGPOLL) sigaction(SIGPOLL, &s_action, 0) fcntl(sg_fd, F_SETOWN, getpid()) flags = fcntl(sg_fd, F_GETFL); fcntl(sg_fd, F_SETFL, flags | O_ASYNC) Utility and Test Programs =========================