sane-project-website/old-archive/1999-08/0272.html

353 wiersze
13 KiB
HTML
Czysty Wina Historia

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

<!-- received="Sun Aug 22 12:58:29 1999 PDT" -->
<!-- sent="Sun, 22 Aug 1999 21:44:22 +0200" -->
<!-- name="abel deuring" -->
<!-- email="a.deuring@satzbau-gmbh.de" -->
<!-- subject="Re: SG_BIG_BUFF, glibc 2.1 weirdness ..." -->
<!-- id="" -->
<!-- inreplyto="SG_BIG_BUFF, glibc 2.1 weirdness ..." -->
<title>sane-devel: Re: SG_BIG_BUFF, glibc 2.1 weirdness ...</title>
<h1>Re: SG_BIG_BUFF, glibc 2.1 weirdness ...</h1>
<b>abel deuring</b> (<a href="mailto:a.deuring@satzbau-gmbh.de"><i>a.deuring@satzbau-gmbh.de</i></a>)<br>
<i>Sun, 22 Aug 1999 21:44:22 +0200</i>
<p>
<ul>
<li> <b>Messages sorted by:</b> <a href="date.html#272">[ date ]</a><a href="index.html#272">[ thread ]</a><a href="subject.html#272">[ subject ]</a><a href="author.html#272">[ author ]</a>
<!-- next="start" -->
<li> <b>Next message:</b> <a href="0273.html">Andreas Beck: "Re: net problem"</a>
<li> <b>Previous message:</b> <a href="0271.html">Cooper: "Machine lock-ups while scanning. HP scanjet 5P/BusLogic Flashpoint LT"</a>
<li> <b>Maybe in reply to:</b> <a href="0163.html">Petter Reinholdtsen: "SG_BIG_BUFF, glibc 2.1 weirdness ..."</a>
<!-- nextthread="start" -->
<li> <b>Next in thread:</b> <a href="0288.html">abel deuring: "Re: SG_BIG_BUFF, glibc 2.1 weirdness ..."</a>
<!-- reply="end" -->
</ul>
<!-- body="start" -->
Hi all!<br>
<p>
Andreas Beck wrote:<br>
<p>
<i>&gt; I'll take care for a graceful handling of the condition as well as support</i><br>
<i>&gt; for the new sg driver in 2.2.6 and up.</i><br>
<p>
Sorry for the delay with my response to Andreas' mail, but I was <br>
on holidays the last weeks.<br>
<p>
I have already made some work on the support for the new Linux <br>
SG driver in sanei_scsi.c, in order to use the capabilites of <br>
this driver to change its buffer size dynamically, and to enable <br>
low level command queueing.<br>
<p>
Some weeks ago, I already sent some patches on the same<br>
topic to this list, but they were not that reliable<br>
regarding the command queueing. Thanks to Douglas Gilbert,<br>
who helped me understanding several details of the SG driver<br>
and even modified an ioctl call, so that it is possible<br>
to read the queue depth of a SCSI adapter (or its low level<br>
driver).<br>
<p>
Two details of the modifications would need an improvement:<br>
<p>
1. It would be fine to have the buffer size user<br>
configurable. This could be done either with a configuration<br>
file, or with an environment variable.<br>
<p>
2. The new SG driver allocates a separate buffer for each<br>
file handle. This means, that a situation is possible, where<br>
the ioctl call to modify the buffer size is successful for<br>
one file handle, but it fails for another. This leads to an<br>
inconsistency with sanei_max_scsi_request_size. This<br>
inconsistency can only be avoided, if<br>
sanei_max_scsi_request_size would become an array, or if the<br>
buffer size would be stored in an additional field in<br>
fd_info. Since this would require modifications to most if<br>
not all backends, and since this inconsistency only occurs<br>
if a frontend tries to attach to two or more scanners at the<br>
same time - which none the existing frontends does - I left<br>
this inconsistency for now. It should of course be fixed, if<br>
these patches will be accepted.<br>
<p>
Abel<br>
<p>
--- sanei_scsi.c-orig Sat Jul 3 16:59:46 1999<br>
+++ sanei_scsi.c Sun Aug 22 20:02:22 1999<br>
@@ -194,6 +194,52 @@<br>
#endif<br>
<br>
int sanei_scsi_max_request_size = MAX_DATA;<br>
+#if USE == LINUX_INTERFACE<br>
+/* to following #defines follow Doug Gilbert's sample code<br>
+ to achieve run time compatibility with the old and the<br>
+ new SG driver for Linux<br>
+*/<br>
+#ifndef SG_SET_COMMAND_Q<br>
+#define SG_SET_COMMAND_Q 0x2271<br>
+#endif<br>
+#ifndef SG_SET_RESERVED_SIZE<br>
+#define SG_SET_RESERVED_SIZE 0x2275<br>
+#endif <br>
+#ifndef SG_GET_RESERVED_SIZE<br>
+#define SG_GET_RESERVED_SIZE 0x2272<br>
+#endif <br>
+#ifndef SG_GET_SCSI_ID<br>
+#define SG_GET_SCSI_ID 0x2276<br>
+#endif <br>
+#ifndef SG_GET_VERSION_NUM<br>
+#define SG_GET_VERSION_NUM 0x2282<br>
+#endif<br>
+<br>
+/* the struct returned by the SG ioctl call SG_GET_SCSI_ID changed<br>
+ from version 2.1.34 to 2.1.35, and we need the informations from<br>
+ version 2.1.35. To get this file compiling also with older versions <br>
+ of sg.h, the struct is re-defined here.<br>
+*/<br>
+typedef struct xsg_scsi_id {<br>
+ int host_no; /* as in "scsi&lt;n&gt;" where 'n' is one of 0, 1, 2<br>
etc */<br>
+ int channel;<br>
+ int scsi_id; /* scsi id of target device */<br>
+ int lun;<br>
+ int scsi_type; /* TYPE_... defined in scsi/scsi.h */<br>
+ short h_cmd_per_lun;/* host (adapter) maximum commands per lun */<br>
+ short d_queue_depth;/* device (or adapter) maximum queue length */<br>
+ int unused1; /* probably find a good use, set 0 for now */<br>
+ int unused2; /* ditto */<br>
+} SG_scsi_id;<br>
+<br>
+typedef struct Fdparms <br>
+ {<br>
+ int queue_used;<br>
+ int queue_max;<br>
+ }<br>
+fdparms;<br>
+<br>
+#endif<br>
<br>
#if USE == FREEBSD_CAM_INTERFACE<br>
# define CAM_MAXDEVS 128<br>
@@ -621,6 +667,7 @@<br>
sanei_scsi_max_request_size = atoi (buf);<br>
DBG (1, "sanei_scsi_open: sanei_scsi_max_request_size=%d bytes\n",<br>
sanei_scsi_max_request_size);<br>
+ close(fd);<br>
}<br>
}<br>
#endif<br>
@@ -913,6 +960,86 @@<br>
}<br>
}<br>
#endif /* SGIOCSTL */<br>
+#if USE == LINUX_INTERFACE<br>
+ {<br>
+ SG_scsi_id sid;<br>
+ int ioctl_val, sg_version;<br>
+ fdparms *fdpa = 0;<br>
+ <br>
+ /* check for the SG version. If the ioctl call is successful, <br>
+ we have the new SG driver, and we can increase the buffer size<br>
+ using another ioctl call. <br>
+ If we have version 21.35 or above, we can additionally enable<br>
+ command queueing.<br>
+ */<br>
+ if (0 == ioctl(fd, SG_GET_VERSION_NUM, &amp;sg_version))<br>
+ {<br>
+ DBG(1, "sanei_scsi_open: SG driver version: %i\n", ioctl_val);<br>
+<br>
+ /* try to reserve a bigger SG buffer. 128 kB should be OK<br>
+ for most situations.<br>
+ xxxxxxx<br>
+ NOTE: sanei_scsi_max_request_size is a global variable<br>
+ used for all devices/file handles, while the new<br>
+ SG driver allocates buffer memory for each opened<br>
+ file separately. Therefore, we have a possible <br>
+ inconsistency, if more than one file is opened and<br>
+ if the SG_SET_RESERVED_SIZE call fails for one<br>
+ of these calls. This needs to be cleaned up!!<br>
+ (ideas: check, if another file has already been<br>
+ opened; if so, check for matching values<br>
+ of SG_GET_RESERVED_SIZE. OTOH, this affects at <br>
+ present a very theoretical situtation, that a <br>
+ frontend accesses more than one scanner.<br>
+ <br>
+ A better solution would be to add a field to struct <br>
+ fd_parms which stores the actual buffer size for each<br>
+ file handle. But to use this requires modifications<br>
+ in many if not all backends....<br>
+ <br>
+ */<br>
+ ioctl_val = 128 * 1024;<br>
+ ioctl(fd, SG_SET_RESERVED_SIZE, &amp;ioctl_val);<br>
+<br>
+ if (0 == ioctl(fd, SG_GET_RESERVED_SIZE, &amp;ioctl_val)) <br>
+ sanei_scsi_max_request_size = ioctl_val;<br>
+ else<br>
+ DBG(1, "sanei_scsi_open: cannot read SG buffer size - %s\n", <br>
+ strerror(errno));<br>
+ DBG(1, "sanei_scsi_open: using %i bytes as SCSI buffer\n", <br>
+ sanei_scsi_max_request_size);<br>
+<br>
+ if (sg_version &gt;= 20135)<br>
+ {<br>
+ DBG(1, "trying to enable low level command queueing\n");<br>
+ <br>
+ if (0 == ioctl(fd, SG_GET_SCSI_ID, &amp;sid)) <br>
+ { <br>
+ DBG(1, "sanei_scsi_open: Host adapter queue depth:<br>
%i\n",<br>
+ sid.d_queue_depth);<br>
+ <br>
+ ioctl_val = 1;<br>
+ if(0 == ioctl(fd, SG_SET_COMMAND_Q, &amp;ioctl_val)) <br>
+ {<br>
+ pdata = fdpa = malloc(sizeof(fdparms));<br>
+ if (!pdata)<br>
+ {<br>
+ close(fd);<br>
+ return SANE_STATUS_NO_MEM;<br>
+ }<br>
+ <br>
+ fdpa-&gt;queue_used = 0;<br>
+ fdpa-&gt;queue_max = sid.d_queue_depth;<br>
+ if (fdpa-&gt;queue_max &lt;= 0)<br>
+ fdpa-&gt;queue_max = 1;<br>
+ }<br>
+ }<br>
+ }<br>
+ }<br>
+ if (fdpa)<br>
+ DBG(1, "sanei_scsi_open: low level command queueing enabled\n");<br>
+ }<br>
+#endif /* LINUX_INTERFACE */<br>
#endif /* !DECUNIX_INTERFACE */<br>
<br>
if (fd &gt;= num_alloced)<br>
@@ -967,6 +1094,10 @@<br>
if (!fd_info[fd].fake_fd)<br>
close (fd);<br>
<br>
+#if USE == LINUX_INTERFACE<br>
+ if (fd_info[fd].pdata) <br>
+ free(fd_info[fd].pdata);<br>
+#endif<br>
#if USE == FREEBSD_CAM_INTERFACE<br>
cam_close_device(cam_devices[fd]);<br>
cam_devices[fd] = NULL;<br>
@@ -1247,16 +1378,44 @@<br>
static void<br>
issue (struct req *req)<br>
{<br>
- ssize_t nwritten;<br>
+ ssize_t nwritten, count = 0;<br>
+ fdparms *fdp;<br>
<br>
if (!req || req-&gt;running)<br>
return;<br>
<br>
+ fdp = (fdparms*) fd_info[req-&gt;fd].pdata;<br>
DBG (4, "sanei_scsi.issue: %p\n", req);<br>
<br>
- ATOMIC (req-&gt;running = 1;<br>
- nwritten = write (req-&gt;fd, &amp;req-&gt;cdb, req-&gt;cdb.hdr.pack_len));<br>
-<br>
+ if (!fdp)<br>
+ {<br>
+ ATOMIC (req-&gt;running = 1;<br>
+ nwritten = write (req-&gt;fd, &amp;req-&gt;cdb,<br>
req-&gt;cdb.hdr.pack_len));<br>
+ }<br>
+ else <br>
+ {<br>
+ DBG(2, "sanei_scsi.issue: queue used: %i, queue max: %i\n", <br>
+ fdp-&gt;queue_used, fdp-&gt;queue_max);<br>
+ assert(fdp-&gt;queue_used &lt; fdp-&gt;queue_max);<br>
+ while (count &lt; 100) <br>
+ {<br>
+ ATOMIC (nwritten = write (req-&gt;fd, &amp;req-&gt;cdb,<br>
req-&gt;cdb.hdr.pack_len);<br>
+ if (nwritten !=req-&gt;cdb.hdr.pack_len <br>
+ &amp;&amp; errno == EAGAIN<br>
+ &amp;&amp; count &lt; 100)<br>
+ count++;<br>
+ else <br>
+ req-&gt;running = 1;<br>
+ );<br>
+ if (!req-&gt;running) <br>
+ {<br>
+ usleep(10000);<br>
+ DBG(2, "sanei_scsi.issue: write call returned EAGAIN\n");<br>
+ }<br>
+ else<br>
+ break;<br>
+ }<br>
+ }<br>
if (nwritten != req-&gt;cdb.hdr.pack_len)<br>
{<br>
DBG (1, "sanei_scsi.issue: bad write (errno=%s)\n",<br>
@@ -1271,6 +1430,9 @@<br>
else<br>
req-&gt;status = SANE_STATUS_IO_ERROR;<br>
}<br>
+ else <br>
+ if (fdp)<br>
+ fdp-&gt;queue_used++;<br>
}<br>
<br>
void<br>
@@ -1281,7 +1443,11 @@<br>
for (req = qhead; req; req = next_req)<br>
{<br>
if (req-&gt;running &amp;&amp; !req-&gt;done)<br>
- read (req-&gt;fd, &amp;req-&gt;cdb, req-&gt;cdb.hdr.reply_len);<br>
+ {<br>
+ read (req-&gt;fd, &amp;req-&gt;cdb, req-&gt;cdb.hdr.reply_len);<br>
+ if (fd_info[req-&gt;fd].pdata)<br>
+ ((fdparms*) fd_info[req-&gt;fd].pdata)-&gt;queue_used--;<br>
+ }<br>
next_req = req-&gt;next;<br>
<br>
req-&gt;next = free_list;<br>
@@ -1339,6 +1505,10 @@<br>
DBG (4, "scsi_req_enter: entered %p\n", req);<br>
<br>
*idp = req;<br>
+ if ( fd_info[fd].pdata<br>
+ &amp;&amp; ((fdparms*) fd_info[req-&gt;fd].pdata)-&gt;queue_used<br>
+ &lt; ((fdparms*) fd_info[req-&gt;fd].pdata)-&gt;queue_max)<br>
+ issue(req);<br>
return SANE_STATUS_GOOD;<br>
}<br>
<br>
@@ -1369,9 +1539,15 @@<br>
select (req-&gt;fd + 1, &amp;readable, 0, 0, 0);<br>
<br>
/* now atomically read result and set DONE: */<br>
+ DBG (4, "sanei_scsi_req_wait: reading...\n"); /* xxx */<br>
ATOMIC (nread = read (req-&gt;fd, &amp;req-&gt;cdb,<br>
req-&gt;cdb.hdr.reply_len);<br>
req-&gt;done = 1);<br>
+ DBG (4, "sanei_scsi_req_wait: reading ok\n"); /* xxx */<br>
+<br>
+ if (fd_info[req-&gt;fd].pdata)<br>
+ ((fdparms*) fd_info[req-&gt;fd].pdata)-&gt;queue_used--;<br>
<br>
+ DBG (4, "sanei_scsi_req_wait: reading ok2 %p\n", req-&gt;next); /*<br>
xxx */<br>
/* Now issue next command asap, if any. We can't do this<br>
earlier since the Linux kernel has space for just one big<br>
buffer. */<br>
<p>
<pre>
--
Source code, list archive, and docs: <a href="http://www.mostang.com/sane/">http://www.mostang.com/sane/</a>
To unsubscribe: echo unsubscribe sane-devel | mail <a href="mailto:majordomo@mostang.com">majordomo@mostang.com</a>
</pre>
<!-- body="end" -->
<p>
<ul>
<!-- next="start" -->
<li> <b>Next message:</b> <a href="0273.html">Andreas Beck: "Re: net problem"</a>
<li> <b>Previous message:</b> <a href="0271.html">Cooper: "Machine lock-ups while scanning. HP scanjet 5P/BusLogic Flashpoint LT"</a>
<li> <b>Maybe in reply to:</b> <a href="0163.html">Petter Reinholdtsen: "SG_BIG_BUFF, glibc 2.1 weirdness ..."</a>
<!-- nextthread="start" -->
<li> <b>Next in thread:</b> <a href="0288.html">abel deuring: "Re: SG_BIG_BUFF, glibc 2.1 weirdness ..."</a>
<!-- reply="end" -->
</ul>