kopia lustrzana https://gitlab.com/sane-project/website
694 wiersze
24 KiB
HTML
694 wiersze
24 KiB
HTML
<!-- received="Fri Oct 29 12:00:15 1999 PDT" -->
|
||
<!-- sent="Fri, 29 Oct 1999 20:56:45 +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>Fri, 29 Oct 1999 20:56:45 +0200</i>
|
||
<p>
|
||
<ul>
|
||
<li> <b>Messages sorted by:</b> <a href="date.html#228">[ date ]</a><a href="index.html#228">[ thread ]</a><a href="subject.html#228">[ subject ]</a><a href="author.html#228">[ author ]</a>
|
||
<!-- next="start" -->
|
||
<li> <b>Next message:</b> <a href="0229.html">abel deuring: "Re: Mustek ScanExpress 6000SP"</a>
|
||
<li> <b>Previous message:</b> <a href="0227.html">Levente NOVAK: "Re: xsane-0.41"</a>
|
||
<!-- nextthread="start" -->
|
||
<!-- reply="end" -->
|
||
</ul>
|
||
<!-- body="start" -->
|
||
Dies ist eine mehrteilige Nachricht im MIME-Format.<br>
|
||
--------------5D2267F9E78A0A1B29D131D6<br>
|
||
Content-Type: text/plain; charset=us-ascii<br>
|
||
Content-Transfer-Encoding: 7bit<br>
|
||
<p>
|
||
abel deuring wrote:<br>
|
||
<p>
|
||
<i>> At the end of the mail are some modifications to sanei_scsi.c to</i><br>
|
||
<i>> get a "better cooperation" with the new Linux SG driver.</i><br>
|
||
<p>
|
||
As Ricardo Ferreira discovered, the patches got a little bit damaged, so<br>
|
||
here they are again (hopefully better useable...)<br>
|
||
<p>
|
||
Abel<br>
|
||
--------------5D2267F9E78A0A1B29D131D6<br>
|
||
Content-Type: text/plain; charset=us-ascii; name="sanei_scsi-diff-sg2.1.34"<br>
|
||
Content-Transfer-Encoding: 7bit<br>
|
||
Content-Disposition: inline; filename="sanei_scsi-diff-sg2.1.34"<br>
|
||
<p>
|
||
--- sane-1.0.1-orig/sanei/sanei_scsi.c Sat Apr 17 22:18:18 1999<br>
|
||
+++ sane-1.0.1/sanei/sanei_scsi.c Thu Oct 28 22:10:21 1999<br>
|
||
@@ -194,6 +194,76 @@<br>
|
||
#endif<br>
|
||
<br>
|
||
int sanei_scsi_max_request_size = MAX_DATA;<br>
|
||
+#if USE == LINUX_INTERFACE<br>
|
||
+/* the following #defines follow Douglas Gilbert's sample code<br>
|
||
+ to maintain 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>
|
||
+#ifndef SCSIBUFFERSIZE<br>
|
||
+#define SCSIBUFFERSIZE (128 * 1024)<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>
|
||
+ the field s_queue_depth, which was introduced in 2.1.35.<br>
|
||
+ To get this file compiling also with older versions of sg.h, the <br>
|
||
+ 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 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 req<br>
|
||
+ {<br>
|
||
+ struct req *next;<br>
|
||
+ int fd;<br>
|
||
+ u_int running:1, done:1;<br>
|
||
+ SANE_Status status;<br>
|
||
+ size_t *dst_len;<br>
|
||
+ void *dst;<br>
|
||
+ struct<br>
|
||
+ {<br>
|
||
+ struct sg_header hdr;<br>
|
||
+ /* Make sure this is the last element, the real size is<br>
|
||
+ SG_BIG_BUFF and machine dependant */<br>
|
||
+ u_int8_t data[1];<br>
|
||
+ }<br>
|
||
+ cdb;<br>
|
||
+ }<br>
|
||
+req;<br>
|
||
+<br>
|
||
+typedef struct Fdparms <br>
|
||
+ {<br>
|
||
+ int sg_queue_used, sg_queue_max;<br>
|
||
+ req *sane_qhead, *sane_qtail, *sane_free_list;<br>
|
||
+ }<br>
|
||
+fdparms;<br>
|
||
+<br>
|
||
+#endif<br>
|
||
<br>
|
||
#if USE == FREEBSD_CAM_INTERFACE<br>
|
||
# define CAM_MAXDEVS 128<br>
|
||
@@ -590,12 +660,25 @@<br>
|
||
<br>
|
||
#endif /* USE_OS2_INTERFACE */<br>
|
||
<br>
|
||
+static int num_alloced = 0;<br>
|
||
+<br>
|
||
+#if USE == LINUX_INTERFACE<br>
|
||
+<br>
|
||
+SANE_Status<br>
|
||
+sanei_scsi_open_extended (const char *dev, int *fdp,<br>
|
||
+ SANEI_SCSI_Sense_Handler handler, <br>
|
||
+ void *handler_arg, int *buffersize)<br>
|
||
+<br>
|
||
+#else<br>
|
||
+<br>
|
||
SANE_Status<br>
|
||
sanei_scsi_open (const char *dev, int *fdp,<br>
|
||
SANEI_SCSI_Sense_Handler handler, void *handler_arg)<br>
|
||
+<br>
|
||
+#endif<br>
|
||
+<br>
|
||
{<br>
|
||
u_int bus = 0, target = 0, lun = 0, fake_fd = 0;<br>
|
||
- static int num_alloced = 0;<br>
|
||
char *real_dev = 0;<br>
|
||
void *pdata = 0;<br>
|
||
int fd;<br>
|
||
@@ -621,6 +704,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 +997,109 @@<br>
|
||
}<br>
|
||
}<br>
|
||
#endif /* SGIOCSTL */<br>
|
||
+#if USE == LINUX_INTERFACE<br>
|
||
+ {<br>
|
||
+ SG_scsi_id sid;<br>
|
||
+ int ioctl_val, sg_version;<br>
|
||
+ int real_buffersize;<br>
|
||
+ fdparms *fdpa = 0;<br>
|
||
+ <br>
|
||
+ pdata = fdpa = malloc(sizeof(fdparms));<br>
|
||
+ if (!pdata)<br>
|
||
+ {<br>
|
||
+ close(fd);<br>
|
||
+ return SANE_STATUS_NO_MEM;<br>
|
||
+ }<br>
|
||
+ memset(fdpa, 0, sizeof(fdparms));<br>
|
||
+ /* default: allow only one command to be sent to the SG driver <br>
|
||
+ */<br>
|
||
+ fdpa->sg_queue_max = 1;<br>
|
||
+<br>
|
||
+ /* Try to read 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 SG version 2.1.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", sg_version);<br>
|
||
+<br>
|
||
+ /* try to reserve a SG buffer of the size specified by *buffersize<br>
|
||
+ */<br>
|
||
+ ioctl(fd, SG_SET_RESERVED_SIZE, buffersize);<br>
|
||
+<br>
|
||
+ /* the set call may not be able to allocate as much memory<br>
|
||
+ as requested, thus we read the actual buffer size.<br>
|
||
+<br>
|
||
+ NOTE: sanei_scsi_max_request_size is a global variable<br>
|
||
+ used for all devices/file handles, while version 2.0 and <br>
|
||
+ above of the SG driver allocate buffer memory for each <br>
|
||
+ opened file separately. Therefore, we have a possible <br>
|
||
+ inconsistency, if more than one file is opened and<br>
|
||
+ if the SG_GET_RESERVED_SIZE return different buffer sizes<br>
|
||
+ for different file handles. (See Douglas Gilbert's<br>
|
||
+ description of the SG driver for details:<br>
|
||
+ <a href="http://www.torque.net/sg/p/scsi-generic_long.txt">http://www.torque.net/sg/p/scsi-generic_long.txt</a>)<br>
|
||
+ <br>
|
||
+ For this reason, sanei_scsi_open does not allow to open <br>
|
||
+ two or more file handles simultaneously.<br>
|
||
+ */<br>
|
||
+ if (0 == ioctl(fd, SG_GET_RESERVED_SIZE, &real_buffersize))<br>
|
||
+ {<br>
|
||
+ /* if we got more memory than requested, we stick with<br>
|
||
+ with the requested value, in order to allow<br>
|
||
+ sanei_scsi_open to check the buffer size exactly.<br>
|
||
+ */<br>
|
||
+ if (real_buffersize > *buffersize)<br>
|
||
+ {<br>
|
||
+ sanei_scsi_max_request_size = *buffersize;<br>
|
||
+ }<br>
|
||
+ else<br>
|
||
+ {<br>
|
||
+ sanei_scsi_max_request_size = real_buffersize;<br>
|
||
+ *buffersize = real_buffersize;<br>
|
||
+ }<br>
|
||
+ }<br>
|
||
+ else <br>
|
||
+ {<br>
|
||
+ DBG(1, "sanei_scsi_open: cannot read SG buffer size - %s\n", <br>
|
||
+ strerror(errno));<br>
|
||
+ close(fd);<br>
|
||
+ return SANE_STATUS_NO_MEM;<br>
|
||
+ }<br>
|
||
+ DBG(1, "sanei_scsi_open_extended: 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: %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>
|
||
+ fdpa->sg_queue_max = sid.d_queue_depth;<br>
|
||
+ if (fdpa->sg_queue_max <= 0)<br>
|
||
+ fdpa->sg_queue_max = 1;<br>
|
||
+ }<br>
|
||
+ }<br>
|
||
+ }<br>
|
||
+ }<br>
|
||
+ else<br>
|
||
+ {<br>
|
||
+ /* we have the old SG driver: */<br>
|
||
+ if (sanei_scsi_max_request_size < *buffersize)<br>
|
||
+ *buffersize = sanei_scsi_max_request_size;<br>
|
||
+ }<br>
|
||
+ if (fdpa->sg_queue_max > 1)<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>
|
||
@@ -958,9 +1145,78 @@<br>
|
||
return SANE_STATUS_GOOD;<br>
|
||
}<br>
|
||
<br>
|
||
+#if USE == LINUX_INTERFACE<br>
|
||
+/* The "wrapper" for the old open call */<br>
|
||
+SANE_Status<br>
|
||
+sanei_scsi_open (const char *dev, int *fdp,<br>
|
||
+ SANEI_SCSI_Sense_Handler handler, void *handler_arg)<br>
|
||
+{<br>
|
||
+ int i, j = 0;<br>
|
||
+ int wanted_buffersize = SCSIBUFFERSIZE, real_buffersize;<br>
|
||
+ SANE_Status res;<br>
|
||
+ char *cc, *cc1;<br>
|
||
+<br>
|
||
+ cc = getenv("SANE_SG_BUFFERSIZE");<br>
|
||
+ if (cc)<br>
|
||
+ {<br>
|
||
+ i = strtol(cc, &cc1, 10);<br>
|
||
+ if (cc != cc1 && i >= 32768)<br>
|
||
+ wanted_buffersize = i;<br>
|
||
+ }<br>
|
||
+<br>
|
||
+ real_buffersize = wanted_buffersize;<br>
|
||
+ res = sanei_scsi_open_extended(dev, fdp, handler, handler_arg, <br>
|
||
+ &real_buffersize);<br>
|
||
+<br>
|
||
+ /* make sure that we got as much memory as we wanted, otherwise<br>
|
||
+ the backend might be confused<br>
|
||
+ */<br>
|
||
+ if (real_buffersize != wanted_buffersize)<br>
|
||
+ {<br>
|
||
+ DBG(1, "sanei_scsi_open: could not allocate SG buffer memory "<br>
|
||
+ "wanted: %i got: %i\n", wanted_buffersize, real_buffersize);<br>
|
||
+ sanei_scsi_close(*fdp);<br>
|
||
+ return SANE_STATUS_NO_MEM;<br>
|
||
+ }<br>
|
||
+<br>
|
||
+ return res;<br>
|
||
+}<br>
|
||
+#else<br>
|
||
+/* dummy for the proposed new open call */<br>
|
||
+sanei_scsi_open_extended (const char *dev, int *fdp,<br>
|
||
+ SANEI_SCSI_Sense_Handler handler, <br>
|
||
+ void *handler_arg, int *buffersize)<br>
|
||
+{<br>
|
||
+ SANE_Status res;<br>
|
||
+ res = sanei_scsi_open(dev, fdp, handler, handler_arg);<br>
|
||
+ if (sanei_scsi_max_request_size < *buffersize)<br>
|
||
+ *buffersize = sanei_scsi_max_request_size;<br>
|
||
+ return res;<br>
|
||
+}<br>
|
||
+#endif<br>
|
||
+<br>
|
||
void<br>
|
||
sanei_scsi_close (int fd)<br>
|
||
{<br>
|
||
+#if USE == LINUX_INTERFACE<br>
|
||
+ if (fd_info[fd].pdata) <br>
|
||
+ {<br>
|
||
+ req *req, *next_req;<br>
|
||
+ <br>
|
||
+ /* make sure that there are no pending SCSI calls */<br>
|
||
+ sanei_scsi_req_flush_all_extended(fd);<br>
|
||
+<br>
|
||
+ req = ((fdparms*) fd_info[fd].pdata)->sane_free_list;<br>
|
||
+ while (req) <br>
|
||
+ {<br>
|
||
+ next_req = req->next;<br>
|
||
+ free(req);<br>
|
||
+ req = next_req;<br>
|
||
+ }<br>
|
||
+ free(fd_info[fd].pdata);<br>
|
||
+ }<br>
|
||
+#endif<br>
|
||
+<br>
|
||
fd_info[fd].in_use = 0;<br>
|
||
fd_info[fd].sense_handler = 0;<br>
|
||
fd_info[fd].sense_handler_arg = 0;<br>
|
||
@@ -1225,69 +1481,133 @@<br>
|
||
} \<br>
|
||
while (0)<br>
|
||
<br>
|
||
-static struct req<br>
|
||
- {<br>
|
||
- struct req *next;<br>
|
||
- int fd;<br>
|
||
- u_int running:1, done:1;<br>
|
||
- SANE_Status status;<br>
|
||
- size_t *dst_len;<br>
|
||
- void *dst;<br>
|
||
- struct<br>
|
||
- {<br>
|
||
- struct sg_header hdr;<br>
|
||
- /* Make sure this is the last element, the real size is<br>
|
||
- SG_BIG_BUFF and machine dependant */<br>
|
||
- u_int8_t data[1];<br>
|
||
- }<br>
|
||
- cdb;<br>
|
||
- }<br>
|
||
-*qhead, *qtail, *free_list;<br>
|
||
-<br>
|
||
static void<br>
|
||
issue (struct req *req)<br>
|
||
{<br>
|
||
ssize_t nwritten;<br>
|
||
+ fdparms *fdp;<br>
|
||
+ struct req *rp;<br>
|
||
+ int retries;<br>
|
||
<br>
|
||
- if (!req || req->running)<br>
|
||
+ if (!req)<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 (nwritten != req->cdb.hdr.pack_len)<br>
|
||
- {<br>
|
||
- DBG (1, "sanei_scsi.issue: bad write (errno=%s)\n",<br>
|
||
- strerror (errno));<br>
|
||
- req->done = 1;<br>
|
||
- if (errno == ENOMEM)<br>
|
||
- {<br>
|
||
- DBG (1, "sanei_scsi.issue: SG_BIG_BUF inconsistency? "<br>
|
||
- "Check file PROBLEMS.\n");<br>
|
||
- req->status = SANE_STATUS_NO_MEM;<br>
|
||
- }<br>
|
||
+ rp = fdp->sane_qhead;<br>
|
||
+ while (rp && rp->running)<br>
|
||
+ rp = rp->next;<br>
|
||
+<br>
|
||
+ while (rp && fdp->sg_queue_used < fdp->sg_queue_max)<br>
|
||
+ {<br>
|
||
+ retries = 20;<br>
|
||
+ while (retries)<br>
|
||
+ {<br>
|
||
+ ATOMIC (rp->running = 1;<br>
|
||
+ nwritten = write (rp->fd, &rp->cdb, rp->cdb.hdr.pack_len);<br>
|
||
+ if (nwritten != rp->cdb.hdr.pack_len)<br>
|
||
+ {<br>
|
||
+ /* ENOMEM can easily happen, if both command queueing<br>
|
||
+ inside the SG driver and large buffers are used.<br>
|
||
+ Therefore, if ENOMEM does not occur for the first <br>
|
||
+ command in the queue, we can simply try to issue<br>
|
||
+ it later again.<br>
|
||
+ */<br>
|
||
+ if ( errno == EAGAIN <br>
|
||
+ || (errno == ENOMEM && rp != fdp->sane_qhead))<br>
|
||
+ {<br>
|
||
+ /* don't try to send the data again, but<br>
|
||
+ wait for the next call to issue()<br>
|
||
+ */<br>
|
||
+ rp->running = 0;<br>
|
||
+ }<br>
|
||
+ }<br>
|
||
+ );<br>
|
||
+ if (rp == fdp->sane_qhead && errno == EAGAIN)<br>
|
||
+ {<br>
|
||
+ retries--;<br>
|
||
+ usleep(10000);<br>
|
||
+ }<br>
|
||
+ else<br>
|
||
+ retries = 0;<br>
|
||
+ }<br>
|
||
+<br>
|
||
+ if (nwritten != rp->cdb.hdr.pack_len)<br>
|
||
+ {<br>
|
||
+ if (rp->running)<br>
|
||
+ {<br>
|
||
+ DBG (1, "sanei_scsi.issue: bad write (errno=%s)\n",<br>
|
||
+ strerror (errno));<br>
|
||
+ rp->done = 1;<br>
|
||
+ if (errno == ENOMEM)<br>
|
||
+ {<br>
|
||
+ DBG (1, "sanei_scsi.issue: SG_BIG_BUF inconsistency? "<br>
|
||
+ "Check file PROBLEMS.\n");<br>
|
||
+ rp->status = SANE_STATUS_NO_MEM;<br>
|
||
+ }<br>
|
||
+ else<br>
|
||
+ rp->status = SANE_STATUS_IO_ERROR;<br>
|
||
+ }<br>
|
||
+ else<br>
|
||
+ {<br>
|
||
+ if (errno == ENOMEM)<br>
|
||
+ DBG(1, "issue: ENOMEM - cannot queue SCSI command. "<br>
|
||
+ "Trying again later.\n");<br>
|
||
+ else<br>
|
||
+ DBG(1, "issue: cannot queue SCSI command. "<br>
|
||
+ "Trying again later.\n");<br>
|
||
+ }<br>
|
||
+ break; /* in case of an error don't try to queue more commands */<br>
|
||
+ }<br>
|
||
else<br>
|
||
- req->status = SANE_STATUS_IO_ERROR;<br>
|
||
+ fdp->sg_queue_used++;<br>
|
||
+ rp = rp->next;<br>
|
||
}<br>
|
||
}<br>
|
||
<br>
|
||
void<br>
|
||
-sanei_scsi_req_flush_all (void)<br>
|
||
+sanei_scsi_req_flush_all_extended (int fd)<br>
|
||
{<br>
|
||
+ fdparms *fdp;<br>
|
||
struct req *req, *next_req;<br>
|
||
<br>
|
||
- for (req = qhead; req; req = next_req)<br>
|
||
+ fdp = (fdparms*) fd_info[fd].pdata;<br>
|
||
+ for (req = fdp->sane_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 (fd, &req->cdb, req->cdb.hdr.reply_len);<br>
|
||
+ ((fdparms*) fd_info[req->fd].pdata)->sg_queue_used--;<br>
|
||
+ }<br>
|
||
next_req = req->next;<br>
|
||
<br>
|
||
- req->next = free_list;<br>
|
||
- free_list = req;<br>
|
||
+ req->next = fdp->sane_free_list;<br>
|
||
+ fdp->sane_free_list = req;<br>
|
||
}<br>
|
||
- qhead = qtail = 0;<br>
|
||
+ fdp->sane_qhead = fdp->sane_qtail = 0;<br>
|
||
+}<br>
|
||
+<br>
|
||
+void<br>
|
||
+sanei_scsi_req_flush_all ()<br>
|
||
+{<br>
|
||
+ int fd, i, j = 0;<br>
|
||
+ <br>
|
||
+ /* sanei_scsi_open allows only one open file handle, so we<br>
|
||
+ can simply look for the first entry where in_use is set<br>
|
||
+ */<br>
|
||
+ +<br>
|
||
+ fd = num_alloced;<br>
|
||
+ for (i = 0; i < num_alloced; i++)<br>
|
||
+ if (fd_info[i].in_use)<br>
|
||
+ {<br>
|
||
+ j++;<br>
|
||
+ fd = i;<br>
|
||
+ }<br>
|
||
+ <br>
|
||
+ assert(j < 2);<br>
|
||
+ <br>
|
||
+ if (fd < num_alloced)<br>
|
||
+ sanei_scsi_req_flush_all_extended(fd);<br>
|
||
}<br>
|
||
<br>
|
||
SANE_Status<br>
|
||
@@ -1296,11 +1616,14 @@<br>
|
||
{<br>
|
||
struct req *req;<br>
|
||
size_t size;<br>
|
||
+ fdparms *fdp;<br>
|
||
+<br>
|
||
+ fdp = (fdparms*) fd_info[fd].pdata;<br>
|
||
<br>
|
||
- if (free_list)<br>
|
||
+ if (fdp->sane_free_list)<br>
|
||
{<br>
|
||
- req = free_list;<br>
|
||
- free_list = req->next;<br>
|
||
+ req = fdp->sane_free_list;<br>
|
||
+ fdp->sane_free_list = req->next;<br>
|
||
req->next = 0;<br>
|
||
}<br>
|
||
else<br>
|
||
@@ -1328,17 +1651,23 @@<br>
|
||
memcpy (&req->cdb.data, src, src_size);<br>
|
||
<br>
|
||
req->next = 0;<br>
|
||
- ATOMIC (if (qtail)<br>
|
||
+ ATOMIC (if (fdp->sane_qtail)<br>
|
||
{<br>
|
||
- qtail->next = req;<br>
|
||
- qtail = req;<br>
|
||
+ fdp->sane_qtail->next = req;<br>
|
||
+ fdp->sane_qtail = req;<br>
|
||
}<br>
|
||
else<br>
|
||
- qhead = qtail = req);<br>
|
||
+ fdp->sane_qhead = fdp->sane_qtail = req);<br>
|
||
<br>
|
||
DBG (4, "scsi_req_enter: entered %p\n", req);<br>
|
||
<br>
|
||
*idp = req;<br>
|
||
+ issue(req);<br>
|
||
+<br>
|
||
+ DBG(10, "scsi_req_enter: queue_used: %i, queue_max: %i\n",<br>
|
||
+ ((fdparms*) fd_info[fd].pdata)->sg_queue_used,<br>
|
||
+ ((fdparms*) fd_info[fd].pdata)->sg_queue_max);<br>
|
||
+<br>
|
||
return SANE_STATUS_GOOD;<br>
|
||
}<br>
|
||
<br>
|
||
@@ -1349,7 +1678,8 @@<br>
|
||
struct req *req = id;<br>
|
||
ssize_t nread = 0;<br>
|
||
<br>
|
||
- assert (req == qhead); /* we don't support out-of-order completion */<br>
|
||
+ /* we don't support out-of-order completion */<br>
|
||
+ assert (req == ((fdparms*)fd_info[req->fd].pdata)->sane_qhead);<br>
|
||
<br>
|
||
DBG (4, "sanei_scsi_req_wait: waiting for %p\n", req);<br>
|
||
<br>
|
||
@@ -1372,6 +1702,9 @@<br>
|
||
ATOMIC (nread = read (req->fd, &req->cdb, req->cdb.hdr.reply_len);<br>
|
||
req->done = 1);<br>
|
||
<br>
|
||
+ if (fd_info[req->fd].pdata)<br>
|
||
+ ((fdparms*) fd_info[req->fd].pdata)->sg_queue_used--;<br>
|
||
+<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>
|
||
@@ -1423,11 +1756,12 @@<br>
|
||
}<br>
|
||
<br>
|
||
/* dequeue and release processed request: */<br>
|
||
- ATOMIC (qhead = qhead->next;<br>
|
||
- if (!qhead)<br>
|
||
- qtail = 0;<br>
|
||
- req->next = free_list;<br>
|
||
- free_list = req);<br>
|
||
+ ATOMIC (((fdparms*) fd_info[req->fd].pdata)->sane_qhead <br>
|
||
+ = ((fdparms*) fd_info[req->fd].pdata)->sane_qhead->next;<br>
|
||
+ if (!((fdparms*) fd_info[req->fd].pdata)->sane_qhead)<br>
|
||
+ ((fdparms*) fd_info[req->fd].pdata)->sane_qtail = 0;<br>
|
||
+ req->next = ((fdparms*) fd_info[req->fd].pdata)->sane_free_list;<br>
|
||
+ ((fdparms*) fd_info[req->fd].pdata)->sane_free_list = req);<br>
|
||
return status;<br>
|
||
}<br>
|
||
<br>
|
||
--- sane-1.0.1-orig/include/sane/sanei_scsi.h Thu May 14 08:08:22 1998<br>
|
||
+++ sane-1.0.1/include/sane/sanei_scsi.h Sat Sep 25 18:25:24 1999<br>
|
||
@@ -48,6 +48,31 @@<br>
|
||
SANEI_SCSI_Sense_Handler sense_handler,<br>
|
||
void *sense_arg);<br>
|
||
<br>
|
||
+/* The extended open call allows a backend to ask for a specific<br>
|
||
+ buffer size. sanei_scsi_open tries to allocate a buffer of the<br>
|
||
+ size given by *buffersize upon entry to this function. If<br>
|
||
+ sanei_scsi_open_extended returns successfully, *buffersize<br>
|
||
+ contains the available buffer size. This value may be both<br>
|
||
+ smaller or larger than the value requested by the backend;<br>
|
||
+ it can even be zero. The backend must decide, if it got enough<br>
|
||
+ buffer memory to work.<br>
|
||
+ <br>
|
||
+ Note that the value of *buffersize may differ for different<br>
|
||
+ files.<br>
|
||
+*/<br>
|
||
+extern SANE_Status sanei_scsi_open_extended (<br>
|
||
+ const char * device_name, int * fd,<br>
|
||
+ SANEI_SCSI_Sense_Handler sense_handler, <br>
|
||
+ void *sense_arg, int *buffersize);<br>
|
||
+<br>
|
||
+/* Let backends decide, which open call to use: <br>
|
||
+ if HAVE_SANEI_SCSI_OPEN_EXTENDED is defined, sanei_scsi_open_extended<br>
|
||
+ may be used.<br>
|
||
+ May also be used to decide, if sanei_scsi_req_flush_all or<br>
|
||
+ sanei_scsi_req_flush_all_extended should be used.<br>
|
||
+*/<br>
|
||
+#define HAVE_SANEI_SCSI_OPEN_EXTENDED<br>
|
||
+<br>
|
||
/* One or more scsi commands can be enqueued by calling req_enter().<br>
|
||
SRC is the pointer to the SCSI command and associated write data<br>
|
||
and SRC_SIZE is the length of the command and data. DST is a<br>
|
||
@@ -76,8 +101,13 @@<br>
|
||
const void * src, size_t src_size,<br>
|
||
void * dst, size_t * dst_size);<br>
|
||
<br>
|
||
-/* Flush all pending SCSI commands. */<br>
|
||
+/* Flush all pending SCSI commands. This function work only,<br>
|
||
+ if zero or one SCSI file handles are open.<br>
|
||
+*/<br>
|
||
extern void sanei_scsi_req_flush_all (void);<br>
|
||
+<br>
|
||
+/* Flush all SCSI commands pending for one handle */<br>
|
||
+extern void sanei_scsi_req_flush_all_extended (int fd);<br>
|
||
<br>
|
||
extern void sanei_scsi_close (int fd);<br>
|
||
<br>
|
||
--- sane-1.0.1-orig/configure.in Sun Apr 4 00:44:56 1999<br>
|
||
+++ sane-1.0.1/configure.in Mon Sep 20 20:41:44 1999<br>
|
||
@@ -192,10 +192,19 @@<br>
|
||
else<br>
|
||
DLL_PRELOAD=""<br>
|
||
fi<br>
|
||
+<br>
|
||
+AC_ARG_ENABLE(scsibuffersize, <br>
|
||
+ [ --enable-scsibuffersize=N <br>
|
||
+ specify the default size of the buffer for SCSI commands],<br>
|
||
+ [set_scsibuffersize="$enableval"], [set_scsibuffersize=131072])<br>
|
||
+CFLAGS="$CFLAGS -DSCSIBUFFERSIZE=$set_scsibuffersize"<br>
|
||
+echo "scsi buffersize: $set_scsibuffersize"<br>
|
||
+<br>
|
||
AC_SUBST(V_MAJOR)<br>
|
||
AC_SUBST(V_MINOR)<br>
|
||
AC_SUBST(V_REV)<br>
|
||
AC_SUBST(DLL_PRELOAD)<br>
|
||
+<br>
|
||
<br>
|
||
AC_OUTPUT([Makefile lib/Makefile sanei/Makefile frontend/Makefile<br>
|
||
japi/Makefile backend/Makefile include/Makefile doc/Makefile<br>
|
||
<p>
|
||
<p>
|
||
--------------5D2267F9E78A0A1B29D131D6--<br>
|
||
<p>
|
||
<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="0229.html">abel deuring: "Re: Mustek ScanExpress 6000SP"</a>
|
||
<li> <b>Previous message:</b> <a href="0227.html">Levente NOVAK: "Re: xsane-0.41"</a>
|
||
<!-- nextthread="start" -->
|
||
<!-- reply="end" -->
|
||
</ul>
|