kopia lustrzana https://gitlab.com/sane-project/website
353 wiersze
13 KiB
HTML
353 wiersze
13 KiB
HTML
<!-- 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>> I'll take care for a graceful handling of the condition as well as support</i><br>
|
||
<i>> 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<n>" 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, &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, &ioctl_val);<br>
|
||
+<br>
|
||
+ if (0 == ioctl(fd, SG_GET_RESERVED_SIZE, &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 >= 20135)<br>
|
||
+ {<br>
|
||
+ DBG(1, "trying to enable low level command queueing\n");<br>
|
||
+ <br>
|
||
+ if (0 == ioctl(fd, SG_GET_SCSI_ID, &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, &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->queue_used = 0;<br>
|
||
+ fdpa->queue_max = sid.d_queue_depth;<br>
|
||
+ if (fdpa->queue_max <= 0)<br>
|
||
+ fdpa->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 >= 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->running)<br>
|
||
return;<br>
|
||
<br>
|
||
+ fdp = (fdparms*) fd_info[req->fd].pdata;<br>
|
||
DBG (4, "sanei_scsi.issue: %p\n", req);<br>
|
||
<br>
|
||
- ATOMIC (req->running = 1;<br>
|
||
- nwritten = write (req->fd, &req->cdb, req->cdb.hdr.pack_len));<br>
|
||
-<br>
|
||
+ if (!fdp)<br>
|
||
+ {<br>
|
||
+ ATOMIC (req->running = 1;<br>
|
||
+ nwritten = write (req->fd, &req->cdb,<br>
|
||
req->cdb.hdr.pack_len));<br>
|
||
+ }<br>
|
||
+ else <br>
|
||
+ {<br>
|
||
+ DBG(2, "sanei_scsi.issue: queue used: %i, queue max: %i\n", <br>
|
||
+ fdp->queue_used, fdp->queue_max);<br>
|
||
+ assert(fdp->queue_used < fdp->queue_max);<br>
|
||
+ while (count < 100) <br>
|
||
+ {<br>
|
||
+ ATOMIC (nwritten = write (req->fd, &req->cdb,<br>
|
||
req->cdb.hdr.pack_len);<br>
|
||
+ if (nwritten !=req->cdb.hdr.pack_len <br>
|
||
+ && errno == EAGAIN<br>
|
||
+ && count < 100)<br>
|
||
+ count++;<br>
|
||
+ else <br>
|
||
+ req->running = 1;<br>
|
||
+ );<br>
|
||
+ if (!req->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->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->status = SANE_STATUS_IO_ERROR;<br>
|
||
}<br>
|
||
+ else <br>
|
||
+ if (fdp)<br>
|
||
+ fdp->queue_used++;<br>
|
||
}<br>
|
||
<br>
|
||
void<br>
|
||
@@ -1281,7 +1443,11 @@<br>
|
||
for (req = qhead; req; req = next_req)<br>
|
||
{<br>
|
||
if (req->running && !req->done)<br>
|
||
- read (req->fd, &req->cdb, req->cdb.hdr.reply_len);<br>
|
||
+ {<br>
|
||
+ read (req->fd, &req->cdb, req->cdb.hdr.reply_len);<br>
|
||
+ if (fd_info[req->fd].pdata)<br>
|
||
+ ((fdparms*) fd_info[req->fd].pdata)->queue_used--;<br>
|
||
+ }<br>
|
||
next_req = req->next;<br>
|
||
<br>
|
||
req->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>
|
||
+ && ((fdparms*) fd_info[req->fd].pdata)->queue_used<br>
|
||
+ < ((fdparms*) fd_info[req->fd].pdata)->queue_max)<br>
|
||
+ issue(req);<br>
|
||
return SANE_STATUS_GOOD;<br>
|
||
}<br>
|
||
<br>
|
||
@@ -1369,9 +1539,15 @@<br>
|
||
select (req->fd + 1, &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->fd, &req->cdb,<br>
|
||
req->cdb.hdr.reply_len);<br>
|
||
req->done = 1);<br>
|
||
+ DBG (4, "sanei_scsi_req_wait: reading ok\n"); /* xxx */<br>
|
||
+<br>
|
||
+ if (fd_info[req->fd].pdata)<br>
|
||
+ ((fdparms*) fd_info[req->fd].pdata)->queue_used--;<br>
|
||
<br>
|
||
+ DBG (4, "sanei_scsi_req_wait: reading ok2 %p\n", req->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>
|