1 /**
2    Copyright (C) 2001-2012 Stéphane Voltz <stef.dev@free.fr>
3    This file is part of the SANE package.
4 
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 
18    As a special exception, the authors of SANE give permission for
19    additional uses of the libraries contained in this release of SANE.
20 
21    The exception is that, if you link a SANE library with other files
22    to produce an executable, this does not by itself cause the
23    resulting executable to be covered by the GNU General Public
24    License.  Your use of that executable is in no way restricted on
25    account of linking the SANE library code into it.
26 
27    This exception does not, however, invalidate any other reasons why
28    the executable file might be covered by the GNU General Public
29    License.
30 
31    If you submit changes to SANE to the maintainers to be included in
32    a subsequent release, you agree by submitting the changes that
33    those changes may be distributed with this exception intact.
34 
35    If you write modifications of your own for SANE, it is your choice
36    whether to permit this exception to apply to your modifications.
37    If you do not wish that, delete this exception notice.
38 
39    This file implements a SANE backend for Umax PP flatbed scanners.  */
40 
41 #undef BACKEND_NAME
42 #define BACKEND_NAME umax_pp_low
43 
44 #include "../include/sane/config.h"
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <math.h>
50 #ifdef HAVE_SYS_TIME_H
51 #include <sys/time.h>
52 #endif
53 #ifdef HAVE_SYS_TYPES_H
54 #include <sys/types.h>
55 #endif
56 #include "../include/sane/sanei_directio.h"
57 #ifdef HAVE_UNISTD_H
58 #include <unistd.h>
59 #endif
60 #ifdef HAVE_FCNTL_H
61 #include <fcntl.h>
62 #endif
63 #include "../include/sane/sanei_debug.h"
64 #include "../include/sane/sanei_backend.h"
65 #include <errno.h>
66 
67 #ifdef HAVE_DEV_PPBUS_PPI_H
68 #include <dev/ppbus/ppi.h>
69 #include <dev/ppbus/ppbconf.h>
70 #endif
71 
72 #ifdef HAVE_MACHINE_CPUFUNC_H
73 #include <machine/cpufunc.h>
74 #endif
75 
76 #ifdef HAVE_I386_SET_IOPERM
77 #include <machine/sysarch.h>
78 #endif
79 
80 #ifdef HAVE_LINUX_PPDEV_H
81 #include <sys/ioctl.h>
82 #include <linux/parport.h>
83 #include <linux/ppdev.h>
84 #endif
85 
86 #include "umax_pp_low.h"
87 
88 #ifdef DMALLOC
89 #include "dmalloc.h"
90 #endif
91 
92 #ifndef __IO__
93 #define __IO__
94 
95 #define DATA                   gPort+0x00
96 #define STATUS                 gPort+0x01
97 #define CONTROL                gPort+0x02
98 #define EPPADDR                 gPort+0x03
99 #define EPPDATA                gPort+0x04
100 
101 #define ECPDATA                gPort+0x400
102 #define ECR		       gPort+0x402
103 
104 #define FIFO_WAIT	      1000
105 #endif
106 
107 static int fonc001 (void);
108 static int foncSendWord (int *cmd);
109 
110 static void setEPPMode (int mode);
111 static int getEPPMode (void);
112 static void setModel (int model);
113 static int getModel (void);
114 static int ringScanner (int count, unsigned long delay);
115 static int testVersion (int no);
116 
117 static int probePS2 (unsigned char *dest);
118 static int probeEPP (unsigned char *dest);
119 static int probeECP (unsigned char *dest);
120 
121 static int sendCommand (int cmd);
122 static void SPPResetLPT (void);
123 static int sendWord (int *cmd);
124 static int sendData (int *cmd, int len);
125 static int receiveData (int *cmd, int len);
126 static int sendLength (int *cmd, int len);
127 
128 static int waitAck (void);
129 static void init001 (void);
130 static int init002 (int arg);
131 static int init005 (int arg);
132 
133 /* 610p comm functions */
134 static int putByte610p (int data);
135 static int EPPputByte610p (int data);
136 static int sendLength610p (int *cmd);
137 static int sendData610p (int *cmd, int len);
138 static int receiveData610p (int *cmd, int len);
139 static int connect610p (void);
140 static int sync610p (void);
141 static int cmdSync610p (int cmd);
142 static int EPPcmdSync610p (int cmd);
143 static int getStatus610p (void);
144 static int EPPgetStatus610p (void);
145 static int disconnect610p (void);
146 static int EPPsendWord610p (int *cmd);
147 static int SPPsendWord610p (int *cmd);
148 static int cmdSet610p (int cmd, int len, int *buffer);
149 static int cmdGet610p (int cmd, int len, int *buffer);
150 static int EPPcmdSet610p (int cmd, int len, int *buffer);
151 static int EPPcmdGet610p (int cmd, int len, int *buffer);
152 static int initScanner610p (int recover);
153 static int cmdGetBuffer610p (int cmd, int len, unsigned char *buffer);
154 
155 
156 /* parport mode setting */
157 static void compatMode (void);
158 static void byteMode (void);
159 static void ECPFifoMode (void);
160 
161 /* block transfer init */
162 static void ECPSetBuffer (int size);
163 
164 /* mode dependent operations */
165 static int PS2Something (int reg);
166 static void PS2bufferRead (int size, unsigned char *dest);
167 static void PS2bufferWrite (int size, unsigned char *source);
168 static int PS2registerRead (int reg);
169 static void PS2registerWrite (int reg, int value);
170 
171 static int EPPconnect (void);
172 static int EPPregisterRead (int reg);
173 static void EPPregisterWrite (int reg, int value);
174 static void EPPbufferRead (int size, unsigned char *dest);
175 static void EPPbufferWrite (int size, unsigned char *source);
176 static void EPPRead32Buffer (int size, unsigned char *dest);
177 static void EPPWrite32Buffer (int size, unsigned char *source);
178 
179 static int ECPconnect (void);
180 static void ECPdisconnect (void);
181 static int ECPregisterRead (int reg);
182 static void ECPregisterWrite (int reg, int value);
183 static int ECPbufferRead (int size, unsigned char *dest);
184 static void ECPbufferWrite (int size, unsigned char *source);
185 static int waitFifoEmpty (void);
186 static int waitFifoNotEmpty (void);
187 static int waitFifoFull (void);
188 
189 /* generic operations */
190 static int connect (void);
191 static void disconnect (void);
192 static void bufferRead (int size, unsigned char *dest);
193 static void bufferWrite (int size, unsigned char *source);
194 static int pausedBufferRead (int size, unsigned char *dest);
195 
196 
197 static void ClearRegister (int reg);
198 
199 static int connect_epat (int r08);
200 static int prologue (int r08);
201 static int epilogue (void);
202 
203 static int cmdSet (int cmd, int len, int *buffer);
204 static int cmdGet (int cmd, int len, int *buffer);
205 static int cmdSetGet (int cmd, int len, int *buffer);
206 
207 
208 static int cmdGetBuffer (int cmd, int len, unsigned char *buffer);
209 static int cmdGetBuffer32 (int cmd, int len, unsigned char *buffer);
210 static int cmdGetBlockBuffer (int cmd, int len, int window,
211 			      unsigned char *buffer);
212 
213 static void bloc2Decode (int *op);
214 static void bloc8Decode (int *op);
215 /*
216  * high level operations
217  */
218 static int loadDefaultTables (void);
219 static int inquire (void);
220 static int offsetCalibration (int color, int *offRed, int *offGreen,
221 			      int *offBlue);
222 static int coarseGainCalibration (int color, int dcRed, int dcGreen,
223 				  int dcBlue, int *vgaRed, int *vgaGreen,
224 				  int *vgaBlue);
225 static int
226 shadingCalibration (int color, int dcRed, int dcGreen, int dcBlue,
227 		    int vgaRed, int vgaGreen, int vgaBlue, int *calibration);
228 static int leftShadingCalibration610p (int color, int dcRed, int dcGreen,
229 				       int dcBlue, int vgaRed, int vgaGreen,
230 				       int vgaBlue, int *calibration);
231 
232 #define WRITESLOW(x,y) \
233         PS2registerWrite((x),(y)); \
234         DBG(16,"PS2registerWrite(0x%X,0x%X) passed...   (%s:%d)\n",(x),(y),__FILE__,__LINE__);
235 #define SLOWNIBBLEREGISTERREAD(x,y) \
236         tmp=PS2registerRead(x);\
237         if(tmp!=y)\
238         {\
239                 DBG(0,"PS2registerRead: found 0x%X expected 0x%X (%s:%d)\n",tmp,y,__FILE__,__LINE__);\
240                 /*return 0;*/ \
241         }\
242         DBG(16,"PS2registerRead(0x%X)=0x%X passed... (%s:%d)\n",x,y,__FILE__,__LINE__);
243 #define REGISTERWRITE(x,y) \
244         registerWrite((x),(y)); \
245         DBG(16,"registerWrite(0x%X,0x%X) passed...   (%s:%d)\n",(x),(y),__FILE__,__LINE__);
246 #define REGISTERREAD(x,y) \
247         tmp=registerRead(x);\
248         if(tmp!=y)\
249         {\
250                 DBG(0,"registerRead, found 0x%X expected 0x%X (%s:%d)\n",tmp,y,__FILE__,__LINE__);\
251                 return 0;\
252         }\
253         DBG(16,"registerRead(0x%X)=0x%X passed... (%s:%d)\n",x,y,__FILE__,__LINE__);
254 #define TRACE(level,msg)        DBG(level, msg"  (%s:%d)\n",__FILE__,__LINE__);
255 #define CMDSYNC(x)        if(sanei_umax_pp_cmdSync(x)!=1)\
256                         {\
257                                 DBG(0,"cmdSync(0x%02X) failed (%s:%d)\n",x,__FILE__,__LINE__);\
258                                 return 0;\
259                         }\
260                         DBG(16,"cmdSync(0x%02X)=%02X passed ... (%s:%d)\n",x,sanei_umax_pp_scannerStatus(),__FILE__,__LINE__)
261 #define CMDSETGET(cmd,len,sent) if(cmdSetGet(cmd,len,sent)!=1)\
262                                 {\
263                                         DBG(0,"cmdSetGet(0x%02X,%d,sent) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\
264                                         return 0;\
265                                 }\
266                                 TRACE(16,"cmdSetGet() passed ...")
267 #define YOFFSET                40
268 #define YOFFSET1220P        40
269 #define YOFFSET2000P        40
270 #define COMPLETIONWAIT        if(completionWait()==0)\
271                         {\
272                                 DBG(0,"completionWait() failed (%s:%d)\n",__FILE__,__LINE__);\
273                                 return 0;\
274                         }\
275                         TRACE(16,"completionWait() passed ...")
276 #define MOVE(x,y,t)        if(move(x,y,t)==0)\
277                         {\
278                                 DBG(0,"move(%d,%d,buffer) failed (%s:%d)\n",x,y,__FILE__,__LINE__);\
279                                 return 0;\
280                         }\
281                         TRACE(16,"move() passed ...")
282 #define CMDGETBUF(cmd,len,sent) if(cmdGetBuffer(cmd,len,sent)!=1)\
283                                 {\
284                                         DBG(0,"cmdGetBuffer(0x%02X,%ld,buffer) failed (%s:%d)\n",cmd,(long)len,__FILE__,__LINE__);\
285                                         return 0;\
286                                 }\
287                                 DBG(16,"cmdGetBuffer(%ld) passed ... (%s:%d)\n",(long)len,__FILE__,__LINE__);
288 #define CMDGETBUF32(cmd,len,sent) if(cmdGetBuffer32(cmd,len,sent)!=1)\
289                                 {\
290                                         DBG(0,"cmdGetBuffer32(0x%02X,%ld,buffer) failed (%s:%d)\n",cmd,(long)len,__FILE__,__LINE__);\
291                                         return 0;\
292                                 }\
293                                 TRACE(16,"cmdGetBuffer32() passed ...")
294 #define CMDSET(cmd,len,sent) if(cmdSet(cmd,len,sent)!=1)\
295                                 {\
296                                         DBG(0,"cmdSet(0x%02X,%d,sent) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\
297                                         return 0;\
298                                 }\
299                                 TRACE(16,"cmdSet() passed ...")
300 #define CMDGET(cmd,len,sent) if(cmdGet(cmd,len,sent)!=1)\
301                                 {\
302                                         DBG(0,"cmdGet(0x%02X,%d,read) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\
303                                         return 0;\
304                                 }\
305                                 TRACE(16,"cmdGet() passed ...")
306 static int gPort = 0x378;
307 static float targetCode = 250.0;
308 
309 /* global control vars */
310 static int gControl = 0;
311 static int gData = 0;
312 static int g674 = 0;		/* semble indiquer qu'on utilise les IRQ */
313 static int g67D = 0;
314 static int g67E = 0;
315 static int gEPAT = 0;		/* signals fast mode ? */
316 static int g6FE = 0;
317 static int gECP = 0;
318 
319 static int gLeft = 144;		/* default value for 1220P */
320 
321 /* default gamma translation table */
322 static int ggamma[256] =
323   { 0x00, 0x06, 0x0A, 0x0D, 0x10, 0x12, 0x14, 0x17, 0x19, 0x1B, 0x1D,
324   0x1F,
325   0x21, 0x23, 0x24, 0x26, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x30, 0x31, 0x33,
326   0x34, 0x36, 0x37, 0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x40, 0x41, 0x42, 0x43,
327   0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4F, 0x50, 0x51, 0x52,
328   0x53, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5E, 0x5F, 0x60,
329   0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
330   0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
331   0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84,
332   0x85, 0x86, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
333   0x90, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99,
334   0x9A, 0x9B, 0x9C, 0x9D, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA2, 0xA3,
335   0xA4, 0xA5, 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAC, 0xAD,
336   0xAE, 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB4, 0xB5, 0xB6, 0xB7,
337   0xB8, 0xB8, 0xB9, 0xBA, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBF, 0xC0,
338   0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC8, 0xC9,
339   0xCA, 0xCB, 0xCB, 0xCC, 0xCD, 0xCE, 0xCE, 0xCF, 0xD0, 0xD1, 0xD1, 0xD2,
340   0xD3, 0xD4, 0xD4, 0xD5, 0xD6, 0xD6, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDB,
341   0xDC, 0xDC, 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE3,
342   0xE4, 0xE5, 0xE6, 0xE6, 0xE7, 0xE8, 0xE8, 0xE9, 0xEA, 0xEA, 0xEB, 0xEC,
343   0xEC, 0xED, 0xEE, 0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF3, 0xF4,
344   0xF5, 0xF5, 0xF6, 0xF7, 0xF7, 0xF8, 0xF9, 0xF9, 0xFA, 0xFB, 0xFB, 0xFC,
345   0xFD, 0xFE, 0xFE, 0xFF
346 };
347 
348 
349 /* default gamma translation table */
350 static int *ggGreen = ggamma;
351 static int *ggBlue = ggamma;
352 static int *ggRed = ggamma;
353 static int gParport = 0;
354 static int gCancel = 0;
355 static int gAutoSettings = 1;
356 
357 
358 /*****************************************************************************/
359 /*                    output one byte on given port                          */
360 /*****************************************************************************/
361 static void Outb (int port, int value);
362 
363 /*****************************************************************************/
364 /*         output 'size' bytes stored in 'source' on given port              */
365 /*****************************************************************************/
366 static void Outsb (int port, unsigned char *source, int size);
367 
368 /*****************************************************************************/
369 /*       output 'size' 32 bits words stored in 'source' on given port        */
370 /*****************************************************************************/
371 static void Outsw (int port, unsigned char *source, int size);
372 
373 
374 /*****************************************************************************/
375 /*                   input one byte from given port                          */
376 /*****************************************************************************/
377 static int Inb (int port);
378 
379 /*****************************************************************************/
380 /*       input 'size' bytes from given port and store them in 'dest'         */
381 /*****************************************************************************/
382 static void Insb (int port, unsigned char *dest, int size);
383 
384 /*****************************************************************************/
385 /*     input 'size' 32 bits word from given port and store them in 'dest'    */
386 /*****************************************************************************/
387 static void Insw (int port, unsigned char *dest, int size);
388 
389 
390 
391 char **
sanei_parport_find_port(void)392 sanei_parport_find_port (void)
393 {
394   char **ports = NULL;
395 #ifdef ENABLE_PARPORT_DIRECTIO
396   int i, addr, ecpaddr;
397   int found = 0;
398   char name[80], buffer[80];
399   FILE *fic = NULL;
400 
401   /* direct I/O detection */
402   /* linux 2.4 + 2.6 with proc support */
403   for (i = 0; i < 4; i++)
404     {
405       /* try to ensure loading of lp module */
406       sprintf (name, "/dev/lp%d", i);
407       fic = fopen (name, "wb");
408       if (fic != NULL)
409 	fclose (fic);
410       sprintf (name, "/proc/sys/dev/parport/parport%d/base-addr", i);
411       fic = fopen (name, "rb");
412       if (fic != NULL)
413 	{
414 	  fread (buffer, 64, 1, fic);
415 	  fclose (fic);
416 	  if (sscanf (buffer, "%d %d", &addr, &ecpaddr) > 0)
417 	    {
418 	      DBG (16, "parport at 0x%X\n", addr);
419 	      ports =
420 		(char **) realloc (ports, (found + 2) * sizeof (char *));
421 	      ports[found] = (char *) malloc (19);
422 	      sprintf (ports[found], "0x%X", addr);
423 	      found++;
424 	      ports[found] = NULL;
425 	    }
426 	}
427     }
428 #endif
429   return ports;
430 }
431 
432 
433 char **
sanei_parport_find_device(void)434 sanei_parport_find_device (void)
435 {
436   char *devices[] = {
437     /* FreeBSD */
438     "/dev/ppi0",
439     "/dev/ppi1",
440     "/dev/ppi2",
441     "/dev/ppi3",
442     /* linux ppdev with devfs */
443     "/dev/parports/0",
444     "/dev/parports/1",
445     "/dev/parports/2",
446     "/dev/parports/3",
447     /* linux ppdev */
448     "/dev/parport0",
449     "/dev/parport1",
450     "/dev/parport2",
451     "/dev/parport3",
452     NULL
453   };
454   int i, file;
455   int rc = 0;
456   int found = 0;
457   char **ports = NULL;
458 
459 
460   /* device finding */
461   i = 0;
462   while (devices[i] != NULL)
463     {
464       DBG (16, "Controlling %s: ", devices[i]);
465       file = open (devices[i], O_RDWR);
466       if (file < 0)
467 	{
468 	  switch (errno)
469 	    {
470 	    case ENOENT:
471 #ifdef ENIO
472 	    case ENXIO:
473 #endif
474 #ifdef ENODEV
475 	    case ENODEV:
476 #endif
477 	      DBG (16, "no %s device ...\n", devices[i]);
478 	      break;
479 	    case EACCES:
480 	      DBG (16, "current user cannot use existing %s device ...\n",
481 		   devices[i]);
482 	      break;
483 	    default:
484 	      perror (devices[i]);
485 	    }
486 	}
487       else
488 	{
489 #ifdef HAVE_LINUX_PPDEV_H
490 	  /* on kernel < 2.4.23, you have to CLAIM the device
491 	   * to check it really exists
492 	   * we may hang if another program already claimed it
493 	   */
494 	  rc = ioctl (file, PPCLAIM);
495 	  if (rc)
496 	    {
497 	      switch (errno)
498 		{
499 		case ENOENT:
500 #ifdef ENXIO
501 		case ENXIO:
502 #endif
503 #ifdef ENODEV
504 		case ENODEV:
505 #endif
506 		  DBG (16, "no %s device ...\n", devices[i]);
507 		  break;
508 		case EACCES:
509 		  DBG (16, "current user cannot use existing %s device ...\n",
510 		       devices[i]);
511 		  break;
512 		default:
513 		  DBG (16, "errno=%d\n", errno);
514 		  perror (devices[i]);
515 		}
516 	    }
517 	  else
518 	    {
519 	      rc = ioctl (file, PPRELEASE);
520 	    }
521 #endif /* HAVE_LINUX_PPDEV_H */
522 	  close (file);
523 	  if (!rc)
524 	    {
525 	      DBG (16, "adding %s to valid devices ...\n", devices[i]);
526 	      ports =
527 		(char **) realloc (ports, (found + 2) * sizeof (char *));
528 	      ports[found] = strdup (devices[i]);
529 	      found++;
530 	      ports[found] = NULL;
531 	    }
532 	}
533 
534       /* suite */
535       i++;
536     }
537   return ports;
538 }
539 
540 
541 
542 /*
543  * gain direct access to IO port, and set parport to the 'right' mode
544  * returns 1 on success, 0 an failure
545  */
546 
547 
548 int
sanei_umax_pp_initPort(int port, const char *name)549 sanei_umax_pp_initPort (int port, const char *name)
550 {
551 #ifndef IO_SUPPORT_MISSING
552 # ifdef HAVE_LINUX_PPDEV_H
553   int found = 0;
554   int fd;
555   int mode, modes, rc;
556 #  ifdef PPGETMODES
557   char strmodes[160];
558 #  endif
559 # endif
560 # ifdef HAVE_DEV_PPBUS_PPI_H
561   int found = 0;
562   int fd;
563 # endif
564 # ifdef HAVE_IOPERM
565   int ectr;
566 # endif
567 #endif
568 
569   /* since this function must be called before */
570   /* any other, we put debug init here         */
571   DBG_INIT ();
572   DBG (1, "SANE_INB level %d\n", SANE_INB);
573 
574   /* sets global vars */
575   ggGreen = ggamma;
576   ggBlue = ggamma;
577   ggRed = ggamma;
578   gParport = 0;
579   gCancel = 0;
580   gAutoSettings = 1;
581   gControl = 0;
582   gData = 0;
583   g674 = 0;
584   g67D = 0;
585   g67E = 0;
586   gEPAT = 0;
587   g6FE = 0;
588   sanei_umax_pp_setparport (0);
589 
590 
591   DBG (1, "sanei_umax_pp_InitPort(0x%X,%s)\n", port, name);
592 #ifndef ENABLE_PARPORT_DIRECTIO
593   if ((name == NULL) || ((name != NULL) && (strlen (name) < 4)))
594     {
595       DBG (0, "sanei_umax_pp_InitPort cannot use direct hardware access\n");
596       DBG (0, "if not compiled with --enable-parport-directio\n");
597       return 0;
598     }
599 #endif
600 
601 
602   /* init global var holding port value */
603   gPort = port;
604 
605 #ifdef IO_SUPPORT_MISSING
606   DBG (1, "*** Direct I/O or ppdev unavailable, giving up ***\n");
607   return 0;
608 #else
609 
610 
611 #ifdef HAVE_LINUX_PPDEV_H
612   if (name != NULL)
613     {
614       if (strlen (name) > 3)
615 	{
616 	  /* ppdev opening and configuration                               */
617 	  found = 0;
618 	  fd = open (name, O_RDWR | O_NOCTTY | O_NONBLOCK);
619 	  if (fd < 0)
620 	    {
621 	      switch (errno)
622 		{
623 		case ENOENT:
624 		  DBG (1, "umax_pp: '%s' does not exist \n", name);
625 		  break;
626 		case EACCES:
627 		  DBG (1,
628 		       "umax_pp: current user has not R/W permissions on '%s' \n",
629 		       name);
630 		  break;
631 		}
632 	      return 0;
633 
634 	    }
635 	  /* claim port */
636 	  if (ioctl (fd, PPCLAIM))
637 	    {
638 	      DBG (1, "umax_pp: cannot claim port '%s'\n", name);
639 	    }
640 	  else
641 	    {
642 	      /* we check if parport does EPP or ECP */
643 #ifdef PPGETMODES
644 	      if (ioctl (fd, PPGETMODES, &modes))
645 		{
646 		  DBG (16,
647 		       "umax_pp: ppdev couldn't gave modes for port '%s'\n",
648 		       name);
649 		}
650 	      else
651 		{
652 		  snprintf(strmodes, sizeof(strmodes),
653 			   "\n%s%s%s%s%s%s",
654 			   (modes & PARPORT_MODE_PCSPP)? "\t\tPARPORT_MODE_PCSPP\n": "",
655 			   (modes & PARPORT_MODE_TRISTATE)? "\t\tPARPORT_MODE_TRISTATE\n": "",
656 			   (modes & PARPORT_MODE_EPP)? "\t\tPARPORT_MODE_EPP\n": "",
657 			   (modes & PARPORT_MODE_ECP)? "\t\tPARPORT_MODE_ECP\n": "",
658 			   (modes & PARPORT_MODE_COMPAT)? "\t\tPARPORT_MODE_COMPAT\n": "",
659 			   (modes & PARPORT_MODE_DMA)? "\t\tPARPORT_MODE_DMA\n": "");
660 
661 		  if (modes & PARPORT_MODE_ECP)
662 		    {
663 		      gECP = 1;
664 		    }
665 
666 		  DBG (32, "parport modes: %X\n", modes);
667 		  DBG (32, "parport modes: %s\n", strmodes);
668 		  if (!(modes & PARPORT_MODE_EPP)
669 		      && !(modes & PARPORT_MODE_ECP))
670 		    {
671 		      DBG (1,
672 			   "port 0x%X does not have EPP or ECP, giving up ...\n",
673 			   port);
674 		      mode = IEEE1284_MODE_COMPAT;
675 		      ioctl (fd, PPSETMODE, &mode);
676 		      ioctl (fd, PPRELEASE);
677 		      close (fd);
678 		      return 0;
679 		    }
680 		}
681 
682 #else
683 	      DBG (16,
684 		   "umax_pp: ppdev used to build SANE doesn't have PPGETMODES.\n");
685 	      /* faking result */
686 	      modes = 0xFFFFFFFF;
687 #endif
688 	      mode = 0;
689 
690 	      /* preferred mode is EPP */
691 	      if (modes & PARPORT_MODE_EPP)
692 		{
693 		  mode = IEEE1284_MODE_EPP;
694 
695 		  /* negot always fail here ... */
696 		  rc = ioctl (fd, PPNEGOT, &mode);
697 		  if (rc)
698 		    {
699 		      DBG (16,
700 			   "umax_pp: ppdev couldn't negotiate mode IEEE1284_MODE_EPP for '%s' (ignored)\n",
701 			   name);
702 		    }
703 		  if (ioctl (fd, PPSETMODE, &mode))
704 		    {
705 		      DBG (16,
706 			   "umax_pp: ppdev couldn't set mode to IEEE1284_MODE_EPP for '%s'\n",
707 			   name);
708 		      /* signal failure for ECP test */
709 		      mode = 0;
710 		    }
711 		  else
712 		    {
713 		      DBG (16,
714 			   "umax_pp: mode set to PARPORT_MODE_EPP for '%s'\n",
715 			   name);
716 		    }
717 		}
718 
719 	      if ((modes & PARPORT_MODE_ECP) && (mode == 0))
720 		{
721 		  mode = IEEE1284_MODE_ECP;
722 		  rc = ioctl (fd, PPNEGOT, &mode);
723 		  if (rc)
724 		    {
725 		      DBG (16,
726 			   "umax_pp: ppdev couldn't negotiate mode IEEE1284_MODE_ECP for '%s' (ignored)\n",
727 			   name);
728 		    }
729 		  if (ioctl (fd, PPSETMODE, &mode))
730 		    {
731 		      DBG (16,
732 			   "umax_pp: ppdev couldn't set mode to IEEE1284_MODE_ECP for '%s'\n",
733 			   name);
734 		      DBG (1,
735 			   "port 0x%X can't be set to EPP or ECP, giving up ...\n",
736 			   port);
737 
738 		      mode = IEEE1284_MODE_COMPAT;
739 		      ioctl (fd, PPSETMODE, &mode);
740 		      ioctl (fd, PPRELEASE);
741 		      close (fd);
742 		      return 0;
743 		    }
744 		  else
745 		    {
746 		      gECP = 1;
747 		      DBG (16,
748 			   "umax_pp: mode set to PARPORT_MODE_ECP for '%s'\n",
749 			   name);
750 		    }
751 		}
752 
753 
754 	      /* always start in compat mode (for probe) */
755 	      mode = IEEE1284_MODE_COMPAT;
756 	      rc = ioctl (fd, PPSETMODE, &mode);
757 	      if (rc)
758 		DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
759 		     strerror (errno), __FILE__, __LINE__);
760 	      mode = 0;		/* data forward */
761 	      rc = ioctl (fd, PPDATADIR, &mode);
762 	      if (rc)
763 		DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
764 		     strerror (errno), __FILE__, __LINE__);
765 	      mode = 1;		/* FW IDLE */
766 	      rc = ioctl (fd, PPSETPHASE, &mode);
767 	      if (rc)
768 		DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
769 		     strerror (errno), __FILE__, __LINE__);
770 	      found = 1;
771 
772 	    }
773 
774 	  if (!found)
775 	    {
776 	      DBG (1, "device %s does not fit ...\n", name);
777 	    }
778 	  else
779 	    {
780 	      DBG (1, "Using %s ...\n", name);
781 	      sanei_umax_pp_setparport (fd);
782 	      return 1;
783 	    }
784 	}
785     }
786 #endif /* HAVE_LINUX_PPDEV_H */
787 
788 
789 #ifdef HAVE_DEV_PPBUS_PPI_H
790 /* the ppi device let user access to parallel port on freebsd */
791   if (name != NULL)
792     {
793       if (strlen (name) > 3)
794 	{
795 	  /* ppi opening and configuration                               */
796 	  found = 0;
797 	  fd = open (name, O_RDONLY);
798 	  if (fd < 0)
799 	    {
800 	      switch (errno)
801 		{
802 		case ENOENT:
803 		  DBG (1, "umax_pp: '%s' does not exist \n", name);
804 		  break;
805 		case EACCES:
806 		  DBG (1,
807 		       "umax_pp: current user has not read permissions on '%s' \n",
808 		       name);
809 		  break;
810 		}
811 	      return 0;
812 	    }
813 	  else
814 	    {
815 	      DBG (1, "Using %s ...\n", name);
816 	      sanei_umax_pp_setparport (fd);
817 	      return 1;
818 	    }
819 	}
820     }
821 #endif /* HAVE_DEV_PPBUS_PPI_H */
822 
823   if (port < 0x400)
824     {
825       if (sanei_ioperm (port, 8, 1) != 0)
826 	{
827 	  DBG (1, "sanei_ioperm() could not gain access to 0x%X\n", port);
828 	  return 0;
829 	}
830       DBG (1, "sanei_ioperm(0x%X, 8, 1) OK ...\n", port);
831     }
832 
833 #ifdef HAVE_IOPERM
834   /* ECP i/o range */
835   if (iopl (3) != 0)
836     {
837       DBG (1, "iopl could not raise IO permission to level 3\n");
838       DBG (1, "*NO* ECP support\n");
839 
840     }
841   else
842     {
843       /* any ECP out there ? */
844       ectr = Inb (ECR);
845       if (ectr != 0xFF)
846 	{
847 	  gECP = 1;
848 
849 	}
850     }
851 #endif
852 
853 
854 
855 #endif /* IO_SUPPORT_MISSING */
856   return 1;
857 }
858 
859 
860 
861 
862 
863 
864 static void
Outb(int port, int value)865 Outb (int port, int value)
866 {
867 #ifndef IO_SUPPORT_MISSING
868 
869 #ifdef HAVE_LINUX_PPDEV_H
870   int fd, rc, mode, exmode;
871   unsigned char val;
872 
873 
874   fd = sanei_umax_pp_getparport ();
875   val = (unsigned char) value;
876   if (fd > 0)
877     {
878       /* there should be ECR that doesn't go through ppdev */
879       /* it will leave when all the I/O will be done with ppdev   */
880       switch (port - gPort)
881 	{
882 	case 0:
883 	  rc = ioctl (fd, PPWDATA, &val);
884 	  if (rc)
885 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
886 		 __FILE__, __LINE__);
887 #ifdef IOLOG
888 	  DBG (0, "outb DATA,%02X\n", value);
889 #endif
890 	  return;
891 	case 2:
892 	  mode = val & 0x20;
893 	  rc = ioctl (fd, PPDATADIR, &mode);
894 	  if (rc)
895 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
896 		 strerror (errno), __FILE__, __LINE__);
897 	  val = val & 0xDF;
898 	  rc = ioctl (fd, PPWCONTROL, &val);
899 	  if (rc)
900 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
901 		 strerror (errno), __FILE__, __LINE__);
902 #ifdef IOLOG
903 	  DBG (0, "outb CONTROL,%02X\n", value);
904 #endif
905 	  return;
906 	case 4:
907 	  rc = ioctl (fd, PPGETMODE, &exmode);
908 	  if (rc)
909 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
910 		 __FILE__, __LINE__);
911 	  mode = 0;		/* data forward */
912 	  rc = ioctl (fd, PPDATADIR, &mode);
913 	  if (rc)
914 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
915 		 __FILE__, __LINE__);
916 	  mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
917 	  rc = ioctl (fd, PPSETMODE, &mode);
918 	  if (rc)
919 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
920 		 __FILE__, __LINE__);
921 	  rc = write (fd, &val, 1);
922 	  if (rc != 1)
923 	    DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
924 	  rc = ioctl (fd, PPSETMODE, &exmode);
925 	  if (rc)
926 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
927 		 __FILE__, __LINE__);
928 #ifdef IOLOG
929 	  DBG (0, "outb EPPDATA,%02X\n", value);
930 #endif
931 	  return;
932 	case 3:
933 	  rc = ioctl (fd, PPGETMODE, &exmode);
934 	  if (rc)
935 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
936 		 __FILE__, __LINE__);
937 	  mode = 0;		/* data forward */
938 	  rc = ioctl (fd, PPDATADIR, &mode);
939 	  if (rc)
940 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
941 		 __FILE__, __LINE__);
942 	  mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
943 	  rc = ioctl (fd, PPSETMODE, &mode);
944 	  if (rc)
945 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
946 		 __FILE__, __LINE__);
947 	  rc = write (fd, &val, 1);
948 	  if (rc != 1)
949 	    DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
950 	  rc = ioctl (fd, PPSETMODE, &exmode);
951 	  if (rc)
952 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
953 		 __FILE__, __LINE__);
954 	  return;
955 	case 0x400:
956 	case 0x402:
957 	  break;
958 	default:
959 	  DBG (16, "Outb(0x%03X,0x%02X) escaped ppdev\n", port, value);
960 	  return;
961 	}
962     }
963 #endif /* HAVE_LINUX_PPDEV_H */
964 
965 
966 #ifdef HAVE_DEV_PPBUS_PPI_H
967   int fd, rc;
968   unsigned char val;
969 
970 
971   fd = sanei_umax_pp_getparport ();
972   val = (unsigned char) value;
973   if (fd > 0)
974     {
975       switch (port - gPort)
976 	{
977 	case 0:
978 	  rc = ioctl (fd, PPISDATA, &val);
979 	  if (rc)
980 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
981 		 __FILE__, __LINE__);
982 	  return;
983 	case 1:
984 	  rc = ioctl (fd, PPISSTATUS, &val);
985 	  if (rc)
986 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
987 		 __FILE__, __LINE__);
988 	  return;
989 	case 2:
990 	  rc = ioctl (fd, PPISCTRL, &val);
991 	  if (rc)
992 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
993 		 __FILE__, __LINE__);
994 	  return;
995 	case 3:
996 	  rc = ioctl (fd, PPISEPPA, &val);
997 	  if (rc)
998 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
999 		 __FILE__, __LINE__);
1000 	  return;
1001 	case 4:
1002 	  rc = ioctl (fd, PPISEPPD, &val);
1003 	  if (rc)
1004 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1005 		 __FILE__, __LINE__);
1006 	  return;
1007 	case 0x402:
1008 	  rc = ioctl (fd, PPISECR, &val);
1009 	  if (rc)
1010 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1011 		 __FILE__, __LINE__);
1012 	  return;
1013 	default:
1014 	  DBG (16, "Outb(0x%03X,0x%02X) escaped ppi\n", port, value);
1015 	  return;
1016 	}
1017     }
1018 #endif /* HAVE_DEV_PPBUS_PPI_H */
1019 
1020   sanei_outb (port, value);
1021 
1022 #endif /* IO_SUPPORT_MISSING */
1023 }
1024 
1025 
1026 
1027 
1028 
1029 static int
Inb(int port)1030 Inb (int port)
1031 {
1032   int res = 0xFF;
1033 #ifndef IO_SUPPORT_MISSING
1034 
1035 #ifdef HAVE_LINUX_PPDEV_H
1036   int fd, rc, mode;
1037   unsigned char val;
1038 
1039 
1040   fd = sanei_umax_pp_getparport ();
1041   if (fd > 0)
1042     {
1043       /* there should be ECR that doesn't go through ppdev */
1044       /* it will leave when all the I/O will be done with ppdev   */
1045       switch (port - gPort)
1046 	{
1047 	case 0:
1048 	  rc = ioctl (fd, PPRDATA, &val);
1049 	  if (rc)
1050 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1051 		 __FILE__, __LINE__);
1052 	  res = val;
1053 #ifdef IOLOG
1054 	  DBG (0, "inb  DATA,%02X\n", res);
1055 #endif
1056 	  return res;
1057 
1058 	case 1:
1059 	  rc = ioctl (fd, PPRSTATUS, &val);
1060 	  if (rc)
1061 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1062 		 __FILE__, __LINE__);
1063 	  res = val;
1064 #ifdef IOLOG
1065 	  DBG (0, "inb  STATUS,%02X\n", res);
1066 #endif
1067 	  return res;
1068 
1069 	case 2:
1070 	  rc = ioctl (fd, PPRCONTROL, &val);
1071 	  if (rc)
1072 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1073 		 __FILE__, __LINE__);
1074 	  res = val;
1075 #ifdef IOLOG
1076 	  DBG (0, "inb  CONTROL,%02X\n", res);
1077 #endif
1078 	  return res;
1079 
1080 	case 4:
1081 	  mode = 1;		/* data_reverse */
1082 	  rc = ioctl (fd, PPDATADIR, &mode);
1083 	  if (rc)
1084 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1085 		 __FILE__, __LINE__);
1086 	  mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
1087 	  rc = ioctl (fd, PPSETMODE, &mode);
1088 	  if (rc)
1089 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1090 		 __FILE__, __LINE__);
1091 	  rc = read (fd, &val, 1);
1092 	  if (rc != 1)
1093 	    DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__);
1094 	  mode = 0;		/* data_forward */
1095 	  rc = ioctl (fd, PPDATADIR, &mode);
1096 	  if (rc)
1097 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1098 		 __FILE__, __LINE__);
1099 	  res = val;
1100 #ifdef IOLOG
1101 	  DBG (0, "inb  EPPDATA,%02X\n", res);
1102 #endif
1103 	  return res;
1104 	case 0x400:
1105 	case 0x402:
1106 	default:
1107 	  DBG (16, "Inb(0x%03X) escaped ppdev\n", port);
1108 	  return 0xFF;
1109 	}
1110     }
1111 #endif /* HAVE_LINUX_PPDEV_H */
1112 
1113 
1114 #ifdef HAVE_DEV_PPBUS_PPI_H
1115   int fd, rc;
1116   unsigned char val;
1117 
1118 
1119   fd = sanei_umax_pp_getparport ();
1120   if (fd > 0)
1121     {
1122       switch (port - gPort)
1123 	{
1124 	case 0:
1125 	  rc = ioctl (fd, PPIGDATA, &val);
1126 	  if (rc)
1127 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1128 		 __FILE__, __LINE__);
1129 	  res = val;
1130 	  return res;
1131 	case 1:
1132 	  rc = ioctl (fd, PPIGSTATUS, &val);
1133 	  if (rc)
1134 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1135 		 __FILE__, __LINE__);
1136 	  res = val;
1137 	  return res;
1138 	case 2:
1139 	  rc = ioctl (fd, PPIGCTRL, &val);
1140 	  if (rc)
1141 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1142 		 __FILE__, __LINE__);
1143 	  res = val;
1144 	  return res;
1145 	case 3:
1146 	  rc = ioctl (fd, PPIGEPPA, &val);
1147 	  if (rc)
1148 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1149 		 __FILE__, __LINE__);
1150 	  res = val;
1151 	  return res;
1152 	case 4:
1153 	  rc = ioctl (fd, PPIGEPPD, &val);
1154 	  if (rc)
1155 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1156 		 __FILE__, __LINE__);
1157 	  res = val;
1158 	  return res;
1159 	case 0x402:
1160 	  rc = ioctl (fd, PPIGECR, &val);
1161 	  if (rc)
1162 	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1163 		 __FILE__, __LINE__);
1164 	  res = val;
1165 	  return res;
1166 	default:
1167 	  DBG (16, "Inb(0x%03X) escaped ppi\n", port);
1168 	  return 0xFF;
1169 	}
1170     }
1171 #endif /* HAVE_DEV_PPBUS_PPI_H */
1172 
1173   res = sanei_inb (port);
1174 
1175 #endif /* IO_SUPPORT_MISSING */
1176   return res;
1177 }
1178 
1179 
1180 static void
Insb(int port, unsigned char *dest, int size)1181 Insb (int port, unsigned char *dest, int size)
1182 {
1183 #ifndef IO_SUPPORT_MISSING
1184 
1185 #ifdef HAVE_DEV_PPBUS_PPI_H
1186   int i;
1187   if (sanei_umax_pp_getparport () > 0)
1188     {
1189       for (i = 0; i < size; i++)
1190 	dest[i] = Inb (port);
1191       return;
1192     }
1193 #endif /* HAVE_DEV_PPBUS_PPI_H */
1194   sanei_insb (port, dest, size);
1195 
1196 #endif
1197 }
1198 
1199 static void
Outsb(int port, unsigned char *source, int size)1200 Outsb (int port, unsigned char *source, int size)
1201 {
1202 #ifndef IO_SUPPORT_MISSING
1203 
1204 #ifdef HAVE_DEV_PPBUS_PPI_H
1205   int i;
1206 
1207   if (sanei_umax_pp_getparport () > 0)
1208     {
1209       for (i = 0; i < size; i++)
1210 	Outb (port, source[i]);
1211       return;
1212     }
1213 #endif /* HAVE_DEV_PPBUS_PPI_H */
1214 
1215   sanei_outsb (port, source, size);
1216 
1217 #endif
1218 }
1219 
1220 
1221 
1222 /* size = nb words */
1223 static void
Insw(int port, unsigned char *dest, int size)1224 Insw (int port, unsigned char *dest, int size)
1225 {
1226 #ifndef IO_SUPPORT_MISSING
1227 
1228 #ifdef HAVE_DEV_PPBUS_PPI_H
1229   int i;
1230 
1231   if (sanei_umax_pp_getparport () > 0)
1232     {
1233       for (i = 0; i < size * 4; i++)
1234 	dest[i] = Inb (port);
1235       return;
1236     }
1237 #endif /* HAVE_DEV_PPBUS_PPI_H */
1238 
1239   sanei_insl (port, dest, size);
1240 
1241 #endif
1242 }
1243 
1244 static void
Outsw(int port, unsigned char *source, int size)1245 Outsw (int port, unsigned char *source, int size)
1246 {
1247 #ifndef IO_SUPPORT_MISSING
1248 
1249 #ifdef HAVE_DEV_PPBUS_PPI_H
1250   int i;
1251 
1252   if (sanei_umax_pp_getparport () > 0)
1253     {
1254       for (i = 0; i < size * 4; i++)
1255 	Outb (port, source[i]);
1256       return;
1257     }
1258 #endif /* HAVE_DEV_PPBUS_PPI_H */
1259 
1260   sanei_outsl (port, source, size);
1261 
1262 #endif
1263 }
1264 
1265 
1266 /* we're trying to gather information on the scanner here, */
1267 /* and published it through an easy interface              */
1268 /* will turn it into a struct when 610P code will be done  */
1269 static int scannerStatus = 0;
1270 static time_t gTime = 0;
1271 static time_t gDelay = 0;
1272 static int epp32 = 1;
1273 static int gMode = 0;
1274 static int gprobed = 0;
1275 static int model = 0x15;
1276 static int astra = 0;
1277 static int hasUTA = 0;
1278 
1279 /* signals that scan width matches full ccd width */
1280 static int fullCCDWidth = 0;
1281 
1282 int
sanei_umax_pp_getfull(void)1283 sanei_umax_pp_getfull (void)
1284 {
1285   return fullCCDWidth;
1286 }
1287 
1288 void
sanei_umax_pp_setfull(int mod)1289 sanei_umax_pp_setfull (int mod)
1290 {
1291   fullCCDWidth = mod;
1292 }
1293 
1294 
1295 int
sanei_umax_pp_UTA(void)1296 sanei_umax_pp_UTA (void)
1297 {
1298   return hasUTA;
1299 }
1300 
1301 int
sanei_umax_pp_scannerStatus(void)1302 sanei_umax_pp_scannerStatus (void)
1303 {
1304   struct timeval tv;
1305 
1306   /* the 610P ASIC needs some time to settle down after probe */
1307   if ((gTime > 0) && (gDelay > 0))
1308     {
1309       gettimeofday (&tv, NULL);
1310       /* delay elapsed ? */
1311       if (tv.tv_sec - gTime < gDelay)
1312 	/* still waiting */
1313 	return ASIC_BIT;
1314       /* wait finished */
1315       gDelay = 0;
1316       gTime = 0;
1317     }
1318 
1319   /* 0x07 variant returns status with bit 0 or 1 always set to 1 */
1320   /* so we mask it out                                            */
1321   return scannerStatus & 0xFC;
1322 }
1323 
1324 static int
getEPPMode(void)1325 getEPPMode (void)
1326 {
1327   if (epp32)
1328     return 32;
1329   return 8;
1330 }
1331 
1332 static void
setEPPMode(int mode)1333 setEPPMode (int mode)
1334 {
1335   if (mode == 8)
1336     epp32 = 0;
1337   else
1338     epp32 = 1;
1339 }
1340 
1341 static int
getModel(void)1342 getModel (void)
1343 {
1344   return model;
1345 }
1346 
1347 static void
setModel(int mod)1348 setModel (int mod)
1349 {
1350   model = mod;
1351 }
1352 
1353 
1354 int
sanei_umax_pp_getparport(void)1355 sanei_umax_pp_getparport (void)
1356 {
1357   return gParport;
1358 }
1359 
1360 void
sanei_umax_pp_setparport(int fd)1361 sanei_umax_pp_setparport (int fd)
1362 {
1363   gParport = fd;
1364 }
1365 
1366 int
sanei_umax_pp_getport(void)1367 sanei_umax_pp_getport (void)
1368 {
1369   return gPort;
1370 }
1371 
1372 void
sanei_umax_pp_setport(int port)1373 sanei_umax_pp_setport (int port)
1374 {
1375   gPort = port;
1376 }
1377 
1378 int
sanei_umax_pp_getastra(void)1379 sanei_umax_pp_getastra (void)
1380 {
1381   return astra;
1382 }
1383 
1384 void
sanei_umax_pp_setastra(int mod)1385 sanei_umax_pp_setastra (int mod)
1386 {
1387   astra = mod;
1388 }
1389 
1390 int
sanei_umax_pp_getLeft(void)1391 sanei_umax_pp_getLeft (void)
1392 {
1393   switch (sanei_umax_pp_getastra ())
1394     {
1395     case 610:
1396       return 92;
1397     default:
1398       return 144;
1399     }
1400 }
1401 
1402 void
sanei_umax_pp_setLeft(int mod)1403 sanei_umax_pp_setLeft (int mod)
1404 {
1405   gLeft = mod;
1406 }
1407 
1408 int
sanei_umax_pp_getauto(void)1409 sanei_umax_pp_getauto (void)
1410 {
1411   return gAutoSettings;
1412 }
1413 
1414 void
sanei_umax_pp_setauto(int autoset)1415 sanei_umax_pp_setauto (int autoset)
1416 {
1417   gAutoSettings = autoset;
1418 }
1419 
1420 #ifdef HAVE_LINUX_PPDEV_H
1421 /* set to the parallel port needed using ppdev
1422  * returns 1 if ok, 0 else
1423  */
1424 static int
ppdev_set_mode(int mode)1425 ppdev_set_mode (int mode)
1426 {
1427   int fd, rc;
1428 
1429   /* check we have ppdev working */
1430   fd = sanei_umax_pp_getparport ();
1431   if (fd > 0)
1432     {
1433       rc = ioctl (fd, PPSETMODE, &mode);
1434       if (rc)
1435 	{
1436 	  DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1437 	       __FILE__, __LINE__);
1438 	  return 0;
1439 	}
1440       return 1;
1441     }
1442   return 0;
1443 }
1444 #endif
1445 
1446 /* set parallel port mode to 'compatible'*/
1447 static void
compatMode(void)1448 compatMode (void)
1449 {
1450 #ifdef HAVE_LINUX_PPDEV_H
1451   if (ppdev_set_mode (IEEE1284_MODE_COMPAT))
1452     return;
1453 #endif
1454   if (!gECP)
1455     return;
1456   Outb (ECR, 0x15);
1457 }
1458 
1459 /* set parallel port mode to 'bidirectionel'*/
1460 static void
byteMode(void)1461 byteMode (void)
1462 {
1463 #ifdef HAVE_LINUX_PPDEV_H
1464   if (ppdev_set_mode (IEEE1284_MODE_BYTE))
1465     return;
1466 #endif
1467   if (!gECP)
1468     return;
1469   Outb (ECR, 0x35);		/* or 0x34 */
1470 }
1471 
1472 /* set parallel port mode to 'fifo'*/
1473 static void
ECPFifoMode(void)1474 ECPFifoMode (void)
1475 {
1476   /* bits 7:5 :
1477      000 Standard Mode
1478      001 Byte Mode
1479      010 Parallel Port FIFO Mode
1480      011 ECP FIFO Mode
1481      100 EPP Mode
1482      101 Reserved
1483      110 FIFO Test Mode
1484      111 Configuration Mode
1485    */
1486   /* logged as 74/75 */
1487 #ifdef HAVE_LINUX_PPDEV_H
1488   if (ppdev_set_mode (IEEE1284_MODE_ECP))
1489     return;
1490 #endif
1491   if (!gECP)
1492     return;
1493   Outb (ECR, 0x75);
1494 }
1495 
1496 /* wait for ack bit */
1497 /* return 1 on success, 0 on error */
1498 static int
waitAcknull1499 waitAck ()
1500 {
1501   unsigned char breg = 0;
1502   int i = 0;
1503 
1504   Outb (CONTROL, 0x0C);		/* select printer + initialize printer */
1505   Outb (CONTROL, 0x0C);
1506   Outb (CONTROL, 0x0C);
1507   breg = Inb (STATUS) & 0xF8;
1508   while ((i < 1024) && ((breg & 0x04) == 0))
1509     {
1510       Outb (CONTROL, 0x0E);	/* autolinefeed ?.. */
1511       Outb (CONTROL, 0x0E);
1512       Outb (CONTROL, 0x0E);
1513       breg = Inb (STATUS) & 0xF8;
1514       i++;
1515       usleep (1000);
1516     }
1517   if (i == 1024)
1518     {
1519       DBG (1, "waitAck failed, time-out waiting for Ack (%s:%d)\n",
1520 	   __FILE__, __LINE__);
1521       /* return 0; seems to be non-blocking ... */
1522     }
1523   Outb (CONTROL, 0x04);		/* printer reset */
1524   Outb (CONTROL, 0x04);
1525   Outb (CONTROL, 0x04);
1526   return 1;
1527 }
1528 
1529 static int
waitFifoEmpty(void)1530 waitFifoEmpty (void)
1531 {
1532   int i;
1533   unsigned char breg;
1534 
1535   breg = Inb (ECR);
1536   i = 0;
1537   while ((i < FIFO_WAIT) && ((breg & 0x01) == 0))
1538     {
1539       breg = Inb (ECR);
1540       i++;
1541     }
1542   if (i == FIFO_WAIT)
1543     {
1544       DBG (0, "waitFifoEmpty failed, time-out waiting for FIFO (%s:%d)\n",
1545 	   __FILE__, __LINE__);
1546       return 0;
1547     }
1548   return 1;
1549 }
1550 
1551 static int
waitFifoNotEmpty(void)1552 waitFifoNotEmpty (void)
1553 {
1554   int i;
1555   unsigned char breg;
1556 
1557   breg = Inb (ECR);
1558   i = 0;
1559   while ((i < FIFO_WAIT) && ((breg & 0x01) != 0))
1560     {
1561       breg = Inb (ECR);
1562       i++;
1563       /* usleep (2000); */
1564     }
1565   if (i == FIFO_WAIT)
1566     {
1567       DBG (0, "waitFifoNotEmpty failed, time-out waiting for FIFO (%s:%d)\n",
1568 	   __FILE__, __LINE__);
1569       return 0;
1570     }
1571   return 1;
1572 }
1573 
1574 
1575 static int
waitFifoFull(void)1576 waitFifoFull (void)
1577 {
1578   int i;
1579   unsigned char breg;
1580 
1581   breg = Inb (ECR);
1582 
1583   /* two wait loop */
1584   /* the first apply to fast data transfer (ie when no scaaning is undergoing) */
1585   /* and we fallback to the second in case the scanner is answering slowly */
1586   i = 0;
1587   while ((i < FIFO_WAIT) && ((breg & 0x02) == 0))
1588     {
1589       breg = Inb (ECR);
1590       i++;
1591     }
1592   /* don't need to wait any longer */
1593   if (i < FIFO_WAIT)
1594     return 1;
1595   i = 0;
1596   while ((i < FIFO_WAIT) && ((breg & 0x02) == 0))
1597     {
1598       breg = Inb (ECR);
1599       i++;
1600       usleep (500);
1601     }
1602   if (i == FIFO_WAIT)
1603     {
1604       DBG (0, "waitFifoFull failed, time-out waiting for FIFO (%s:%d)\n",
1605 	   __FILE__, __LINE__);
1606       return 0;
1607     }
1608   return 1;
1609 }
1610 
1611 /*
1612  * surely some register reading in PS2 mode
1613  * only one nibble is accessed, may be
1614  * PS2RegisterLowNibbleRead(reg)
1615  */
1616 static int
PS2Something(int reg)1617 PS2Something (int reg)
1618 {
1619   unsigned char breg, low, high = 0;
1620 
1621   Outb (CONTROL, 0x04);
1622   Outb (DATA, reg);		/* register number ? */
1623   Outb (CONTROL, 0x06);
1624   Outb (CONTROL, 0x06);
1625   Outb (CONTROL, 0x06);
1626   breg = Inb (STATUS) & 0xF8;
1627   low = breg;
1628   breg = breg & 0x08;
1629   /* surely means register(0x10)=0x0B */
1630   /* since reg & 0x08 != 0, high and low nibble
1631    * differ, but we don't care, since we surely expect it
1632    * to be 0
1633    */
1634   if (breg != 0x08)
1635     {
1636       DBG (0, "PS2Something failed, expecting 0x08, got 0x%02X (%s:%d)\n",
1637 	   breg, __FILE__, __LINE__);
1638     }
1639   Outb (CONTROL, 0x07);
1640   Outb (CONTROL, 0x07);
1641   Outb (CONTROL, 0x07);
1642   Outb (CONTROL, 0x07);
1643   Outb (CONTROL, 0x07);
1644   Outb (CONTROL, 0x04);
1645   Outb (CONTROL, 0x04);
1646   Outb (CONTROL, 0x04);
1647   if (breg != 0x08)
1648     high = Inb (STATUS) & 0xF0;
1649   return high + ((low & 0xF0) >> 4);
1650 }
1651 
1652 static int
PS2Read(void)1653 PS2Read (void)
1654 {
1655   int res;
1656   int tmp;
1657 
1658   res = Inb (STATUS);
1659   res = Inb (STATUS);
1660   res = res & 0xF0;
1661   Outb (CONTROL, 5);
1662   Outb (CONTROL, 5);
1663   Outb (CONTROL, 5);
1664   Outb (CONTROL, 5);
1665   Outb (CONTROL, 5);
1666   Outb (CONTROL, 5);
1667   Outb (CONTROL, 4);
1668   Outb (CONTROL, 4);
1669   Outb (CONTROL, 4);
1670   Outb (CONTROL, 4);
1671   Outb (CONTROL, 4);
1672   Outb (CONTROL, 4);
1673 
1674   tmp = Inb (STATUS);
1675   tmp = Inb (STATUS);
1676   tmp = (tmp & 0xF0) >> 4;
1677   res = res | tmp;
1678   Outb (CONTROL, 5);
1679   Outb (CONTROL, 5);
1680   Outb (CONTROL, 5);
1681   Outb (CONTROL, 5);
1682   Outb (CONTROL, 5);
1683   Outb (CONTROL, 5);
1684   Outb (CONTROL, 4);
1685   Outb (CONTROL, 4);
1686   Outb (CONTROL, 4);
1687   Outb (CONTROL, 4);
1688   Outb (CONTROL, 4);
1689   Outb (CONTROL, 4);
1690 
1691   return res;
1692 }
1693 
1694 
1695 /******************************************************************************/
1696 /* PS2registerWrite: write value in register, slow method                            */
1697 /******************************************************************************/
1698 static void
PS2registerWrite(int reg, int value)1699 PS2registerWrite (int reg, int value)
1700 {
1701   /* select register */
1702   Outb (DATA, reg | 0x60);
1703   Outb (DATA, reg | 0x60);
1704   Outb (CONTROL, 0x01);
1705   Outb (CONTROL, 0x01);
1706   Outb (CONTROL, 0x01);
1707 
1708   /* send value */
1709   Outb (DATA, value);
1710   Outb (DATA, value);
1711   Outb (CONTROL, 0x04);
1712   Outb (CONTROL, 0x04);
1713   Outb (CONTROL, 0x04);
1714 }
1715 
1716 
1717 
1718 /*****************************************************************************/
1719 /* Send command returns 0 on failure, 1 on success                           */
1720 /*****************************************************************************/
1721 static int
sendCommand(int cmd)1722 sendCommand (int cmd)
1723 {
1724   int control;
1725   int tmp;
1726   int val;
1727   int i;
1728 
1729   if (g674 != 0)
1730     {
1731       DBG (0, "No scanner attached, sendCommand(0x%X) failed\n", cmd);
1732       return 0;
1733     }
1734 
1735   control = Inb (CONTROL) & 0x3F;
1736   tmp = cmd & 0xF8;
1737 
1738 
1739   if ((g67D != 1) && (tmp != 0xE0) && (tmp != 0x20) && (tmp != 0x40)
1740       && (tmp != 0xD0) && (tmp != 0x08) && (tmp != 0x48))
1741     {
1742       Outb (CONTROL, 4);	/* reset printer */
1743     }
1744   else
1745     {
1746       val = control & 0x1F;
1747       if (g67D != 1)
1748 	val = val & 0xF;	/* no IRQ */
1749       val = val | 0x4;
1750       Outb (CONTROL, val);
1751       Outb (CONTROL, val);
1752     }
1753 
1754   /* send sequence */
1755   Outb (DATA, 0x22);
1756   Outb (DATA, 0x22);
1757   Outb (DATA, 0xAA);
1758   Outb (DATA, 0xAA);
1759   Outb (DATA, 0x55);
1760   Outb (DATA, 0x55);
1761   Outb (DATA, 0x00);
1762   Outb (DATA, 0x00);
1763   Outb (DATA, 0xFF);
1764   Outb (DATA, 0xFF);
1765   Outb (DATA, 0x87);
1766   Outb (DATA, 0x87);
1767   Outb (DATA, 0x78);
1768   Outb (DATA, 0x78);
1769   Outb (DATA, cmd);
1770   Outb (DATA, cmd);
1771 
1772   cmd = cmd & 0xF8;
1773 
1774   if ((g67D == 1) && (cmd == 0xE0))
1775     {
1776       val = Inb (CONTROL);
1777       val = (val & 0xC) | 0x01;
1778       Outb (CONTROL, val);
1779       Outb (CONTROL, val);
1780       val = val & 0xC;
1781       Outb (CONTROL, val);
1782       Outb (CONTROL, val);
1783       goto sendCommandEnd;
1784     }
1785 
1786   if ((cmd != 8) && (cmd != 0x48))
1787     {
1788       tmp = Inb (CONTROL);
1789       tmp = Inb (CONTROL);
1790       tmp = tmp & 0x1E;
1791       if (g67D != 1)
1792 	tmp = tmp & 0xE;
1793       Outb (CONTROL, tmp);
1794       Outb (CONTROL, tmp);
1795     }
1796 
1797   if (cmd == 0x10)
1798     {
1799       tmp = PS2Read ();
1800       tmp = tmp * 256 + PS2Read ();
1801       goto sendCommandEnd;
1802     }
1803 
1804   if (cmd == 8)
1805     {
1806       if (g67D == 1)
1807 	{
1808 	  i = 0;
1809 	  while (i < g67E)
1810 	    {
1811 	      tmp = Inb (CONTROL);
1812 	      tmp = Inb (CONTROL);
1813 	      tmp = (tmp & 0x1E) | 0x1;
1814 	      Outb (CONTROL, tmp);
1815 	      Outb (CONTROL, tmp);
1816 	      Inb (STATUS);
1817 	      tmp = tmp & 0x1E;
1818 	      Outb (CONTROL, tmp);
1819 	      Outb (CONTROL, tmp);
1820 
1821 	      /* next read */
1822 	      i++;
1823 	      if (i < g67E)
1824 		{
1825 		  Outb (DATA, i | 8);
1826 		  Outb (DATA, i | 8);
1827 		}
1828 	    }
1829 	  goto sendCommandEnd;
1830 	}
1831       else
1832 	{
1833 	  DBG (0, "UNEXPLORED BRANCH %s:%d\n", __FILE__, __LINE__);
1834 	  return 0;
1835 	}
1836     }
1837 
1838   /*  */
1839   if (cmd == 0)
1840     {
1841       i = 0;
1842       do
1843 	{
1844 	  tmp = Inb (CONTROL);
1845 	  tmp = (tmp & 0xE) | 0x1;
1846 	  Outb (CONTROL, tmp);
1847 	  Outb (CONTROL, tmp);
1848 	  tmp = tmp & 0xE;
1849 	  Outb (CONTROL, tmp);
1850 	  Outb (CONTROL, tmp);
1851 
1852 	  i++;
1853 	  if (i < g67E)
1854 	    {
1855 	      Outb (DATA, i);
1856 	      Outb (DATA, i);
1857 	    }
1858 	}
1859       while (i < g67E);
1860       goto sendCommandEnd;
1861     }
1862 
1863   if (cmd == 0x48)
1864     {
1865       /* this case is unneeded, should fit with the rest */
1866       tmp = Inb (CONTROL) & 0x1E;
1867       if (g67D != 1)
1868 	tmp = tmp & 0xE;
1869       Outb (CONTROL, tmp | 0x1);
1870       Outb (CONTROL, tmp | 0x1);
1871       Outb (CONTROL, tmp);
1872       Outb (CONTROL, tmp);
1873       goto sendCommandEnd;
1874     }
1875 
1876   /*  */
1877   tmp = Inb (CONTROL) & 0x1E;
1878   if (g67D != 1)
1879     tmp = tmp & 0xE;
1880   Outb (CONTROL, tmp | 0x1);
1881   Outb (CONTROL, tmp | 0x1);
1882   Outb (CONTROL, tmp);
1883   Outb (CONTROL, tmp);
1884 
1885   /* success */
1886 sendCommandEnd:
1887 
1888   if (cmd == 0x48)
1889     Outb (CONTROL, (control & 0xF) | 0x4);
1890   if (cmd == 0x30)
1891     Outb (CONTROL, (gControl & 0xF) | 0x4);
1892 
1893   /* end signature */
1894   Outb (DATA, 0xFF);
1895   Outb (DATA, 0xFF);
1896 
1897   if (cmd == 8)
1898     {
1899       Outb (CONTROL, control);
1900       return 1;
1901     }
1902 
1903   if (cmd == 0x30)
1904     {
1905       Outb (CONTROL, gControl);
1906       return 1;
1907     }
1908 
1909   if (cmd != 0xE0)
1910     Outb (CONTROL, control);
1911 
1912   return 1;
1913 }
1914 
1915 
1916 static void
ClearRegister(int reg)1917 ClearRegister (int reg)
1918 {
1919 
1920   /* choose register */
1921   Outb (DATA, reg);
1922   Outb (DATA, reg);
1923   Outb (CONTROL, 1);
1924   Outb (CONTROL, 1);
1925   if ((g6FE == 0) || (g674 != 0))
1926     {
1927       Outb (CONTROL, 1);
1928       Outb (CONTROL, 1);
1929       Outb (CONTROL, 1);
1930       Outb (CONTROL, 1);
1931     }
1932 
1933   /* clears it by not sending new value */
1934   Outb (CONTROL, 4);
1935   Outb (CONTROL, 4);
1936   Outb (CONTROL, 4);
1937   Outb (CONTROL, 4);
1938 }
1939 
1940 static void
SPPResetLPT(void)1941 SPPResetLPT (void)
1942 {
1943   Outb (CONTROL, 0x04);
1944 }
1945 
1946 
1947 static int
PS2registerRead(int reg)1948 PS2registerRead (int reg)
1949 {
1950   int low, high;
1951 
1952 
1953   /* send register number */
1954   Outb (DATA, reg);
1955   Outb (DATA, reg);
1956 
1957   /* get low nibble */
1958   Outb (CONTROL, 1);
1959   Outb (CONTROL, 3);
1960   Outb (CONTROL, 3);
1961   Outb (CONTROL, 3);
1962   Outb (CONTROL, 3);
1963   low = Inb (STATUS);
1964   low = Inb (STATUS);
1965 
1966   /* get high nibble */
1967   Outb (CONTROL, 4);
1968   Outb (CONTROL, 4);
1969   Outb (CONTROL, 4);
1970   high = Inb (STATUS);
1971   high = Inb (STATUS);
1972 
1973   /* merge nibbles and return */
1974   high = (high & 0xF0) | ((low & 0xF0) >> 4);
1975   return high;
1976 }
1977 
1978 
1979 static void
PS2bufferRead(int size, unsigned char *dest)1980 PS2bufferRead (int size, unsigned char *dest)
1981 {
1982   int high;
1983   int low;
1984   int i;
1985   int count;
1986   int bytel, byteh;
1987 
1988   /* init transfer */
1989   Outb (DATA, 7);
1990   Outb (DATA, 7);
1991   Outb (CONTROL, 1);
1992   Outb (CONTROL, 1);
1993   Outb (CONTROL, 3);
1994   Outb (CONTROL, 3);
1995   Outb (CONTROL, 3);
1996   Outb (DATA, 0xFF);
1997   Outb (DATA, 0xFF);
1998   count = (size - 2) / 2;
1999   i = 0;
2000   bytel = 0x06;			/* signals low byte of word  */
2001   byteh = 0x07;			/* signals high byte of word */
2002 
2003   /* read loop */
2004   while (count > 0)
2005     {
2006       /* low nibble byte 0 */
2007       Outb (CONTROL, bytel);
2008       Outb (CONTROL, bytel);
2009       Outb (CONTROL, bytel);
2010       low = Inb (STATUS);
2011       if ((low & 0x08) == 0)
2012 	{
2013 	  /* high nibble <> low nibble */
2014 	  Outb (CONTROL, bytel & 0x05);
2015 	  Outb (CONTROL, bytel & 0x05);
2016 	  Outb (CONTROL, bytel & 0x05);
2017 	  high = Inb (STATUS);
2018 	}
2019       else
2020 	{
2021 	  high = low;
2022 	}
2023       low = low & 0xF0;
2024       high = high & 0xF0;
2025       dest[i] = (unsigned char) (high | (low >> 4));
2026       i++;
2027 
2028       /* low nibble byte 1 */
2029       Outb (CONTROL, byteh);
2030       Outb (CONTROL, byteh);
2031       Outb (CONTROL, byteh);
2032       low = Inb (STATUS);
2033       if ((low & 0x08) == 0)
2034 	{
2035 	  /* high nibble <> low nibble */
2036 	  Outb (CONTROL, byteh & 0x05);
2037 	  Outb (CONTROL, byteh & 0x05);
2038 	  Outb (CONTROL, byteh & 0x05);
2039 	  high = Inb (STATUS);
2040 	}
2041       else
2042 	{
2043 	  high = low;
2044 	}
2045       low = low & 0xF0;
2046       high = high & 0xF0;
2047       dest[i] = (unsigned char) (high | (low >> 4));
2048       i++;
2049 
2050       /* next read */
2051       count--;
2052     }
2053 
2054   /* final read        */
2055   /* low nibble byte 0 */
2056   Outb (CONTROL, bytel);
2057   Outb (CONTROL, bytel);
2058   Outb (CONTROL, bytel);
2059   low = Inb (STATUS);
2060   if ((low & 0x08) == 0)
2061     {
2062       /* high nibble <> low nibble */
2063       Outb (CONTROL, bytel & 0x05);
2064       Outb (CONTROL, bytel & 0x05);
2065       Outb (CONTROL, bytel & 0x05);
2066       high = Inb (STATUS);
2067     }
2068   else
2069     {
2070       high = low;
2071     }
2072   low = low & 0xF0;
2073   high = high & 0xF0;
2074   dest[i] = (unsigned char) (high | (low >> 4));
2075   i++;
2076 
2077   /* uneven size need an extra read */
2078   if ((size & 0x01) == 1)
2079     {
2080       /* low nibble byte 1 */
2081       Outb (CONTROL, byteh);
2082       Outb (CONTROL, byteh);
2083       Outb (CONTROL, byteh);
2084       low = Inb (STATUS);
2085       if ((low & 0x08) == 0)
2086 	{
2087 	  /* high nibble <> low nibble */
2088 	  Outb (CONTROL, byteh & 0x05);
2089 	  Outb (CONTROL, byteh & 0x05);
2090 	  Outb (CONTROL, byteh & 0x05);
2091 	  high = Inb (STATUS);
2092 	}
2093       else
2094 	{
2095 	  high = low;
2096 	}
2097       low = low & 0xF0;
2098       high = high & 0xF0;
2099       dest[i] = (unsigned char) (high | (low >> 4));
2100       i++;
2101 
2102       /* swap high/low word */
2103       count = bytel;
2104       bytel = byteh;
2105       byteh = count;
2106     }
2107 
2108   /* final byte ... */
2109   Outb (DATA, 0xFD);
2110   Outb (DATA, 0xFD);
2111   Outb (DATA, 0xFD);
2112 
2113   /* low nibble */
2114   Outb (CONTROL, byteh);
2115   Outb (CONTROL, byteh);
2116   Outb (CONTROL, byteh);
2117   low = Inb (STATUS);
2118   if ((low & 0x08) == 0)
2119     {
2120       /* high nibble <> low nibble */
2121       Outb (CONTROL, byteh & 0x05);
2122       Outb (CONTROL, byteh & 0x05);
2123       Outb (CONTROL, byteh & 0x05);
2124       high = Inb (STATUS);
2125     }
2126   else
2127     {
2128       high = low;
2129     }
2130   low = low & 0xF0;
2131   high = high & 0xF0;
2132   dest[i] = (unsigned char) (high | (low >> 4));
2133   i++;
2134 
2135   /* reset port */
2136   Outb (DATA, 0x00);
2137   Outb (DATA, 0x00);
2138   Outb (CONTROL, 0x04);
2139 }
2140 
2141 static void
PS2bufferWrite(int size, unsigned char *source)2142 PS2bufferWrite (int size, unsigned char *source)
2143 {
2144   int i;
2145   int count;
2146   int val;
2147 
2148   /* init buffer write */
2149   i = 0;
2150   count = size / 2;
2151   Outb (DATA, 0x67);
2152   Outb (CONTROL, 0x01);
2153   Outb (CONTROL, 0x01);
2154   Outb (CONTROL, 0x05);
2155 
2156   /* write loop */
2157   while (count > 0)
2158     {
2159       /* low byte of word */
2160       val = source[i];
2161       i++;
2162       Outb (DATA, val);
2163       Outb (DATA, val);
2164       Outb (CONTROL, 0x04);
2165       Outb (CONTROL, 0x04);
2166       Outb (CONTROL, 0x04);
2167       Outb (CONTROL, 0x04);
2168 
2169       /* high byte of word */
2170       val = source[i];
2171       i++;
2172       Outb (DATA, val);
2173       Outb (DATA, val);
2174       Outb (CONTROL, 0x05);
2175       Outb (CONTROL, 0x05);
2176       Outb (CONTROL, 0x05);
2177       Outb (CONTROL, 0x05);
2178 
2179       /* next write */
2180       count--;
2181     }
2182 
2183   /* termination sequence */
2184   Outb (CONTROL, 0x05);
2185   Outb (CONTROL, 0x05);
2186   Outb (CONTROL, 0x05);
2187   Outb (CONTROL, 0x05);
2188   Outb (CONTROL, 0x07);
2189   Outb (CONTROL, 0x07);
2190   Outb (CONTROL, 0x07);
2191   Outb (CONTROL, 0x07);
2192   Outb (CONTROL, 0x04);
2193   Outb (CONTROL, 0x04);
2194 }
2195 
2196 
2197 
2198 
2199 static void
init001(void)2200 init001 (void)
2201 {
2202   int i;
2203   int val;
2204   int status;
2205 
2206   ClearRegister (0);
2207   Outb (CONTROL, 0x0C);
2208   if (g674 != 0)
2209     {
2210       Outb (CONTROL, 0x0C);
2211       Outb (CONTROL, 0x0C);
2212       Outb (CONTROL, 0x0C);
2213     }
2214   Outb (DATA, 0x40);
2215   if (g674 != 0)
2216     {
2217       Outb (DATA, 0x40);
2218       Outb (DATA, 0x40);
2219       Outb (DATA, 0x40);
2220     }
2221   Outb (CONTROL, 0x06);
2222   Outb (CONTROL, 0x06);
2223   Outb (CONTROL, 0x06);
2224   if (g674 != 0)
2225     {
2226       Outb (CONTROL, 0x06);
2227       Outb (CONTROL, 0x06);
2228       Outb (CONTROL, 0x06);
2229     }
2230 
2231   /* sync loop */
2232   i = 256;
2233   do
2234     {
2235       status = Inb (STATUS);
2236       i--;
2237     }
2238   while ((i > 0) && ((status & 0x40)));
2239   val = 0x0C;
2240   if (i > 0)
2241     {
2242       Outb (CONTROL, 0x07);
2243       Outb (CONTROL, 0x07);
2244       Outb (CONTROL, 0x07);
2245       if (g674 != 0)
2246 	{
2247 	  Outb (CONTROL, 0x07);
2248 	  Outb (CONTROL, 0x07);
2249 	  Outb (CONTROL, 0x07);
2250 	}
2251       val = 0x04;
2252       Outb (CONTROL, val);
2253       Outb (CONTROL, val);
2254       Outb (CONTROL, val);
2255       if (g674 != 0)
2256 	{
2257 	  Outb (CONTROL, val);
2258 	  Outb (CONTROL, val);
2259 	  Outb (CONTROL, val);
2260 	}
2261     }
2262   val = val | 0x0C;
2263   Outb (CONTROL, val);
2264   Outb (CONTROL, val);
2265   Outb (CONTROL, val);
2266   if (g674 != 0)
2267     {
2268       Outb (CONTROL, val);
2269       Outb (CONTROL, val);
2270       Outb (CONTROL, val);
2271     }
2272   val = val & 0xF7;
2273   Outb (CONTROL, val);
2274   Outb (CONTROL, val);
2275   Outb (CONTROL, val);
2276   if (g674 != 0)
2277     {
2278       Outb (CONTROL, val);
2279       Outb (CONTROL, val);
2280       Outb (CONTROL, val);
2281     }
2282 }
2283 
2284 /* SPP register reading */
2285 static int
init002(int arg)2286 init002 (int arg)
2287 {
2288   int data;
2289 
2290   if (arg == 1)
2291     return 0;
2292   Outb (DATA, 0x0B);
2293   Outb (CONTROL, 0x04);
2294   Outb (CONTROL, 0x04);
2295   Outb (CONTROL, 0x04);
2296   Outb (CONTROL, 0x0C);
2297   Outb (CONTROL, 0x0C);
2298   Outb (CONTROL, 0x0C);
2299   Outb (CONTROL, 0x04);
2300   Outb (CONTROL, 0x24);
2301   Outb (CONTROL, 0x24);
2302   Outb (CONTROL, 0x26);
2303   Outb (CONTROL, 0x26);
2304 
2305   data = Inb (DATA);
2306   Outb (CONTROL, 0x04);
2307   if (data == gEPAT)
2308     {
2309       return 1;
2310     }
2311   return 0;
2312 }
2313 
2314 /*
2315  * connecct to the EPAT chip, and
2316  * prepare command sending
2317  */
2318 static int
ECPconnect(void)2319 ECPconnect (void)
2320 {
2321   int ret, control;
2322 
2323   /* these 3 lines set to 'inital mode' */
2324   byteMode ();			/*Outb (ECR, 0x20); */
2325   Outb (DATA, 0x04);		/* gData */
2326   Outb (CONTROL, 0x0C);		/* gControl */
2327 
2328   Inb (ECR);			/* 0x35 */
2329   byteMode ();			/*Outb (ECR, 0x20); */
2330   byteMode ();			/*Outb (ECR, 0x20); */
2331 
2332   gData = Inb (DATA);
2333   gControl = Inb (CONTROL);
2334 
2335   Inb (DATA);
2336   control = Inb (CONTROL);
2337   Outb (CONTROL, control & 0x1F);
2338   control = Inb (CONTROL);
2339   Outb (CONTROL, control & 0x1F);
2340   sendCommand (0xE0);
2341 
2342   Outb (DATA, 0xFF);
2343   Outb (DATA, 0xFF);
2344   ClearRegister (0);
2345   Outb (CONTROL, 0x0C);
2346   Outb (CONTROL, 0x04);
2347   ClearRegister (0);
2348   ret = PS2Something (0x10);
2349   if (ret != 0x0B)
2350     {
2351       DBG (16,
2352 	   "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", ret,
2353 	   __FILE__, __LINE__);
2354     }
2355   return 1;
2356 }
2357 
2358 static void
EPPdisconnect(void)2359 EPPdisconnect (void)
2360 {
2361   if (getModel () != 0x07)
2362     sendCommand (40);
2363   sendCommand (30);
2364   Outb (DATA, gData);
2365   Outb (CONTROL, gControl);
2366 }
2367 
2368 static void
ECPdisconnect(void)2369 ECPdisconnect (void)
2370 {
2371   int control;
2372 
2373   if (getModel () != 0x07)	/* guessed */
2374     sendCommand (40);		/* guessed */
2375   sendCommand (0x30);
2376   control = Inb (CONTROL) | 0x01;
2377   Outb (CONTROL, control);
2378   Outb (CONTROL, control);
2379   control = control & 0x04;
2380   Outb (CONTROL, control);
2381   Outb (CONTROL, control);
2382   control = control | 0x08;
2383   Outb (CONTROL, control);
2384   Outb (DATA, 0xFF);
2385   Outb (DATA, 0xFF);
2386   Outb (CONTROL, control);
2387 }
2388 
2389 static int
ECPregisterRead(int reg)2390 ECPregisterRead (int reg)
2391 {
2392   unsigned char breg, value;
2393 
2394 #ifdef HAVE_LINUX_PPDEV_H
2395   int rc, mode, fd;
2396   unsigned char bval;
2397 
2398   fd = sanei_umax_pp_getparport ();
2399   if (fd > 0)
2400     {
2401       Outb (CONTROL, 0x04);
2402       ECPFifoMode ();
2403       Outb (DATA, reg);
2404       mode = 1;			/* data_reverse */
2405       rc = ioctl (fd, PPDATADIR, &mode);
2406       if (rc)
2407 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2408 	     __FILE__, __LINE__);
2409       rc = read (fd, &bval, 1);
2410       if (rc != 1)
2411 	DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__);
2412       value = bval;
2413       breg = (Inb (CONTROL) & 0x3F);
2414       if (breg != 0x20)
2415 	{
2416 	  DBG (0,
2417 	       "ECPregisterRead failed, expecting 0x20, got 0x%02X (%s:%d)\n",
2418 	       breg, __FILE__, __LINE__);
2419 	}
2420 
2421       /* restore port state */
2422       mode = 0;			/* data_forward */
2423       rc = ioctl (fd, PPDATADIR, &mode);
2424       if (rc)
2425 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2426 	     __FILE__, __LINE__);
2427       Outb (CONTROL, 0x04);
2428       byteMode ();
2429       return value;
2430     }
2431 #endif
2432 
2433   Outb (CONTROL, 0x4);
2434 
2435   /* ECP FIFO mode, interrupt bit, dma disabled,
2436      service bit, fifo full=0, fifo empty=0 */
2437   ECPFifoMode ();		/*Outb (ECR, 0x60); */
2438   if (waitFifoEmpty () == 0)
2439     {
2440       DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n",
2441 	   __FILE__, __LINE__);
2442     }
2443   breg = Inb (ECR);
2444 
2445   Outb (DATA, reg);
2446   if (waitFifoEmpty () == 0)
2447     {
2448       DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n",
2449 	   __FILE__, __LINE__);
2450     }
2451   breg = Inb (ECR);
2452 
2453   /* byte mode, interrupt bit, dma disabled,
2454      service bit, fifo full=0, fifo empty=0 */
2455   byteMode ();			/*Outb (ECR, 0x20); */
2456   Outb (CONTROL, 0x20);		/* data reverse */
2457 
2458   /* ECP FIFO mode, interrupt bit, dma disabled,
2459      service bit, fifo full=0, fifo empty=0 */
2460   ECPFifoMode ();		/*Outb (ECR, 0x60); */
2461   if (waitFifoNotEmpty () == 0)
2462     {
2463       DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n",
2464 	   __FILE__, __LINE__);
2465     }
2466   breg = Inb (ECR);
2467   value = Inb (ECPDATA);
2468 
2469   /* according to the spec bit 7 and 6 are unused */
2470   breg = (Inb (CONTROL) & 0x3F);
2471   if (breg != 0x20)
2472     {
2473       DBG (0, "ECPregisterRead failed, expecting 0x20, got 0x%02X (%s:%d)\n",
2474 	   breg, __FILE__, __LINE__);
2475     }
2476   Outb (CONTROL, 0x04);
2477   byteMode ();
2478   return value;
2479 }
2480 
2481 static int
EPPregisterRead(int reg)2482 EPPregisterRead (int reg)
2483 {
2484 #ifdef HAVE_LINUX_PPDEV_H
2485   int fd, mode, rc;
2486   unsigned char breg, bval;
2487   int value;
2488 #endif
2489   int control;
2490 
2491 
2492 #ifdef HAVE_LINUX_PPDEV_H
2493   /* check we have ppdev working */
2494   fd = sanei_umax_pp_getparport ();
2495   if (fd > 0)
2496     {
2497       breg = (unsigned char) (reg);
2498       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2499       rc = ioctl (fd, PPSETMODE, &mode);
2500       if (rc)
2501 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2502 	     __FILE__, __LINE__);
2503       rc = write (fd, &breg, 1);
2504       if (rc != 1)
2505 	DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
2506 
2507       mode = 1;			/* data_reverse */
2508       rc = ioctl (fd, PPDATADIR, &mode);
2509       if (rc)
2510 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2511 	     __FILE__, __LINE__);
2512 
2513       mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2514       rc = ioctl (fd, PPSETMODE, &mode);
2515       if (rc)
2516 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2517 	     __FILE__, __LINE__);
2518       rc = read (fd, &bval, 1);
2519       if (rc != 1)
2520 	DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__);
2521       value = bval;
2522 
2523       mode = 0;			/* forward */
2524       rc = ioctl (fd, PPDATADIR, &mode);
2525       if (rc)
2526 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2527 	     __FILE__, __LINE__);
2528 
2529       return value;
2530     }
2531   /* if not, direct hardware access */
2532 #endif
2533 
2534   Outb (EPPADDR, reg);
2535   control = Inb (CONTROL);
2536   control = (control & 0x1F) | 0x20;
2537   Outb (CONTROL, control);
2538   Inb (EPPDATA);
2539   control = Inb (CONTROL);
2540   control = control & 0x1F;
2541   Outb (CONTROL, control);
2542   return 0xFF;
2543   /* return value; */
2544 }
2545 
2546 static int
registerRead(int reg)2547 registerRead (int reg)
2548 {
2549   switch (gMode)
2550     {
2551     case UMAX_PP_PARPORT_ECP:
2552       return ECPregisterRead (reg);
2553     case UMAX_PP_PARPORT_BYTE:
2554       DBG (0, "STEF: gMode BYTE in registerRead !!\n");
2555       return 0xFF;
2556     case UMAX_PP_PARPORT_EPP:
2557       return EPPregisterRead (reg);
2558     case UMAX_PP_PARPORT_PS2:
2559       DBG (0, "STEF: gMode PS2 in registerRead !!\n");
2560       return PS2registerRead (reg);
2561     default:
2562       DBG (0, "STEF: gMode unset in registerRead !!\n");
2563       return 0xFF;
2564     }
2565 }
2566 
2567 
2568 static void
ECPregisterWrite(int reg, int value)2569 ECPregisterWrite (int reg, int value)
2570 {
2571 #ifdef HAVE_LINUX_PPDEV_H
2572   unsigned char breg;
2573   int rc, fd;
2574 
2575   fd = sanei_umax_pp_getparport ();
2576   if (fd > 0)
2577     {
2578       ECPFifoMode ();
2579       Outb (DATA, reg);
2580       breg = value;
2581       rc = write (fd, &breg, 1);
2582       if (rc != 1)
2583 	DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
2584       Outb (CONTROL, 0x04);
2585       byteMode ();
2586       return;
2587     }
2588 #endif
2589 
2590   /* standard mode, interrupt bit, dma disabled,
2591      service bit, fifo full=0, fifo empty=0 */
2592   compatMode ();
2593   Outb (CONTROL, 0x04);		/* reset ? */
2594 
2595   /* ECP FIFO mode, interrupt bit, dma disabled,
2596      service bit, fifo full=0, fifo empty=0 */
2597   ECPFifoMode ();		/*Outb (ECR, 0x60); */
2598   if (waitFifoEmpty () == 0)
2599     {
2600       DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n",
2601 	   __FILE__, __LINE__);
2602       return;
2603     }
2604   Inb (ECR);
2605 
2606   Outb (DATA, reg);
2607   if (waitFifoEmpty () == 0)
2608     {
2609       DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n",
2610 	   __FILE__, __LINE__);
2611       return;
2612     }
2613   Inb (ECR);
2614 
2615   Outb (ECPDATA, value);
2616   if (waitFifoEmpty () == 0)
2617     {
2618       DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n",
2619 	   __FILE__, __LINE__);
2620       return;
2621     }
2622   Inb (ECR);
2623   Outb (CONTROL, 0x04);
2624   byteMode ();
2625   return;
2626 }
2627 
2628 static void
EPPregisterWrite(int reg, int value)2629 EPPregisterWrite (int reg, int value)
2630 {
2631 #ifdef HAVE_LINUX_PPDEV_H
2632   int fd, mode, rc;
2633   unsigned char breg, bval;
2634 #endif
2635 
2636   reg = reg | 0x40;
2637 
2638 #ifdef HAVE_LINUX_PPDEV_H
2639   /* check we have ppdev working */
2640   fd = sanei_umax_pp_getparport ();
2641   if (fd > 0)
2642     {
2643       breg = (unsigned char) (reg);
2644       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2645       rc = ioctl (fd, PPSETMODE, &mode);
2646       if (rc)
2647 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2648 	     __FILE__, __LINE__);
2649       rc = write (fd, &breg, 1);
2650       if (rc != 1)
2651 	DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
2652 
2653       bval = (unsigned char) (value);
2654       mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2655       rc = ioctl (fd, PPSETMODE, &mode);
2656       if (rc)
2657 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2658 	     __FILE__, __LINE__);
2659       rc = write (fd, &bval, 1);
2660 
2661       return;
2662     }
2663   /* if not, direct hardware access */
2664 #endif
2665   Outb (EPPADDR, reg);
2666   Outb (EPPDATA, value);
2667 }
2668 
2669 static void
registerWrite(int reg, int value)2670 registerWrite (int reg, int value)
2671 {
2672   switch (gMode)
2673     {
2674     case UMAX_PP_PARPORT_PS2:
2675       PS2registerWrite (reg, value);
2676       DBG (0, "STEF: gMode PS2 in registerWrite !!\n");
2677       break;
2678     case UMAX_PP_PARPORT_ECP:
2679       ECPregisterWrite (reg, value);
2680       break;
2681     case UMAX_PP_PARPORT_EPP:
2682       EPPregisterWrite (reg, value);
2683       break;
2684     case UMAX_PP_PARPORT_BYTE:
2685       DBG (0, "STEF: gMode BYTE in registerWrite !!\n");
2686       break;
2687     default:
2688       DBG (0, "STEF: gMode unset in registerWrite !!\n");
2689       break;
2690     }
2691 }
2692 
2693 static void
EPPBlockMode(int flag)2694 EPPBlockMode (int flag)
2695 {
2696 #ifdef HAVE_LINUX_PPDEV_H
2697   int fd, mode, rc;
2698   unsigned char bval;
2699 
2700   /* check we have ppdev working */
2701   fd = sanei_umax_pp_getparport ();
2702   if (fd > 0)
2703     {
2704       bval = (unsigned char) (flag);
2705       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2706       rc = ioctl (fd, PPSETMODE, &mode);
2707       if (rc)
2708 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2709 	     __FILE__, __LINE__);
2710       rc = write (fd, &bval, 1);
2711       return;
2712     }
2713 #endif
2714   Outb (EPPADDR, flag);
2715 }
2716 
2717 static void
EPPbufferRead(int size, unsigned char *dest)2718 EPPbufferRead (int size, unsigned char *dest)
2719 {
2720 #ifdef HAVE_LINUX_PPDEV_H
2721   int fd, mode, rc, nb;
2722   unsigned char bval;
2723 #endif
2724   int control;
2725 
2726 #ifdef HAVE_LINUX_PPDEV_H
2727   /* check we have ppdev working */
2728   fd = sanei_umax_pp_getparport ();
2729   if (fd > 0)
2730     {
2731 
2732       bval = 0x80;
2733       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2734       rc = ioctl (fd, PPSETMODE, &mode);
2735       if (rc)
2736 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2737 	     __FILE__, __LINE__);
2738       rc = write (fd, &bval, 1);
2739 
2740       mode = 1;			/* data_reverse */
2741       rc = ioctl (fd, PPDATADIR, &mode);
2742       if (rc)
2743 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2744 	     __FILE__, __LINE__);
2745 #ifdef PPSETFLAGS
2746       mode = PP_FASTREAD;
2747       rc = ioctl (fd, PPSETFLAGS, &mode);
2748       if (rc)
2749 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2750 	     __FILE__, __LINE__);
2751 #endif
2752       mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2753       rc = ioctl (fd, PPSETMODE, &mode);
2754       if (rc)
2755 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2756 	     __FILE__, __LINE__);
2757       nb = 0;
2758       while (nb < size - 1)
2759 	{
2760 	  rc = read (fd, dest + nb, size - 1 - nb);
2761 	  nb += rc;
2762 	}
2763 
2764       mode = 0;			/* forward */
2765       rc = ioctl (fd, PPDATADIR, &mode);
2766       if (rc)
2767 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2768 	     __FILE__, __LINE__);
2769       bval = 0xA0;
2770       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2771       rc = ioctl (fd, PPSETMODE, &mode);
2772       if (rc)
2773 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2774 	     __FILE__, __LINE__);
2775       rc = write (fd, &bval, 1);
2776 
2777       mode = 1;			/* data_reverse */
2778       rc = ioctl (fd, PPDATADIR, &mode);
2779       if (rc)
2780 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2781 	     __FILE__, __LINE__);
2782       mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2783       rc = ioctl (fd, PPSETMODE, &mode);
2784       if (rc)
2785 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2786 	     __FILE__, __LINE__);
2787       rc = read (fd, dest + size - 1, 1);
2788 
2789       mode = 0;			/* forward */
2790       rc = ioctl (fd, PPDATADIR, &mode);
2791       if (rc)
2792 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2793 	     __FILE__, __LINE__);
2794 
2795       return;
2796     }
2797   /* if not, direct hardware access */
2798 #endif
2799 
2800   EPPBlockMode (0x80);
2801   control = Inb (CONTROL);
2802   Outb (CONTROL, (control & 0x1F) | 0x20);	/* reverse */
2803   Insb (EPPDATA, dest, size - 1);
2804   control = Inb (CONTROL);
2805 
2806   Outb (CONTROL, (control & 0x1F));	/* forward */
2807   EPPBlockMode (0xA0);
2808   control = Inb (CONTROL);
2809 
2810   Outb (CONTROL, (control & 0x1F) | 0x20);	/* reverse */
2811   Insb (EPPDATA, (unsigned char *) (dest + size - 1), 1);
2812 
2813   control = Inb (CONTROL);
2814   Outb (CONTROL, (control & 0x1F));	/* forward */
2815 }
2816 
2817 
2818 /* block transfer init */
2819 static void
ECPSetBuffer(int size)2820 ECPSetBuffer (int size)
2821 {
2822   static int last = 0;
2823 
2824   /* routine XX */
2825   compatMode ();
2826   Outb (CONTROL, 0x04);		/* reset ? */
2827 
2828   /* we set size only if it has changed */
2829   /* from last time        */
2830   if (size == last)
2831     return;
2832   last = size;
2833 
2834   /* mode and size setting */
2835   ECPFifoMode ();		/*Outb (ECR, 0x60);         */
2836   if (waitFifoEmpty () == 0)
2837     {
2838       DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2839 	   __FILE__, __LINE__);
2840       return;
2841     }
2842   Inb (ECR);
2843 
2844   Outb (DATA, 0x0E);
2845   if (waitFifoEmpty () == 0)
2846     {
2847       DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2848 	   __FILE__, __LINE__);
2849       return;
2850     }
2851   Inb (ECR);
2852 
2853   Outb (ECPDATA, 0x0B);		/* R0E=0x0B */
2854   if (waitFifoEmpty () == 0)
2855     {
2856       DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2857 	   __FILE__, __LINE__);
2858       return;
2859     }
2860   Inb (ECR);
2861 
2862   Outb (DATA, 0x0F);		/* R0F=size MSB */
2863   if (waitFifoEmpty () == 0)
2864     {
2865       DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2866 	   __FILE__, __LINE__);
2867       return;
2868     }
2869   Inb (ECR);
2870 
2871   Outb (ECPDATA, size / 256);
2872   if (waitFifoEmpty () == 0)
2873     {
2874       DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2875 	   __FILE__, __LINE__);
2876       return;
2877     }
2878   Inb (ECR);
2879 
2880   Outb (DATA, 0x0B);		/* R0B=size LSB */
2881   if (waitFifoEmpty () == 0)
2882     {
2883       DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2884 	   __FILE__, __LINE__);
2885       return;
2886     }
2887   Inb (ECR);
2888 
2889   Outb (ECPDATA, size % 256);
2890   if (waitFifoEmpty () == 0)
2891     {
2892       DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2893 	   __FILE__, __LINE__);
2894       return;
2895     }
2896   Inb (ECR);
2897   DBG (16, "ECPSetBuffer(%d) passed ...\n", size);
2898 }
2899 
2900 
2901 
2902 static int
ECPbufferRead(int size, unsigned char *dest)2903 ECPbufferRead (int size, unsigned char *dest)
2904 {
2905   int n, idx, remain;
2906 
2907   idx = 0;
2908   n = size / 16;
2909   remain = size - 16 * n;
2910 
2911   /* block transfer */
2912   Inb (ECR);			/* 0x15,0x75 expected: fifo empty */
2913 
2914   byteMode ();			/*Outb (ECR, 0x20);            byte mode */
2915   Outb (CONTROL, 0x04);
2916 
2917   ECPFifoMode ();		/*Outb (ECR, 0x60); */
2918   if (waitFifoEmpty () == 0)
2919     {
2920       DBG (0, "ECPbufferRead failed, time-out waiting for FIFO (%s:%d)\n",
2921 	   __FILE__, __LINE__);
2922       return idx;
2923     }
2924   Inb (ECR);
2925 
2926   Outb (DATA, 0x80);
2927   if (waitFifoEmpty () == 0)
2928     {
2929       DBG (0, "ECPbufferRead failed, time-out waiting for FIFO (%s:%d)\n",
2930 	   __FILE__, __LINE__);
2931       return idx;
2932     }
2933   Inb (ECR);			/* 0x75 expected */
2934 
2935   byteMode ();			/*Outb (ECR, 0x20);            byte mode */
2936   Outb (CONTROL, 0x20);		/* data reverse */
2937   ECPFifoMode ();		/*Outb (ECR, 0x60); */
2938 
2939   while (n > 0)
2940     {
2941       if (waitFifoFull () == 0)
2942 	{
2943 	  DBG (0,
2944 	       "ECPbufferRead failed, time-out waiting for FIFO idx=%d (%s:%d)\n",
2945 	       idx, __FILE__, __LINE__);
2946 	  return idx;
2947 	}
2948       Insb (ECPDATA, dest + idx, 16);
2949       idx += 16;
2950       n--;
2951     }
2952 
2953   /* reading trailing bytes */
2954   while (remain > 0)
2955     {
2956       if (waitFifoNotEmpty () == 0)
2957 	{
2958 	  DBG (0, "ECPbufferRead failed, FIFO time-out (%s:%d)\n",
2959 	       __FILE__, __LINE__);
2960 	}
2961       dest[idx] = Inb (ECPDATA);
2962       idx++;
2963       remain--;
2964     }
2965 
2966   return idx;
2967 }
2968 
2969 static void
EPPbufferWrite(int size, unsigned char *source)2970 EPPbufferWrite (int size, unsigned char *source)
2971 {
2972 #ifdef HAVE_LINUX_PPDEV_H
2973   int fd, mode, rc;
2974   unsigned char bval;
2975 #endif
2976 
2977 
2978 #ifdef HAVE_LINUX_PPDEV_H
2979   /* check we have ppdev working */
2980   fd = sanei_umax_pp_getparport ();
2981   if (fd > 0)
2982     {
2983       bval = 0xC0;
2984       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2985       rc = ioctl (fd, PPSETMODE, &mode);
2986       if (rc)
2987 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2988 	     __FILE__, __LINE__);
2989       rc = write (fd, &bval, 1);
2990 
2991       mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2992       rc = ioctl (fd, PPSETMODE, &mode);
2993       if (rc)
2994 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2995 	     __FILE__, __LINE__);
2996       rc = write (fd, source, size);
2997       return;
2998     }
2999   /* if not, direct hardware access */
3000 #endif
3001   EPPBlockMode (0xC0);
3002   Outsb (EPPDATA, source, size);
3003 }
3004 
3005 static void
ECPbufferWrite(int size, unsigned char *source)3006 ECPbufferWrite (int size, unsigned char *source)
3007 {
3008   unsigned char breg;
3009   int n, idx;
3010 
3011   /* until we know to handle that case, fail */
3012   if (size % 16 != 0)
3013     {
3014       DBG (0, "ECPbufferWrite failed, size %%16 !=0 (%s:%d)\n",
3015 	   __FILE__, __LINE__);
3016       return;
3017     }
3018 
3019   /* prepare actual transfer */
3020   compatMode ();
3021   Outb (CONTROL, 0x04);		/* reset ? */
3022   breg = Inb (CONTROL);
3023   Outb (CONTROL, 0x04);		/* data forward */
3024   ECPFifoMode ();		/*Outb (ECR, 0x60);         */
3025   if (waitFifoEmpty () == 0)
3026     {
3027       DBG (0, "ECPWriteBuffer failed, time-out waiting for FIFO (%s:%d)\n",
3028 	   __FILE__, __LINE__);
3029       return;
3030     }
3031   breg = Inb (ECR);
3032   breg = (Inb (STATUS)) & 0xF8;
3033   n = 0;
3034   while ((n < 1024) && (breg != 0xF8))
3035     {
3036       breg = (Inb (STATUS)) & 0xF8;
3037       n++;
3038     }
3039   if (breg != 0xF8)
3040     {
3041       DBG (0,
3042 	   "ECPbufferWrite failed, expected status=0xF8, got 0x%02X (%s:%d)\n",
3043 	   breg, __FILE__, __LINE__);
3044       return;
3045     }
3046 
3047   /* wait for FIFO empty (bit 0) */
3048   if (waitFifoEmpty () == 0)
3049     {
3050       DBG (0, "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n",
3051 	   __FILE__, __LINE__);
3052       return;
3053     }
3054   breg = Inb (ECR);
3055 
3056   /* block transfer direction
3057    * 0x80 means from scanner to PC, 0xC0 means PC to scanner
3058    */
3059   Outb (DATA, 0xC0);
3060 
3061   n = size / 16;
3062   idx = 0;
3063   while (n > 0)
3064     {
3065       /* wait for FIFO empty */
3066       if (waitFifoEmpty () == 0)
3067 	{
3068 	  DBG (0,
3069 	       "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n",
3070 	       __FILE__, __LINE__);
3071 	  return;
3072 	}
3073       breg = Inb (ECR);
3074 
3075       Outsb (ECPDATA, source + idx * 16, 16);
3076       idx++;
3077       n--;
3078     }
3079 
3080 
3081   /* final FIFO check and go to Byte mode */
3082   if (waitFifoEmpty () == 0)
3083     {
3084       DBG (0, "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n",
3085 	   __FILE__, __LINE__);
3086       return;
3087     }
3088   breg = Inb (ECR);
3089   Outb (CONTROL, 0x04);
3090   byteMode ();
3091 }
3092 
3093 static void
bufferWrite(int size, unsigned char *source)3094 bufferWrite (int size, unsigned char *source)
3095 {
3096   switch (gMode)
3097     {
3098     case UMAX_PP_PARPORT_PS2:
3099       PS2bufferWrite (size, source);
3100       DBG (0, "STEF: gMode PS2 in bufferWrite !!\n");
3101       break;
3102     case UMAX_PP_PARPORT_ECP:
3103       ECPbufferWrite (size, source);
3104       break;
3105     case UMAX_PP_PARPORT_EPP:
3106       switch (getEPPMode ())
3107 	{
3108 	case 32:
3109 	  EPPWrite32Buffer (size, source);
3110 	  break;
3111 	default:
3112 	  EPPbufferWrite (size, source);
3113 	  break;
3114 	}
3115       break;
3116     default:
3117       DBG (0, "STEF: gMode PS2 in bufferWrite !!\n");
3118       break;
3119     }
3120   return;
3121 }
3122 
3123 static void
bufferRead(int size, unsigned char *dest)3124 bufferRead (int size, unsigned char *dest)
3125 {
3126   switch (gMode)
3127     {
3128     case UMAX_PP_PARPORT_PS2:
3129       PS2bufferRead (size, dest);
3130       DBG (0, "STEF: gMode PS2 in bufferRead !!\n");
3131       break;
3132     case UMAX_PP_PARPORT_ECP:
3133       ECPbufferRead (size, dest);
3134       break;
3135     case UMAX_PP_PARPORT_EPP:
3136       switch (getEPPMode ())
3137 	{
3138 	case 32:
3139 	  EPPRead32Buffer (size, dest);
3140 	  break;
3141 	default:
3142 	  EPPbufferRead (size, dest);
3143 	  break;
3144 	}
3145       break;
3146     default:
3147       DBG (0, "STEF: gMode unset in bufferRead !!\n");
3148       break;
3149     }
3150   return;
3151 }
3152 
3153 static int
connect(void)3154 connect (void)
3155 {
3156   if (sanei_umax_pp_getastra () == 610)
3157     return connect610p ();
3158 
3159   switch (gMode)
3160     {
3161     case UMAX_PP_PARPORT_PS2:
3162       DBG (0, "STEF: unimplemented gMode PS2 in connect() !!\n");
3163       return 0;
3164       break;
3165     case UMAX_PP_PARPORT_ECP:
3166       return ECPconnect ();
3167       break;
3168     case UMAX_PP_PARPORT_BYTE:
3169       DBG (0, "STEF: unimplemented gMode BYTE in connect() !!\n");
3170       return 0;
3171       break;
3172     case UMAX_PP_PARPORT_EPP:
3173       return EPPconnect ();
3174     default:
3175       DBG (0, "STEF: gMode unset in connect() !!\n");
3176       break;
3177     }
3178   return 0;
3179 }
3180 
3181 
3182 static void
disconnect(void)3183 disconnect (void)
3184 {
3185   if (sanei_umax_pp_getastra () == 610)
3186     disconnect610p ();
3187   switch (gMode)
3188     {
3189     case UMAX_PP_PARPORT_PS2:
3190       DBG (0, "STEF: unimplemented gMode PS2 in disconnect() !!\n");
3191       break;
3192     case UMAX_PP_PARPORT_ECP:
3193       ECPdisconnect ();
3194       break;
3195     case UMAX_PP_PARPORT_BYTE:
3196       DBG (0, "STEF: unimplemented gMode BYTE in disconnect() !!\n");
3197       break;
3198     case UMAX_PP_PARPORT_EPP:
3199       EPPdisconnect ();
3200       break;
3201     default:
3202       DBG (0, "STEF: gMode unset in disconnect() !!\n");
3203       break;
3204     }
3205 }
3206 
3207 
3208 /* returns 0 if mode OK, else -1 */
3209 static int
checkEPAT(void)3210 checkEPAT (void)
3211 {
3212   int version;
3213 
3214   version = registerRead (0x0B);
3215   if (version == 0xC7)
3216     return 0;
3217   DBG (0, "checkEPAT: expected EPAT version 0xC7, got 0x%X! (%s:%d)\n",
3218        version, __FILE__, __LINE__);
3219   return -1;
3220 
3221 }
3222 
3223 static int
init005(int arg)3224 init005 (int arg)
3225 {
3226   int count = 5;
3227   int res;
3228 
3229   while (count > 0)
3230     {
3231       registerWrite (0x0A, arg);
3232       Outb (DATA, 0xFF);
3233       res = registerRead (0x0A);
3234 
3235       /* failed ? */
3236       if (res != arg)
3237 	return 1;
3238 
3239       /* ror arg */
3240       res = arg & 0x01;
3241       arg = arg / 2;
3242       if (res == 1)
3243 	arg = arg | 0x80;
3244 
3245       /* next loop */
3246       count--;
3247     }
3248   return 0;
3249 }
3250 
3251 /* write 1 byte in EPP mode, returning scnner's status */
3252 static int
EPPputByte610p(int data)3253 EPPputByte610p (int data)
3254 {
3255   int status, control;
3256 
3257   status = Inb (STATUS) & 0xF8;
3258   if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0))
3259     {
3260       DBG (0,
3261 	   "EPPputByte610p failed, expected 0xC8, 0xD0 or 0xC0 got 0x%02X ! (%s:%d)\n",
3262 	   status, __FILE__, __LINE__);
3263       return 0;
3264     }
3265   control = (Inb (CONTROL) & 0x44) | 0x44;	/* data forward, bit 5 cleared (!!) */
3266   Outb (CONTROL, control);
3267   Outb (EPPDATA, data);
3268   return status;
3269 }
3270 
3271 static int
putByte610p(int data)3272 putByte610p (int data)
3273 {
3274   int status, control, j;
3275 
3276   if (gMode == UMAX_PP_PARPORT_EPP)
3277     return EPPputByte610p (data);
3278   j = 0;
3279   do
3280     {
3281       status = Inb (STATUS) & 0xF8;
3282       j++;
3283     }
3284   while ((j < 20) && (status & 0x08));
3285 
3286   if ((status != 0xC8) && (status != 0xC0))
3287     {
3288       DBG (0,
3289 	   "putByte610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n",
3290 	   status, __FILE__, __LINE__);
3291       return 0;
3292     }
3293   control = Inb (CONTROL) & 0x1F;	/* data forward */
3294   Outb (CONTROL, control);
3295 
3296   Outb (DATA, data);
3297   Outb (CONTROL, 0x07);
3298   status = Inb (STATUS) & 0xF8;
3299   if ((status != 0x48) && (status != 0x40))
3300     {
3301       DBG (0,
3302 	   "putByte610p failed, expected 0x48 or 0x40 got 0x%02X ! (%s:%d)\n",
3303 	   status, __FILE__, __LINE__);
3304       return 0;
3305     }
3306 
3307 
3308   Outb (CONTROL, 0x05);
3309   status = Inb (STATUS) & 0xF8;
3310   Outb (CONTROL, control);
3311   return status;
3312 }
3313 
3314 
3315 /* 1 OK, 0 failure */
3316 static int
sync610p(void)3317 sync610p (void)
3318 {
3319   int status;
3320 
3321   Outb (DATA, 0x40);
3322   Outb (CONTROL, 0x06);
3323   status = Inb (STATUS) & 0xF8;
3324   if (status != 0x38)
3325     {
3326       DBG (0, "sync610p failed (got 0x%02X expected 0x38)! (%s:%d)\n",
3327 	   status, __FILE__, __LINE__);
3328       return 0;
3329     }
3330   Outb (CONTROL, 0x07);
3331   status = Inb (STATUS) & 0xF8;
3332   if (status != 0x38)
3333     {
3334       DBG (0, "sync610p failed (got 0x%02X expected 0x38)! (%s:%d)\n",
3335 	   status, __FILE__, __LINE__);
3336       return 0;
3337     }
3338   Outb (CONTROL, 0x04);
3339   status = Inb (STATUS) & 0xF8;
3340   if (status != 0xF8)
3341     {
3342       DBG (0, "sync610p failed (got 0x%02X expected 0xF8)! (%s:%d)\n",
3343 	   status, __FILE__, __LINE__);
3344       return 0;
3345     }
3346   Outb (CONTROL, 0x05);
3347   Inb (CONTROL);		/* 0x05 expected */
3348   Outb (CONTROL, 0x04);
3349   return 1;
3350 }
3351 
3352 static int
EPPcmdSync610p(int cmd)3353 EPPcmdSync610p (int cmd)
3354 {
3355   int word[5];
3356   int status;
3357   int i;
3358 
3359   word[0] = 0;
3360   word[1] = 0;
3361   word[2] = 0;
3362   word[3] = cmd;
3363 
3364   connect610p ();
3365   sync610p ();
3366 
3367   /* sends magic seal 55 AA */
3368   status = EPPputByte610p (0x55);
3369   if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0))
3370     {
3371       DBG (1,
3372 	   "EPPcmdSync610p: Found 0x%X expected 0xC8, 0xC0 or 0xD0 (%s:%d)\n",
3373 	   status, __FILE__, __LINE__);
3374       return 0;
3375     }
3376   status = EPPputByte610p (0xAA);
3377   if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0))
3378     {
3379       DBG (1,
3380 	   "EPPcmdSync610p: Found 0x%X expected 0xC8, 0xC0 or 0xD0 (%s:%d)\n",
3381 	   status, __FILE__, __LINE__);
3382       return 0;
3383     }
3384 
3385   status = EPPgetStatus610p ();
3386   if (status == 0xC0)
3387     for (i = 0; i < 10; i++)
3388       status = Inb (STATUS) & 0xF8;
3389   if (status != 0xC8)
3390     {
3391       DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC8 (%s:%d)\n", status,
3392 	   __FILE__, __LINE__);
3393       /*return 0; */
3394     }
3395 
3396   /* sends 4 bytes of data */
3397   for (i = 0; i < 4; i++)
3398     {
3399       status = EPPputByte610p (word[i]);
3400     }
3401   if (status != 0xC8)
3402     {
3403       DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC8 (%s:%d)\n", status,
3404 	   __FILE__, __LINE__);
3405       /*return 0; */
3406     }
3407 
3408   /* tests status */
3409   Outb (DATA, 0xFF);
3410   if (cmd == 0xC2)
3411     {
3412       status = EPPgetStatus610p ();
3413       if (status != 0xC0)
3414 	{
3415 	  DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC0 (%s:%d)\n",
3416 	       status, __FILE__, __LINE__);
3417 	  /*return 0; */
3418 	}
3419     }
3420   status = EPPgetStatus610p ();
3421   if (status != 0xC0)
3422     {
3423       DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC0 (%s:%d)\n", status,
3424 	   __FILE__, __LINE__);
3425       /*return 0; */
3426     }
3427   disconnect610p ();
3428   return 1;
3429 }
3430 
3431 static int
cmdSync610p(int cmd)3432 cmdSync610p (int cmd)
3433 {
3434   int word[5];
3435   int status;
3436 
3437   if (gMode == UMAX_PP_PARPORT_EPP)
3438     return EPPcmdSync610p (cmd);
3439 
3440   word[0] = 0;
3441   word[1] = 0;
3442   word[2] = 0;
3443   word[3] = cmd;
3444 
3445   connect610p ();
3446   sync610p ();
3447   if (sendLength610p (word) == 0)
3448     {
3449       DBG (0, "sendLength610p() failed... (%s:%d)\n", __FILE__, __LINE__);
3450       return 0;
3451     }
3452   if (cmd == 0xC2)
3453     {
3454       status = getStatus610p ();
3455       if (status != 0xC0)
3456 	{
3457 	  DBG (1, "Found 0x%X expected 0xC0  (%s:%d)\n", status, __FILE__,
3458 	       __LINE__);
3459 	  return 0;
3460 	}
3461     }
3462   status = getStatus610p ();
3463   if (status != 0xC0)
3464     {
3465       DBG (1, "Found 0x%X expected 0xC0  (%s:%d)\n", status, __FILE__,
3466 	   __LINE__);
3467       return 0;
3468     }
3469   disconnect610p ();
3470   return 1;
3471 }
3472 
3473 static int
EPPgetStatus610p(void)3474 EPPgetStatus610p (void)
3475 {
3476   int data, status, control, i;
3477 
3478   control = Inb (CONTROL) & 0xA4;
3479   control = control | 0xE0;
3480   Outb (CONTROL, control);
3481   status = Inb (STATUS) & 0xF8;
3482   if (status & 0x08)
3483     {
3484       for (i = 1; i < 10; i++)
3485 	status = Inb (STATUS) & 0xF8;
3486     }
3487   else
3488     {
3489       data = Inb (EPPDATA);
3490       scannerStatus = data;
3491     }
3492   return status;
3493 }
3494 
3495 static int
getStatus610p(void)3496 getStatus610p (void)
3497 {
3498   int data, status;
3499 
3500   byteMode ();
3501   status = Inb (STATUS) & 0xF8;
3502   Outb (CONTROL, 0x26);		/* data reverse */
3503   data = Inb (DATA);
3504   scannerStatus = data;
3505   Outb (CONTROL, 0x24);
3506   return status;
3507 }
3508 
3509 
3510 int
sendLength610p(int *cmd)3511 sendLength610p (int *cmd)
3512 {
3513   int ret, i, wait;
3514 /* 55,AA,x,y,z,t */
3515 
3516   byteMode ();
3517   wait = putByte610p (0x55);
3518   if ((wait != 0xC8) && (wait != 0xC0))
3519     {
3520       DBG (0,
3521 	   "sendLength610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n",
3522 	   wait, __FILE__, __LINE__);
3523       return 0;
3524     }
3525   wait = putByte610p (0xAA);
3526   if ((wait != 0xC8) && (wait != 0xC0))
3527     {
3528       DBG (0,
3529 	   "sendLength610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n",
3530 	   wait, __FILE__, __LINE__);
3531       return 0;
3532     }
3533 
3534   /* if wait=C0, we have to ... wait */
3535   if (wait == 0xC0)
3536     {
3537       byteMode ();
3538       wait = Inb (STATUS);	/* C0 expected */
3539       Outb (CONTROL, 0x26);
3540       ret = Inb (DATA);		/* 88 expected */
3541       Outb (CONTROL, 0x24);
3542       for (i = 0; i < 10; i++)
3543 	wait = Inb (STATUS);	/* C8 expected */
3544       byteMode ();
3545     }
3546 
3547   for (i = 0; i < 3; i++)
3548     {
3549       ret = putByte610p (cmd[i]);
3550       if (ret != 0xC8)
3551 	{
3552 	  DBG (0,
3553 	       "sendLength610p failed, expected 0xC8 got 0x%02X ! (%s:%d)\n",
3554 	       ret, __FILE__, __LINE__);
3555 	  return 0;
3556 	}
3557     }
3558   ret = putByte610p (cmd[3]);
3559   if ((ret != 0xC0) && (ret != 0xD0))
3560     {
3561       DBG (0,
3562 	   "sendLength610p failed, expected 0xC0 or 0xD0 got 0x%02X ! (%s:%d)\n",
3563 	   ret, __FILE__, __LINE__);
3564       return 0;
3565     }
3566   return 1;
3567 }
3568 
3569 /* 1 OK, 0 failure */
3570 static int
disconnect610p(void)3571 disconnect610p (void)
3572 {
3573   int control, i;
3574 
3575   Outb (CONTROL, 0x04);
3576   for (i = 0; i < 41; i++)
3577     {
3578       control = Inb (CONTROL) & 0x3F;
3579       if (control != 0x04)
3580 	{
3581 	  DBG (0, "disconnect610p failed (idx %d=%02X)! (%s:%d)\n",
3582 	       i, control, __FILE__, __LINE__);
3583 	  return 0;
3584 	}
3585     }
3586   Outb (CONTROL, 0x0C);
3587   control = Inb (CONTROL) & 0x3F;
3588   if (control != 0x0C)
3589     {
3590       DBG (0, "disconnect610p failed expected 0x0C got %02X (%s:%d)\n",
3591 	   control, __FILE__, __LINE__);
3592       return 0;
3593     }
3594   /* XXX STEF XXX Outb (DATA, gData); */
3595   Outb (DATA, 0xFF);
3596   return 1;
3597 }
3598 
3599 /* 1 OK, 0 failure */
3600 /* 0: short connect, 1 long connect */
3601 static int
connect610p(void)3602 connect610p (void)
3603 {
3604   int control;
3605 
3606   gData = Inb (DATA);		/* to gDATA ? */
3607 
3608   Outb (DATA, 0xAA);
3609   Outb (CONTROL, 0x0E);
3610   control = Inb (CONTROL);	/* 0x0E expected */
3611   control = Inb (CONTROL) & 0x3F;
3612   if (control != 0x0E)
3613     {
3614       DBG (0, "connect610p control=%02X, expected 0x0E (%s:%d)\n", control,
3615 	   __FILE__, __LINE__);
3616     }
3617 
3618   Outb (DATA, 0x00);
3619   Outb (CONTROL, 0x0C);
3620   control = Inb (CONTROL);	/* 0x0C expected */
3621   control = Inb (CONTROL) & 0x3F;
3622   if (control != 0x0C)
3623     {
3624       DBG (0, "connect610p control=%02X, expected 0x0C (%s:%d)\n", control,
3625 	   __FILE__, __LINE__);
3626     }
3627 
3628   Outb (DATA, 0x55);
3629   Outb (CONTROL, 0x0E);
3630   control = Inb (CONTROL);	/* 0x0E expected */
3631   control = Inb (CONTROL) & 0x3F;
3632   if (control != 0x0E)
3633     {
3634       DBG (0, "connect610p control=%02X, expected 0x0E (%s:%d)\n", control,
3635 	   __FILE__, __LINE__);
3636     }
3637 
3638   Outb (DATA, 0xFF);
3639   Outb (CONTROL, 0x0C);
3640   control = Inb (CONTROL);	/* 0x0C expected */
3641   control = Inb (CONTROL) & 0x3F;
3642   if (control != 0x0C)
3643     {
3644       DBG (0, "connect610p control=%02X, expected 0x0C (%s:%d)\n", control,
3645 	   __FILE__, __LINE__);
3646     }
3647 
3648   Outb (CONTROL, 0x04);
3649   control = Inb (CONTROL);	/* 0x04 expected */
3650   control = Inb (CONTROL) & 0x3F;
3651   if (control != 0x04)
3652     {
3653       DBG (0, "connect610p control=%02X, expected 0x04 (%s:%d)\n", control,
3654 	   __FILE__, __LINE__);
3655     }
3656   return 1;
3657 }
3658 
3659 /* 1 OK, 0 failure */
3660 static int
EPPconnect(void)3661 EPPconnect (void)
3662 {
3663   int control;
3664 
3665   /* initial values, don't hardcode */
3666   Outb (DATA, 0x04);
3667   Outb (CONTROL, 0x0C);
3668 
3669   Inb (DATA);
3670   control = Inb (CONTROL);
3671   Outb (CONTROL, control & 0x1F);
3672   control = Inb (CONTROL);
3673   Outb (CONTROL, control & 0x1F);
3674 
3675   if (sendCommand (0xE0) != 1)
3676     {
3677       DBG (0, "EPPconnect: sendCommand(0xE0) failed! (%s:%d)\n", __FILE__,
3678 	   __LINE__);
3679       return 0;
3680     }
3681   ClearRegister (0);
3682   init001 ();
3683   return 1;
3684 }
3685 
3686 
3687 
3688 static void
EPPRead32Buffer(int size, unsigned char *dest)3689 EPPRead32Buffer (int size, unsigned char *dest)
3690 {
3691 #ifdef HAVE_LINUX_PPDEV_H
3692   int fd, mode, rc, nb;
3693   unsigned char bval;
3694 #endif
3695   int control;
3696 
3697 #ifdef HAVE_LINUX_PPDEV_H
3698   /* check we have ppdev working */
3699   fd = sanei_umax_pp_getparport ();
3700   if (fd > 0)
3701     {
3702 
3703       bval = 0x80;
3704       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
3705       rc = ioctl (fd, PPSETMODE, &mode);
3706       if (rc)
3707 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3708 	     __FILE__, __LINE__);
3709       rc = write (fd, &bval, 1);
3710 
3711       mode = 1;			/* data_reverse */
3712       rc = ioctl (fd, PPDATADIR, &mode);
3713       if (rc)
3714 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3715 	     __FILE__, __LINE__);
3716 #ifdef PPSETFLAGS
3717       mode = PP_FASTREAD;
3718       rc = ioctl (fd, PPSETFLAGS, &mode);
3719       if (rc)
3720 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3721 	     __FILE__, __LINE__);
3722 #endif
3723       mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
3724       rc = ioctl (fd, PPSETMODE, &mode);
3725       if (rc)
3726 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3727 	     __FILE__, __LINE__);
3728       nb = 0;
3729       while (nb < size - 4)
3730 	{
3731 	  rc = read (fd, dest + nb, size - 4 - nb);
3732 	  nb += rc;
3733 	}
3734 
3735       rc = read (fd, dest + size - 4, 3);
3736 
3737       mode = 0;			/* forward */
3738       rc = ioctl (fd, PPDATADIR, &mode);
3739       if (rc)
3740 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3741 	     __FILE__, __LINE__);
3742       bval = 0xA0;
3743       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
3744       rc = ioctl (fd, PPSETMODE, &mode);
3745       if (rc)
3746 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3747 	     __FILE__, __LINE__);
3748       rc = write (fd, &bval, 1);
3749 
3750       mode = 1;			/* data_reverse */
3751       rc = ioctl (fd, PPDATADIR, &mode);
3752       if (rc)
3753 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3754 	     __FILE__, __LINE__);
3755       mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
3756       rc = ioctl (fd, PPSETMODE, &mode);
3757       if (rc)
3758 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3759 	     __FILE__, __LINE__);
3760       rc = read (fd, dest + size - 1, 1);
3761 
3762       mode = 0;			/* forward */
3763       rc = ioctl (fd, PPDATADIR, &mode);
3764       if (rc)
3765 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3766 	     __FILE__, __LINE__);
3767 
3768       return;
3769     }
3770   /* if not, direct hardware access */
3771 #endif
3772 
3773   EPPBlockMode (0x80);
3774 
3775   control = Inb (CONTROL);
3776   Outb (CONTROL, (control & 0x1F) | 0x20);
3777   Insw (EPPDATA, dest, size / 4 - 1);
3778 
3779   Insb (EPPDATA, (unsigned char *) (dest + size - 4), 3);
3780   control = Inb (CONTROL);
3781   Outb (CONTROL, (control & 0x1F));
3782 
3783   EPPBlockMode (0xA0);
3784   control = Inb (CONTROL);
3785   Outb (CONTROL, (control & 0x1F) | 0x20);
3786 
3787   Insb (EPPDATA, (unsigned char *) (dest + size - 1), 1);
3788   control = Inb (CONTROL);
3789   Outb (CONTROL, (control & 0x1F));
3790 }
3791 
3792 static void
EPPWrite32Buffer(int size, unsigned char *source)3793 EPPWrite32Buffer (int size, unsigned char *source)
3794 {
3795 #ifdef HAVE_LINUX_PPDEV_H
3796   int fd, mode, rc;
3797   unsigned char bval;
3798 #endif
3799 
3800   if ((size % 4) != 0)
3801     {
3802       DBG (0, "EPPWrite32Buffer: size %% 4 != 0!! (%s:%d)\n", __FILE__,
3803 	   __LINE__);
3804     }
3805 #ifdef HAVE_LINUX_PPDEV_H
3806   /* check we have ppdev working */
3807   fd = sanei_umax_pp_getparport ();
3808   if (fd > 0)
3809     {
3810 
3811       bval = 0xC0;
3812       mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
3813       rc = ioctl (fd, PPSETMODE, &mode);
3814       if (rc)
3815 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3816 	     __FILE__, __LINE__);
3817       rc = write (fd, &bval, 1);
3818 
3819 #ifdef PPSETFLAGS
3820       mode = PP_FASTWRITE;
3821       rc = ioctl (fd, PPSETFLAGS, &mode);
3822       if (rc)
3823 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3824 	     __FILE__, __LINE__);
3825 #endif
3826       mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
3827       rc = ioctl (fd, PPSETMODE, &mode);
3828       if (rc)
3829 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3830 	     __FILE__, __LINE__);
3831       rc = write (fd, source, size);
3832 
3833       return;
3834     }
3835   /* if not, direct hardware access */
3836 #endif
3837   EPPBlockMode (0xC0);
3838   Outsw (EPPDATA, source, size / 4);
3839 }
3840 
3841 
3842 
3843 
3844 
3845 
3846 /* returns 0 if ERROR cleared in STATUS within 1024 inb, else 1 */
3847 static int
WaitOnError(void)3848 WaitOnError (void)
3849 {
3850   int c = 0;
3851   int count = 1024;
3852   int status;
3853 
3854   do
3855     {
3856       do
3857 	{
3858 	  status = Inb (STATUS) & 0x08;
3859 	  if (status != 0)
3860 	    {
3861 	      count--;
3862 	      if (count == 0)
3863 		c = 1;
3864 	    }
3865 	}
3866       while ((count > 0) && (status != 0));
3867       if (status == 0)
3868 	{
3869 	  status = Inb (STATUS) & 0x08;
3870 	  if (status == 0)
3871 	    c = 0;
3872 	}
3873     }
3874   while ((status != 0) && (c == 0));
3875   return c;
3876 }
3877 
3878 
3879 
3880 #ifdef HAVE_LINUX_PPDEV_H
3881 /* read up to size bytes, returns bytes read */
3882 static int
ParportpausedBufferRead(int size, unsigned char *dest)3883 ParportpausedBufferRead (int size, unsigned char *dest)
3884 {
3885   unsigned char status, bval;
3886   int error;
3887   int word;
3888   int bread;
3889   int c;
3890   int fd, rc, mode;
3891 
3892   /* WIP check */
3893   if (gMode == UMAX_PP_PARPORT_ECP)
3894     {
3895       DBG (0, "ECP access not implemented yet (WIP) ! (%s:%d)\n",
3896 	   __FILE__, __LINE__);
3897     }
3898 
3899   /* init */
3900   bread = 0;
3901   error = 0;
3902   fd = sanei_umax_pp_getparport ();
3903 
3904   mode = 1;			/* data_reverse */
3905   rc = ioctl (fd, PPDATADIR, &mode);
3906   if (rc)
3907     DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3908 	 __FILE__, __LINE__);
3909 #ifdef PPSETFLAGS
3910   mode = PP_FASTREAD;
3911   rc = ioctl (fd, PPSETFLAGS, &mode);
3912   if (rc)
3913     DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3914 	 __FILE__, __LINE__);
3915 #endif
3916   mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
3917   rc = ioctl (fd, PPSETMODE, &mode);
3918   if (rc)
3919     DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3920 	 __FILE__, __LINE__);
3921 
3922   if ((size & 0x03) != 0)
3923     {
3924       while ((!error) && ((size & 0x03) != 0))
3925 	{
3926 	  rc = read (fd, dest, 1);
3927 	  size--;
3928 	  dest++;
3929 	  bread++;
3930 	  rc = ioctl (fd, PPRSTATUS, &status);
3931 	  if (rc)
3932 	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3933 		 __FILE__, __LINE__);
3934 	  error = status & 0x08;
3935 	}
3936       if (error)
3937 	{
3938 	  DBG (0, "Read error (%s:%d)\n", __FILE__, __LINE__);
3939 	  return 0;
3940 	}
3941     }
3942 
3943   /* from here, we read 1 byte, then size/4-1 32 bits words, and then
3944      3 bytes, pausing on ERROR bit of STATUS */
3945   size -= 4;
3946 
3947   /* sanity test, seems to be wrongly handled ... */
3948   if (size == 0)
3949     {
3950       DBG (0, "case not handled! (%s:%d)\n", __FILE__, __LINE__);
3951       return 0;
3952     }
3953 
3954   word = 0;
3955   error = 0;
3956   bread += size;
3957   do
3958     {
3959       do
3960 	{
3961 	  rc = read (fd, dest, 1);
3962 	  size--;
3963 	  dest++;
3964 	readstatus:
3965 	  if (size > 0)
3966 	    {
3967 	      rc = ioctl (fd, PPRSTATUS, &status);
3968 	      if (rc)
3969 		DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
3970 		     strerror (errno), __FILE__, __LINE__);
3971 	      word = status & 0x10;
3972 	      error = status & 0x08;
3973 	    }
3974 	}
3975       while ((size > 0) && (!error) && (!word));
3976     }
3977   while ((size < 4) && (!error) && (size > 0));
3978 
3979   /* here size=0 or error=8 or word=0x10 */
3980   if ((word) && (!error) && (size))
3981     {
3982       rc = read (fd, dest, 4);
3983       dest += 4;
3984       size -= 4;
3985       if (size != 0)
3986 	error = 0x08;
3987     }
3988   if (!error)
3989     {
3990       c = 0;
3991       rc = ioctl (fd, PPRSTATUS, &status);
3992       if (rc)
3993 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3994 	     __FILE__, __LINE__);
3995       error = status & 0x08;
3996       if (error)
3997 	c = WaitOnError ();
3998     }
3999   else
4000     {				/* 8282 */
4001       c = WaitOnError ();
4002       if (c == 0)
4003 	goto readstatus;
4004     }
4005   if (c == 1)
4006     {
4007       bread -= size;
4008     }
4009   else
4010     {
4011       bread += 3;
4012       size = 3;
4013       do
4014 	{
4015 	  do
4016 	    {
4017 	      rc = read (fd, dest, 1);
4018 	      dest++;
4019 	      size--;
4020 	      if (size)
4021 		{
4022 		  rc = ioctl (fd, PPRSTATUS, &status);
4023 		  if (rc)
4024 		    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
4025 			 strerror (errno), __FILE__, __LINE__);
4026 		  error = status & 0x08;
4027 		  if (!error)
4028 		    {
4029 		      rc = ioctl (fd, PPRSTATUS, &status);
4030 		      if (rc)
4031 			DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
4032 			     strerror (errno), __FILE__, __LINE__);
4033 		      error = status & 0x08;
4034 		    }
4035 		}
4036 	    }
4037 	  while ((size > 0) && (!error));
4038 	  c = 0;
4039 	  if (error)
4040 	    c = WaitOnError ();
4041 	}
4042       while ((size > 0) && (c == 0));
4043     }
4044 
4045   /* end reading */
4046   mode = 0;			/* forward */
4047   rc = ioctl (fd, PPDATADIR, &mode);
4048   if (rc)
4049     DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4050 	 __FILE__, __LINE__);
4051   bval = 0xA0;
4052   mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
4053   rc = ioctl (fd, PPSETMODE, &mode);
4054   if (rc)
4055     DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4056 	 __FILE__, __LINE__);
4057   rc = write (fd, &bval, 1);
4058 
4059   mode = 1;			/* data_reverse */
4060   rc = ioctl (fd, PPDATADIR, &mode);
4061   if (rc)
4062     DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4063 	 __FILE__, __LINE__);
4064   mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
4065   rc = ioctl (fd, PPSETMODE, &mode);
4066   if (rc)
4067     DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4068 	 __FILE__, __LINE__);
4069   rc = read (fd, dest, 1);
4070   bread++;
4071 
4072   mode = 0;			/* forward */
4073   rc = ioctl (fd, PPDATADIR, &mode);
4074   if (rc)
4075     DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4076 	 __FILE__, __LINE__);
4077   return bread;
4078 }
4079 #endif
4080 
4081 /* read up to size bytes, returns bytes read */
4082 static int
DirectpausedBufferRead(int size, unsigned char *dest)4083 DirectpausedBufferRead (int size, unsigned char *dest)
4084 {
4085   int control;
4086   int status;
4087   int error;
4088   int word;
4089   int read;
4090   int c;
4091 
4092   /* init */
4093   read = 0;
4094   error = 0;
4095   control = Inb (CONTROL) & 0x1F;
4096   Outb (CONTROL, control | 0x20);
4097   if ((size & 0x03) != 0)
4098     {
4099       /* 8174 */
4100       while ((!error) && ((size & 0x03) != 0))
4101 	{
4102 	  Insb (EPPDATA, dest, 1);
4103 	  size--;
4104 	  dest++;
4105 	  read++;
4106 	  status = Inb (STATUS) & 0x1F;
4107 	  error = status & 0x08;
4108 	}
4109       if (error)
4110 	{
4111 	  DBG (0, "Read error (%s:%d)\n", __FILE__, __LINE__);
4112 	  return 0;
4113 	}
4114     }
4115 
4116   /* from here, we read 1 byte, then size/4-1 32 bits words, and then
4117      3 bytes, pausing on ERROR bit of STATUS */
4118   size -= 4;
4119 
4120   /* sanity test, seems to be wrongly handled ... */
4121   if (size == 0)
4122     {
4123       DBG (0, "case not handled! (%s:%d)\n", __FILE__, __LINE__);
4124       return 0;
4125     }
4126 
4127   word = 0;
4128   error = 0;
4129   read += size;
4130   do
4131     {
4132       do
4133 	{
4134 	  Insb (EPPDATA, dest, 1);
4135 	  size--;
4136 	  dest++;
4137 	readstatus:
4138 	  if (size > 0)
4139 	    {
4140 	      status = Inb (STATUS) & 0x1F;
4141 	      word = status & 0x10;
4142 	      error = status & 0x08;
4143 	    }
4144 	}
4145       while ((size > 0) && (!error) && (!word));
4146     }
4147   while ((size < 4) && (!error) && (size > 0));
4148 
4149   /* here size=0 or error=8 or word=0x10 */
4150   if ((word) && (!error) && (size))
4151     {
4152       if (epp32)
4153 	Insw (EPPDATA, dest, 1);
4154       else
4155 	Insb (EPPDATA, dest, 4);
4156       dest += 4;
4157       size -= 4;
4158       if (size != 0)
4159 	error = 0x08;
4160     }
4161   if (!error)
4162     {
4163       c = 0;
4164       error = Inb (STATUS) & 0x08;
4165       if (error)
4166 	c = WaitOnError ();
4167     }
4168   else
4169     {				/* 8282 */
4170       c = WaitOnError ();
4171       if (c == 0)
4172 	goto readstatus;
4173     }
4174   if (c == 1)
4175     {
4176       read -= size;
4177     }
4178   else
4179     {
4180       read += 3;
4181       size = 3;
4182       do
4183 	{
4184 	  do
4185 	    {
4186 	      Insb (EPPDATA, dest, 1);
4187 	      dest++;
4188 	      size--;
4189 	      if (size)
4190 		{
4191 		  error = Inb (STATUS) & 0x08;
4192 		  if (!error)
4193 		    error = Inb (STATUS) & 0x08;
4194 		}
4195 	    }
4196 	  while ((size > 0) && (!error));
4197 	  c = 0;
4198 	  if (error)
4199 	    c = WaitOnError ();
4200 	}
4201       while ((size > 0) && (c == 0));
4202     }
4203 
4204   /* end reading */
4205   control = Inb (CONTROL) & 0x1F;
4206   Outb (CONTROL, control);
4207   EPPBlockMode (0xA0);
4208   control = Inb (CONTROL) & 0x1F;
4209   Outb (CONTROL, control | 0x20);
4210   Insb (EPPDATA, dest, 1);
4211   read++;
4212   control = Inb (CONTROL) & 0x1F;
4213   Outb (CONTROL, control);
4214   return read;
4215 }
4216 
4217 
4218 int
pausedBufferRead(int size, unsigned char *dest)4219 pausedBufferRead (int size, unsigned char *dest)
4220 {
4221   EPPBlockMode (0x80);
4222 #ifdef HAVE_LINUX_PPDEV_H
4223   if (sanei_umax_pp_getparport () > 0)
4224     return ParportpausedBufferRead (size, dest);
4225 #endif
4226   /* only EPP hardware access for now */
4227   if (gMode == UMAX_PP_PARPORT_EPP)
4228     return DirectpausedBufferRead (size, dest);
4229   return 0;
4230 }
4231 
4232 
4233 
4234 
4235 /* returns 1 on success, 0 otherwise */
4236 static int
sendWord1220P(int *cmd)4237 sendWord1220P (int *cmd)
4238 {
4239   int i;
4240   int reg;
4241   int try = 0;
4242 
4243   /* send header */
4244   reg = registerRead (0x19) & 0xF8;
4245 retry:
4246   registerWrite (0x1C, 0x55);
4247   reg = registerRead (0x19) & 0xF8;
4248 
4249   registerWrite (0x1C, 0xAA);
4250   reg = registerRead (0x19) & 0xF8;
4251 
4252   /* sync when needed */
4253   if ((reg & 0x08) == 0x00)
4254     {
4255       reg = registerRead (0x1C);
4256       DBG (16, "UTA: reg1C=0x%02X   (%s:%d)\n", reg, __FILE__, __LINE__);
4257       if (((reg & 0x10) != 0x10) && (reg != 0x6B) && (reg != 0xAB)
4258 	  && (reg != 0x23))
4259 	{
4260 	  DBG (0, "sendWord failed (reg1C=0x%02X)   (%s:%d)\n", reg, __FILE__,
4261 	       __LINE__);
4262 	  return 0;
4263 	}
4264       for (i = 0; i < 10; i++)
4265 	{
4266 	  usleep (1000);
4267 	  reg = registerRead (0x19) & 0xF8;
4268 	  if (reg != 0xC8)
4269 	    {
4270 	      DBG (0, "Unexpected reg19=0x%2X  (%s:%d)\n", reg, __FILE__,
4271 		   __LINE__);
4272 	    }
4273 	}
4274       do
4275 	{
4276 	  if ((reg != 0xC0) && (reg != 0xC8))
4277 	    {
4278 	      DBG (0, "Unexpected reg19=0x%2X  (%s:%d)\n", reg, __FILE__,
4279 		   __LINE__);
4280 	    }
4281 	  /* 0xF0 certainly means error */
4282 	  if ((reg == 0xC0) || (reg == 0xD0))
4283 	    {
4284 	      try++;
4285 	      goto retry;
4286 	    }
4287 	  reg = registerRead (0x19) & 0xF8;
4288 	}
4289       while (reg != 0xC8);
4290     }
4291 
4292   /* send word */
4293   i = 0;
4294   while ((reg == 0xC8) && (cmd[i] != -1))
4295     {
4296       registerWrite (0x1C, cmd[i]);
4297       i++;
4298       reg = registerRead (0x19) & 0xF8;
4299     }
4300   TRACE (16, "sendWord() passed ");
4301   if ((reg != 0xC0) && (reg != 0xD0))
4302     {
4303       DBG (0, "sendWord failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
4304 	   reg, __FILE__, __LINE__);
4305       DBG (0, "Blindly going on .....\n");
4306     }
4307   if (((reg == 0xC0) || (reg == 0xD0)) && (cmd[i] != -1))
4308     {
4309       DBG (0, "sendWord failed: short send  (%s:%d)\n", __FILE__, __LINE__);
4310       return 0;
4311     }
4312   reg = registerRead (0x1C);
4313   DBG (16, "sendWord, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
4314   /* model 0x07 has always the last bit set to 1, and even bit 1 */
4315   /* when UTA is present, we get 0x6B there */
4316   scannerStatus = reg & 0xFC;
4317   if (scannerStatus == 0x68)
4318     hasUTA = 1;
4319 
4320   reg = reg & 0x10;
4321   if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8))
4322     {
4323       DBG (0, "sendWord failed: acknowledge not received (%s:%d)\n", __FILE__,
4324 	   __LINE__);
4325       return 0;
4326     }
4327   if (try)
4328     {
4329       DBG (0, "sendWord retry success (retry %d time%s) ... (%s:%d)\n", try,
4330 	   (try > 1) ? "s" : "", __FILE__, __LINE__);
4331     }
4332   return 1;
4333 }
4334 
4335 
4336 /* returns 1 on success, 0 otherwise */
4337 static int
SPPsendWord610p(int *cmd)4338 SPPsendWord610p (int *cmd)
4339 {
4340   int i, j;
4341   int tmp, status;
4342 
4343 #ifdef HAVE_LINUX_PPDEV_H
4344   int exmode, mode, rc, fd;
4345 #endif
4346   connect610p ();
4347 
4348 #ifdef HAVE_LINUX_PPDEV_H
4349   fd = sanei_umax_pp_getparport ();
4350   if (fd > 0)
4351     {
4352       rc = ioctl (fd, PPGETMODE, &exmode);
4353       if (rc)
4354 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4355 	     __FILE__, __LINE__);
4356       mode = IEEE1284_MODE_COMPAT;
4357       rc = ioctl (fd, PPSETMODE, &mode);
4358       if (rc)
4359 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4360 	     __FILE__, __LINE__);
4361     }
4362 #endif
4363 
4364   Outb (DATA, 0x55);
4365   Outb (CONTROL, 0x05);
4366   status = Inb (STATUS) & 0xF8;
4367   if (status != 0x88)
4368     {
4369       DBG (0, "SPPsendWord610p found 0x%02X expected 0x88  (%s:%d)\n", status,
4370 	   __FILE__, __LINE__);
4371       return 0;
4372     }
4373   Outb (CONTROL, 0x04);
4374 
4375   Outb (DATA, 0xAA);
4376   Outb (CONTROL, 0x05);
4377   status = Inb (STATUS) & 0xF8;
4378   if (status != 0x88)
4379     {
4380       DBG (0, "SPPsendWord610p found 0x%02X expected 0x88  (%s:%d)\n", status,
4381 	   __FILE__, __LINE__);
4382       return 0;
4383     }
4384   Outb (CONTROL, 0x04);
4385 
4386   for (i = 0; i < 4; i++)
4387     {
4388       Outb (DATA, cmd[i]);
4389       Outb (CONTROL, 0x05);
4390       status = Inb (STATUS) & 0xF8;
4391       if (status != 0x88)
4392 	{
4393 	  DBG (0, "SPPsendWord610p found 0x%02X expected 0x88  (%s:%d)\n",
4394 	       status, __FILE__, __LINE__);
4395 	  return 0;
4396 	}
4397       Outb (CONTROL, 0x04);
4398     }
4399 
4400   Outb (CONTROL, 0x07);
4401   Outb (DATA, 0xFF);
4402   tmp = Inb (DATA);
4403   if (tmp != 0xFF)
4404     {
4405       DBG (0, "SPPsendWord610p found 0x%X expected 0xFF  (%s:%d)\n", tmp,
4406 	   __FILE__, __LINE__);
4407       return 0;
4408     }
4409   status = Inb (STATUS) & 0xF8;
4410   j = 0;
4411   while ((j < 256) && (status & 0x08))
4412     {
4413       j++;
4414       status = Inb (STATUS) & 0xF8;
4415     }
4416   if ((status != 0x80) && (status != 0xA0))
4417     {
4418       DBG (0, "SPPsendWord610p found 0x%X expected 0x80 or 0xA0 (%s:%d)\n",
4419 	   status, __FILE__, __LINE__);
4420       return 0;
4421     }
4422   Outb (DATA, 0x7F);
4423   status = Inb (STATUS) & 0xF8;
4424   if (status != 0xC0)
4425     {
4426       DBG (0, "SPPsendWord610p found 0x%X expected 0xC0  (%s:%d)\n", status,
4427 	   __FILE__, __LINE__);
4428       return 0;
4429     }
4430   Outb (DATA, 0xFF);
4431   if (cmd[3] == 0xC2)
4432     {
4433       Outb (CONTROL, 0x07);
4434       Outb (DATA, 0xFF);
4435       tmp = Inb (DATA);
4436       if (tmp != 0xFF)
4437 	{
4438 	  DBG (0, "SPPsendWord610p found 0x%X expected 0xFF  (%s:%d)\n", tmp,
4439 	       __FILE__, __LINE__);
4440 	  return 0;
4441 	}
4442       status = Inb (STATUS) & 0xF8;
4443       if ((status != 0x80) && (status != 0xA0))
4444 	{
4445 	  DBG (0,
4446 	       "SPPsendWord610p found 0x%X expected 0x80 or 0xA0 (%s:%d)\n",
4447 	       status, __FILE__, __LINE__);
4448 	  return 0;
4449 	}
4450       Outb (DATA, 0x7F);
4451       status = Inb (STATUS) & 0xF8;
4452       if (status != 0xC0)
4453 	{
4454 	  DBG (0, "SPPsendWord610p found 0x%X expected 0xC0  (%s:%d)\n",
4455 	       status, __FILE__, __LINE__);
4456 	  return 0;
4457 	}
4458       Outb (DATA, 0xFF);
4459     }
4460 
4461 #ifdef HAVE_LINUX_PPDEV_H
4462   fd = sanei_umax_pp_getparport ();
4463   if (fd > 0)
4464     {
4465       rc = ioctl (fd, PPSETMODE, &exmode);
4466       if (rc)
4467 	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4468 	     __FILE__, __LINE__);
4469     }
4470 #endif
4471   disconnect610p ();
4472 
4473   return 1;
4474 }
4475 
4476 /* returns 1 on success, 0 otherwise */
4477 static int
EPPsendWord610p(int *cmd)4478 EPPsendWord610p (int *cmd)
4479 {
4480   int i;
4481   int tmp, control;
4482 
4483   /* send magic tag */
4484   tmp = Inb (STATUS) & 0xF8;
4485   if (tmp != 0xC8)
4486     {
4487       DBG (0,
4488 	   "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n",
4489 	   tmp, __FILE__, __LINE__);
4490       return 0;
4491     }
4492 
4493   /* sets to EPP, and get sure that data direction is forward */
4494   tmp = (Inb (CONTROL) & 0x44) | 0x44;	/* !! */
4495   Outb (CONTROL, tmp);
4496   Outb (EPPDATA, 0x55);
4497 
4498   /* bit0 is timeout bit in EPP mode, should we take care of it ? */
4499   tmp = Inb (STATUS) & 0xF8;
4500   if (tmp != 0xC8)
4501     {
4502       DBG (0,
4503 	   "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n",
4504 	   tmp, __FILE__, __LINE__);
4505       return 0;
4506     }
4507   tmp = (Inb (CONTROL) & 0x44) | 0x44;
4508   Outb (CONTROL, tmp);
4509   Outb (EPPDATA, 0xAA);
4510 
4511   control = (Inb (CONTROL) & 0xE0) | 0xE4;
4512   Outb (CONTROL, control);	/* bit 7 + data reverse + reset */
4513   for (i = 0; i < 10; i++)
4514     {
4515       tmp = Inb (STATUS) & 0xF8;
4516       if (tmp != 0xC8)
4517 	{
4518 	  DBG (0,
4519 	       "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n",
4520 	       tmp, __FILE__, __LINE__);
4521 	  return 0;
4522 	}
4523     }
4524 
4525   i = 0;
4526   while ((tmp == 0xC8) && (cmd[i] != -1))
4527     {
4528       tmp = Inb (STATUS) & 0xF8;
4529       control = (Inb (CONTROL) & 0x44) | 0x44;	/* !! */
4530       Outb (CONTROL, control);
4531       Outb (EPPDATA, cmd[i]);
4532       i++;
4533     }
4534 
4535   /* end */
4536   Outb (DATA, 0xFF);
4537   control = (Inb (CONTROL) & 0x44) | 0xE4;
4538   Outb (CONTROL, control);	/* data reverse + ????? */
4539   tmp = Inb (STATUS) & 0xF8;
4540   if (tmp == 0xC8)
4541     {
4542       for (i = 0; i < 9; i++)
4543 	tmp = Inb (STATUS) & 0xF8;
4544       scannerStatus = tmp;
4545     }
4546   else
4547     {
4548       scannerStatus = Inb (EPPDATA);
4549     }
4550   if ((tmp != 0xC0) && (tmp != 0xD0))
4551     {
4552       DBG (0,
4553 	   "EPPsendWord610p failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
4554 	   tmp, __FILE__, __LINE__);
4555       return 0;
4556     }
4557   return 1;
4558 }
4559 
4560 /*
4561  * 0: failure
4562  * 1: success
4563  */
4564 static int
sendWord(int *cmd)4565 sendWord (int *cmd)
4566 {
4567   switch (sanei_umax_pp_getastra ())
4568     {
4569     case 610:
4570       return sendLength610p (cmd);
4571     case 1220:
4572     case 1600:
4573     case 2000:
4574     default:
4575       return sendWord1220P (cmd);
4576     }
4577 }
4578 
4579 
4580 
4581 /******************************************************************************/
4582 /* ringScanner: returns 1 if scanner present, else 0                          */
4583 /******************************************************************************/
4584 /*
4585  * in fact this function is really close to CPP macro in
4586  * /usr/src/linux/drivers/block/paride/epat.c .....
4587  * we have almost CPP(8)
4588  */
4589 
4590 static int
ringScanner(int count, unsigned long delay)4591 ringScanner (int count, unsigned long delay)
4592 {
4593   int status;
4594   int data;
4595   int control;
4596   int ret = 1;
4597 
4598   /* save state */
4599   data = Inb (DATA);
4600   control = Inb (CONTROL) & 0x1F;
4601 
4602   /* send -irq,+reset */
4603   Outb (CONTROL, (control & 0xF) | 0x4);
4604 
4605   /* unhandled case */
4606   if (g674 == 1)
4607     {
4608       DBG (1, "OUCH! %s:%d\n", __FILE__, __LINE__);
4609       return 0;
4610     }
4611 
4612   /* send ring string */
4613   Outb (DATA, 0x22);
4614   usleep (delay);
4615   Outb (DATA, 0x22);
4616   usleep (delay);
4617   if (count == 5)
4618     {
4619       Outb (DATA, 0x22);
4620       usleep (delay);
4621       Outb (DATA, 0x22);
4622       usleep (delay);
4623       Outb (DATA, 0x22);
4624       usleep (delay);
4625     }
4626   Outb (DATA, 0xAA);
4627   usleep (delay);
4628   Outb (DATA, 0xAA);
4629   usleep (delay);
4630   if (count == 5)
4631     {
4632       Outb (DATA, 0xAA);
4633       usleep (delay);
4634       Outb (DATA, 0xAA);
4635       usleep (delay);
4636       Outb (DATA, 0xAA);
4637       usleep (delay);
4638     }
4639   Outb (DATA, 0x55);
4640   usleep (delay);
4641   Outb (DATA, 0x55);
4642   usleep (delay);
4643   if (count == 5)
4644     {
4645       Outb (DATA, 0x55);
4646       usleep (delay);
4647       Outb (DATA, 0x55);
4648       usleep (delay);
4649       Outb (DATA, 0x55);
4650       usleep (delay);
4651     }
4652   Outb (DATA, 0x00);
4653   usleep (delay);
4654   Outb (DATA, 0x00);
4655   usleep (delay);
4656   if (count == 5)
4657     {
4658       Outb (DATA, 0x00);
4659       usleep (delay);
4660       Outb (DATA, 0x00);
4661       usleep (delay);
4662       Outb (DATA, 0x00);
4663       usleep (delay);
4664     }
4665   Outb (DATA, 0xFF);
4666   usleep (delay);
4667   Outb (DATA, 0xFF);
4668   usleep (delay);
4669   if (count == 5)
4670     {
4671       Outb (DATA, 0xFF);
4672       usleep (delay);
4673       Outb (DATA, 0xFF);
4674       usleep (delay);
4675       Outb (DATA, 0xFF);
4676       usleep (delay);
4677     }
4678 
4679   /* OK ? */
4680   status = Inb (STATUS) & 0xF8;
4681   usleep (delay);
4682   if ((status & 0xB8) != 0xB8)
4683     {
4684       DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__, __LINE__);
4685       ret = 0;
4686     }
4687 
4688   /* if OK send 0x87 */
4689   if (ret)
4690     {
4691       Outb (DATA, 0x87);
4692       usleep (delay);
4693       Outb (DATA, 0x87);
4694       usleep (delay);
4695       if (count == 5)
4696 	{
4697 	  Outb (DATA, 0x87);
4698 	  usleep (delay);
4699 	  Outb (DATA, 0x87);
4700 	  usleep (delay);
4701 	  Outb (DATA, 0x87);
4702 	  usleep (delay);
4703 	}
4704       status = Inb (STATUS);
4705       /* status = 126 when scanner not connected .... */
4706       if ((status & 0xB8) != 0x18)
4707 	{
4708 	  DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__,
4709 	       __LINE__);
4710 	  ret = 0;
4711 	}
4712     }
4713 
4714   /* if OK send 0x78 */
4715   if (ret)
4716     {
4717       Outb (DATA, 0x78);
4718       usleep (delay);
4719       Outb (DATA, 0x78);
4720       usleep (delay);
4721       if (count == 5)
4722 	{
4723 	  Outb (DATA, 0x78);
4724 	  usleep (delay);
4725 	  Outb (DATA, 0x78);
4726 	  usleep (delay);
4727 	  Outb (DATA, 0x78);
4728 	  usleep (delay);
4729 	}
4730       status = Inb (STATUS);
4731       if ((status & 0x30) != 0x30)
4732 	{
4733 	  DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__,
4734 	       __LINE__);
4735 	  ret = 0;
4736 	}
4737     }
4738 
4739   /* ring OK, send termination */
4740   if (ret)
4741     {
4742       Outb (DATA, 0x08);
4743       usleep (delay);
4744       Outb (DATA, 0x08);
4745       usleep (delay);
4746       if (count == 5)
4747 	{
4748 	  Outb (DATA, 0x08);
4749 	  usleep (delay);
4750 	  Outb (DATA, 0x08);
4751 	  usleep (delay);
4752 	  Outb (DATA, 0x08);
4753 	  usleep (delay);
4754 	}
4755       Outb (DATA, 0xFF);
4756       usleep (delay);
4757       Outb (DATA, 0xFF);
4758       usleep (delay);
4759       if (count == 5)
4760 	{
4761 	  Outb (DATA, 0xFF);
4762 	  usleep (delay);
4763 	  Outb (DATA, 0xFF);
4764 	  usleep (delay);
4765 	  Outb (DATA, 0xFF);
4766 	  usleep (delay);
4767 	}
4768     }
4769 
4770   /* restore state */
4771   Outb (CONTROL, control);
4772   Outb (DATA, data);
4773   return ret;
4774 }
4775 
4776 /*****************************************************************************/
4777 /* test some version       : returns 1 on success, 0 otherwise               */
4778 /*****************************************************************************/
4779 
4780 
4781 static int
testVersion(int no)4782 testVersion (int no)
4783 {
4784   int data;
4785   int status;
4786   int control;
4787   int count;
4788   int tmp;
4789 
4790   data = Inb (DATA);
4791   control = Inb (CONTROL) & 0x3F;
4792   Outb (CONTROL, (control & 0x1F) | 0x04);
4793 
4794   /* send magic sequence */
4795   Outb (DATA, 0x22);
4796   Outb (DATA, 0x22);
4797   Outb (DATA, 0x22);
4798   Outb (DATA, 0x22);
4799   Outb (DATA, 0xAA);
4800   Outb (DATA, 0xAA);
4801   Outb (DATA, 0xAA);
4802   Outb (DATA, 0xAA);
4803   Outb (DATA, 0xAA);
4804   Outb (DATA, 0xAA);
4805   Outb (DATA, 0x55);
4806   Outb (DATA, 0x55);
4807   Outb (DATA, 0x55);
4808   Outb (DATA, 0x55);
4809   Outb (DATA, 0x55);
4810   Outb (DATA, 0x55);
4811   Outb (DATA, 0x00);
4812   Outb (DATA, 0x00);
4813   Outb (DATA, 0x00);
4814   Outb (DATA, 0x00);
4815   Outb (DATA, 0x00);
4816   Outb (DATA, 0x00);
4817   Outb (DATA, 0xFF);
4818   Outb (DATA, 0xFF);
4819   Outb (DATA, 0xFF);
4820   Outb (DATA, 0xFF);
4821   Outb (DATA, 0xFF);
4822   Outb (DATA, 0xFF);
4823   Outb (DATA, 0x87);
4824   Outb (DATA, 0x87);
4825   Outb (DATA, 0x87);
4826   Outb (DATA, 0x87);
4827   Outb (DATA, 0x87);
4828   Outb (DATA, 0x87);
4829   Outb (DATA, 0x78);
4830   Outb (DATA, 0x78);
4831   Outb (DATA, 0x78);
4832   Outb (DATA, 0x78);
4833   Outb (DATA, 0x78);
4834   Outb (DATA, 0x78);
4835   tmp = no | 0x88;
4836   Outb (DATA, tmp);
4837   Outb (DATA, tmp);
4838   Outb (DATA, tmp);
4839   Outb (DATA, tmp);
4840   Outb (DATA, tmp);
4841   Outb (DATA, tmp);
4842 
4843   /* test status */
4844   status = Inb (STATUS);
4845   status = Inb (STATUS);
4846   if ((status & 0xB8) != 0)
4847     {
4848       /* 1600P fails here */
4849       DBG (64, "status %d doesn't match! %s:%d\n", status, __FILE__,
4850 	   __LINE__);
4851       Outb (CONTROL, control);
4852       Outb (DATA, data);
4853       return 0;
4854     }
4855 
4856   count = 0xF0;
4857   do
4858     {
4859       tmp = no | 0x80;
4860       Outb (DATA, tmp);
4861       Outb (DATA, tmp);
4862       Outb (DATA, tmp);
4863       Outb (DATA, tmp);
4864       Outb (DATA, tmp);
4865       Outb (DATA, tmp);
4866       tmp = no | 0x88;
4867       Outb (DATA, tmp);
4868       Outb (DATA, tmp);
4869       Outb (DATA, tmp);
4870       Outb (DATA, tmp);
4871       Outb (DATA, tmp);
4872       Outb (DATA, tmp);
4873 
4874       /* command received ? */
4875       status = Inb (STATUS);
4876       status = ((status << 1) & 0x70) | (status & 0x80);
4877       if (status != count)
4878 	{
4879 	  /* since failure is expected, we don't alaways print */
4880 	  /* this message ...                                   */
4881 	  DBG (2, "status %d doesn't match count 0x%X! %s:%d\n", status,
4882 	       count, __FILE__, __LINE__);
4883 	  Outb (CONTROL, control);
4884 	  Outb (DATA, data);
4885 	  return 0;
4886 	}
4887 
4888       /* next */
4889       count -= 0x10;
4890     }
4891   while (count > 0);
4892 
4893   /* restore port , successful exit */
4894   Outb (CONTROL, control);
4895   Outb (DATA, data);
4896   return 1;
4897 }
4898 
4899 
4900 /* sends len bytes to scanner        */
4901 /* needs data channel to be set up   */
4902 /* returns 1 on success, 0 otherwise */
4903 static int
sendLength(int *cmd, int len)4904 sendLength (int *cmd, int len)
4905 {
4906   int i;
4907   int reg, wait;
4908   int try = 0;
4909 
4910   /* send header */
4911 retry:
4912   wait = registerRead (0x19) & 0xF8;
4913 
4914   registerWrite (0x1C, 0x55);
4915   reg = registerRead (0x19) & 0xF8;
4916 
4917   registerWrite (0x1C, 0xAA);
4918   reg = registerRead (0x19) & 0xF8;
4919 
4920   /* sync when needed */
4921   if ((wait & 0x08) == 0x00)
4922     {
4923       reg = registerRead (0x1C);
4924       while (((reg & 0x10) != 0x10) && (reg != 0x6B) && (reg != 0xAB)
4925 	     && (reg != 0x23))
4926 	{
4927 	  DBG (0,
4928 	       "sendLength failed, expected reg & 0x10=0x10 , found 0x%02X (%s:%d)\n",
4929 	       reg, __FILE__, __LINE__);
4930 	  if (try > 10)
4931 	    {
4932 	      DBG (0, "Aborting...\n");
4933 	      return 0;
4934 	    }
4935 	  else
4936 	    {
4937 	      DBG (0, "Retrying ...\n");
4938 	    }
4939 	  /* resend */
4940 	  epilogue ();
4941 	  prologue (0x10);
4942 	  try++;
4943 	  goto retry;
4944 	}
4945       for (i = 0; i < 10; i++)
4946 	{
4947 	  reg = registerRead (0x19) & 0xF8;
4948 	  if (reg != 0xC8)
4949 	    {
4950 	      DBG (0, "Unexpected reg19=0x%2X  (%s:%d)\n", reg, __FILE__,
4951 		   __LINE__);
4952 	      /* 0xF0 certainly means error */
4953 	      if ((reg == 0xC0) || (reg == 0xD0) || (reg == 0x80))
4954 		{
4955 		  /* resend */
4956 		  try++;
4957 		  if (try > 20)
4958 		    {
4959 		      DBG (0, "sendLength retry failed (%s:%d)\n", __FILE__,
4960 			   __LINE__);
4961 		      return 0;
4962 		    }
4963 
4964 		  epilogue ();
4965 		  sendCommand (0x00);
4966 		  sendCommand (0xE0);
4967 		  Outb (DATA, 0x00);
4968 		  Outb (CONTROL, 0x01);
4969 		  Outb (CONTROL, 0x04);
4970 		  sendCommand (0x30);
4971 
4972 		  prologue (0x10);
4973 		  goto retry;
4974 		}
4975 	    }
4976 	}
4977       do
4978 	{
4979 	  if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0xC8))
4980 	    {
4981 	      /* status has changed while waiting */
4982 	      /* but it's too early               */
4983 	      DBG (0, "Unexpected reg19=0x%2X  (%s:%d)\n", reg, __FILE__,
4984 		   __LINE__);
4985 	    }
4986 	  /* 0xF0 certainly means error */
4987 	  if ((reg == 0xC0) || (reg == 0xD0) || (reg == 0x80))
4988 	    {
4989 	      /* resend */
4990 	      try++;
4991 	      epilogue ();
4992 
4993 	      sendCommand (0x00);
4994 	      sendCommand (0xE0);
4995 	      Outb (DATA, 0x00);
4996 	      Outb (CONTROL, 0x01);
4997 	      Outb (CONTROL, 0x04);
4998 	      sendCommand (0x30);
4999 
5000 	      prologue (0x10);
5001 	      goto retry;
5002 	    }
5003 	  reg = registerRead (0x19) & 0xF8;
5004 	}
5005       while (reg != 0xC8);
5006     }
5007 
5008   /* send bytes */
5009   i = 0;
5010   while ((reg == 0xC8) && (i < len))
5011     {
5012       /* write byte */
5013       registerWrite (0x1C, cmd[i]);
5014       reg = registerRead (0x19) & 0xF8;
5015 
5016       /* 1B handling: escape it to confirm value  */
5017       if (cmd[i] == 0x1B)
5018 	{
5019 	  registerWrite (0x1C, cmd[i]);
5020 	  reg = registerRead (0x19) & 0xF8;
5021 	}
5022       i++;
5023     }
5024   DBG (16, "sendLength, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5025   if ((reg != 0xC0) && (reg != 0xD0))
5026     {
5027       DBG (0,
5028 	   "sendLength failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
5029 	   reg, __FILE__, __LINE__);
5030       DBG (0, "Blindly going on .....\n");
5031     }
5032 
5033   /* check if 'finished status' received too early */
5034   if (((reg == 0xC0) || (reg == 0xD0)) && (i != len))
5035     {
5036       DBG (0, "sendLength failed: sent only %d bytes out of %d (%s:%d)\n", i,
5037 	   len, __FILE__, __LINE__);
5038       return 0;
5039     }
5040 
5041 
5042   reg = registerRead (0x1C);
5043   DBG (16, "sendLength, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5044 
5045   /* model 0x07 has always the last bit set to 1 */
5046   scannerStatus = reg & 0xFC;
5047   reg = reg & 0x10;
5048   if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8))
5049     {
5050       DBG (0, "sendLength failed: acknowledge not received (%s:%d)\n",
5051 	   __FILE__, __LINE__);
5052       return 0;
5053     }
5054   if (try)
5055     {
5056       DBG (0, "sendLength retry success (retry %d time%s) ... (%s:%d)\n", try,
5057 	   (try > 1) ? "s" : "", __FILE__, __LINE__);
5058     }
5059   return 1;
5060 }
5061 
5062 
5063 /* sends data bytes to scanner       */
5064 /* needs data channel to be set up   */
5065 /* returns 1 on success, 0 otherwise */
5066 static int
sendData610p(int *cmd, int len)5067 sendData610p (int *cmd, int len)
5068 {
5069   int i, status, j;
5070 
5071   i = 0;
5072   status = 0xC8;
5073   /* while ((i < len) && ((status & 0x08) == 0x08)) XXX STEF XXX */
5074   while (i < len)
5075     {
5076       /* escape special values */
5077       if (cmd[i] == 0x1B)
5078 	status = putByte610p (0x1B);
5079       if (i > 0)
5080 	{
5081 	  if ((cmd[i] == 0xAA) && (cmd[i - 1] == 0x55))
5082 	    status = putByte610p (0x1B);
5083 	}
5084       /* regular values */
5085       status = putByte610p (cmd[i]);
5086       i++;
5087     }
5088   j = 0;
5089   while ((status & 0x08) && (j < 256))
5090     {
5091       status = getStatus610p ();
5092       j++;
5093     }
5094   if ((status != 0xC0) && (status != 0xD0))
5095     {
5096       DBG (0,
5097 	   "sendData610p() failed, status=0x%02X, expected 0xC0 or 0xD0 (%s:%d)\n",
5098 	   status, __FILE__, __LINE__);
5099       return 0;
5100     }
5101 
5102   /* check if 'finished status' received too early */
5103   if (i < len)
5104     {
5105       DBG (0, "sendData610p failed: sent only %d bytes out of %d (%s:%d)\n",
5106 	   i, len, __FILE__, __LINE__);
5107       return 0;
5108     }
5109   return 1;
5110 }
5111 
5112 
5113 /* sends data bytes to scanner       */
5114 /* needs data channel to be set up   */
5115 /* returns 1 on success, 0 otherwise */
5116 static int
sendData(int *cmd, int len)5117 sendData (int *cmd, int len)
5118 {
5119   int i;
5120   int reg;
5121 
5122   if (sanei_umax_pp_getastra () == 610)
5123     return sendData610p (cmd, len);
5124 
5125   /* send header */
5126   reg = registerRead (0x19) & 0xF8;
5127 
5128   /* send bytes */
5129   i = 0;
5130   while ((reg == 0xC8) && (i < len))
5131     {
5132       /* write byte */
5133       registerWrite (0x1C, cmd[i]);
5134       reg = registerRead (0x19) & 0xF8;
5135 
5136       /* 1B handling: escape it to confirm value  */
5137       if (cmd[i] == 0x1B)
5138 	{
5139 	  registerWrite (0x1C, 0x1B);
5140 	  reg = registerRead (0x19) & 0xF8;
5141 	}
5142 
5143       /* escape 55 AA pattern by adding 1B */
5144       if ((i < len - 1) && (cmd[i] == 0x55) && (cmd[i + 1] == 0xAA))
5145 	{
5146 	  registerWrite (0x1C, 0x1B);
5147 	  reg = registerRead (0x19) & 0xF8;
5148 	}
5149 
5150       /* next value */
5151       i++;
5152     }
5153   DBG (16, "sendData, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5154   if ((reg != 0xC0) && (reg != 0xD0))
5155     {
5156       DBG (0, "sendData failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
5157 	   reg, __FILE__, __LINE__);
5158       DBG (0, "Blindly going on .....\n");
5159     }
5160 
5161   /* check if 'finished status' received too early */
5162   if (((reg == 0xC0) || (reg == 0xD0)) && (i < len))
5163     {
5164       DBG (0, "sendData failed: sent only %d bytes out of %d (%s:%d)\n", i,
5165 	   len, __FILE__, __LINE__);
5166       return 0;
5167     }
5168 
5169 
5170   reg = registerRead (0x1C);
5171   DBG (16, "sendData, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5172 
5173   /* model 0x07 has always the last bit set to 1 */
5174   scannerStatus = reg & 0xFC;
5175   reg = reg & 0x10;
5176   if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8)
5177       && (scannerStatus != 0x20))
5178     {
5179       DBG (0, "sendData failed: acknowledge not received (%s:%d)\n", __FILE__,
5180 	   __LINE__);
5181       return 0;
5182     }
5183   return 1;
5184 }
5185 
5186 
5187 /* receive data bytes from scanner   */
5188 /* needs data channel to be set up   */
5189 /* returns 1 on success, 0 otherwise */
5190 /* uses pausedBufferRead             */
5191 static int
pausedReadData(int size, unsigned char *dest)5192 pausedReadData (int size, unsigned char *dest)
5193 {
5194   int reg;
5195   int tmp;
5196   int read;
5197 
5198   REGISTERWRITE (0x0E, 0x0D);
5199   REGISTERWRITE (0x0F, 0x00);
5200   reg = registerRead (0x19) & 0xF8;
5201   if ((reg != 0xC0) && (reg != 0xD0))
5202     {
5203       DBG (0, "Unexpected reg19: 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
5204 	   reg, __FILE__, __LINE__);
5205       return 0;
5206     }
5207   if (gMode == UMAX_PP_PARPORT_ECP)
5208     {
5209       REGISTERWRITE (0x1A, 0x44);
5210     }
5211   REGISTERREAD (0x0C, 0x04);
5212   REGISTERWRITE (0x0C, 0x44);	/* sets data direction ? */
5213   if (gMode == UMAX_PP_PARPORT_ECP)
5214     {
5215       compatMode ();
5216       Outb (CONTROL, 0x04);	/* reset ? */
5217       ECPSetBuffer (size);
5218       read = ECPbufferRead (size, dest);
5219       DBG (16, "ECPbufferRead(%d,dest) passed (%s:%d)\n", size, __FILE__,
5220 	   __LINE__);
5221       REGISTERWRITE (0x1A, 0x84);
5222     }
5223   else
5224     {
5225       read = pausedBufferRead (size, dest);
5226     }
5227   if (read < size)
5228     {
5229       DBG (16,
5230 	   "pausedBufferRead(%d,dest) failed, only got %d bytes (%s:%d)\n",
5231 	   size, read, __FILE__, __LINE__);
5232       return 0;
5233     }
5234   DBG (16, "pausedBufferRead(%d,dest) passed (%s:%d)\n", size, __FILE__,
5235        __LINE__);
5236   REGISTERWRITE (0x0E, 0x0D);
5237   REGISTERWRITE (0x0F, 0x00);
5238   return 1;
5239 }
5240 
5241 
5242 
5243 /* receive data bytes from scanner   */
5244 /* needs data channel to be set up   */
5245 /* returns 1 on success, 0 otherwise */
5246 static int
receiveData610p(int *cmd, int len)5247 receiveData610p (int *cmd, int len)
5248 {
5249   int i;
5250   int status;
5251 
5252   i = 0;
5253   status = 0xD0;
5254   byteMode ();
5255   while (i < len)
5256     {
5257       status = Inb (STATUS) & 0xF8;
5258       Outb (CONTROL, 0x26);	/* data reverse+ 'reg' */
5259       cmd[i] = Inb (DATA);
5260       Outb (CONTROL, 0x24);	/* data reverse+ 'reg' */
5261       i++;
5262     }
5263   if (status != 0xC0)
5264     {
5265       DBG (0, "receiveData610p failed  got 0x%02X instead of 0xC0 (%s:%d)\n",
5266 	   status, __FILE__, __LINE__);
5267       DBG (0, "Blindly going on .....\n");
5268     }
5269 
5270   /* check if 'finished status' received to early */
5271   if ((status == 0xC0) && (i != len))
5272     {
5273       DBG (0,
5274 	   "receiveData610p failed: received only %d bytes out of %d (%s:%d)\n",
5275 	   i, len, __FILE__, __LINE__);
5276       return 0;
5277     }
5278   return 1;
5279 }
5280 
5281 /* receive data bytes from scanner   */
5282 /* needs data channel to be set up   */
5283 /* returns 1 on success, 0 otherwise */
5284 static int
receiveData(int *cmd, int len)5285 receiveData (int *cmd, int len)
5286 {
5287   int i;
5288   int reg;
5289 
5290   /* send header */
5291   reg = registerRead (0x19) & 0xF8;
5292 
5293   /* send bytes */
5294   i = 0;
5295   while (((reg == 0xD0) || (reg == 0xC0)) && (i < len))
5296     {
5297       /* write byte */
5298       cmd[i] = registerRead (0x1C);
5299       reg = registerRead (0x19) & 0xF8;
5300       i++;
5301     }
5302   DBG (16, "receiveData, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5303   if ((reg != 0xC0) && (reg != 0xD0))
5304     {
5305       DBG (0, "sendData failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
5306 	   reg, __FILE__, __LINE__);
5307       DBG (0, "Blindly going on .....\n");
5308     }
5309 
5310   /* check if 'finished status' received to early */
5311   if (((reg == 0xC0) || (reg == 0xD0)) && (i != len))
5312     {
5313       DBG (0,
5314 	   "receiveData failed: received only %d bytes out of %d (%s:%d)\n",
5315 	   i, len, __FILE__, __LINE__);
5316       return 0;
5317     }
5318 
5319 
5320   reg = registerRead (0x1C);
5321   DBG (16, "receiveData, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5322 
5323   /* model 0x07 has always the last bit set to 1 */
5324   scannerStatus = reg & 0xF8;
5325   reg = reg & 0x10;
5326   if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8))
5327     {
5328       DBG (0, "receiveData failed: acknowledge not received (%s:%d)\n",
5329 	   __FILE__, __LINE__);
5330       return 0;
5331     }
5332   return 1;
5333 }
5334 
5335 
5336 /* 1=success, 0 failed */
5337 static int
fonc001(void)5338 fonc001 (void)
5339 {
5340   int i;
5341   int res;
5342   int reg;
5343 
5344   res = 1;
5345   while (res == 1)
5346     {
5347       registerWrite (0x1A, 0x0C);
5348       registerWrite (0x18, 0x40);
5349 
5350       /* send 0x06 */
5351       registerWrite (0x1A, 0x06);
5352       for (i = 0; i < 10; i++)
5353 	{
5354 	  reg = registerRead (0x19) & 0xF8;
5355 	  if ((reg & 0x78) == 0x38)
5356 	    {
5357 	      res = 0;
5358 	      break;
5359 	    }
5360 	}
5361       if (res == 1)
5362 	{
5363 	  registerWrite (0x1A, 0x00);
5364 	  registerWrite (0x1A, 0x0C);
5365 	}
5366     }
5367 
5368   /* send 0x07 */
5369   registerWrite (0x1A, 0x07);
5370   res = 1;
5371   for (i = 0; i < 10; i++)
5372     {
5373       reg = registerRead (0x19) & 0xF8;
5374       if ((reg & 0x78) == 0x38)
5375 	{
5376 	  res = 0;
5377 	  break;
5378 	}
5379     }
5380   if (res != 0)
5381     return 0;
5382 
5383   /* send 0x04 */
5384   registerWrite (0x1A, 0x04);
5385   res = 1;
5386   for (i = 0; i < 10; i++)
5387     {
5388       reg = registerRead (0x19) & 0xF8;
5389       if ((reg & 0xF8) == 0xF8)
5390 	{
5391 	  res = 0;
5392 	  break;
5393 	}
5394     }
5395   if (res != 0)
5396     return 0;
5397 
5398   /* send 0x05 */
5399   registerWrite (0x1A, 0x05);
5400   res = 1;
5401   for (i = 0; i < 10; i++)
5402     {
5403       reg = registerRead (0x1A);
5404       if (reg == 0x05)
5405 	{
5406 	  res = 0;
5407 	  break;
5408 	}
5409     }
5410   if (res != 0)
5411     return 0;
5412 
5413   /* end */
5414   registerWrite (0x1A, 0x84);
5415   return 1;
5416 }
5417 
5418 
5419 
5420 
5421 
5422 
5423 
5424 /* 1 OK, 0 failed */
5425 static int
foncSendWord(int *cmd)5426 foncSendWord (int *cmd)
5427 {
5428   prologue (0x10);
5429   if (sendWord (cmd) == 0)
5430     {
5431       DBG (0, "sendWord(cmd) failed (%s:%d)\n", __FILE__, __LINE__);
5432       return 0;
5433     }
5434   epilogue ();
5435 
5436   return 1;
5437 }
5438 
5439 
5440 static int
cmdSetDataBuffer(int *data)5441 cmdSetDataBuffer (int *data)
5442 {
5443   int cmd1[] = { 0x00, 0x00, 0x22, 0x88, -1 };	/* 34 bytes write on channel 8 */
5444   int cmd2[] =
5445     { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80,
5446     0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
5447     0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -1
5448   };
5449   int cmd3[] = { 0x00, 0x08, 0x00, 0x84, -1 };	/* 2048 bytes size write on channel 4 (data) */
5450   int cmd4[] = { 0x00, 0x08, 0x00, 0xC4, -1 };	/* 2048 bytes size read on channel 4 (data) */
5451   int i;
5452   unsigned char dest[2048];
5453 
5454   /* cmdSet(8,34,cmd2), but without prologue/epilogue */
5455   /* set block length to 34 bytes on 'channel 8' */
5456   sendWord (cmd1);
5457   DBG (16, "sendWord(cmd1) passed (%s:%d) \n", __FILE__, __LINE__);
5458 
5459   /* sendData */
5460   sendData (cmd2, 0x22);
5461   DBG (16, "sendData(cmd2) passed (%s:%d) \n", __FILE__, __LINE__);
5462 
5463   if (DBG_LEVEL >= 128)
5464     {
5465       bloc8Decode (cmd2);
5466     }
5467 
5468   /* set block length to 2048, write on 'channel 4' */
5469   sendWord (cmd3);
5470   DBG (16, "sendWord(cmd3) passed (%s:%d) \n", __FILE__, __LINE__);
5471 
5472   if (sendData (data, 2048) == 0)
5473     {
5474       DBG (0, "sendData(data,%d) failed (%s:%d)\n", 2048, __FILE__, __LINE__);
5475       return 0;
5476     }
5477   TRACE (16, "sendData(data,2048) passed ...");
5478 
5479   /* read back all data sent to 'channel 4' */
5480   sendWord (cmd4);
5481   DBG (16, "sendWord(cmd4) passed (%s:%d) \n", __FILE__, __LINE__);
5482 
5483   if (pausedReadData (2048, dest) == 0)
5484     {
5485       DBG (16, "pausedReadData(2048,dest) failed (%s:%d)\n", __FILE__,
5486 	   __LINE__);
5487       return 0;
5488     }
5489   DBG (16, "pausedReadData(2048,dest) passed (%s:%d)\n", __FILE__, __LINE__);
5490 
5491   /* dest should hold the same data than donnees */
5492   for (i = 0; i < 2047; i++)
5493     {
5494       if (data[i] != (int) (dest[i]))
5495 	{
5496 	  DBG
5497 	    (0,
5498 	     "Warning data read back differs: expected %02X found dest[%d]=%02X ! (%s:%d)\n",
5499 	     data[i], i, dest[i], __FILE__, __LINE__);
5500 	}
5501     }
5502   return 1;
5503 }
5504 
5505 
5506 /* 1: OK
5507    0: end session failed */
5508 
5509 int
sanei_umax_pp_endSession(void)5510 sanei_umax_pp_endSession (void)
5511 {
5512   int zero[5] = { 0, 0, 0, 0, -1 };
5513 
5514   if (sanei_umax_pp_getastra () != 610)
5515     {
5516       prologue (0x00);
5517       sendWord (zero);
5518       epilogue ();
5519       sanei_umax_pp_cmdSync (0xC2);
5520       sanei_umax_pp_cmdSync (0x00);	/* cancels any pending operation */
5521       sanei_umax_pp_cmdSync (0x00);	/* cancels any pending operation */
5522     }
5523   else
5524     {
5525       CMDSYNC (0x00);
5526       CMDSYNC (0xC2);
5527       CMDSYNC (0x00);
5528       CMDSYNC (0x00);
5529     }
5530   compatMode ();
5531 
5532   /* restore port state */
5533   Outb (DATA, gData);
5534   Outb (CONTROL, gControl);
5535 
5536   /* OUF */
5537   DBG (1, "End session done ...\n");
5538   return 1;
5539 }
5540 
5541 
5542 /* initialize scanner with default values
5543  * and do head re-homing if needed */
5544 int
initScanner610p(int recover)5545 initScanner610p (int recover)
5546 {
5547   int first, rc, x;
5548   int cmd55AA[9] = { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, -1 };
5549   int cmd02[17] = { 0x02, 0x80, 0x00, 0x40, 0x30, 0x00, 0xC0, 0x2F,
5550     0x2F, 0x07, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x00, -1
5551   };
5552   int op01[17] =
5553     { 0x01, 0x00, 0x32, 0x70, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00,
5554     0x00, 0x80, 0xA4, 0x00, -1
5555   };
5556   int op11[17] =
5557     { 0x01, 0x80, 0x0C, 0x70, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x01, 0x00, 0x00,
5558     0x00, 0x80, 0xA4, 0x00, -1
5559   };
5560   int op21[17] =
5561     { 0x01, 0x00, 0x01, 0x40, 0x30, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00,
5562     0x00, 0x80, 0xF4, 0x00, -1
5563   };
5564   int op31[17] =
5565     { 0x01, 0x00, 0x39, 0x73, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00,
5566     0x00, 0x80, 0xB4, 0x00, -1
5567   };
5568 
5569   int op02[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
5570     0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00,
5571     0x76, 0x00, 0x75, 0xEF, 0x06, 0x00, 0x00, 0xF6,
5572     0x4D, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
5573     0xDF, 0x1B, -1
5574   };
5575   int op22[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
5576     0x00, 0x03, 0xC1, 0x80, 0x00, 0x20, 0x02, 0x00,
5577     0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00,
5578     0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
5579     0xDF, 0x1B, -1
5580   };
5581 
5582   int op03[9] = { 0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0xFF, 0xFF, -1 };
5583   struct timeval tv;
5584 
5585   byteMode ();			/* just to get sure */
5586   first = 0;
5587   rc = inquire ();
5588 
5589   /* get time to handle settle time delay */
5590   gettimeofday (&tv, NULL);
5591   gTime = tv.tv_sec;
5592   /* default delay */
5593   gDelay = 5;
5594 
5595   if (rc == 0)
5596     {
5597       DBG (0, "inquire() failed ! (%s:%d) \n", __FILE__, __LINE__);
5598       return 0;
5599     }
5600   if (rc == 2)
5601     {
5602       /* same value used by windows driver */
5603       gDelay = 45;
5604       DBG (1, "inquire() signals re-homing needed ... (%s:%d) \n",
5605 	   __FILE__, __LINE__);
5606       first = 1;
5607     }
5608   DBG (1, "inquire() passed ... (%s:%d) \n", __FILE__, __LINE__);
5609 
5610   rc = loadDefaultTables ();
5611   if (rc == 0)
5612     {
5613       DBG (0, "loadDefaultTables() failed ! (%s:%d) \n", __FILE__, __LINE__);
5614       return 0;
5615     }
5616   DBG (1, "loadDefaultTables() passed ... (%s:%d) \n", __FILE__, __LINE__);
5617   if (recover)
5618     first = 1;
5619 
5620   CMDSETGET (2, 0x10, cmd02);
5621   CMDSETGET (1, 0x08, cmd55AA);
5622 
5623   if (!first)
5624     {
5625       CMDSYNC (0x00);
5626       CMDSYNC (0xC2);
5627       CMDSYNC (0x00);
5628       DBG (1, "initScanner610p done ...\n");
5629       return 1;
5630     }
5631 
5632   /* here we do re-homing
5633    * since it is first probe or recover */
5634   /* move forward */
5635   CMDSYNC (0xC2);
5636   if (!recover)
5637     {
5638       CMDSETGET (2, 0x10, op01);
5639       CMDSETGET (8, 0x22, op02);
5640       CMDSYNC (0xC2);
5641       CMDSYNC (0x00);
5642       CMDSETGET (4, 0x08, op03);
5643       CMDSYNC (0x40);
5644       CMDSYNC (0xC2);
5645       sleep (2);
5646     }
5647 
5648   /* move backward */
5649   CMDSETGET (2, 0x10, op11);
5650   CMDSETGET (8, 0x22, op02);
5651   CMDSYNC (0xC2);
5652   CMDSYNC (0x00);
5653   CMDSYNC (0x00);
5654   CMDSETGET (4, 0x08, op03);
5655   CMDSYNC (0x40);
5656   CMDSYNC (0xC2);
5657   sleep (2);
5658 
5659   /* means 'CONTINUE MOVE' */
5660   CMDSYNC (0x00);
5661   while ((scannerStatus & MOTOR_BIT) == 0)
5662     {
5663       CMDSYNC (0xC2);
5664       CMDSETGET (2, 0x10, op21);
5665       CMDSETGET (8, 0x22, op22);
5666       CMDSYNC (0x40);
5667       usleep (20000);
5668     }
5669   CMDSYNC (0xC2);
5670   CMDSYNC (0x00);
5671 
5672   /* send head away */
5673   if (!recover)
5674     {
5675       CMDSETGET (2, 0x10, op31);
5676       CMDSETGET (8, 0x22, op02);
5677       if (DBG_LEVEL > 8)
5678 	{
5679 	  bloc2Decode (op31);
5680 	  bloc8Decode (op02);
5681 	}
5682       CMDSYNC (0xC2);
5683       CMDSYNC (0x00);
5684       CMDSETGET (4, 0x08, op03);
5685       CMDSYNC (0x40);
5686       CMDSYNC (0xC2);
5687       sleep (9);
5688     }
5689 
5690   CMDSYNC (0x00);
5691 
5692   /* this code has been added, without corresponding logs/
5693    * it seem I just can't found 'real' parking command ...
5694    */
5695   /* send park command */
5696   if (sanei_umax_pp_park () == 0)
5697     {
5698       TRACE (0, "sanei_umax_pp_park failed! ");
5699       return 0;
5700     }
5701   /* and wait it to succeed */
5702   if (sanei_umax_pp_parkWait () == 0)
5703     {
5704       TRACE (0, "sanei_umax_pp_parkWait failed! ");
5705       return 0;
5706     }
5707 
5708   /* override gamma table with 610P defaults */
5709   for (x = 0; x < 256; x++)
5710     {
5711       ggRed[x] = x;
5712       ggGreen[x] = x;
5713       ggBlue[x] = x;
5714     }
5715 
5716   DBG (1, "initScanner610p done ...\n");
5717   return 1;
5718 }
5719 
5720 /* 1: OK
5721    2: homing happened
5722    3: scanner busy
5723    0: init failed
5724 
5725    init transport layer
5726    init scanner
5727 */
5728 
5729 int
sanei_umax_pp_initScanner(int recover)5730 sanei_umax_pp_initScanner (int recover)
5731 {
5732   int i;
5733   int status;
5734   int readcmd[64];
5735   /* in umax1220u, this buffer is opc[16] */
5736   int sentcmd[17] =
5737     { 0x02, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00, 0x2F, 0x2F, 0x07, 0x00,
5738     0x00, 0x00, 0x80, 0xF0, 0x00, -1
5739   };
5740   int cmdA7[9] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, -1 };
5741 
5742   if (sanei_umax_pp_getastra () == 610)
5743     return initScanner610p (recover);
5744 
5745   if (getModel () == 0x07)
5746     sentcmd[15] = 0x00;
5747   else
5748     sentcmd[15] = 0x18;
5749 
5750   /* fails here if there is an unfinished previous scan */
5751   CMDSETGET (0x02, 16, sentcmd);
5752 
5753   /* needs some init */
5754   if (sentcmd[15] == 0x18)
5755     {
5756       sentcmd[15] = 0x00;	/* was 0x18 */
5757       CMDSETGET (0x02, 16, sentcmd);
5758 
5759       /* in umax1220u, this buffer does not exist */
5760       CMDSETGET (0x01, 8, cmdA7);
5761     }
5762 
5763 
5764   /* ~ opb3: inquire status */
5765   CMDGET (0x08, 36, readcmd);
5766   if (DBG_LEVEL >= 32)
5767     {
5768       bloc8Decode (readcmd);
5769     }
5770   DBG (16, "cmdGet(0x08,36,readcmd) passed (%s:%d)\n", __FILE__, __LINE__);
5771 
5772   /* is the scanner busy parking ? */
5773   status = sanei_umax_pp_scannerStatus ();
5774   DBG (8, "INQUIRE SCANNER STATUS IS 0x%02X  (%s:%d)\n", status, __FILE__,
5775        __LINE__);
5776   if ((!recover) && (status & MOTOR_BIT) == 0x00)
5777     {
5778       DBG (1, "Warning: scanner motor on, giving up ...  (%s:%d)\n", __FILE__,
5779 	   __LINE__);
5780       return 3;
5781     }
5782 
5783   /* head homing needed ? */
5784   if ((readcmd[34] != 0x1A) || (recover == 1))
5785     {				/* homing needed, readcmd[34] should be 0x48 */
5786       int op01[17] =
5787 	{ 0x01, 0x00, 0x32, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x17, 0x05, 0x00,
5788 	0x00, 0x00, 0x80, 0xE4, 0x00, -1
5789       };
5790       int op05[17] =
5791 	{ 0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x13, 0x05, 0x00,
5792 	0x00, 0x00, 0x80, 0xF0, 0x00, -1
5793       };
5794       int op02[37] =
5795 	{ 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40,
5796 	0x01, 0x00, 0x20, 0x02, 0x00, 0x16, 0x00, 0x70, 0x9F, 0x06, 0x00,
5797 	0x00, 0xF6, 0x4D, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF,
5798 	0x0B, 0x1A, 0x00, -1
5799       };
5800       int op04[37] =
5801 	{ 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1,
5802 	0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03,
5803 	0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF,
5804 	0x0B, 0x1A, 0x00, -1
5805       };
5806       int op03[9] = { 0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0xFF, 0xFF, -1 };
5807 
5808       CMDSYNC (0xC2);
5809       CMDSETGET (0x02, 16, op01);
5810       CMDSETGET (0x08, 36, op02);
5811 
5812       if (!recover)
5813 	{
5814 	  CMDSYNC (0xC2);
5815 	  CMDSYNC (0x00);
5816 	  CMDSETGET (0x04, 8, op03);
5817 	  CMDSYNC (0x40);
5818 	  do
5819 	    {
5820 	      sleep (1);
5821 	      CMDSYNC (0xC2);
5822 	    }
5823 	  while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90);
5824 
5825 	  op01[2] = 0x1E;
5826 	  op01[9] = 0x01;
5827 	  CMDSETGET (0x02, 16, op01);
5828 	  CMDSETGET (0x08, 36, op02);
5829 	  CMDSYNC (0x00);
5830 	  CMDSYNC (0x00);
5831 	  CMDSETGET (0x04, 8, op03);
5832 
5833 	  CMDSYNC (0x40);
5834 	  do
5835 	    {
5836 	      sleep (1);
5837 	      CMDSYNC (0xC2);
5838 	    }
5839 	  while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90);
5840 	  CMDSYNC (0x00);
5841 	}
5842 
5843       for (i = 0; i < 4; i++)
5844 	{
5845 
5846 	  do
5847 	    {
5848 	      usleep (500000);
5849 	      CMDSYNC (0xC2);
5850 	      status = sanei_umax_pp_scannerStatus ();
5851 	      status = status & 0x10;
5852 	    }
5853 	  while (status != 0x10);	/* was 0x90 */
5854 	  CMDSETGET (0x02, 16, op05);
5855 	  CMDSETGET (0x08, 36, op04);
5856 	  CMDSYNC (0x40);
5857 	  status = sanei_umax_pp_scannerStatus ();
5858 	  DBG (16, "loop %d passed, status=0x%02X (%s:%d)\n", i, status,
5859 	       __FILE__, __LINE__);
5860 	}
5861 
5862 
5863 
5864       /* get head back home ... */
5865       do
5866 	{
5867 	  i++;
5868 	  do
5869 	    {
5870 	      usleep (500000);
5871 	      CMDSYNC (0xC2);
5872 	      status = sanei_umax_pp_scannerStatus ();
5873 	      status = status & 0x10;
5874 	    }
5875 	  while (status != 0x10);	/* was 0x90 */
5876 	  CMDSETGET (0x02, 16, op05);
5877 	  CMDSETGET (0x08, 36, op04);
5878 	  CMDSYNC (0x40);
5879 	  status = sanei_umax_pp_scannerStatus ();
5880 	  DBG (16, "loop %d passed, status=0x%02X (%s:%d)\n", i, status,
5881 	       __FILE__, __LINE__);
5882 	}
5883       while ((status & MOTOR_BIT) == 0x00);	/* 0xD0 when head is back home */
5884 
5885       do
5886 	{
5887 	  usleep (500000);
5888 	  CMDSYNC (0xC2);
5889 	}
5890       while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90);
5891 
5892 
5893       /* don't do automatic home sequence on recovery */
5894       if (!recover)
5895 	{
5896 	  CMDSYNC (0x00);
5897 	  op01[2] = 0x1A;
5898 	  op01[3] = 0x74;	/* was 0x70 */
5899 	  op01[9] = 0x05;	/* initial value */
5900 	  op01[14] = 0xF4;	/* was 0xE4 */
5901 	  CMDSETGET (0x02, 16, op01);
5902 	  CMDSETGET (0x08, 36, op02);
5903 	  CMDSYNC (0xC2);
5904 	  CMDSYNC (0x00);
5905 	  CMDSETGET (0x04, 8, op03);
5906 	  CMDSYNC (0x40);
5907 
5908 	  /* wait for automatic homing sequence */
5909 	  /* to complete, thus avoiding         */
5910 	  /* scanning too early                 */
5911 	  do
5912 	    {
5913 	      /* the sleep is here to prevent */
5914 	      /* excessive CPU usage, can be  */
5915 	      /* removed, if we don't care    */
5916 	      sleep (3);
5917 	      CMDSYNC (0xC2);
5918 	      DBG (16, "PARKING polling status is 0x%02X   (%s:%d)\n",
5919 		   sanei_umax_pp_scannerStatus (), __FILE__, __LINE__);
5920 	    }
5921 	  while (sanei_umax_pp_scannerStatus () == 0x90);
5922 	}
5923 
5924       /* signal homing */
5925       return 2;
5926     }
5927 
5928 
5929   /* end ... */
5930   DBG (1, "Scanner init done ...\n");
5931   return 1;
5932 }
5933 
5934 
5935 /*
5936         1: OK
5937            2: failed, try again
5938            0: init failed
5939 
5940         initialize the transport layer
5941 
5942    */
5943 
5944 static int
initTransport610p(void)5945 initTransport610p (void)
5946 {
5947   int tmp, i;
5948   int zero[5] = { 0, 0, 0, 0, -1 };
5949 
5950   /* test EPP availability */
5951   connect610p ();
5952   if (sync610p () == 0)
5953     {
5954       DBG (0,
5955 	   "sync610p failed! Scanner not present or powered off ...  (%s:%d)\n",
5956 	   __FILE__, __LINE__);
5957       return 0;
5958     }
5959   if (EPPsendWord610p (zero) == 0)
5960     {
5961       DBG (1, "No EPP mode detected\n");
5962       gMode = UMAX_PP_PARPORT_BYTE;
5963     }
5964   else
5965     {
5966       DBG (1, "EPP mode detected\n");
5967       gMode = UMAX_PP_PARPORT_EPP;
5968     }
5969   disconnect610p ();
5970 
5971   /* set up to bidirectionnal */
5972   /* in fact we could add support for EPP */
5973   /* but let's make 610 work first */
5974   if (gMode == UMAX_PP_PARPORT_BYTE)
5975     {
5976       byteMode ();
5977 
5978       /* reset after failure */
5979       /* set to data reverse */
5980       Outb (CONTROL, 0x2C);
5981       Inb (CONTROL);
5982       for (i = 0; i < 10; i++)
5983 	Outb (DATA, 0xAA);
5984       tmp = Inb (DATA);
5985       tmp = Inb (DATA);
5986       if (tmp != 0xFF)
5987 	{
5988 	  DBG (1, "Found 0x%X expected 0xFF  (%s:%d)\n", tmp, __FILE__,
5989 	       __LINE__);
5990 	}
5991       for (i = 0; i < 4; i++)
5992 	{
5993 	  Outb (DATA, 0x00);
5994 	  tmp = Inb (DATA);
5995 	  if (tmp != 0xFF)
5996 	    {
5997 	      DBG (1, "Found 0x%X expected 0xFF  (%s:%d)\n", tmp, __FILE__,
5998 		   __LINE__);
5999 	      return 0;
6000 	    }
6001 	  Outb (DATA, 0xFF);
6002 	  tmp = Inb (DATA);
6003 	  if (tmp != 0xFF)
6004 	    {
6005 	      DBG (1, "Found 0x%X expected 0xFF  (%s:%d)\n", tmp, __FILE__,
6006 		   __LINE__);
6007 	      return 0;
6008 	    }
6009 	}
6010       TRACE (16, "RESET done... ");
6011       byteMode ();
6012 
6013       if (SPPsendWord610p (zero) == 0)
6014 	{
6015 	  DBG (0, "SPPsendWord610p(zero) failed! (%s:%d)\n", __FILE__,
6016 	       __LINE__);
6017 	  return 0;
6018 	}
6019       TRACE (16, "SPPsendWord610p(zero) passed... ");
6020     }
6021 
6022   /* OK ! */
6023   TRACE (1, "initTransport610p done... ");
6024   return 1;
6025 }
6026 
6027 /*
6028         1: OK
6029            2: failed, try again
6030            0: init failed
6031 
6032         initialize the transport layer
6033 
6034    */
6035 
6036 static int
initTransport1220P(int recover)6037 initTransport1220P (int recover)	/* ECP OK !! */
6038 {
6039   int i, j;
6040   int reg, tmp;
6041   unsigned char *dest = NULL;
6042   int zero[5] = { 0, 0, 0, 0, -1 };
6043   int model, nb;
6044 
6045   connect ();
6046   DBG (16, "connect() passed... (%s:%d)\n", __FILE__, __LINE__);
6047   gEPAT = 0xC7;
6048   reg = registerRead (0x0B);
6049   if (reg != gEPAT)
6050     {
6051       DBG (16, "Error! expected reg0B=0x%02X, found 0x%02X! (%s:%d) \n",
6052 	   gEPAT, reg, __FILE__, __LINE__);
6053       DBG (16, "Scanner needs probing ... \n");
6054       if (sanei_umax_pp_probeScanner (recover) != 1)
6055 	{
6056 	  return 0;
6057 	}
6058       else
6059 	{
6060 	  return 2;		/* signals retry initTransport() */
6061 	}
6062     }
6063 
6064   reg = registerRead (0x0D);
6065   reg = (reg & 0xE8) | 0x43;
6066   registerWrite (0x0D, reg);
6067   REGISTERWRITE (0x0C, 0x04);
6068   reg = registerRead (0x0A);
6069   if (reg != 0x00)
6070     {
6071       if (reg != 0x1C)
6072 	{
6073 	  DBG (0, "Warning! expected reg0A=0x00, found 0x%02X! (%s:%d) \n",
6074 	       reg, __FILE__, __LINE__);
6075 	}
6076       else
6077 	{
6078 	  DBG (16, "Scanner in idle state .... (%s:%d)\n", __FILE__,
6079 	       __LINE__);
6080 	}
6081     }
6082 
6083   /* model detection: redone since we might not be probing each time ... */
6084   /* write addr in 0x0E, read value at 0x0F                              */
6085   REGISTERWRITE (0x0E, 0x01);
6086   model = registerRead (0x0F);
6087   setModel (model);
6088 
6089   REGISTERWRITE (0x0A, 0x1C);
6090   if (gMode == UMAX_PP_PARPORT_ECP)
6091     {
6092       REGISTERWRITE (0x08, 0x10);
6093     }
6094   else
6095     {
6096       REGISTERWRITE (0x08, 0x21);
6097     }
6098   REGISTERWRITE (0x0E, 0x0F);
6099   REGISTERWRITE (0x0F, 0x0C);
6100 
6101   REGISTERWRITE (0x0A, 0x1C);
6102   REGISTERWRITE (0x0E, 0x10);
6103   REGISTERWRITE (0x0F, 0x1C);
6104   if (gMode == UMAX_PP_PARPORT_ECP)
6105     {
6106       REGISTERWRITE (0x0F, 0x00);
6107     }
6108   REGISTERWRITE (0x0A, 0x11);
6109 
6110   dest = (unsigned char *) (malloc (65536));
6111   if (dest == NULL)
6112     {
6113       DBG (0, "Failed to allocate 64 Ko !\n");
6114       return 0;
6115     }
6116   for (i = 0; i < 256; i++)
6117     {
6118       dest[i * 2] = i;
6119       dest[i * 2 + 1] = 0xFF - i;
6120       dest[512 + i * 2] = i;
6121       dest[512 + i * 2 + 1] = 0xFF - i;
6122     }
6123   nb = 150;
6124   for (i = 0; i < nb; i++)
6125     {
6126       bufferWrite (0x400, dest);
6127       DBG (16,
6128 	   "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
6129 	   __FILE__, __LINE__);
6130     }
6131 
6132   REGISTERWRITE (0x0A, 0x18);
6133   REGISTERWRITE (0x0A, 0x11);
6134 
6135   if (gMode == UMAX_PP_PARPORT_ECP)
6136     {
6137       ECPSetBuffer (0x400);
6138     }
6139   for (i = 0; i < nb; i++)
6140     {
6141       /* XXX Compat/Byte ??? XXX */
6142       bufferRead (0x400, dest);
6143       for (j = 0; j < 256; j++)
6144 	{
6145 	  if (dest[j * 2] != j)
6146 	    {
6147 	      DBG (0,
6148 		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6149 		   j * 2, j, dest[j * 2]);
6150 	      return 0;
6151 	    }
6152 	  if (dest[j * 2 + 1] != 0xFF - j)
6153 	    {
6154 	      DBG
6155 		(0,
6156 		 "Altered buffer value at %03X, expected %02X, found %02X\n",
6157 		 j * 2 + 1, 0xFF - j, dest[j * 2 + 1]);
6158 	      return 0;
6159 	    }
6160 	  if (dest[512 + j * 2] != j)
6161 	    {
6162 	      DBG (0,
6163 		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6164 		   512 + j * 2, j, dest[512 + j * 2]);
6165 	      return 0;
6166 	    }
6167 	  if (dest[512 + j * 2 + 1] != 0xFF - j)
6168 	    {
6169 	      DBG
6170 		(0,
6171 		 "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n",
6172 		 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]);
6173 	      return 0;
6174 	    }
6175 	}
6176       DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n",
6177 	   i, __FILE__, __LINE__);
6178     }
6179   REGISTERWRITE (0x0A, 0x18);
6180   /* ECP: "HEAVY" reconnect here */
6181   if (gMode == UMAX_PP_PARPORT_ECP)
6182     {
6183       epilogue ();
6184       /* 3 line: set to initial parport state ? */
6185       byteMode ();		/*Outb (ECR, 0x20); */
6186       Outb (DATA, 0x04);
6187       Outb (CONTROL, 0x0C);
6188 
6189       /* the following is a variant of connect(); */
6190       Inb (ECR);
6191       Inb (ECR);
6192       byteMode ();		/*Outb (ECR, 0x20); */
6193       byteMode ();		/*Outb (ECR, 0x20); */
6194       Inb (CONTROL);
6195       Outb (CONTROL, 0x0C);
6196       Inb (DATA);
6197       sendCommand (0xE0);
6198       Outb (DATA, 0XFF);
6199       Outb (DATA, 0XFF);
6200       ClearRegister (0);
6201       WRITESLOW (0x0E, 0x0A);
6202       SLOWNIBBLEREGISTERREAD (0x0F, 0x08);
6203       /* resend value OR'ed 0x08 ? */
6204       WRITESLOW (0x0F, 0x08);
6205       WRITESLOW (0x08, 0x10);
6206       disconnect ();
6207       prologue (0x10);
6208     }
6209 
6210   if (fonc001 () != 1)
6211     {
6212       DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__);
6213       return 0;
6214     }
6215   DBG (16, "fonc001() passed ...  (%s:%d) \n", __FILE__, __LINE__);
6216 
6217   /* sync */
6218   if (sendWord (zero) == 0)
6219     {
6220       DBG (0, "sendWord(zero) failed (%s:%d)\n", __FILE__, __LINE__);
6221       return 0;
6222     }
6223   DBG (16, "sendWord(zero) passed (%s:%d)\n", __FILE__, __LINE__);
6224   epilogue ();
6225 
6226   /* OK ! */
6227   free (dest);
6228   DBG (1, "initTransport1220P done ...\n");
6229   return 1;
6230 }
6231 
6232 /*
6233         1: OK
6234            2: failed, try again
6235            0: init failed
6236 
6237         initialize the transport layer
6238 
6239    */
6240 
6241 int
sanei_umax_pp_initTransport(int recover)6242 sanei_umax_pp_initTransport (int recover)
6243 {
6244   TRACE (16, "sanei_umax_pp_initTransport");
6245   switch (sanei_umax_pp_getastra ())
6246     {
6247     case 610:
6248       return initTransport610p ();
6249     case 1220:
6250     case 1600:
6251     case 2000:
6252     default:
6253       return initTransport1220P (recover);
6254     }
6255 }
6256 
6257 
6258 /* 1: OK
6259    0: probe failed */
6260 
6261 static int
probe610p(int recover)6262 probe610p (int recover)
6263 {
6264   if (initTransport610p () == 0)
6265     {
6266       DBG (0, "initTransport610p() failed (%s:%d)\n", __FILE__, __LINE__);
6267       return 0;
6268     }
6269 
6270   /* make sure we won't try 1220/200P later
6271    * since we got here, we have a 610, and in any case
6272    * NOT a 1220P/2000P, since no EPAT present */
6273   sanei_umax_pp_setastra (610);
6274 
6275   if (initScanner610p (recover) == 0)
6276     {
6277       DBG (0, "initScanner610p() failed (%s:%d)\n", __FILE__, __LINE__);
6278       return 0;
6279     }
6280   /* successful end ... */
6281   DBG (1, "UMAX Astra 610p detected\n");
6282   DBG (1, "probe610p done ...\n");
6283   return 1;
6284 }
6285 
6286 
6287   /*
6288    * try PS2 mode
6289    * returns 1 on success, 0 on failure
6290    */
6291 int
probePS2(unsigned char *dest)6292 probePS2 (unsigned char *dest)
6293 {
6294   int i, tmp;
6295 
6296   /* write/read full buffer */
6297   for (i = 0; i < 256; i++)
6298     {
6299       WRITESLOW (0x0A, i);
6300       SLOWNIBBLEREGISTERREAD (0x0A, i);
6301       WRITESLOW (0x0A, 0xFF - i);
6302       SLOWNIBBLEREGISTERREAD (0x0A, 0xFF - i);
6303     }
6304 
6305   /* end test for nibble byte/byte mode */
6306 
6307   /* now we try nibble buffered mode */
6308   WRITESLOW (0x13, 0x01);
6309   WRITESLOW (0x13, 0x00);	/*reset something */
6310   WRITESLOW (0x0A, 0x11);
6311   for (i = 0; i < 10; i++)	/* 10 ~ 11 ? */
6312     {
6313       PS2bufferRead (0x400, dest);
6314       DBG (16, "Loop %d: PS2bufferRead passed ... (%s:%d)\n", i, __FILE__,
6315 	   __LINE__);
6316     }
6317 
6318   /* write buffer */
6319   for (i = 0; i < 10; i++)
6320     {
6321       PS2bufferWrite (0x400, dest);
6322       DBG (16, "Loop %d: PS2bufferWrite passed ... (%s:%d)\n", i, __FILE__,
6323 	   __LINE__);
6324     }
6325 
6326   SLOWNIBBLEREGISTERREAD (0x0C, 0x04);
6327   WRITESLOW (0x13, 0x01);
6328   WRITESLOW (0x13, 0x00);
6329   WRITESLOW (0x0A, 0x18);
6330 
6331   return 1;
6332 }
6333 
6334   /*
6335    * try EPP 8 then 32 bits
6336    * returns 1 on success, 0 on failure
6337    */
6338 int
probeEPP(unsigned char *dest)6339 probeEPP (unsigned char *dest)
6340 {
6341   int tmp, i, j;
6342   int reg;
6343 
6344   /* test EPP MODE */
6345   setEPPMode (8);
6346   gMode = UMAX_PP_PARPORT_EPP;
6347   ClearRegister (0);
6348   DBG (16, "ClearRegister(0) passed... (%s:%d)\n", __FILE__, __LINE__);
6349   WRITESLOW (0x08, 0x22);
6350   init001 ();
6351   DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
6352   gEPAT = 0xC7;
6353   init002 (0);
6354   DBG (16, "init002(0) passed... (%s:%d)\n", __FILE__, __LINE__);
6355 
6356   REGISTERWRITE (0x0A, 0);
6357 
6358   /* catch any failure to read back data in EPP mode */
6359   reg = registerRead (0x0A);
6360   if (reg != 0)
6361     {
6362       DBG (0, "registerRead, found 0x%X expected 0x00 (%s:%d)\n", reg,
6363 	   __FILE__, __LINE__);
6364       if (reg == 0xFF)
6365 	{
6366 	  DBG (0,
6367 	       "*** It appears that EPP data transfer doesn't work    ***\n");
6368 	  DBG (0,
6369 	       "*** Please read SETTING EPP section in sane-umax_pp.5 ***\n");
6370 	}
6371       return 0;
6372     }
6373   else
6374     {
6375       DBG (16, "registerRead(0x0A)=0x00 passed... (%s:%d)\n", __FILE__,
6376 	   __LINE__);
6377     }
6378   registerWrite (0x0A, 0xFF);
6379   DBG (16, "registerWrite(0x%X,0x%X) passed...   (%s:%d)\n", 0x0A, 0xFF,
6380        __FILE__, __LINE__);
6381   REGISTERREAD (0x0A, 0xFF);
6382   for (i = 1; i < 256; i++)
6383     {
6384       REGISTERWRITE (0x0A, i);
6385       REGISTERREAD (0x0A, i);
6386       REGISTERWRITE (0x0A, 0xFF - i);
6387       REGISTERREAD (0x0A, 0xFF - i);
6388     }
6389 
6390   REGISTERWRITE (0x13, 0x01);
6391   REGISTERWRITE (0x13, 0x00);
6392   REGISTERWRITE (0x0A, 0x11);
6393 
6394   for (i = 0; i < 10; i++)
6395     {
6396       bufferRead (0x400, dest);
6397       for (j = 0; j < 512; j++)
6398 	{
6399 	  if (dest[2 * j] != (j % 256))
6400 	    {
6401 	      DBG (0, "Loop %d, char %d bufferRead failed! (%s:%d)\n", i,
6402 		   j * 2, __FILE__, __LINE__);
6403 	      return 0;
6404 	    }
6405 	  if (dest[2 * j + 1] != (0xFF - (j % 256)))
6406 	    {
6407 	      DBG (0, "Loop %d, char %d bufferRead failed! (%s:%d)\n", i,
6408 		   j * 2 + 1, __FILE__, __LINE__);
6409 	      return 0;
6410 	    }
6411 	}
6412       DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n", i,
6413 	   __FILE__, __LINE__);
6414     }
6415 
6416   for (i = 0; i < 10; i++)
6417     {
6418       bufferWrite (0x400, dest);
6419       DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
6420 	   __FILE__, __LINE__);
6421     }
6422 
6423 
6424   REGISTERREAD (0x0C, 4);
6425   REGISTERWRITE (0x13, 0x01);
6426   REGISTERWRITE (0x13, 0x00);
6427   REGISTERWRITE (0x0A, 0x18);
6428 
6429   Outb (DATA, 0x0);
6430   ClearRegister (0);
6431   init001 ();
6432 
6433   if (checkEPAT () != 0)
6434     return 0;
6435   DBG (16, "checkEPAT() passed... (%s:%d)\n", __FILE__, __LINE__);
6436 
6437   tmp = Inb (CONTROL) & 0x1F;
6438   Outb (CONTROL, tmp);
6439   Outb (CONTROL, tmp);
6440 
6441   WRITESLOW (0x08, 0x21);
6442   init001 ();
6443   DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
6444   WRITESLOW (0x08, 0x21);
6445   init001 ();
6446   DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
6447   SPPResetLPT ();
6448 
6449 
6450   if (init005 (0x80))
6451     {
6452       DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__);
6453     }
6454   DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__);
6455   if (init005 (0xEC))
6456     {
6457       DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__);
6458     }
6459   DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__);
6460 
6461 
6462   /* write/read buffer loop */
6463   for (i = 0; i < 256; i++)
6464     {
6465       REGISTERWRITE (0x0A, i);
6466       REGISTERREAD (0x0A, i);
6467       REGISTERWRITE (0x0A, 0xFF - i);
6468       REGISTERREAD (0x0A, 0xFF - i);
6469     }
6470   DBG (16, "EPP write/read buffer loop passed... (%s:%d)\n", __FILE__,
6471        __LINE__);
6472 
6473   REGISTERWRITE (0x13, 0x01);
6474   REGISTERWRITE (0x13, 0x00);
6475   REGISTERWRITE (0x0A, 0x11);
6476 
6477   /* test EPP32 mode */
6478   /* we set 32 bits I/O mode first, then step back to */
6479   /* 8bits if tests fail                              */
6480   setEPPMode (32);
6481   for (i = 0; (i < 10) && (getEPPMode () == 32); i++)
6482     {
6483       bufferRead (0x400, dest);
6484       /* if 32 bit I/O work, we should have a buffer */
6485       /* filled by 00 FF 01 FE 02 FD 03 FC .....     */
6486       for (j = 0; j < 0x200; j++)
6487 	{
6488 	  if ((dest[j * 2] != j % 256)
6489 	      || (dest[j * 2 + 1] != 0xFF - (j % 256)))
6490 	    {
6491 	      DBG (1, "Setting EPP I/O to 8 bits ... (%s:%d)\n", __FILE__,
6492 		   __LINE__);
6493 	      setEPPMode (8);
6494 	      /* leave out current loop since an error was detected */
6495 	      break;
6496 	    }
6497 	}
6498       DBG (16, "Loop %d: bufferRead(0x400) passed... (%s:%d)\n", i,
6499 	   __FILE__, __LINE__);
6500     }
6501   DBG (1, "%d bits EPP data transfer\n", getEPPMode ());
6502 
6503 
6504   for (i = 0; i < 10; i++)
6505     {
6506       bufferWrite (0x400, dest);
6507       DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
6508 	   __FILE__, __LINE__);
6509     }
6510 
6511 
6512 
6513   REGISTERREAD (0x0C, 0x04);
6514   REGISTERWRITE (0x13, 0x01);
6515   REGISTERWRITE (0x13, 0x00);
6516   REGISTERWRITE (0x0A, 0x18);
6517 
6518   WRITESLOW (0x08, 0x21);
6519   init001 ();
6520   DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
6521   SPPResetLPT ();
6522 
6523   if (init005 (0x80))
6524     {
6525       DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__);
6526     }
6527   DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__);
6528   if (init005 (0xEC))
6529     {
6530       DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__);
6531     }
6532   DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__);
6533 
6534 
6535   /* write/read buffer loop */
6536   for (i = 0; i < 256; i++)
6537     {
6538       REGISTERWRITE (0x0A, i);
6539       REGISTERREAD (0x0A, i);
6540       REGISTERWRITE (0x0A, 0xFF - i);
6541       REGISTERREAD (0x0A, 0xFF - i);
6542     }
6543   DBG (16, "EPP write/read buffer loop passed... (%s:%d)\n", __FILE__,
6544        __LINE__);
6545 
6546   REGISTERWRITE (0x13, 0x01);
6547   REGISTERWRITE (0x13, 0x00);
6548   REGISTERWRITE (0x0A, 0x11);
6549 
6550 
6551   for (i = 0; i < 10; i++)
6552     {
6553       bufferRead (0x400, dest);
6554       DBG (16, "Loop %d: bufferRead(0x400) passed... (%s:%d)\n", i,
6555 	   __FILE__, __LINE__);
6556     }
6557 
6558   for (i = 0; i < 10; i++)
6559     {
6560       bufferWrite (0x400, dest);
6561       DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
6562 	   __FILE__, __LINE__);
6563     }
6564   REGISTERREAD (0x0C, 0x04);
6565   REGISTERWRITE (0x13, 0x01);
6566   REGISTERWRITE (0x13, 0x00);
6567   REGISTERWRITE (0x0A, 0x18);
6568   gMode = UMAX_PP_PARPORT_EPP;
6569   return 1;
6570 }
6571 
6572   /*
6573    * try ECP mode
6574    * returns 1 on success, 0 on failure
6575    */
6576 int
probeECP(unsigned char *dest)6577 probeECP (unsigned char *dest)
6578 {
6579   int i, j, tmp;
6580   unsigned char breg;
6581 
6582   /* if ECP not available, fail */
6583   if (gECP != 1)
6584     {
6585       DBG (1, "Hardware can't do ECP, giving up (%s:%d) ...\n", __FILE__,
6586 	   __LINE__);
6587       return 0;
6588     }
6589   gMode = UMAX_PP_PARPORT_ECP;
6590 
6591 /* clean from EPP failure */
6592   breg = Inb (CONTROL);
6593   Outb (CONTROL, breg & 0x04);
6594 
6595 /* reset sequence */
6596   byteMode ();			/*Outb (ECR, 0x20);            byte mode */
6597   Outb (CONTROL, 0x04);
6598   Outb (CONTROL, 0x0C);
6599   Outb (CONTROL, 0x0C);
6600   Outb (CONTROL, 0x0C);
6601   Outb (CONTROL, 0x0C);
6602   for (i = 0; i < 256; i++)
6603     {
6604       breg = (Inb (STATUS)) & 0xF8;
6605       if (breg != 0x48)
6606 	{
6607 	  DBG (0,
6608 	       "probeECP() failed at sync step %d, status=0x%02X, expected 0x48 (%s:%d)\n",
6609 	       i, breg, __FILE__, __LINE__);
6610 	  return 0;
6611 	}
6612     }
6613   Outb (CONTROL, 0x0E);
6614   Outb (CONTROL, 0x0E);
6615   Outb (CONTROL, 0x0E);
6616   breg = (Inb (STATUS)) & 0xF8;
6617   if (breg != 0x48)
6618     {
6619       DBG (0, "probeECP() failed, status=0x%02X, expected 0x48 (%s:%d)\n",
6620 	   breg, __FILE__, __LINE__);
6621       return 0;
6622     }
6623   Outb (CONTROL, 0x04);
6624   Outb (CONTROL, 0x04);
6625   Outb (CONTROL, 0x04);
6626   breg = Inb (STATUS) & 0xF8;
6627   breg = (Inb (STATUS)) & 0xF8;
6628   if (breg != 0xC8)
6629     {
6630       DBG (0, "probeECP() failed, status=0x%02X, expected 0xC8 (%s:%d)\n",
6631 	   breg, __FILE__, __LINE__);
6632       return 0;
6633     }
6634 /* end of reset sequence */
6635 
6636   Outb (DATA, 0x00);
6637   ClearRegister (0);
6638 
6639 /* utile ? semble tester le registre de configuration
6640  * inb ECR,35
6641  * inb 77B,FF
6642  * inb ECR,35
6643  */
6644 /* routine A */
6645   breg = Inb (CONTROL);		/* 0x04 évidemment! */
6646   breg = Inb (ECR);
6647   breg = Inb (ECR);
6648   breg = Inb (ECR);
6649   breg = Inb (ECR);
6650   breg = Inb (CONTROL);
6651   byteMode ();			/*Outb (ECR, 0x20);            byte mode */
6652   /*byteMode ();                        Outb (ECR, 0x20); */
6653   breg = Inb (CONTROL);
6654   Outb (CONTROL, 0x04);
6655   Outb (CONTROL, 0x04);
6656   breg = Inb (ECR);		/* 35 expected */
6657   breg = Inb (ECR);		/* 35 expected */
6658   breg = Inb (ECR);		/* 35 expected */
6659   breg = Inb (ECR);		/* 35 expected */
6660   Outb (CONTROL, 0x04);
6661   Outb (CONTROL, 0x04);
6662   byteMode ();
6663   byteMode ();
6664 
6665   ClearRegister (0);
6666 
6667 /* routine C */
6668   PS2registerWrite (0x08, 0x01);
6669 
6670   Outb (CONTROL, 0x0C);
6671   Outb (CONTROL, 0x04);
6672 
6673   ClearRegister (0);
6674 
6675   breg = PS2Something (0x10);
6676   if (breg != 0x0B)
6677     {
6678       DBG (0, "probeECP() failed, reg10=0x%02X, expected 0x0B (%s:%d)\n",
6679 	   breg, __FILE__, __LINE__);
6680       /* return 0; */
6681     }
6682 
6683 
6684   for (i = 0; i < 256; i++)
6685     {
6686       ECPregisterWrite (0x0A, i);
6687       breg = ECPregisterRead (0x0A);
6688       if (breg != i)
6689 	{
6690 	  DBG (0, "probeECP(), loop %d failed (%s:%d)\n", i, __FILE__,
6691 	       __LINE__);
6692 	  return 0;
6693 	}
6694       ECPregisterWrite (0x0A, 0xFF - i);
6695       breg = ECPregisterRead (0x0A);
6696       if (breg != 0xFF - i)
6697 	{
6698 	  DBG (0, "probeECP(), loop %d failed (%s:%d)\n", i, __FILE__,
6699 	       __LINE__);
6700 	  return 0;
6701 	}
6702     }
6703   DBG (16, "probeECP(), loop passed (%s:%d)\n", __FILE__, __LINE__);
6704 
6705   ECPregisterWrite (0x13, 0x01);
6706   ECPregisterWrite (0x13, 0x00);
6707   ECPregisterWrite (0x0A, 0x11);
6708 
6709   /* there is one buffer transfer size set up */
6710   /* subsequent reads are done in a row       */
6711   ECPSetBuffer (0x400);
6712   for (i = 0; i < 10; i++)
6713     {
6714       /* if (i > 0) */
6715       compatMode ();
6716       Outb (CONTROL, 0x04);	/* reset ? */
6717 
6718       ECPbufferRead (1024, dest);
6719       /* check content of the returned buffer */
6720       for (j = 0; j < 256; j++)
6721 	{
6722 	  if (dest[j * 2] != j)
6723 	    {
6724 	      DBG (0,
6725 		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6726 		   j * 2, j, dest[j * 2]);
6727 	      return 0;
6728 	    }
6729 	  if (dest[j * 2 + 1] != 0xFF - j)
6730 	    {
6731 	      DBG
6732 		(0,
6733 		 "Altered buffer value at %03X, expected %02X, found %02X\n",
6734 		 j * 2 + 1, 0xFF - j, dest[j * 2 + 1]);
6735 	      return 0;
6736 	    }
6737 	  if (dest[512 + j * 2] != j)
6738 	    {
6739 	      DBG (0,
6740 		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6741 		   512 + j * 2, j, dest[512 + j * 2]);
6742 	      return 0;
6743 	    }
6744 	  if (dest[512 + j * 2 + 1] != 0xFF - j)
6745 	    {
6746 	      DBG
6747 		(0,
6748 		 "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n",
6749 		 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]);
6750 	      return 0;
6751 	    }
6752 	}
6753       Outb (CONTROL, 0x04);
6754       byteMode ();
6755     }
6756 
6757   for (i = 0; i < 10; i++)
6758     ECPbufferWrite (1024, dest);
6759 
6760   breg = ECPregisterRead (0x0C);
6761   if (breg != 0x04)
6762     {
6763       DBG (0, "Warning! expected reg0C=0x04, found 0x%02X! (%s:%d) \n", breg,
6764 	   __FILE__, __LINE__);
6765     }
6766 
6767   ECPregisterWrite (0x13, 0x01);
6768   ECPregisterWrite (0x13, 0x00);
6769   ECPregisterWrite (0x0A, 0x18);
6770 
6771   /* reset printer ? */
6772   Outb (DATA, 0x00);
6773   Outb (CONTROL, 0x00);
6774   Outb (CONTROL, 0x04);
6775 
6776   for (i = 0; i < 3; i++)
6777     {				/* will go in a function */
6778       ClearRegister (0);
6779       if (waitAck () != 1)
6780 	{
6781 	  DBG (0, "probeECP failed because of waitAck() (%s:%d) \n", __FILE__,
6782 	       __LINE__);
6783 	  /* return 0; may fail without harm ... ??? */
6784 	}
6785       /* are these 2 out really needed ? */
6786       PS2registerWrite (0x08, 0x01);
6787       Outb (CONTROL, 0x0C);	/* select + reset */
6788       Outb (CONTROL, 0x04);	/* reset */
6789     }
6790 
6791   /* prologue of the 'rotate test' */
6792   ClearRegister (0);
6793   breg = PS2Something (0x10);
6794   if (breg != 0x0B)
6795     {
6796       DBG (0,
6797 	   "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", breg,
6798 	   __FILE__, __LINE__);
6799     }
6800   Outb (CONTROL, 0x04);		/* reset */
6801 
6802   if (init005 (0x80))
6803     {
6804       DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__);
6805     }
6806   DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__);
6807   if (init005 (0xEC))
6808     {
6809       DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__);
6810     }
6811   DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__);
6812 
6813   for (i = 0; i < 256; i++)
6814     {
6815       REGISTERWRITE (0x0A, i);
6816       REGISTERREAD (0x0A, i);
6817       REGISTERWRITE (0x0A, 0xFF - i);
6818       REGISTERREAD (0x0A, 0xFF - i);
6819     }
6820   DBG (16, "ECPprobe(), write/read buffer loop passed (%s:%d)\n", __FILE__,
6821        __LINE__);
6822 
6823   REGISTERWRITE (0x13, 0x01);
6824   REGISTERWRITE (0x13, 0x00);
6825   REGISTERWRITE (0x0A, 0x11);
6826 
6827   /* should be a function */
6828   /* in probeEPP(), we begin 32 bit mode test here */
6829   for (i = 0; i < 10; i++)
6830     {
6831       compatMode ();
6832       Outb (CONTROL, 0x04);	/* reset ? */
6833 
6834       ECPbufferRead (0x400, dest);
6835       /* check content of the returned buffer */
6836       for (j = 0; j < 256; j++)
6837 	{
6838 	  if (dest[j * 2] != j)
6839 	    {
6840 	      DBG (0,
6841 		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6842 		   j * 2, j, dest[j * 2]);
6843 	      return 0;
6844 	    }
6845 	  if (dest[j * 2 + 1] != 0xFF - j)
6846 	    {
6847 	      DBG
6848 		(0,
6849 		 "Altered buffer value at %03X, expected %02X, found %02X\n",
6850 		 j * 2 + 1, 0xFF - j, dest[j * 2 + 1]);
6851 	      return 0;
6852 	    }
6853 	  if (dest[512 + j * 2] != j)
6854 	    {
6855 	      DBG (0,
6856 		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6857 		   512 + j * 2, j, dest[512 + j * 2]);
6858 	      return 0;
6859 	    }
6860 	  if (dest[512 + j * 2 + 1] != 0xFF - j)
6861 	    {
6862 	      DBG
6863 		(0,
6864 		 "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n",
6865 		 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]);
6866 	      return 0;
6867 	    }
6868 	}
6869       Outb (CONTROL, 0x04);
6870       byteMode ();
6871     }
6872 
6873   for (i = 0; i < 10; i++)
6874     ECPbufferWrite (1024, dest);
6875 
6876   REGISTERREAD (0x0C, 0x04);
6877   REGISTERWRITE (0x13, 0x01);
6878   REGISTERWRITE (0x13, 0x00);
6879   REGISTERWRITE (0x0A, 0x18);
6880   waitAck ();
6881 
6882   return 1;
6883 }
6884 
6885 
6886 
6887 /* 1: OK
6888    0: probe failed */
6889 
6890 int
sanei_umax_pp_probeScanner(int recover)6891 sanei_umax_pp_probeScanner (int recover)
6892 {
6893   int tmp, i, j;
6894   int reg, nb;
6895   unsigned char *dest = NULL;
6896   int initbuf[2049];
6897   int voidbuf[2049];
6898   int val;
6899   int zero[5] = { 0, 0, 0, 0, -1 };
6900   int model;
6901 
6902   /* saves port state */
6903   gData = Inb (DATA);
6904   gControl = Inb (CONTROL);
6905 
6906   if (sanei_umax_pp_getastra () == 610)
6907     return probe610p (recover);
6908 
6909   /* save and set CONTROL */
6910   tmp = (Inb (CONTROL)) & 0x1F;
6911   tmp = (Inb (CONTROL)) & 0x1F;
6912   Outb (CONTROL, tmp);
6913   Outb (CONTROL, tmp);
6914 
6915   tmp = Inb (DATA);
6916   tmp = Inb (CONTROL) & 0x3F;
6917   Outb (CONTROL, tmp);
6918 
6919   tmp = Inb (CONTROL) & 0x3F;
6920   tmp = Inb (DATA);
6921   tmp = Inb (CONTROL) & 0x3F;
6922   tmp = Inb (DATA);
6923 
6924   /*  any scanner ? */
6925   /* fast detect */
6926   tmp = ringScanner (2, 0);
6927   if (!tmp)
6928     {
6929       DBG (1, "No scanner detected by 'ringScanner(2,0)'...\n");
6930       tmp = ringScanner (5, 0);
6931       if (!tmp)
6932 	{
6933 	  DBG (1, "No scanner detected by 'ringScanner(5,0)'...\n");
6934 	  tmp = ringScanner (5, 10000);
6935 	  if (!tmp)
6936 	    {
6937 	      DBG (1, "No scanner detected by 'ringScanner(5,10000)'...\n");
6938 	      tmp = ringScanner (5, 10000);
6939 	      if (!tmp)
6940 		{
6941 		  DBG (1,
6942 		       "No scanner detected by 'ringScanner(5,10000)'...\n");
6943 		}
6944 	    }
6945 	}
6946     }
6947   if (!tmp)
6948     {
6949       DBG (1, "No 1220P/2000P scanner detected by 'ringScanner()'...\n");
6950     }
6951   DBG (16, "ringScanner passed...\n");
6952 
6953   gControl = Inb (CONTROL) & 0x3F;
6954   g67D = 1;
6955   if (sendCommand (0x30) == 0)
6956     {
6957       DBG (0, "sendCommand(0x30) (%s:%d) failed ...\n", __FILE__, __LINE__);
6958       return 0;
6959     }
6960   DBG (16, "sendCommand(0x30) passed ... (%s:%d)\n", __FILE__, __LINE__);
6961   g67E = 4;			/* bytes to read */
6962   if (sendCommand (0x00) == 0)
6963     {
6964       DBG (0, "sendCommand(0x00) (%s:%d) failed ...\n", __FILE__, __LINE__);
6965       return 0;
6966     }
6967   DBG (16, "sendCommand(0x00) passed... (%s:%d)\n", __FILE__, __LINE__);
6968   g67E = 0;			/* bytes to read */
6969   if (testVersion (0) == 0)
6970     {
6971       DBG (16, "testVersion(0) (%s:%d) failed ...\n", __FILE__, __LINE__);
6972     }
6973   DBG (16, "testVersion(0) passed...\n");
6974   /* must fail for 1220P and 2000P */
6975   if (testVersion (1) == 0)	/* software doesn't do it for model 0x07 */
6976     {				/* but it works ..                       */
6977       DBG (16, "testVersion(1) failed (expected) ... (%s:%d)\n", __FILE__,
6978 	   __LINE__);
6979     }
6980   else
6981     {
6982       DBG (16, "Unexpected success on testVersion(1) ... (%s:%d)\n", __FILE__,
6983 	   __LINE__);
6984     }
6985   if (testVersion (0) == 0)
6986     {
6987       DBG (16, "testVersion(0) (%s:%d) failed ...\n", __FILE__, __LINE__);
6988     }
6989   DBG (16, "testVersion(0) passed...\n");
6990   /* must fail */
6991   if (testVersion (1) == 0)
6992     {
6993       DBG (16, "testVersion(1) failed (expected) ... (%s:%d)\n", __FILE__,
6994 	   __LINE__);
6995     }
6996   else
6997     {
6998       DBG (16, "Unexpected success on testVersion(1) ... (%s:%d)\n", __FILE__,
6999 	   __LINE__);
7000     }
7001 
7002   Outb (DATA, 0x04);
7003   Outb (CONTROL, 0x0C);
7004   Outb (DATA, 0x04);
7005   Outb (CONTROL, 0x0C);
7006 
7007   gControl = Inb (CONTROL) & 0x3F;
7008   Outb (CONTROL, gControl & 0xEF);
7009 
7010 
7011 
7012   if (sendCommand (0x40) == 0)
7013     {
7014       DBG (0, "sendCommand(0x40) (%s:%d) failed ...\n", __FILE__, __LINE__);
7015       return 0;
7016     }
7017   DBG (16, "sendCommand(0x40) passed...\n");
7018   if (sendCommand (0xE0) == 0)
7019     {
7020       DBG (0, "sendCommand(0xE0) (%s:%d) failed ...\n", __FILE__, __LINE__);
7021       return 0;
7022     }
7023   DBG (16, "sendCommand(0xE0) passed...\n");
7024 
7025   ClearRegister (0);
7026   DBG (16, "ClearRegister(0) passed...\n");
7027 
7028   SPPResetLPT ();
7029   DBG (16, "SPPResetLPT() passed...\n");
7030 
7031   Outb (CONTROL, 4);
7032   Outb (CONTROL, 4);
7033 
7034 
7035   /* test PS2 mode */
7036 
7037   tmp = PS2registerRead (0x0B);
7038   if (tmp == 0xC7)
7039     {
7040       /* epat C7 detected */
7041       DBG (16, "PS2registerRead(0x0B)=0x%X passed...\n", tmp);
7042 
7043       PS2registerWrite (8, 0);
7044       DBG (16, "PS2registerWrite(8,0) passed...   (%s:%d)\n", __FILE__,
7045 	   __LINE__);
7046 
7047       tmp = PS2registerRead (0x0A);
7048       if (tmp != 0x00)
7049 	{
7050 	  if (tmp == 0x1C)
7051 	    {
7052 	      DBG (16, "Previous probe detected ... (%s:%d)\n", __FILE__,
7053 		   __LINE__);
7054 	    }
7055 	  else
7056 	    {
7057 	      DBG (0, "Found 0x%X expected 0x00  (%s:%d)\n", tmp, __FILE__,
7058 		   __LINE__);
7059 	    }
7060 	}
7061       DBG (16, "PS2registerRead(0x0A)=0x%X passed ...(%s:%d)\n", tmp,
7062 	   __FILE__, __LINE__);
7063 
7064     }
7065   else
7066     {
7067       DBG (4, "Found 0x%X expected 0xC7 (%s:%d)\n", tmp, __FILE__, __LINE__);
7068       if ((tmp == 0xFF) && (sanei_umax_pp_getparport () < 1))
7069 	{
7070 	  DBG (0,
7071 	       "It is likely that the hardware address (0x%X) you specified is wrong\n",
7072 	       gPort);
7073 	  return 0;
7074 	}
7075       /* probe for a 610p, since we can't detect an EPAT */
7076       DBG (1, "Trying 610p (%s:%d)\n", __FILE__, __LINE__);
7077       return probe610p (recover);
7078     }
7079 
7080   /* clear register 3 */
7081   ClearRegister (3);
7082   DBG (16, "ClearRegister(3) passed...\n");
7083 
7084   /* wait ? */
7085   i = 65535;
7086   while (i > 0)
7087     {
7088       tmp = Inb (DATA);
7089       tmp = Inb (DATA);
7090       i--;
7091     }
7092   DBG (16, "FFFF in loop passed...\n");
7093 
7094   ClearRegister (0);
7095   DBG (16, "ClearRegister(0) passed... (%s:%d)\n", __FILE__, __LINE__);
7096   fflush (stdout);
7097 
7098   /* 1220/2000P branch */
7099   WRITESLOW (0x0E, 1);
7100 
7101   /* register 0x0F used only once: model number ? Or ASIC revision ? */
7102   /* comm mode ?                                                     */
7103   model = PS2registerRead (0x0F);
7104   DBG (1, "UMAX Astra 1220/1600/2000 P ASIC detected (mode=%d)\n", model);
7105   setModel (model);
7106   DBG (16, "PS2registerRead(0x0F) passed... (%s:%d)\n", __FILE__, __LINE__);
7107 
7108   /* scanner powered off */
7109   if (model == 0x1B)
7110     {
7111       DBG (0, "Register 0x0F=0x1B, scanner powered off ! (%s:%d)\n", __FILE__,
7112 	   __LINE__);
7113       return 0;
7114     }
7115 
7116 
7117   if ((model != 0x1F) && (model != 0x07))
7118     {
7119       DBG
7120 	(0,
7121 	 "Unexpected value for for register 0x0F, expected 0x07 or 0x1F, got 0x%02X ! (%s:%d)\n",
7122 	 model, __FILE__, __LINE__);
7123       DBG (0, "There is a new scanner revision in town, or a bug ....\n");
7124     }
7125 
7126   WRITESLOW (0x08, 0x02);
7127   WRITESLOW (0x0E, 0x0F);
7128   WRITESLOW (0x0F, 0x0C);
7129   WRITESLOW (0x0C, 0x04);
7130   tmp = PS2registerRead (0x0D);
7131   if ((tmp != 0x00) && (tmp != 0x40))
7132     {
7133       DBG
7134 	(0,
7135 	 "Unexpected value for for register 0x0D, expected 0x00 or 0x40, got 0x%02X ! (%s:%d)\n",
7136 	 tmp, __FILE__, __LINE__);
7137     }
7138   WRITESLOW (0x0D, 0x1B);
7139   switch (model)
7140     {
7141     case 0x1F:
7142       WRITESLOW (0x12, 0x14);
7143       SLOWNIBBLEREGISTERREAD (0x12, 0x10);
7144       break;
7145     case 0x07:
7146       WRITESLOW (0x12, 0x00);
7147       SLOWNIBBLEREGISTERREAD (0x12, 0x00);
7148       /* we may get 0x20, in this case some color aberration may occur */
7149       /* must depend on the parport */
7150       /* model 0x07 + 0x00=>0x20=2000P */
7151       break;
7152     default:
7153       WRITESLOW (0x12, 0x00);
7154       SLOWNIBBLEREGISTERREAD (0x12, 0x20);
7155       break;
7156     }
7157   SLOWNIBBLEREGISTERREAD (0x0D, 0x18);
7158   SLOWNIBBLEREGISTERREAD (0x0C, 0x04);
7159   SLOWNIBBLEREGISTERREAD (0x0A, 0x00);
7160   WRITESLOW (0x0E, 0x0A);
7161   WRITESLOW (0x0F, 0x00);
7162   WRITESLOW (0x0E, 0x0D);
7163   WRITESLOW (0x0F, 0x00);
7164   dest = (unsigned char *) malloc (65536);
7165   if (dest == NULL)
7166     {
7167       DBG (0, "Failed to allocate 64K (%s:%d)\n", __FILE__, __LINE__);
7168       return 0;
7169     }
7170 
7171   gMode = UMAX_PP_PARPORT_PS2;
7172   if (probePS2 (dest))
7173     {				/* PS2 mode works */
7174       DBG (16, "probePS2 passed ... (%s:%d)\n", __FILE__, __LINE__);
7175       gprobed = UMAX_PP_PARPORT_PS2;
7176     }
7177 
7178   Outb (CONTROL, 4);
7179   SLOWNIBBLEREGISTERREAD (0x0A, 0x18);
7180   WRITESLOW (0x08, 0x40);
7181   WRITESLOW (0x08, 0x60);
7182   WRITESLOW (0x08, 0x22);
7183 
7184   gMode = UMAX_PP_PARPORT_EPP;
7185   if (probeEPP (dest))
7186     {				/* EPP mode works */
7187       gprobed = UMAX_PP_PARPORT_EPP;
7188       gMode = UMAX_PP_PARPORT_EPP;
7189       DBG (16, "probeEPP passed ... (%s:%d)\n", __FILE__, __LINE__);
7190     }
7191   else
7192     {				/* EPP fails, try ECP */
7193       DBG (16, "probeEPP failed ... (%s:%d)\n", __FILE__, __LINE__);
7194       gMode = UMAX_PP_PARPORT_ECP;
7195       if (probeECP (dest))
7196 	{			/* ECP mode works */
7197 	  DBG (16, "probeECP passed ... (%s:%d)\n", __FILE__, __LINE__);
7198 	  gprobed = UMAX_PP_PARPORT_ECP;
7199 	}
7200       else
7201 	{			/* ECP and EPP fail, give up */
7202 	  /* PS2 could be used */
7203 	  DBG (16, "probeECP failed ... (%s:%d)\n", __FILE__, __LINE__);
7204 	  DBG (1, "No EPP or ECP mode working, giving up ... (%s:%d)\n",
7205 	       __FILE__, __LINE__);
7206 	  free (dest);
7207 	  return 0;
7208 	}
7209     }
7210 
7211   /* some operations here may have to go into probeEPP/probeECP */
7212   g6FE = 1;
7213   if (gMode == UMAX_PP_PARPORT_ECP)
7214     {
7215       WRITESLOW (0x08, 0x01);
7216       Outb (CONTROL, 0x0C);
7217       Outb (CONTROL, 0x04);
7218       ClearRegister (0);
7219       tmp = PS2Something (0x10);
7220       if (tmp != 0x0B)
7221 	{
7222 	  DBG (0,
7223 	       "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", tmp,
7224 	       __FILE__, __LINE__);
7225 	}
7226     }
7227   else
7228     {
7229       WRITESLOW (0x08, 0x21);
7230       init001 ();
7231       DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
7232     }
7233 
7234 
7235   reg = registerRead (0x0D);
7236   reg = (reg & 0xE8) | 0x43;
7237   registerWrite (0x0D, reg);
7238 
7239   REGISTERWRITE (0x0A, 0x18);
7240   REGISTERWRITE (0x0E, 0x0F);
7241   REGISTERWRITE (0x0F, 0x0C);
7242 
7243   REGISTERWRITE (0x0A, 0x1C);
7244   REGISTERWRITE (0x0E, 0x10);
7245   REGISTERWRITE (0x0F, 0x1C);
7246 
7247 
7248   reg = registerRead (0x0D);	/* 0x48 expected */
7249   reg = registerRead (0x0D);
7250   reg = registerRead (0x0D);
7251   reg = (reg & 0xB7) | 0x03;
7252   registerWrite (0x0D, reg);
7253   DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
7254 
7255   reg = registerRead (0x12);	/* 0x10 for model 0x0F, 0x20 for model 0x07 */
7256   /* 0x00 when in ECP mode ... */
7257   reg = reg & 0xEF;
7258   registerWrite (0x12, reg);
7259   DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
7260 
7261   reg = registerRead (0x0A);
7262   if (reg != 0x1C)
7263     {
7264       DBG (0, "Warning! expected reg0A=0x1C, found 0x%02X! (%s:%d) \n", reg,
7265 	   __FILE__, __LINE__);
7266     }
7267   DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
7268 
7269   /*Inb(CONTROL);       ECP 0x04 expected */
7270   disconnect ();
7271   DBG (16, "disconnect() passed... (%s:%d)\n", __FILE__, __LINE__);
7272   connect ();
7273   DBG (16, "connect() passed... (%s:%d)\n", __FILE__, __LINE__);
7274 
7275 
7276   /* some sort of countdown, some warming-up ? */
7277   /* maybe some data sent to the stepper motor */
7278   /* if (model == 0x07) */
7279   {
7280     /* REGISTERWRITE (0x0A, 0x00);
7281        reg = registerRead (0x0D);
7282        reg = (reg & 0xE8);
7283        registerWrite (0x0D, reg);
7284        DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__); */
7285     epilogue ();
7286     prologue (0x10);
7287 
7288     reg = registerRead (0x13);
7289     if (reg != 0x00)
7290       {
7291 	DBG (0, "Warning! expected reg13=0x00, found 0x%02X! (%s:%d) \n",
7292 	     reg, __FILE__, __LINE__);
7293       }
7294     REGISTERWRITE (0x13, 0x81);
7295     usleep (10000);
7296     REGISTERWRITE (0x13, 0x80);
7297     /* could it be step-motor values ? */
7298     REGISTERWRITE (0x0E, 0x04);	/* FF->R04 */
7299     REGISTERWRITE (0x0F, 0xFF);
7300     REGISTERWRITE (0x0E, 0x05);	/* 03->R05 */
7301     REGISTERWRITE (0x0F, 0x03);
7302     REGISTERWRITE (0x10, 0x66);
7303     usleep (10000);
7304 
7305     REGISTERWRITE (0x0E, 0x04);	/* FF->R04 */
7306     REGISTERWRITE (0x0F, 0xFF);
7307     REGISTERWRITE (0x0E, 0x05);	/* 01 ->R05 */
7308     REGISTERWRITE (0x0F, 0x01);
7309     REGISTERWRITE (0x10, 0x55);
7310     usleep (10000);
7311 
7312     REGISTERWRITE (0x0E, 0x04);	/* FF -> R04 */
7313     REGISTERWRITE (0x0F, 0xFF);
7314     REGISTERWRITE (0x0E, 0x05);	/* 00 -> R05 */
7315     REGISTERWRITE (0x0F, 0x00);
7316     REGISTERWRITE (0x10, 0x44);
7317     usleep (10000);
7318 
7319     REGISTERWRITE (0x0E, 0x04);	/* 7F -> R04 */
7320     REGISTERWRITE (0x0F, 0x7F);
7321     REGISTERWRITE (0x0E, 0x05);	/* 00 -> R05 */
7322     REGISTERWRITE (0x0F, 0x00);
7323     REGISTERWRITE (0x10, 0x33);
7324     usleep (10000);
7325 
7326     REGISTERWRITE (0x0E, 0x04);	/* 3F -> R04 */
7327     REGISTERWRITE (0x0F, 0x3F);
7328     REGISTERWRITE (0x0E, 0x05);
7329     REGISTERWRITE (0x0F, 0x00);	/* 00 -> R05 */
7330     REGISTERWRITE (0x10, 0x22);
7331     usleep (10000);
7332 
7333     REGISTERWRITE (0x0E, 0x04);
7334     REGISTERWRITE (0x0F, 0x00);
7335     REGISTERWRITE (0x0E, 0x05);
7336     REGISTERWRITE (0x0F, 0x00);
7337     REGISTERWRITE (0x10, 0x11);
7338     usleep (10000);
7339 
7340     REGISTERWRITE (0x13, 0x81);
7341     usleep (10000);
7342     REGISTERWRITE (0x13, 0x80);
7343 
7344     REGISTERWRITE (0x0E, 0x04);
7345     REGISTERWRITE (0x0F, 0x00);
7346     REGISTERWRITE (0x0E, 0x05);
7347     REGISTERWRITE (0x0F, 0x00);
7348     usleep (10000);
7349 
7350     reg = registerRead (0x10);
7351     DBG (1, "Count-down value is 0x%02X  (%s:%d)\n", reg, __FILE__, __LINE__);
7352     /* 2 reports of CF, was FF first (typo ?) */
7353     /* CF seems a valid value                 */
7354     /* in case of CF, we may have timeout ... */
7355     /*if (reg != 0x00)
7356        {
7357        DBG (0, "Warning! expected reg10=0x00, found 0x%02X! (%s:%d) \n",
7358        reg, __FILE__, __LINE__);
7359        } */
7360     REGISTERWRITE (0x13, 0x00);
7361   }
7362 /* end of countdown */
7363   DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
7364   /* *NOT* epilogue(); (when EPP) */
7365   /*REGISTERWRITE (0x0A, 0x00);
7366      REGISTERREAD (0x0D, 0x40);
7367      REGISTERWRITE (0x0D, 0x00); */
7368   epilogue ();
7369   prologue (0x10);
7370   REGISTERWRITE (0x0E, 0x0D);
7371   REGISTERWRITE (0x0F, 0x00);
7372   REGISTERWRITE (0x0A, 0x1C);
7373 
7374   /* real start of high level protocol ? */
7375   if (fonc001 () != 1)
7376     {
7377       DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__);
7378       return 0;
7379     }
7380   DBG (16, "fonc001() passed (%s:%d) \n", __FILE__, __LINE__);
7381   reg = registerRead (0x19) & 0xC8;
7382   /* if reg=E8 or D8 , we have a 'messed' scanner */
7383 
7384   /* 4 transform buffers + 'void' are sent: 1 B&W, and 3 RGB ? */
7385   memset (initbuf, 0x00, 2048 * sizeof (int));
7386   memset (voidbuf, 0x00, 2048 * sizeof (int));
7387 
7388   initbuf[512] = 0xFF;
7389   initbuf[513] = 0xAA;
7390   initbuf[514] = 0x55;
7391 
7392   for (j = 0; j < 4; j++)
7393     {
7394       for (i = 0; i < 256; i++)
7395 	{
7396 	  voidbuf[512 * j + 2 * i] = i;
7397 	  voidbuf[512 * j + 2 * i] = 0xFF - i;
7398 	}
7399     }
7400 
7401   /* one pass (B&W ?) */
7402   if (cmdSetDataBuffer (initbuf) != 1)
7403     {
7404       DBG (0, "cmdSetDataBuffer(initbuf) failed ! (%s:%d) \n", __FILE__,
7405 	   __LINE__);
7406       return 0;
7407     }
7408   DBG (16, "cmdSetDataBuffer(initbuf) passed... (%s:%d)\n", __FILE__,
7409        __LINE__);
7410   if (cmdSetDataBuffer (voidbuf) != 1)
7411     {
7412       DBG (0, "cmdSetDataBuffer(voidbuf) failed ! (%s:%d) \n", __FILE__,
7413 	   __LINE__);
7414       return 0;
7415     }
7416   DBG (16, "cmdSetDataBuffer(voidbuf) passed... (%s:%d)\n", __FILE__,
7417        __LINE__);
7418 
7419   /* everything above the FF 55 AA tag is 'void' */
7420   /* it seems that the buffer is reused and only the beginning is initialized */
7421   for (i = 515; i < 2048; i++)
7422     initbuf[i] = voidbuf[i];
7423 
7424   /* three pass (RGB ?) */
7425   for (i = 0; i < 3; i++)
7426     {
7427       if (cmdSetDataBuffer (initbuf) != 1)
7428 	{
7429 	  DBG (0, "cmdSetDataBuffer(initbuf) failed ! (%s:%d) \n", __FILE__,
7430 	       __LINE__);
7431 	  return 0;
7432 	}
7433       DBG (16, "Loop %d: cmdSetDataBuffer(initbuf) passed... (%s:%d)\n", i,
7434 	   __FILE__, __LINE__);
7435       if (cmdSetDataBuffer (voidbuf) != 1)
7436 	{
7437 	  DBG (0, "Loop %d: cmdSetDataBuffer(voidbuf) failed ! (%s:%d) \n", i,
7438 	       __FILE__, __LINE__);
7439 	  return 0;
7440 	}
7441     }
7442 
7443 
7444   /* memory size testing ? */
7445   /* load 150 Ko in scanner */
7446   REGISTERWRITE (0x1A, 0x00);
7447   REGISTERWRITE (0x1A, 0x0C);
7448   REGISTERWRITE (0x1A, 0x00);
7449   REGISTERWRITE (0x1A, 0x0C);
7450 
7451 
7452   REGISTERWRITE (0x0A, 0x11);	/* start */
7453   nb = 150;
7454   for (i = 0; i < nb; i++)	/* 300 for ECP ??? */
7455     {
7456       bufferWrite (0x400, dest);
7457       DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
7458 	   __FILE__, __LINE__);
7459     }
7460   REGISTERWRITE (0x0A, 0x18);	/* end */
7461 
7462   /* read them back */
7463   REGISTERWRITE (0x0A, 0x11);	/*start transfer */
7464   if (gMode == UMAX_PP_PARPORT_ECP)
7465     {
7466       ECPSetBuffer (0x400);
7467     }
7468 
7469   for (i = 0; i < nb; i++)	/* 300 for ECP ??? */
7470     {
7471       bufferRead (0x400, dest);
7472       DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n", i,
7473 	   __FILE__, __LINE__);
7474     }
7475   REGISTERWRITE (0x0A, 0x18);	/*end transfer */
7476 
7477   /* fully disconnect, then reconnect */
7478   if (gMode == UMAX_PP_PARPORT_ECP)
7479     {
7480       epilogue ();
7481       sendCommand (0xE0);
7482       Outb (DATA, 0xFF);
7483       Outb (DATA, 0xFF);
7484       ClearRegister (0);
7485       WRITESLOW (0x0E, 0x0A);
7486       SLOWNIBBLEREGISTERREAD (0x0F, 0x00);
7487       WRITESLOW (0x0F, 0x08);
7488       WRITESLOW (0x08, 0x10);	/* 0x10 ?? */
7489       prologue (0x10);
7490     }
7491 
7492 
7493   /* almost cmdSync(0x00) which halts any pending operation */
7494   if (fonc001 () != 1)
7495     {
7496       DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__);
7497       return 0;
7498     }
7499   DBG (16, "Fct001() passed (%s:%d) \n", __FILE__, __LINE__);
7500   if (sendWord (zero) == 0)
7501     {
7502       DBG (0, "sendWord(zero) failed (%s:%d)\n", __FILE__, __LINE__);
7503       return 0;
7504     }
7505   epilogue ();
7506   DBG (16, "sendWord(zero) passed (%s:%d)\n", __FILE__, __LINE__);
7507 
7508 
7509   /* end transport init */
7510   /* now high level (connected) protocol begins */
7511   val = sanei_umax_pp_initScanner (recover);
7512   if (val == 0)
7513     {
7514       DBG (0, "initScanner() failed (%s:%d)\n", __FILE__, __LINE__);
7515       return 0;
7516     }
7517 
7518 
7519   /* if no homing .... */
7520   if (val == 1)
7521     {
7522       CMDSYNC (0);
7523       CMDSYNC (0xC2);
7524       CMDSYNC (0);
7525     }
7526 
7527   /* set port to its initial state */
7528   Outb (DATA, gData);
7529   Outb (CONTROL, gControl);
7530 
7531   free (dest);
7532   DBG (1, "probe done ...\n");
7533   return 1;
7534 }
7535 
7536 
7537 static int
disconnect_epat(void)7538 disconnect_epat (void)
7539 {
7540   REGISTERWRITE (0x0A, 0x00);
7541   registerRead (0x0D);
7542   REGISTERWRITE (0x0D, 0x00);
7543   disconnect ();
7544   return 1;
7545 }
7546 
7547 
7548 static int
connect_epat(int r08)7549 connect_epat (int r08)
7550 {
7551   int reg;
7552 
7553   if (connect () != 1)
7554     {
7555       DBG (0, "connect_epat: connect() failed! (%s:%d)\n", __FILE__,
7556 	   __LINE__);
7557       return 0;
7558     }
7559 
7560   reg = registerRead (0x0B);
7561   if (reg != gEPAT)
7562     {
7563       /* ASIC version            is not */
7564       /* the one expected (epat c7)     */
7565       DBG (0, "Error! expected reg0B=0x%02X, found 0x%02X! (%s:%d) \n", gEPAT,
7566 	   reg, __FILE__, __LINE__);
7567       /* we try to clean all */
7568       disconnect ();
7569       return 0;
7570     }
7571   reg = registerRead (0x0D);
7572   reg = (reg | 0x43) & 0xEB;
7573   REGISTERWRITE (0x0D, reg);
7574   REGISTERWRITE (0x0C, 0x04);
7575   reg = registerRead (0x0A);
7576   if (reg != 0x00)
7577     {
7578       /* a previous unfinished command */
7579       /* has left an uncleared value   */
7580       DBG (0, "Warning! expected reg0A=0x00, found 0x%02X! (%s:%d) \n", reg,
7581 	   __FILE__, __LINE__);
7582     }
7583   REGISTERWRITE (0x0A, 0x1C);
7584   if (r08 != 0)
7585     {
7586       if (gMode == UMAX_PP_PARPORT_ECP)
7587 	{
7588 	  REGISTERWRITE (0x08, r08);	/* 0x01 or 0x10 ??? */
7589 	}
7590       else
7591 	{
7592 	  REGISTERWRITE (0x08, 0x21);
7593 	}
7594     }
7595   REGISTERWRITE (0x0E, 0x0F);
7596   REGISTERWRITE (0x0F, 0x0C);
7597   REGISTERWRITE (0x0A, 0x1C);
7598   REGISTERWRITE (0x0E, 0x10);
7599   REGISTERWRITE (0x0F, 0x1C);
7600   if (gMode == UMAX_PP_PARPORT_ECP)
7601     {
7602       REGISTERWRITE (0x0F, 0x00);
7603     }
7604   return 1;
7605 }
7606 
7607 
7608 static int
prologue(int r08)7609 prologue (int r08)
7610 {
7611   switch (sanei_umax_pp_getastra ())
7612     {
7613     case 610:
7614       connect610p ();
7615       return sync610p ();
7616     case 1220:
7617     case 1600:
7618     case 2000:
7619     default:
7620       return connect_epat (r08);
7621     }
7622 }
7623 
7624 
7625 
7626 static int
epilogue(void)7627 epilogue (void)
7628 {
7629   switch (sanei_umax_pp_getastra ())
7630     {
7631     case 610:
7632       return disconnect610p ();
7633     case 1220:
7634     case 1600:
7635     case 2000:
7636     default:
7637       return disconnect_epat ();
7638     }
7639 }
7640 
7641 
7642 static int
EPPcmdGet610p(int cmd, int len, int *val)7643 EPPcmdGet610p (int cmd, int len, int *val)
7644 {
7645   int word[4];
7646   int i, status, control;
7647 
7648   word[0] = len / 65536;
7649   word[1] = len / 256 % 256;
7650   word[2] = len % 256;
7651   word[3] = (cmd & 0x3F) | 0x80 | 0x40;	/* 0x40 means 'read' */
7652 
7653   connect610p ();
7654   sync610p ();
7655 
7656   /* sends magic seal 55 AA */
7657   status = EPPputByte610p (0x55);
7658   if (status != 0xC8)
7659     {
7660       DBG (1, "EPPcmdGet610p: Found 0x%X expected 0xC8  (%s:%d)\n", status,
7661 	   __FILE__, __LINE__);
7662       return 0;
7663     }
7664   status = EPPputByte610p (0xAA);
7665   if (status != 0xC8)
7666     {
7667       DBG (1, "EPPcmdGet610p: Found 0x%02X expected 0xC8  (%s:%d)\n", status,
7668 	   __FILE__, __LINE__);
7669       return 0;
7670     }
7671 
7672   /* tests status */
7673   /* scannerStatus=0x58 */
7674   status = EPPgetStatus610p ();
7675   if (status != 0xC8)
7676     {
7677       DBG (1,
7678 	   "EPPcmdGet610p: Found 0x%X expected 0xC8, status=0x%02X  (%s:%d)\n",
7679 	   status, scannerStatus, __FILE__, __LINE__);
7680       return 0;
7681     }
7682 
7683 
7684   /* sends length of data */
7685   for (i = 0; (i < 4) && (status == 0xC8); i++)
7686     {
7687       status = EPPputByte610p (word[i]);
7688     }
7689   if (status != 0xC8)
7690     {
7691       DBG (1, "EPPcmdGet610p: loop %d, found 0x%02X expected 0xC8  (%s:%d)\n",
7692 	   i, status, __FILE__, __LINE__);
7693       return 0;
7694     }
7695 
7696   Outb (DATA, 0xFF);
7697 
7698   /* tests status */
7699   /* scannerStatus=0x58 */
7700   status = EPPgetStatus610p ();
7701   if (status != 0xD0)
7702     {
7703       DBG (1,
7704 	   "EPPcmdGet610p: Found 0x%X expected 0xD0, status=0x%02X  (%s:%d)\n",
7705 	   status, scannerStatus, __FILE__, __LINE__);
7706       return 0;
7707     }
7708 
7709   /* data reverse */
7710   control = Inb (CONTROL) & 0xF4;
7711   control = control | 0xA0;
7712 
7713   /* receive data */
7714   i = 0;
7715   while (i < len)
7716     {
7717       status = Inb (STATUS) & 0xF8;
7718       if (status & 0x08)
7719 	{
7720 	  DBG (1,
7721 	       "EPPcmdGet610p: loop %d, found 0x%X expected 0xD0 or 0xC0  (%s:%d)\n",
7722 	       i, status, __FILE__, __LINE__);
7723 	  return 0;
7724 	}
7725       val[i] = Inb (EPPDATA);
7726       i++;
7727     }
7728 
7729   if (DBG_LEVEL >= 8)
7730     {
7731       char *str = NULL;
7732 
7733       str = malloc (3 * len + 1);
7734       if (str != NULL)
7735 	{
7736 	  for (i = 0; i < len; i++)
7737 	    {
7738 	      sprintf (str + 3 * i, "%02X ", val[i]);
7739 	    }
7740 	  str[3 * i] = 0x00;
7741 	  DBG (8, "String received for %02X: %s\n", cmd, str);
7742 	  free (str);
7743 	}
7744       else
7745 	{
7746 	  TRACE (8, "not enough memory for debugging ...");
7747 	}
7748     }
7749 
7750   /* scannerStatus=0x58 */
7751   status = EPPgetStatus610p ();
7752   scannerStatus = status;
7753   if (status != 0xC0)
7754     {
7755       DBG (0, "EPPcmdGet610p: Found 0x%02X expected 0xC0  (%s:%d)\n", status,
7756 	   __FILE__, __LINE__);
7757       return 0;
7758     }
7759   disconnect610p ();
7760   return 1;
7761 }
7762 
7763 
7764 
7765 static int
cmdGet610p(int cmd, int len, int *val)7766 cmdGet610p (int cmd, int len, int *val)
7767 {
7768   int word[5];
7769   int i, j, status;
7770 
7771   if ((cmd == 8) && (len > 0x23))
7772     len = 0x23;
7773 
7774   if (gMode == UMAX_PP_PARPORT_EPP)
7775     return EPPcmdGet610p (cmd, len, val);
7776 
7777   /* compute word */
7778   word[0] = len / 65536;
7779   word[1] = len / 256 % 256;
7780   word[2] = len % 256;
7781   word[3] = (cmd & 0x3F) | 0x80 | 0x40;	/* 0x40 means 'read' */
7782   word[4] = -1;
7783 
7784   connect610p ();
7785   sync610p ();
7786   if (sendLength610p (word) == 0)
7787     {
7788       DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__);
7789       return 0;
7790     }
7791   status = getStatus610p ();
7792   scannerStatus = status;
7793   if ((status != 0xC0) && (status != 0xD0))
7794     {
7795       DBG (0, "Found 0x%02X expected 0xC0 or 0xD0 (%s:%d)\n", status,
7796 	   __FILE__, __LINE__);
7797       return 0;
7798     }
7799   if (receiveData610p (val, len) == 0)
7800     {
7801       DBG (0, "sendData610p(val,%d) failed  (%s:%d)\n", len, __FILE__,
7802 	   __LINE__);
7803       return 0;
7804     }
7805   status = getStatus610p ();
7806   scannerStatus = status;
7807   j = 0;
7808   while ((j < 256) && (status & 0x08))
7809     {
7810       status = getStatus610p ();
7811       j++;
7812     }
7813   if (status != 0xC0)
7814     {
7815       DBG (0, "Found 0x%02X expected 0xC0  (%s:%d)\n", status, __FILE__,
7816 	   __LINE__);
7817       return 0;
7818     }
7819   disconnect610p ();
7820 
7821   if (DBG_LEVEL >= 8)
7822     {
7823       char *str = NULL;
7824 
7825       str = malloc (3 * len + 1);
7826       if (str != NULL)
7827 	{
7828 	  for (i = 0; i < len; i++)
7829 	    {
7830 	      sprintf (str + 3 * i, "%02X ", val[i]);
7831 	    }
7832 	  str[3 * i] = 0x00;
7833 	  DBG (8, "String received for %02X: %s\n", cmd, str);
7834 	  free (str);
7835 	}
7836       else
7837 	{
7838 	  TRACE (8, "not enough memory for debugging ...");
7839 	}
7840     }
7841   return 1;
7842 }
7843 
7844 
7845 static int
EPPcmdSet610p(int cmd, int len, int *val)7846 EPPcmdSet610p (int cmd, int len, int *val)
7847 {
7848   int word[5];
7849   int i, status;
7850 
7851   if ((cmd == 8) && (len > 0x23))
7852     {
7853       /* blank useless extra bytes */
7854       for (i = 0x22; i < len; i++)
7855 	val[i] = 0x00;
7856     }
7857 
7858   word[0] = len / 65536;
7859   word[1] = len / 256 % 256;
7860   word[2] = len % 256;
7861   word[3] = (cmd & 0x3F) | 0x80;
7862 
7863   connect610p ();
7864   sync610p ();
7865 
7866   /* sends magic seal 55 AA */
7867   status = EPPputByte610p (0x55);
7868   if ((status != 0xC8) && (status!=0xC0))
7869     {
7870       DBG (0, "EPPcmdSet610p: Found 0x%X expected 0xC0 or 0xC8  (%s:%d)\n", status,
7871 	   __FILE__, __LINE__);
7872       return 0;
7873     }
7874   status = EPPputByte610p (0xAA);
7875   if ((status != 0xC8) && (status!=0xC0))
7876     {
7877       DBG (0, "EPPcmdSet610p: Found 0x%X expected 0xC0 or 0xC8  (%s:%d)\n", status,
7878 	   __FILE__, __LINE__);
7879       return 0;
7880     }
7881 
7882   /* tests status */
7883   status = EPPgetStatus610p ();
7884   if ((status != 0xC8) && (status!=0xC0))
7885     {
7886       DBG (0, "EPPcmdSet610p: Found 0x%02X expected 0xC0 or 0xC8  (%s:%d)\n", status,
7887 	   __FILE__, __LINE__);
7888       return 0;
7889     }
7890 
7891   /* sends length of data */
7892   for (i = 0; i < 4; i++)
7893     {
7894       status = EPPputByte610p (word[i]);
7895     }
7896   if ((status != 0xC8) && (status!=0xC0))
7897     {
7898       DBG (0, "EPPcmdSet610p: loop %d, found 0x%02X expected 0xC0 or 0xC8  (%s:%d)\n",
7899 	   i, status, __FILE__, __LINE__);
7900       return 0;
7901     }
7902 
7903   Outb (DATA, 0xFF);
7904 
7905   /* tests status */
7906   status = EPPgetStatus610p ();
7907   if (status != 0xC0)
7908     {
7909       DBG (0, "Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__,
7910 	   __LINE__);
7911       return 0;
7912     }
7913 
7914   /* sends data */
7915   status = 0xC8;
7916   for (i = 0; (i < len) && (status == 0xC8); i++)
7917     {
7918       /* escape special values with ESC (0x1B) */
7919       if (val[i] == 0x1B)
7920 	status = EPPputByte610p (0x1B);
7921       if (i > 0)
7922 	{
7923 	  if ((val[i] == 0xAA) && (val[i - 1] == 0x55))
7924 	    status = EPPputByte610p (0x1B);
7925 	}
7926       /* now send data */
7927       status = EPPputByte610p (val[i]);
7928     }
7929 
7930   if (status != 0xC8)
7931     {
7932       DBG (0, "EPPcmdSet610p: loop %d, found 0x%02X expected 0xC8 (%s:%d)\n",
7933 	   i, status, __FILE__, __LINE__);
7934       return 0;
7935     }
7936 
7937   Outb (DATA, 0xFF);
7938   status = EPPgetStatus610p ();
7939   if (status != 0xC0)
7940     {
7941       DBG (0, "Found 0x%X expected 0xC0  (%s:%d)\n", status, __FILE__,
7942 	   __LINE__);
7943       return 0;
7944     }
7945 
7946   disconnect610p ();
7947   return 1;
7948 }
7949 
7950 
7951 static int
cmdSet610p(int cmd, int len, int *val)7952 cmdSet610p (int cmd, int len, int *val)
7953 {
7954   int word[5];
7955   int i, j, status;
7956 
7957   if (gMode == UMAX_PP_PARPORT_EPP)
7958     return EPPcmdSet610p (cmd, len, val);
7959 
7960   if ((cmd == 8) && (len > 0x23))
7961     {
7962       /* blank useless extra bytes */
7963       for (i = 0x22; i < len; i++)
7964 	val[i] = 0x00;
7965     }
7966 
7967   /* compute word */
7968   word[0] = len / 65536;
7969   word[1] = len / 256 % 256;
7970   word[2] = len % 256;
7971   word[3] = (cmd & 0x3F) | 0x80;
7972   word[4] = -1;
7973 
7974   connect610p ();
7975   sync610p ();
7976   if (sendLength610p (word) == 0)
7977     {
7978       DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__);
7979       return 0;
7980     }
7981   status = getStatus610p ();
7982   scannerStatus = status;
7983   if ((status != 0xC0) && (status != 0xD0))
7984     {
7985       DBG (1, "Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__,
7986 	   __LINE__);
7987       return 0;
7988     }
7989   if (sendData610p (val, len) == 0)
7990     {
7991       DBG (1, "sendData610p(val,%d) failed  (%s:%d)\n", len, __FILE__,
7992 	   __LINE__);
7993       return 0;
7994     }
7995   status = getStatus610p ();
7996   scannerStatus = status;
7997   j = 0;
7998   while ((j < 256) && (status & 0x08))
7999     {
8000       status = getStatus610p ();
8001       j++;
8002     }
8003   if (status != 0xC0)
8004     {
8005       DBG (1, "Found 0x%X expected 0xC0  (%s:%d)\n", status, __FILE__,
8006 	   __LINE__);
8007       /* return 0; */
8008     }
8009   disconnect610p ();
8010   return 1;
8011 }
8012 
8013 static int
cmdSet(int cmd, int len, int *val)8014 cmdSet (int cmd, int len, int *val)
8015 {
8016   int word[5];
8017   int i;
8018 
8019   if (DBG_LEVEL >= 8)
8020     {
8021       char *str = NULL;
8022 
8023       str = malloc (3 * len + 1);
8024       if (str != NULL)
8025 	{
8026 	  for (i = 0; i < len; i++)
8027 	    {
8028 	      sprintf (str + 3 * i, "%02X ", val[i]);
8029 	    }
8030 	  str[3 * i] = 0x00;
8031 	  DBG (8, "String sent     for %02X: %s\n", cmd, str);
8032 	  free (str);
8033 	}
8034       else
8035 	{
8036 	  TRACE (8, "not enough memory for debugging ...");
8037 	}
8038     }
8039 
8040   if (sanei_umax_pp_getastra () == 610)
8041     return cmdSet610p (cmd, len, val);
8042 
8043   /* cmd 08 as 2 length depending upon model */
8044   if ((cmd == 8) && (getModel () == 0x07))
8045     {
8046       len = 35;
8047     }
8048 
8049   /* compute word */
8050   word[0] = len / 65536;
8051   word[1] = len / 256 % 256;
8052   word[2] = len % 256;
8053   word[3] = (cmd & 0x3F) | 0x80;
8054 
8055   if (!prologue (0x10))
8056     {
8057       DBG (0, "cmdSet: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8058       return 0;
8059     }
8060 
8061   /* send data */
8062   if (sendLength (word, 4) == 0)
8063     {
8064       DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8065       return 0;
8066     }
8067   TRACE (16, "sendLength(word,4) passed ...");
8068 
8069   /* head end */
8070   epilogue ();
8071 
8072   if (len > 0)
8073     {
8074       /* send body */
8075       if (!prologue (0x10))
8076 	{
8077 	  DBG (0, "cmdSet: prologue failed !   (%s:%d)\n", __FILE__,
8078 	       __LINE__);
8079 	}
8080 
8081       /* send data */
8082       if (sendData (val, len) == 0)
8083 	{
8084 	  DBG (0, "sendData(word,%d) failed (%s:%d)\n", len, __FILE__,
8085 	       __LINE__);
8086 	  epilogue ();
8087 	  return 0;
8088 	}
8089       TRACE (16, "sendData(val,len) passed ...");
8090       /* body end */
8091       epilogue ();
8092     }
8093   return 1;
8094 }
8095 
8096 static int
cmdGet(int cmd, int len, int *val)8097 cmdGet (int cmd, int len, int *val)
8098 {
8099   int word[5];
8100   int i;
8101 
8102   if (sanei_umax_pp_getastra () == 610)
8103     return cmdGet610p (cmd, len, val);
8104 
8105   /* cmd 08 as 2 length depending upon model */
8106   if ((cmd == 8) && (getModel () == 0x07))
8107     {
8108       len = 35;
8109     }
8110 
8111   /* compute word */
8112   word[0] = len / 65536;
8113   word[1] = len / 256 % 256;
8114   word[2] = len % 256;
8115   word[3] = (cmd & 0x3F) | 0x80 | 0x40;	/* 0x40 means 'read' */
8116   word[4] = -1;
8117 
8118   /* send header */
8119   if (!prologue (0x10))
8120     {
8121       DBG (0, "cmdGet: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8122       return 0;
8123     }
8124 
8125   /* send data */
8126   if (sendLength (word, 4) == 0)
8127     {
8128       DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8129       return 0;
8130     }
8131   TRACE (16, "sendLength(word,4) passed ...");
8132 
8133   /* head end */
8134   epilogue ();
8135 
8136 
8137   /* send header */
8138   if (!prologue (0x10))
8139     {
8140       DBG (0, "cmdGet: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8141       return 0;
8142     }
8143 
8144   /* get actual data */
8145   if (receiveData (val, len) == 0)
8146     {
8147       DBG (0, "receiveData(val,len) failed (%s:%d)\n", __FILE__, __LINE__);
8148       epilogue ();
8149       return 0;
8150     }
8151   if (DBG_LEVEL >= 8)
8152     {
8153       char *str = NULL;
8154 
8155       str = malloc (3 * len + 1);
8156       if (str != NULL)
8157 	{
8158 	  for (i = 0; i < len; i++)
8159 	    {
8160 	      sprintf (str + 3 * i, "%02X ", val[i]);
8161 	    }
8162 	  str[3 * i] = 0x00;
8163 	  DBG (8, "String received for %02X: %s\n", cmd, str);
8164 	  free (str);
8165 	}
8166       else
8167 	{
8168 	  TRACE (8, "not enough memory for debugging ...");
8169 	}
8170     }
8171   epilogue ();
8172   return 1;
8173 }
8174 
8175 
8176 
8177 static int
cmdSetGet(int cmd, int len, int *val)8178 cmdSetGet (int cmd, int len, int *val)
8179 {
8180   int *tampon;
8181   int i;
8182 
8183   /* model revision 0x07 uses 35 bytes buffers */
8184   /* cmd 08 as 2 length depending upon model */
8185   if ((cmd == 8) && (getModel () == 0x07))
8186     {
8187       len = 0x23;
8188     }
8189 
8190   /* first we send */
8191   if (cmdSet (cmd, len, val) == 0)
8192     {
8193       DBG (0, "cmdSetGet failed !  (%s:%d)\n", __FILE__, __LINE__);
8194       return 0;
8195     }
8196 
8197   tampon = (int *) malloc (len * sizeof (int));
8198   memset (tampon, 0x00, len * sizeof (int));
8199   if (tampon == NULL)
8200     {
8201       DBG (0, "Failed to allocate room for %d int ! (%s:%d)\n", len, __FILE__,
8202 	   __LINE__);
8203       epilogue ();
8204       return 0;
8205     }
8206 
8207   /* then we receive */
8208   if (cmdGet (cmd, len, tampon) == 0)
8209     {
8210       DBG (0, "cmdSetGet failed !  (%s:%d)\n", __FILE__, __LINE__);
8211       free (tampon);
8212       epilogue ();
8213       return 0;
8214     }
8215 
8216   /* check and copy */
8217   for (i = 0; (i < len) && (val[i] >= 0); i++)
8218     {
8219       if (tampon[i] != val[i])
8220 	{
8221 	  DBG
8222 	    (0,
8223 	     "Warning data read back differs: expected %02X found tampon[%d]=%02X ! (%s:%d)\n",
8224 	     val[i], i, tampon[i], __FILE__, __LINE__);
8225 	}
8226       val[i] = tampon[i];
8227     }
8228 
8229 
8230   /* OK */
8231   free (tampon);
8232   return 1;
8233 }
8234 
8235 
8236 /* 1 OK, 0 failed */
8237 static int
EPPcmdGetBuffer610p(int cmd, int len, unsigned char *buffer)8238 EPPcmdGetBuffer610p (int cmd, int len, unsigned char *buffer)
8239 {
8240   int status, i, tmp, control;
8241   int word[5];
8242   int count, needed, max;
8243 #ifdef HAVE_LINUX_PPDEV_H
8244   int fd, mode, rc, wait;
8245 #endif
8246   int loop, remain;
8247 
8248   /* first we set length and channel */
8249   /* compute word */
8250   word[0] = len / 65536;
8251   word[1] = (len / 256) % 256;
8252   word[2] = len % 256;
8253   word[3] = (cmd & 0x0F) | 0xC0;
8254   word[4] = -1;
8255 
8256   connect610p ();		/* start of EPPsendLength610p */
8257   sync610p ();
8258 
8259   /* sends magic seal 55 AA */
8260   status = EPPputByte610p (0x55);
8261   if ((status != 0xD0) && (status != 0xC8))
8262     {
8263       DBG (0, "EPPcmdGetBuffer610p: Found 0x%X expected 0xC8 or 0xD0 (%s:%d)\n",
8264 	   status, __FILE__, __LINE__);
8265       return 0;
8266     }
8267   status = EPPputByte610p (0xAA);
8268   if ((status != 0xD0) && (status != 0xC8))
8269     {
8270       DBG (0, "EPPcmdGetBuffer610p: Found 0x%02X expected 0xC8 or 0xD0 (%s:%d)\n",
8271 	   status, __FILE__, __LINE__);
8272       return 0;
8273     }
8274 
8275   /* tests status */
8276   status = EPPgetStatus610p ();
8277   if ((status != 0xD0) && (status != 0xC8))
8278     {
8279       DBG (0, "EPPcmdGetBuffer610p: Found 0x%X expected 0xC8 or 0xD0 (%s:%d)\n",
8280 	   status, __FILE__, __LINE__);
8281       return 0;
8282     }
8283 
8284   /* sends length of data */
8285   for (i = 0; i < 4; i++)
8286     {
8287       status = EPPputByte610p (word[i]);
8288     }
8289   if ((status != 0xC0) && (status != 0xC8))
8290     {
8291       DBG (0,
8292 	   "EPPcmdGetBuffer610p: loop %d, found 0x%02X expected 0xC0 or 0xC8  (%s:%d)\n",
8293 	   i, status, __FILE__, __LINE__);
8294       return 0;
8295     }
8296 
8297   Outb (DATA, 0xFF);
8298 
8299   /* test status */
8300   status = EPPgetStatus610p ();
8301   if ((status != 0xC0) && (status != 0xD0))
8302     {
8303       DBG (0,
8304 	   "EPPcmdGetBuffer610p: Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n",
8305 	   status, __FILE__, __LINE__);
8306       /*return 0; */
8307     }
8308   disconnect610p ();		/* end of EPPsendLength610p */
8309 
8310   /* max data read in one go */
8311   if (sanei_umax_pp_getfull () == 1)
8312     max = 2550 / 3;
8313   else
8314     max = 32768;
8315 
8316   /* loop until enough data is read */
8317   count = 0;
8318   while (count < len)
8319     {
8320       if (len - count > max)
8321 	needed = max;
8322       else
8323 	needed = len - count;
8324       if (needed % 4)
8325 	remain = needed % 4;
8326       else
8327 	remain = 4;
8328       loop = (needed - remain) / 2;
8329       DBG (32, "EPPcmdGetBuffer610p: %d loops to do \n", loop);
8330 
8331       status = 0x20;
8332 
8333       /* wait for data ready */
8334       while ((status & 0x80) != 0x80)
8335 	{
8336 	  /* this is SPPgetStatus */
8337 	  connect610p ();
8338 	  Outb (CONTROL, 0x07);
8339 	  Outb (DATA, 0xFF);
8340 	  tmp = Inb (DATA);
8341 	  if (tmp != 0xFF)
8342 	    {
8343 	      DBG (0,
8344 		   "EPPcmdGetBuffer610p found 0x%02X expected 0xFF  (%s:%d)\n",
8345 		   tmp, __FILE__, __LINE__);
8346 	      return 0;
8347 	    }
8348 	  status = Inb (STATUS) & 0xF8;
8349 	  if ((status & 0x80) != 0x80)
8350 	    {
8351 	      disconnect610p ();
8352 	      usleep(1000);
8353 	    }
8354 	  else
8355 	    {
8356 	      Outb (CONTROL, 0x04);
8357 	      sync610p ();
8358 	      Outb (DATA, 0xFF);
8359 	      control = (Inb (CONTROL) & 0x44) | 0xE4;
8360 	      Outb (CONTROL, control);
8361 	    }
8362 	}
8363 
8364       /* EPP block read */
8365       /* there is one form for full CCD width reads, and another for other
8366          reads */
8367 #ifdef HAVE_LINUX_PPDEV_H
8368       wait = 0;
8369       /* check we have ppdev working */
8370       fd = sanei_umax_pp_getparport ();
8371       if (fd > 0)
8372 	{
8373 	  mode = 1;		/* data_reverse */
8374 	  rc = ioctl (fd, PPDATADIR, &mode);
8375 	  if (rc)
8376 	    DBG (0,
8377 		 "EPPcmdGetBuffer610p: ppdev ioctl returned <%s>  (%s:%d)\n",
8378 		 strerror (errno), __FILE__, __LINE__);
8379 
8380 #ifdef PPSETFLAGS
8381 	  mode = PP_FASTREAD;
8382 	  rc = ioctl (fd, PPSETFLAGS, &mode);
8383 	  if (rc)
8384 	    DBG (0,
8385 		 "EPPcmdGetBuffer610p: ppdev ioctl returned <%s>  (%s:%d)\n",
8386 		 strerror (errno), __FILE__, __LINE__);
8387 #endif
8388 	  mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
8389 	  rc = ioctl (fd, PPSETMODE, &mode);
8390 	  if (rc)
8391 	    {
8392 	      DBG (0,
8393 		   "EPPcmdGetBuffer610p: ppdev ioctl returned <%s>  (%s:%d)\n",
8394 		   strerror (errno), __FILE__, __LINE__);
8395 	      return 0;
8396 	    }
8397 	  if (sanei_umax_pp_getfull () == 1)
8398 	    {
8399 	      do
8400 		{
8401 		  rc = read (fd, buffer + count, needed);
8402 		}
8403 	      while (rc == EAGAIN);
8404 	      if (rc < 0)
8405 		{
8406 		  DBG (0,
8407 		       "EPPcmdGetBuffer610p: ppdev read failed <%s> (%s:%d)\n",
8408 		       strerror (errno), __FILE__, __LINE__);
8409 		  return 0;
8410 		}
8411 #ifdef IOLOG
8412 	      DBG (0, "insb *%d\n", rc);
8413 #endif
8414 	      needed = rc;
8415 	    }
8416 	  else
8417 	    {
8418 		  for (loop = 0; (loop < needed) && (wait==0); loop++)
8419 		    {
8420 		      status = Inb (STATUS) & 0xF8;
8421 		      if ((status != 0xD0) && (status != 0xC0)
8422 			  && (status != 0xC8))
8423 			{
8424 			  DBG (0,
8425 			       "EPPcmdGetBuffer610p found 0x%02X expected 0xD0 or 0xC0 (%s:%d)\n",
8426 			       status, __FILE__, __LINE__);
8427 			  return 0;
8428 			}
8429 		      if (status == 0xC8)
8430 		        {
8431 		          wait = 1;
8432 		          needed=loop;
8433 			}
8434 		      else
8435 		        {
8436 		          tmp = Inb (EPPDATA);
8437 		          buffer[count + loop] = tmp;
8438 			}
8439 		    }
8440 	    }
8441 	}
8442       else
8443 #endif /* HAVE_LINUX_PPDEV_H */
8444 	{
8445 	  Insb (EPPDATA, buffer + count, needed);
8446 	}
8447       count += needed;
8448       disconnect610p ();
8449     }
8450   usleep (10000);
8451   /* ??? CMDSYNC (0x00); */
8452   /* everything went fine */
8453   return 1;
8454 }
8455 
8456 /* 1 OK, 0 failed */
8457 static int
cmdGetBuffer610p(int cmd, int len, unsigned char *buffer)8458 cmdGetBuffer610p (int cmd, int len, unsigned char *buffer)
8459 {
8460   int status, i, tmp;
8461   int word[5];
8462   int read, needed, max;
8463 
8464   if (gMode == UMAX_PP_PARPORT_EPP)
8465     return EPPcmdGetBuffer610p (cmd, len, buffer);
8466 
8467   /* first we set length and channel */
8468   /* compute word */
8469   word[0] = len / 65536;
8470   word[1] = (len / 256) % 256;
8471   word[2] = len % 256;
8472   word[3] = (cmd & 0x0F) | 0xC0;
8473   word[4] = -1;
8474 
8475   connect610p ();
8476   sync610p ();
8477   if (sendLength610p (word) == 0)
8478     {
8479       DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__);
8480       return 0;
8481     }
8482   status = getStatus610p ();
8483   scannerStatus = status;
8484   if ((status != 0xC0) && (status != 0xD0))
8485     {
8486       DBG (1, "Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__,
8487 	   __LINE__);
8488       return 0;
8489     }
8490   disconnect610p ();
8491 
8492   if (sanei_umax_pp_getfull () == 1)
8493     max = 2550 / 3;
8494   else
8495     max = 32768;
8496   read = 0;
8497   while (read < len)
8498     {
8499       if (len - read > max)
8500 	needed = max;
8501       else
8502 	needed = len - read;
8503 
8504       if (sanei_umax_pp_getfull () == 0)
8505 	status = getStatus610p ();
8506       else
8507 	status = 0x20;
8508 
8509       /* wait for data ready */
8510       while ((status & 0x80) == 0x00)
8511 	{
8512 	  connect610p ();
8513 	  Outb (CONTROL, 0x07);
8514 	  Outb (DATA, 0xFF);
8515 	  tmp = Inb (DATA);
8516 	  if (tmp != 0xFF)
8517 	    {
8518 	      DBG (0,
8519 		   "cmdGetBuffer610p found 0x%02X expected 0xFF  (%s:%d)\n",
8520 		   tmp, __FILE__, __LINE__);
8521 	      return 0;
8522 	    }
8523 	  status = Inb (STATUS) & 0xF8;
8524 	  if ((status & 0x80) == 0x00)
8525 	    disconnect610p ();
8526 	  else
8527 	    {
8528 	      Outb (CONTROL, 0x04);
8529 	      sync610p ();
8530 	      byteMode ();
8531 	    }
8532 	}
8533 
8534       i = 0;
8535       while (i < needed)
8536 	{
8537 	  if (sanei_umax_pp_getfull () == 0)
8538 	    {
8539 	      status = Inb (STATUS) & 0xF8;
8540 	      if (status == 0xC8)
8541 		{
8542 		  for (tmp = 0; tmp < 18; tmp++)
8543 		    status = Inb (STATUS) & 0xF8;
8544 		  break;
8545 		}
8546 	    }
8547 	  Outb (CONTROL, 0x26);	/* data reverse+ 'reg' */
8548 	  buffer[read + i] = Inb (DATA);
8549 	  Outb (CONTROL, 0x24);	/* data reverse+ 'reg' */
8550 	  i++;
8551 	}
8552       byteMode ();
8553       disconnect610p ();
8554       read += i;
8555     }
8556 
8557   return 1;
8558 }
8559 
8560 
8561 /* 1 OK, 0 failed */
8562 static int
cmdGetBuffer(int cmd, int len, unsigned char *buffer)8563 cmdGetBuffer (int cmd, int len, unsigned char *buffer)
8564 {
8565   int reg, tmp;
8566   int word[5], read;
8567   int needed;
8568 
8569   if (sanei_umax_pp_getastra () == 610)
8570     return cmdGetBuffer610p (cmd, len, buffer);
8571 
8572   /* compute word */
8573   word[0] = len / 65536;
8574   word[1] = len / 256 % 256;
8575   word[2] = len % 256;
8576   word[3] = (cmd & 0x0F) | 0xC0;
8577   word[4] = -1;
8578 
8579   /* send word: len+addr(?) */
8580   if (foncSendWord (word) == 0)
8581     {
8582       DBG (0, "foncSendWord(word) failed (%s:%d)\n", __FILE__, __LINE__);
8583       return 0;
8584     }
8585   DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
8586 
8587   prologue (0x10);
8588 
8589   REGISTERWRITE (0x0E, 0x0D);
8590   REGISTERWRITE (0x0F, 0x00);
8591 
8592   reg = registerRead (0x19) & 0xF8;
8593 
8594   /* wait if busy */
8595   while ((reg & 0x08) == 0x08)
8596     reg = registerRead (0x19) & 0xF8;
8597   if ((reg != 0xC0) && (reg != 0xD0))
8598     {
8599       DBG (0, "cmdGetBuffer failed (%s:%d)\n", __FILE__, __LINE__);
8600       return 0;
8601     }
8602 
8603   if (gMode == UMAX_PP_PARPORT_ECP)
8604     {
8605       REGISTERWRITE (0x1A, 0x44);
8606     }
8607 
8608   read = 0;
8609   reg = registerRead (0x0C);
8610   if (reg != 0x04)
8611     {
8612       DBG (0, "cmdGetBuffer failed: unexpected status 0x%02X  ...(%s:%d)\n",
8613 	   reg, __FILE__, __LINE__);
8614       return 0;
8615     }
8616   REGISTERWRITE (0x0C, reg | 0x40);
8617 
8618   /* actual data */
8619   read = 0;
8620   while (read < len)
8621     {
8622       needed = len - read;
8623       if (needed > 32768)
8624 	needed = 32768;
8625       if (gMode == UMAX_PP_PARPORT_ECP)
8626 	{
8627 	  compatMode ();
8628 	  Outb (CONTROL, 0x04);	/* reset ? */
8629 	  ECPSetBuffer (needed);
8630 	  tmp = ECPbufferRead (needed, buffer + read);
8631 	  DBG (16, "ECPbufferRead(%d,buffer+read) passed (%s:%d)\n", needed,
8632 	       __FILE__, __LINE__);
8633 	  REGISTERWRITE (0x1A, 0x84);
8634 	}
8635       else
8636 	{
8637 	  tmp = pausedBufferRead (needed, buffer + read);
8638 	}
8639       if (tmp < needed)
8640 	{
8641 	  DBG (64, "cmdGetBuffer only got %d bytes out of %d ...(%s:%d)\n",
8642 	       tmp, needed, __FILE__, __LINE__);
8643 	}
8644       else
8645 	{
8646 	  DBG (64,
8647 	       "cmdGetBuffer got all %d bytes out of %d , read=%d...(%s:%d)\n",
8648 	       tmp, 32768, read, __FILE__, __LINE__);
8649 	}
8650       read += tmp;
8651       DBG (16, "Read %d bytes out of %d (last block is %d bytes) (%s:%d)\n",
8652 	   read, len, tmp, __FILE__, __LINE__);
8653       if (read < len)
8654 	{
8655 	  /* wait for scanner to be ready */
8656 	  reg = registerRead (0x19) & 0xF8;
8657 	  DBG (64, "Status after block read is 0x%02X (%s:%d)\n", reg,
8658 	       __FILE__, __LINE__);
8659 	  if ((reg & 0x08) == 0x08)
8660 	    {
8661 	      int pass = 0;
8662 
8663 	      do
8664 		{
8665 		  reg = registerRead (0x19) & 0xF8;
8666 		  usleep (100);
8667 		  pass++;
8668 		}
8669 	      while ((pass < 32768) && ((reg & 0x08) == 0x08));
8670 	      DBG (64, "Status after waiting is 0x%02X (pass=%d) (%s:%d)\n",
8671 		   reg, pass, __FILE__, __LINE__);
8672 	      if ((reg != 0xC0) && (reg != 0xD0))
8673 		{
8674 		  DBG (0,
8675 		       "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n",
8676 		       reg, __FILE__, __LINE__);
8677 		  DBG (0, "Going on...\n");
8678 		}
8679 	    }
8680 
8681 	  /* signal we want next data chunk */
8682 	  if (gMode == UMAX_PP_PARPORT_ECP)
8683 	    {
8684 	      REGISTERWRITE (0x1A, 0x44);
8685 	    }
8686 	  reg = registerRead (0x0C);
8687 	  registerWrite (0x0C, reg | 0x40);
8688 	}
8689     }
8690 
8691   /* OK ! */
8692   REGISTERWRITE (0x0E, 0x0D);
8693   REGISTERWRITE (0x0F, 0x00);
8694 
8695   /* epilogue */
8696   epilogue ();
8697   return 1;
8698 }
8699 
8700 /* 1 OK, 0 failed */
8701 static int
cmdGetBuffer32(int cmd, int len, unsigned char *buffer)8702 cmdGetBuffer32 (int cmd, int len, unsigned char *buffer)
8703 {
8704   int reg, tmp;
8705   int word[5], read;
8706 
8707   /* compute word */
8708   word[0] = len / 65536;
8709   word[1] = len / 256 % 256;
8710   word[2] = len % 256;
8711   word[3] = (cmd & 0x3F) | 0x80 | 0x40;
8712 
8713   if (!prologue (0x10))
8714     {
8715       DBG (0, "cmdSet: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8716       return 0;
8717     }
8718 
8719   /* send data */
8720   if (sendLength (word, 4) == 0)
8721     {
8722       DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8723       return 0;
8724     }
8725   TRACE (16, "sendLength(word,4) passed ...");
8726 
8727   /* head end */
8728   epilogue ();
8729 
8730   prologue (0x10);
8731   REGISTERWRITE (0x0E, 0x0D);
8732   REGISTERWRITE (0x0F, 0x00);
8733 
8734   reg = registerRead (0x19) & 0xF8;
8735 
8736   /* wait if busy */
8737   while ((reg & 0x08) == 0x08)
8738     reg = registerRead (0x19) & 0xF8;
8739   if ((reg != 0xC0) && (reg != 0xD0))
8740     {
8741       DBG (0, "cmdGetBuffer32 failed: unexpected status 0x%02X  ...(%s:%d)\n",
8742 	   reg, __FILE__, __LINE__);
8743       return 0;
8744     }
8745   reg = registerRead (0x0C);
8746   if (reg != 0x04)
8747     {
8748       DBG (0, "cmdGetBuffer32 failed: unexpected status 0x%02X  ...(%s:%d)\n",
8749 	   reg, __FILE__, __LINE__);
8750       return 0;
8751     }
8752   REGISTERWRITE (0x0C, reg | 0x40);
8753 
8754   read = 0;
8755   while (read < len)
8756     {
8757       if (read + 1700 < len)
8758 	{
8759 	  tmp = 1700;
8760 	  bufferRead (tmp, buffer + read);
8761 	  reg = registerRead (0x19) & 0xF8;
8762 	  if ((read + tmp < len) && (reg & 0x08) == 0x08)
8763 	    {
8764 	      do
8765 		{
8766 		  reg = registerRead (0x19) & 0xF8;
8767 		}
8768 	      while ((reg & 0x08) == 0x08);
8769 	      if ((reg != 0xC0) && (reg != 0xD0))
8770 		{
8771 		  DBG (0,
8772 		       "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n",
8773 		       reg, __FILE__, __LINE__);
8774 		  DBG (0, "Going on...\n");
8775 		}
8776 	    }
8777 	  reg = registerRead (0x0C);
8778 	  registerWrite (0x0C, reg | 0x40);
8779 	  read += tmp;
8780 	}
8781       else
8782 	{
8783 	  tmp = len - read;
8784 	  bufferRead (tmp, buffer + read);
8785 	  read += tmp;
8786 	  if ((read < len))
8787 	    {
8788 	      reg = registerRead (0x19) & 0xF8;
8789 	      while ((reg & 0x08) == 0x08)
8790 		{
8791 		  reg = registerRead (0x19) & 0xF8;
8792 		}
8793 	    }
8794 	}
8795     }
8796 
8797   /* OK ! */
8798   epilogue ();
8799   return 1;
8800 }
8801 
8802 int
sanei_umax_pp_cmdSync(int cmd)8803 sanei_umax_pp_cmdSync (int cmd)
8804 {
8805   int word[5];
8806 
8807 
8808   if (sanei_umax_pp_getastra () == 610)
8809     return cmdSync610p (cmd);
8810 
8811   /* compute word */
8812   word[0] = 0x00;
8813   word[1] = 0x00;
8814   word[2] = 0x00;
8815   word[3] = cmd;
8816 
8817   if (!prologue (0x10))
8818     {
8819       DBG (0, "cmdSync: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8820     }
8821 
8822   /* send data */
8823   if (sendLength (word, 4) == 0)
8824     {
8825       DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8826       return 0;
8827     }
8828   TRACE (16, "sendLength(word,4) passed ...");
8829 
8830   /* end OK */
8831   epilogue ();
8832 
8833   return 1;
8834 }
8835 
8836 
8837 /* numbers of bytes read, else 0 (failed)                             */
8838 /* read data by chunk EXACTLY the width of the scan area in the given */
8839 /* resolution . If a valid file descriptor is given, we write data    */
8840 /* in it according to the color mode, before polling the scanner      */
8841 /* len should not be bigger than 2 Megs                                      */
8842 
8843 int
cmdGetBlockBuffer(int cmd, int len, int window, unsigned char *buffer)8844 cmdGetBlockBuffer (int cmd, int len, int window, unsigned char *buffer)
8845 {
8846 #ifdef HAVE_SYS_TIME_H
8847   struct timeval td, tf;
8848   float elapsed;
8849 #endif
8850   int reg;
8851   int word[5], read;
8852 
8853   /* compute word */
8854   word[0] = len / 65536;
8855   word[1] = len / 256 % 256;
8856   word[2] = len % 256;
8857   word[3] = (cmd & 0x3F) | 0x80 | 0x40;
8858 
8859   if (!prologue (0x10))
8860     {
8861       DBG (0, "cmdGetBlockBuffer: prologue failed !   (%s:%d)\n", __FILE__,
8862 	   __LINE__);
8863     }
8864 
8865   /* send data */
8866   if (sendLength (word, 4) == 0)
8867     {
8868       DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8869       return 0;
8870     }
8871   TRACE (16, "sendLength(word,4) passed ...");
8872   /* head end */
8873   epilogue ();
8874 
8875 
8876 
8877   if (!prologue (0x10))
8878     {
8879       DBG (0, "cmdGetBlockBuffer: prologue failed !   (%s:%d)\n", __FILE__,
8880 	   __LINE__);
8881     }
8882 
8883 
8884   REGISTERWRITE (0x0E, 0x0D);
8885   REGISTERWRITE (0x0F, 0x00);
8886 
8887   /* init counter */
8888   read = 0;
8889 
8890   /* read scanner state */
8891   reg = registerRead (0x19) & 0xF8;
8892 
8893 
8894   /* read loop */
8895   while (read < len)
8896     {
8897       /* wait for the data to be ready */
8898 #ifdef HAVE_SYS_TIME_H
8899       gettimeofday (&td, NULL);
8900 #endif
8901       while ((reg & 0x08) == 0x08)
8902 	{
8903 	  reg = registerRead (0x19) & 0xF8;
8904 #ifdef HAVE_SYS_TIME_H
8905 	  gettimeofday (&tf, NULL);
8906 	  elapsed =
8907 	    ((tf.tv_sec * 1000000 + tf.tv_usec) -
8908 	     (td.tv_sec * 1000000 + td.tv_usec)) / 1000000;
8909 	  if (elapsed > 3)
8910 	    {
8911 	      DBG
8912 		(0,
8913 		 "Time-out (%.2f s) waiting for scanner ... giving up on status 0x%02X !   (%s:%d)\n",
8914 		 elapsed, reg, __FILE__, __LINE__);
8915 	      epilogue ();
8916 	      return read;
8917 	    }
8918 #endif
8919 	}
8920       if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0x00))
8921 	{
8922 	  DBG (0,
8923 	       "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n",
8924 	       reg, __FILE__, __LINE__);
8925 	  DBG (0, "Going on...\n");
8926 	}
8927 
8928       /* signals next chunk */
8929       reg = registerRead (0x0C);
8930       if (reg != 0x04)
8931 	{
8932 	  DBG (0,
8933 	       "cmdGetBlockBuffer failed: unexpected value reg0C=0x%02X  ...(%s:%d)\n",
8934 	       reg, __FILE__, __LINE__);
8935 	  return 0;
8936 	}
8937       REGISTERWRITE (0x0C, reg | 0x40);
8938 
8939 
8940       /* there is always a full block ready when scanner is ready */
8941       /* 32 bits I/O read , window must match the width of scan   */
8942       bufferRead (window, buffer + read);
8943 
8944       /* add bytes read */
8945       read += window;
8946 
8947 
8948       DBG (16, "Read %d bytes out of %d (last block is %d bytes) (%s:%d)\n",
8949 	   read, len, window, __FILE__, __LINE__);
8950 
8951       /* test status after read */
8952       reg = registerRead (0x19) & 0xF8;
8953     }
8954 
8955 
8956   /* wait for the data to be ready */
8957 #ifdef HAVE_SYS_TIME_H
8958   gettimeofday (&td, NULL);
8959 #endif
8960   while ((reg & 0x08) == 0x08)
8961     {
8962       reg = registerRead (0x19) & 0xF8;
8963 #ifdef HAVE_SYS_TIME_H
8964       gettimeofday (&tf, NULL);
8965       elapsed =
8966 	((tf.tv_sec * 1000000 + tf.tv_usec) -
8967 	 (td.tv_sec * 1000000 + td.tv_usec)) / 1000000;
8968       if (elapsed > 3)
8969 	{
8970 	  DBG
8971 	    (0,
8972 	     "Time-out (%.2f s) waiting for scanner ... giving up on status 0x%02X !   (%s:%d)\n",
8973 	     elapsed, reg, __FILE__, __LINE__);
8974 	  epilogue ();
8975 	  return read;
8976 	}
8977 #endif
8978     }
8979   if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0x00))
8980     {
8981       DBG (0, "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n",
8982 	   reg, __FILE__, __LINE__);
8983       DBG (0, "Going on...\n");
8984     }
8985 
8986   REGISTERWRITE (0x0E, 0x0D);
8987   REGISTERWRITE (0x0F, 0x00);
8988 
8989 
8990   /* OK ! */
8991   epilogue ();
8992   return read;
8993 }
8994 
8995 /*
8996  * encodes DC offsets: must be in [0..0x0F] range
8997  */
8998 static void
encodeDC(int dcRed, int dcGreen, int dcBlue, int *motor)8999 encodeDC (int dcRed, int dcGreen, int dcBlue, int *motor)
9000 {
9001   motor[11] = (motor[11] & 0x0F) | dcRed << 4;
9002   motor[12] = (motor[12] & 0xC3) | dcGreen << 2;
9003   motor[13] = (motor[13] & 0xF0) | dcBlue;
9004 }
9005 
9006 static void
decodeDC(int *motor)9007 decodeDC (int *motor)
9008 {
9009   DBG (0, "DC (R,G,B)=(%d,%d,%d)\n",
9010        (motor[11] & 0xF0) >> 4, (motor[12] & 0x3C) >> 2, motor[13] & 0x0F);
9011 }
9012 
9013 
9014 /*
9015  * encodes VGA : must be in [0..0x0F] range
9016  */
9017 static void
encodeVGA(int vgaRed, int vgaGreen, int vgaBlue, int *motor)9018 encodeVGA (int vgaRed, int vgaGreen, int vgaBlue, int *motor)
9019 {
9020   if (sanei_umax_pp_getastra () > 610)
9021     {
9022       motor[10] = (vgaRed << 4) | vgaGreen;
9023       motor[11] = (motor[11] & 0xF0) | vgaBlue;
9024     }
9025   else
9026     {
9027       motor[10] = (vgaGreen << 4) | vgaBlue;
9028       motor[11] = (motor[11] & 0xF0) | vgaRed;
9029       /* ancien
9030          F00: vert
9031          0F0: bleu
9032          00F: rouge
9033          motor[10] = (vgaRed << 4) | vgaGreen;
9034          motor[11] = (motor[11] & 0xF0) | vgaBlue; */
9035     }
9036 }
9037 
9038 static void
decodeVGA(int *motor)9039 decodeVGA (int *motor)
9040 {
9041   if (sanei_umax_pp_getastra () > 610)
9042     {
9043       DBG (0, "VGA (R,G,B)=(%d,%d,%d)\n",
9044 	   (motor[10] & 0xF0) >> 4, (motor[10] & 0x0F), (motor[11] & 0x0F));
9045     }
9046   else
9047     {
9048       DBG (0, "VGA (R,G,B)=(%d,%d,%d)\n",
9049 	   (motor[11] & 0x0F), (motor[10] & 0xF0) >> 4, (motor[10] & 0x0F));
9050     }
9051 }
9052 
9053 /*
9054  * this function encodes total head movement which includes
9055  * y movement and scan area height
9056  * height is scan area height
9057  * ypos   is head movement before scan
9058  * total move will be ypos+height */
9059 static void
encodeHY(int height, int ypos, int *motor)9060 encodeHY (int height, int ypos, int *motor)
9061 {
9062   motor[0] = height % 256;
9063   motor[1] = (height / 256) & 0x3F;
9064   motor[1] = motor[1] | (ypos & 0x03) << 6;
9065   motor[2] = (ypos >> 2) % 256;
9066   motor[3] = (motor[3] & 0xF0) | ((ypos >> 10) & 0x0F);
9067 }
9068 
9069 /*
9070  * this function encodes x start and x end on the CCD
9071  * w is width of scanning area
9072  * x is start of scanning area
9073  * dpi is x resolution
9074  * color is non zero if scanning in color
9075  * bytes is on aoverride for bpl, since it sin't clear today when
9076  * the formula has to be applied
9077  */
9078 static void
encodeWX(int width, int xstart, int dpi, int color, int *ccd, int bytes)9079 encodeWX (int width, int xstart, int dpi, int color, int *ccd, int bytes)
9080 {
9081   int xend;
9082   int bpl;
9083   int x;
9084 
9085   xend = xstart + width;
9086   x = xstart - 1;
9087 
9088   /* x start encoding */
9089   ccd[17] = x % 256;
9090   ccd[18] = (ccd[18] & 0xF0) | ((x / 256) & 0x0F);
9091   /* models >=1220P have a 600 dpi CCD: x is bigger */
9092   if (sanei_umax_pp_getastra () > 610)
9093     {
9094       if (x > 0x1000)
9095 	ccd[33] |= 0x40;
9096       else
9097 	ccd[33] &= 0xBF;
9098     }
9099 
9100   /* x end encoding */
9101   ccd[18] = (ccd[18] & 0x0F) | ((xend % 16) << 4);
9102   ccd[19] = (xend / 16) % 256;
9103   /* models >=1220P have a 600 dpi CCD: x is bigger */
9104   if (sanei_umax_pp_getastra () > 610)
9105     {
9106       if (xend > 0x1000)
9107 	ccd[33] |= 0x80;
9108       else
9109 	ccd[33] &= 0x7F;
9110     }
9111 
9112   /* now bytes per line */
9113   /* bpl = (op[24] - 0x41) * 256 + 8192 * (op[34] & 0x01) + op[23]; */
9114   bpl = (color == 0 ? 1 : 3) * width * dpi;
9115   if (sanei_umax_pp_getastra () > 610)
9116     {
9117       bpl /= 600;
9118       if (bpl >= 8192)
9119 	ccd[34] |= 0x01;
9120       else
9121 	ccd[34] &= 0xFE;
9122     }
9123   else
9124     {
9125       bpl /= 300;
9126     }
9127   if (bytes > 0)
9128     bpl = bytes;
9129   ccd[23] = bpl % 256;
9130   ccd[24] = 0x41 + ((bpl / 256) & 0x1F);
9131 }
9132 
9133   /* cropping coefficient: last 2 bytes gives the coefficient applied */
9134   /* to data scanned to get the actual image resolution               */
9135 static void
encodeCoefficient(int color, int dpi, int *calibration)9136 encodeCoefficient (int color, int dpi, int *calibration)
9137 {
9138   int w, idx = 0;
9139   int *coeff;
9140 
9141   /* 75, 150, 300, 600 and 1200 dpi */
9142   int color610p[4][2] =
9143     { {0x88, 0x88}, {0xAA, 0xAA}, {0xFF, 0xFF}, {0xFF, 0xFF} };
9144   int gray610p[4][2] =
9145     { {0x88, 0x01}, {0xAA, 0x11}, {0xFF, 0xAA}, {0xFF, 0xFF} };
9146 
9147   /* FF means coeff=1
9148    * AA       coeff=1/2
9149    * 88       coeff=1/4
9150    * 80       coeff=1/8
9151    * first coeff for CCD (x)
9152    * second coeff for motor steps (y)
9153    */
9154   int color1220p[5][2] =
9155     { {0x80, 0xAA}, {0x88, 0xFF}, {0xAA, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} };
9156   int gray1220p[5][2] =
9157     { {0x80, 0x88}, {0x88, 0xAA}, {0xAA, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} };
9158 
9159   switch (dpi)
9160     {
9161     case 1200:
9162       idx = 4;
9163       break;
9164     case 600:
9165       idx = 3;
9166       break;
9167     case 300:
9168       idx = 2;
9169       break;
9170     case 150:
9171       idx = 1;
9172       break;
9173     case 75:
9174       idx = 0;
9175       break;
9176     }
9177 
9178   if (sanei_umax_pp_getastra () < 1210)
9179     {
9180       w = 2550;
9181       if (color >= RGB_MODE)
9182 	coeff = color610p[idx];
9183       else
9184 	coeff = gray610p[idx];
9185     }
9186   else
9187     {
9188       w = 5100;
9189       if (color >= RGB_MODE)
9190 	coeff = color1220p[idx];
9191       else
9192 	coeff = gray1220p[idx];
9193     }
9194 
9195   /* x coefficient */
9196   calibration[3 * w + 768] = coeff[0];
9197 
9198   /* y coefficient */
9199   calibration[3 * w + 769] = coeff[1];
9200 }
9201 
9202 
9203 static void
bloc2Decode(int *op)9204 bloc2Decode (int *op)
9205 {
9206   int i;
9207   int scanh;
9208   int skiph;
9209   int dpi = 0;
9210   int dir = 0;
9211   int color = 0;
9212   char str[64];
9213 
9214   for (i = 0; i < 16; i++)
9215     sprintf (str + 3 * i, "%02X ", (unsigned char) op[i]);
9216   str[48] = 0x00;
9217   DBG (0, "Command block 2: %s\n", str);
9218 
9219 
9220   scanh = op[0] + (op[1] & 0x3F) * 256;
9221   skiph = ((op[1] & 0xC0) >> 6) + (op[2] << 2) + ((op[3] & 0x0F) << 10);
9222 
9223   if (op[3] & 0x10)
9224     dir = 1;
9225   else
9226     dir = 0;
9227 
9228   /* XXX STEF XXX seems to conflict with DC definitions */
9229   if (op[13] & 0x40)
9230     color = 1;
9231   else
9232     color = 0;
9233 
9234   /* op[6]=0x60 at 600 and 1200 dpi */
9235   if ((op[8] == 0x17) && (op[9] != 0x05))
9236     dpi = 150;
9237   if ((op[8] == 0x17) && (op[9] == 0x05))
9238     dpi = 300;
9239   if ((op[9] == 0x05) && (op[14] & 0x08))
9240     dpi = 1200;
9241   if ((dpi == 0) && ((op[14] & 0x08) == 0))
9242     dpi = 600;
9243 
9244 
9245 
9246   DBG (0, "\t->scan height   =0x%04X (%d)\n", scanh, scanh);
9247   DBG (0, "\t->skip height   =0x%04X (%d)\n", skiph, skiph);
9248   DBG (0, "\t->y dpi         =0x%04X (%d)\n", dpi, dpi);
9249   decodeVGA (op);
9250   decodeDC (op);
9251   if (dir)
9252     DBG (0, "\t->forward direction\n");
9253   else
9254     DBG (0, "\t->reverse direction\n");
9255   if (color)
9256     DBG (0, "\t->color scan       \n");
9257   else
9258     DBG (0, "\t->no color scan    \n");
9259 
9260   /* byte 14 */
9261   if (op[14] & 0x20)
9262     {
9263       DBG (0, "\t->lamp on    \n");
9264     }
9265   else
9266     {
9267       DBG (0, "\t->lamp off    \n");
9268     }
9269   if (op[14] & 0x04)
9270     {
9271       DBG (0, "\t->normal scan (head stops at each row)    \n");
9272     }
9273   else
9274     {
9275       DBG (0, "\t->move and scan (head doesn't stop at each row)    \n");
9276     }
9277   DBG (0, "\n");
9278 }
9279 
9280 
9281 static void
bloc8Decode(int *op)9282 bloc8Decode (int *op)
9283 {
9284   int i, bpl;
9285   int xskip;
9286   int xend, len;
9287   char str[128];
9288 
9289   if (sanei_umax_pp_getastra () < 1220)
9290     len = 34;
9291   else
9292     len = 36;
9293   for (i = 0; i < len; i++)
9294     sprintf (str + 3 * i, "%02X ", (unsigned char) op[i]);
9295   str[3 * i] = 0x00;
9296   DBG (0, "Command block 8: %s\n", str);
9297 
9298   xskip = op[17] + 256 * (op[18] & 0x0F);
9299   if (op[33] & 0x40)
9300     xskip += 0x1000;
9301   xend = (op[18] & 0xF0) / 16 + 16 * op[19];
9302   if (op[33] & 0x80)
9303     xend += 0x1000;
9304   if (len > 34)
9305     bpl = (op[24] - 0x41) * 256 + 8192 * (op[34] & 0x01) + op[23];
9306   else
9307     bpl = (op[24] - 0x41) * 256 + op[23];
9308 
9309   DBG (0, "\t->xskip     =0x%X (%d)\n", xskip, xskip);
9310   DBG (0, "\t->xend      =0x%X (%d)\n", xend, xend);
9311   DBG (0, "\t->scan width=0x%X (%d)\n", xend - xskip - 1, xend - xskip - 1);
9312   DBG (0, "\t->bytes/line=0x%X (%d)\n", bpl, bpl);
9313   DBG (0, "\t->raw       =0x%X (%d)\n", op[24] * 256 + op[23],
9314        op[24] * 256 + op[23]);
9315   DBG (0, "\n");
9316 }
9317 static int
completionWait(void)9318 completionWait (void)
9319 {
9320   /* for 610P, wait and sync is done while
9321    * reading data from the scanner */
9322   CMDSYNC (0x40);
9323   usleep (100000);
9324   CMDSYNC (0xC2);
9325   if ((sanei_umax_pp_getastra () == 610)
9326       || ((sanei_umax_pp_scannerStatus () & 0x90) == 0x90))
9327     return 1;
9328   do
9329     {
9330       usleep (100000);
9331       CMDSYNC (0xC2);
9332     }
9333   while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90);
9334   CMDSYNC (0xC2);
9335   return 1;
9336 }
9337 
9338 int
sanei_umax_pp_setLamp(int on)9339 sanei_umax_pp_setLamp (int on)
9340 {
9341   int buffer[17];
9342   int state;
9343 
9344   /* reset? */
9345   sanei_umax_pp_cmdSync (0x00);
9346   sanei_umax_pp_cmdSync (0xC2);
9347   sanei_umax_pp_cmdSync (0x00);
9348 
9349   /* get status */
9350   cmdGet (0x02, 16, buffer);
9351   state = buffer[14] & LAMP_STATE;
9352   buffer[16] = -1;
9353   if ((state == 0) && (on == 0))
9354     {
9355       DBG (0, "Lamp already off ... (%s:%d)\n", __FILE__, __LINE__);
9356       return 1;
9357     }
9358   if ((state) && (on))
9359     {
9360       DBG (2, "Lamp already on ... (%s:%d)\n", __FILE__, __LINE__);
9361       return 1;
9362     }
9363 
9364   /* set lamp state */
9365   if (on)
9366     buffer[14] = buffer[14] | LAMP_STATE;
9367   else
9368     buffer[14] = buffer[14] & ~LAMP_STATE;
9369   CMDSETGET (0x02, 16, buffer);
9370   TRACE (16, "setLamp passed ...");
9371   return 1;
9372 }
9373 
9374 static int num = 0;
9375 static void
Dump(int len, unsigned char *data, char *name)9376 Dump (int len, unsigned char *data, char *name)
9377 {
9378   FILE *fic;
9379   char titre[80];
9380 
9381   if (name == NULL)
9382     {
9383       sprintf (titre, "dump%04d.bin", num);
9384       num++;
9385     }
9386   else
9387     {
9388       sprintf (titre, "%s", name);
9389     }
9390   fic = fopen (titre, "wb");
9391   if (fic == NULL)
9392     {
9393       DBG (0, "could not open %s for writing\n", titre);
9394       return;
9395     }
9396   fwrite (data, 1, len, fic);
9397   fclose (fic);
9398 }
9399 
9400 
9401 static void
DumpNB(int width, int height, unsigned char *data, char *name)9402 DumpNB (int width, int height, unsigned char *data, char *name)
9403 {
9404   FILE *fic;
9405   char titre[80];
9406 
9407   if (name == NULL)
9408     {
9409       sprintf (titre, "dump%04d.pnm", num);
9410       num++;
9411     }
9412   else
9413     {
9414       sprintf (titre, "%s", name);
9415     }
9416   fic = fopen (titre, "wb");
9417   if (fic == NULL)
9418     {
9419       DBG (0, "could not open %s for writing\n", titre);
9420       return;
9421     }
9422   fprintf (fic, "P5\n%d %d\n255\n", width, height);
9423   fwrite (data, width, height, fic);
9424   fclose (fic);
9425 }
9426 
9427 
9428 /* dump data has received from scanner (red line/green line/blue line)
9429    to a color pnm file */
9430 static void
DumpRVB(int width, int height, unsigned char *data, char *name)9431 DumpRVB (int width, int height, unsigned char *data, char *name)
9432 {
9433   FILE *fic;
9434   char titre[80];
9435   int y, x;
9436 
9437   if (name == NULL)
9438     {
9439       sprintf (titre, "dump%04d.pnm", num);
9440       num++;
9441     }
9442   else
9443     {
9444       sprintf (titre, "%s", name);
9445     }
9446   fic = fopen (titre, "wb");
9447   if (fic == NULL)
9448     {
9449       DBG (0, "could not open %s for writing\n", titre);
9450       return;
9451     }
9452   fprintf (fic, "P6\n%d %d\n255\n", width, height);
9453   for (y = 0; y < height; y++)
9454     {
9455       for (x = 0; x < width; x++)
9456 	{
9457 	  fputc (data[3 * y * width + 2 * width + x], fic);
9458 	  fputc (data[3 * y * width + width + x], fic);
9459 	  fputc (data[3 * y * width + x], fic);
9460 	}
9461     }
9462   fclose (fic);
9463 }
9464 
9465 /* dump a color buffer in a color PNM */
9466 static void
DumpRGB(int width, int height, unsigned char *data, char *name)9467 DumpRGB (int width, int height, unsigned char *data, char *name)
9468 {
9469   FILE *fic;
9470   char titre[80];
9471   int y, x;
9472 
9473   if (name == NULL)
9474     {
9475       sprintf (titre, "dump%04d.pnm", num);
9476       num++;
9477     }
9478   else
9479     {
9480       sprintf (titre, "%s", name);
9481     }
9482   fic = fopen (titre, "wb");
9483   fprintf (fic, "P6\n%d %d\n255\n", width, height);
9484   if (fic == NULL)
9485     {
9486       DBG (0, "could not open %s for writing\n", titre);
9487       return;
9488     }
9489   for (y = 0; y < height; y++)
9490     {
9491       for (x = 0; x < width; x++)
9492 	{
9493 	  fputc (data[3 * y * width + x * 3], fic);
9494 	  fputc (data[3 * y * width + x * 3 + 1], fic);
9495 	  fputc (data[3 * y * width + x * 3 + 2], fic);
9496 	}
9497     }
9498   fclose (fic);
9499 }
9500 
9501 static int
evalGain(int sum, int count)9502 evalGain (int sum, int count)
9503 {
9504   int gn;
9505   float pct;
9506   float avg;
9507   float area=50;
9508   float coeff=2.5;
9509   float cnst=0.9;
9510 
9511 
9512   /* after ~ 60 * 10 scans , it looks like 1 step is a 0.57% increase   */
9513   /* so we take the value and compute the percent increase to reach 250 */
9514   /* (target code) not 255, because we want some room for inaccuracy    */
9515   /* pct=100-(value*100)/250                                            */
9516   /* then correction is pct/0.57                                        */
9517   avg = (float) (sum) / (float) (count);
9518   pct = 100.0 - (avg * 100.0) / targetCode;
9519   gn = (int) (pct / 0.57);
9520 
9521   /* give gain for dark areas a boost */
9522 #ifdef UMAX_PP_DANGEROUS_EXPERIMENT
9523   if(getenv("AREA")!=NULL)
9524         cnst=atol(getenv("AREA"));
9525   if(getenv("COEFF")!=NULL)
9526         cnst=atol(getenv("COEFF"));
9527   if(getenv("CNST")!=NULL)
9528         cnst=atol(getenv("CNST"));
9529 #endif
9530 
9531   pct = gn;
9532   avg = exp((-pct)/area)*coeff+cnst;
9533   gn = gn * avg;
9534 
9535   /* bound checking : there are sightings of >127 values being negative */
9536   if (gn < 0)
9537     gn = 0;
9538   else if (gn > 127)
9539     gn = 127;
9540   return gn;
9541 }
9542 
9543 static void
computeCalibrationData(int color, int width, unsigned char *source, int *data)9544 computeCalibrationData (int color, int width, unsigned char *source,
9545 			int *data)
9546 {
9547   int p, i, l;
9548   int sum;
9549 
9550 
9551   memset (data, 0, (3 * 5100 + 768 + 3) * sizeof (int));
9552 
9553 
9554   /* 0 -> 5099 */
9555   for (i = 0; i < width; i++)
9556     {				/* red calibration data */
9557       if (color >= RGB_MODE)
9558 	{
9559 	  /* compute average */
9560 	  sum = 0;
9561 	  for (l = 0; l < 66; l++)
9562 	    sum += source[i + l * 5100 * 3];
9563 	  data[i] = evalGain (sum, l);
9564 	}
9565       else
9566 	data[i] = 0x00;
9567     }
9568 
9569 
9570   /* 5100 -> 10199: green data */
9571   p = 5100;
9572   for (i = 0; i < width; i++)
9573     {
9574       /* compute average */
9575       sum = 0;
9576       for (l = 0; l < 66; l++)
9577 	sum += source[i + l * 5100 * 3 + 5100];
9578       data[p + i] = evalGain (sum, l);
9579     }
9580 
9581 
9582   /* 10200 -> 15299: blue */
9583   p = 10200;
9584   for (i = 0; i < width; i++)
9585     {
9586       if (color >= RGB_MODE)
9587 	{
9588 	  /* compute average */
9589 	  sum = 0;
9590 	  for (l = 0; l < 66; l++)
9591 	    sum += source[i + l * 5100 * 3 + 5100 * 2];
9592 	  data[p + i] = evalGain (sum, l);
9593 	}
9594       else
9595 	data[p + i] = 0x00;
9596     }
9597 
9598 
9599   /* gamma tables */
9600   for (i = 0; i < 256; i++)
9601     data[15300 + i] = ggRed[i];
9602   for (i = 0; i < 256; i++)
9603     data[15300 + 256 + i] = ggGreen[i];
9604   for (i = 0; i < 256; i++)
9605     data[15300 + 512 + i] = ggBlue[i];
9606   data[16070] = -1;
9607 }
9608 
9609 
9610 
9611 /* move head by the distance given using precision or not */
9612 /* 0: failed
9613    1: success                                          */
9614 static int
move(int distance, int precision, unsigned char *buffer)9615 move (int distance, int precision, unsigned char *buffer)
9616 {
9617   int header[17] = {
9618     0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x2F,
9619     0x2F, 0x01, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x00,
9620     -1
9621   };
9622   int body[37] = {
9623     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9624     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
9625     0x6E, 0xF6, 0x79, 0xBF, 0x01, 0x00, 0x00, 0x00,
9626     0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68,
9627     0xDF, 0x13, 0x1A, 0x00,
9628     -1
9629   };
9630   int end[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 };
9631   int steps, len, cmdlen;
9632   unsigned char tmp[0x200];
9633   unsigned char *ptr;
9634 
9635   if (distance == 0)
9636     return 0;
9637 
9638   if (buffer == NULL)
9639     ptr = tmp;
9640   else
9641     ptr = buffer;
9642 
9643   /* build commands */
9644   if (distance < 0)
9645     {
9646       /* header */
9647       steps = -distance - 1;
9648       header[3] = 0x20;
9649       header[9] = 0x01;
9650 
9651       /* reverse direction body by default */
9652 
9653       /* end */
9654       end[1] = 0xFF;
9655       end[2] = 0xFF;
9656       end[3] = -1;
9657       len = 3;
9658     }
9659   else
9660     {
9661       /* header */
9662       steps = distance - 1;
9663       header[3] = 0x70;
9664       header[9] = 0x05;
9665 
9666       /* body */
9667       body[2] = 0x04;
9668       body[4] = 0x02;
9669       body[7] = 0x0C;
9670       body[9] = 0x04;
9671       body[10] = 0x40;
9672       body[11] = 0x01;
9673       /* end */
9674       len = 8;
9675     }
9676   if (steps > 0)
9677     {
9678       encodeHY (1, steps, header);
9679     }
9680 
9681 
9682   if (sanei_umax_pp_getastra () < 1220)
9683     {
9684       header[6] = 0xC0;
9685 
9686       body[16] = 0x76;		/* encodeWX */
9687       body[17] = 0x00;
9688       body[18] = 0x15;
9689       body[19] = 0x70;
9690       body[20] = 0x01;
9691       body[21] = 0x00;
9692 
9693       body[28] = 0x4D;
9694       body[29] = 0x4B;
9695       body[30] = 0xD0;
9696 
9697       cmdlen = 0x22;
9698     }
9699   else
9700     cmdlen = 0x24;
9701 
9702   /* precision: default header set to precision on */
9703   if (precision == PRECISION_OFF)
9704     {
9705       if (sanei_umax_pp_getastra () == 1600)
9706 	header[8] = 0x15;
9707       else
9708 	header[8] = 0x17;
9709       if (sanei_umax_pp_getastra () > 610)
9710 	header[14] = 0xAC;
9711       body[20] = 0x06;
9712     }
9713   CMDSETGET (0x02, 16, header);
9714   CMDSETGET (0x08, cmdlen, body);
9715   if (DBG_LEVEL >= 128)
9716     {
9717       bloc2Decode (header);
9718       bloc8Decode (body);
9719     }
9720   CMDSYNC (0xC2);
9721   if ((sanei_umax_pp_scannerStatus () & 0x80)
9722       || (sanei_umax_pp_getastra () < 1220))
9723     {
9724       CMDSYNC (0x00);
9725     }
9726   CMDSETGET (4, len, end);
9727   COMPLETIONWAIT;
9728   CMDGETBUF (4, 0x200, ptr);
9729   if (DBG_LEVEL >= 128)
9730     {
9731       Dump (0x200, ptr, NULL);
9732     }
9733   DBG (16, "MOVE STATUS IS 0x%02X  (%s:%d)\n", sanei_umax_pp_scannerStatus (),
9734        __FILE__, __LINE__);
9735   CMDSYNC (0x00);
9736   return 1;
9737 }
9738 
9739 
9740 
9741 /* for each column, finds the row where white/black transition occurs
9742         then returns the average */
9743 static float
edgePosition(int width, int height, unsigned char *data)9744 edgePosition (int width, int height, unsigned char *data)
9745 {
9746   int ecnt, x, y;
9747   float epos;
9748   int d, dmax, dpos, i;
9749   unsigned char *dbuffer = NULL;
9750 
9751   if (DBG_LEVEL > 128)
9752     {
9753       dbuffer = (unsigned char *) malloc (3 * width * height);
9754       memset (dbuffer, 0x00, 3 * width * height);
9755     }
9756   epos = 0;
9757   ecnt = 0;
9758   for (x = 0; x < width; x++)
9759     {
9760       /* edge: white->black drop  */
9761       /* loop stops on black area */
9762       dmax = 0;
9763       dpos = 0;
9764       d = 0;
9765       i = 0;
9766       for (y = 10; (y < height) && (data[i] > 10); y++)
9767 	{
9768 	  i = x + y * width;
9769 	  d = data[i - width] - data[i];
9770 	  if (d > dmax)
9771 	    {
9772 	      dmax = d;
9773 	      dpos = y;
9774 	    }
9775 	  if ((DBG_LEVEL > 128) && (dbuffer != NULL))
9776 	    {
9777 	      dbuffer[i * 3] = data[i];
9778 	      dbuffer[i * 3 + 1] = data[i];
9779 	      dbuffer[i * 3 + 2] = data[i];
9780 	    }
9781 	}
9782       epos += dpos;
9783       ecnt++;
9784       if ((DBG_LEVEL > 128) && (dbuffer != NULL))
9785 	{
9786 	  dbuffer[(x + dpos * width) * 3] = 0xFF;
9787 	  dbuffer[(x + dpos * width) * 3 + 1] = 0x00;
9788 	  dbuffer[(x + dpos * width) * 3 + 2] = 0x00;
9789 	}
9790     }
9791   if (ecnt == 0)
9792     epos = 70;
9793   else
9794     epos = epos / ecnt;
9795   if ((DBG_LEVEL > 128) && (dbuffer != NULL))
9796     {
9797       i = ((int) epos) * width;
9798       for (x = 0; x < width; x++)
9799 	{
9800 	  dbuffer[(x + i) * 3] = 0x00;
9801 	  dbuffer[(x + i) * 3 + 1] = 0xFF;
9802 	  dbuffer[(x + i) * 3 + 2] = 0xFF;
9803 	}
9804       for (y = 0; y < height; y++)
9805 	{
9806 	  dbuffer[(width / 2 + y * width) * 3] = 0x00;
9807 	  dbuffer[(width / 2 + y * width) * 3 + 1] = 0xFF;
9808 	  dbuffer[(width / 2 + y * width) * 3 + 2] = 0x00;
9809 	}
9810       DumpRGB (width, height, dbuffer, NULL);
9811       free (dbuffer);
9812     }
9813   return epos;
9814 }
9815 
9816 
9817 
9818 static int
moveToOrigin(void)9819 moveToOrigin (void)
9820 {
9821   unsigned char buffer[54000];
9822   float edge;
9823   int val, delta = 188;
9824   int header[17] = {
9825     0xB4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F,
9826     0x2F, 0x05, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x00, -1
9827   };
9828 
9829   int body[37] = {
9830     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
9831     0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00,
9832     0x6E, 0xFB, 0xC4, 0xE5, 0x06, 0x00, 0x00, 0x60,
9833     0x4D, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68,
9834     0xDF, 0x13, 0x1A, 0x00, -1
9835   };
9836 
9837   int end[9] = {
9838     0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x08, 0x00,
9839     -1
9840   };
9841   int opsc03[9] = {
9842     0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0x80, 0xFF,
9843     -1
9844   };
9845   int w = 300, h = 180, len = 36;
9846 
9847   switch (sanei_umax_pp_getastra ())
9848     {
9849     case 1600:
9850       header[8] = 0x2B;
9851 
9852       body[29] = 0x1A;
9853       body[30] = 0xEE;
9854 
9855       end[0] = 0x19;
9856       end[1] = 0xD5;
9857       end[4] = 0x1B;
9858       // fall through
9859     case 1220:
9860     case 2000:
9861       w = 300;
9862       h = 180;
9863       len = 36;
9864       delta = -188;
9865       CMDSYNC (0x00);
9866       CMDSYNC (0xC2);
9867       CMDSYNC (0x00);
9868       MOVE (196, PRECISION_OFF, NULL);
9869       break;
9870 
9871     case 610:
9872 
9873       w = 512;
9874       h = 90;
9875       len = 34;
9876       delta = -81;
9877 
9878       opsc03[6] = 0xFF;		/* instead of 0x80 */
9879 
9880       encodeHY (h, 60, header);
9881 
9882       /* will add encodeDpi(dpi,cmd) */
9883       header[6] = 0xC0;
9884       header[8] = 0x17;
9885 
9886       body[13] = 0x20;
9887       body[14] = 0x02;
9888 
9889       body[16] = 0x76;
9890 
9891       encodeWX (0x200, 0x501, 300, 0, body, 0x500);
9892 
9893       /* fixed values for all 610p commands */
9894       body[28] = 0x4D;
9895       body[29] = 0x4B;
9896       body[30] = 0xD0;
9897 
9898       /* LM9811 command block ? */
9899       end[0] = 0x88;
9900       end[1] = 0xE6;
9901       end[2] = 0xFD;
9902       end[3] = 0x8E;
9903       end[4] = 0x30;
9904 
9905       break;
9906     }
9907 
9908 
9909   /* scan an area where is a white and a black regions, which  */
9910   /* can be detected and gives this offset to the origin of the */
9911   /* scanning windows                                          */
9912   CMDSETGET (2, 0x10, header);
9913   CMDSETGET (8, len, body);
9914   CMDSETGET (1, 0x08, end);
9915 
9916   CMDSYNC (0xC2);
9917   CMDSYNC (0x00);
9918   /* signals black & white ? */
9919   CMDSETGET (4, 8, opsc03);
9920   COMPLETIONWAIT;
9921   CMDGETBUF (4, w * h, buffer);	/* get find position data */
9922   if (DBG_LEVEL > 128)
9923     {
9924       DumpNB (w, h, buffer, NULL);
9925     }
9926 
9927   /* detection of 1600P is a by product of origin finding */
9928   edge = 0.0;
9929   for (val = 0; val < w * h; val++)
9930     if (buffer[val] > edge)
9931       edge = buffer[val];
9932   DBG (32, "MAX VALUE=%f        (%s:%d)\n", edge, __FILE__, __LINE__);
9933   if ((edge <= 30) && (sanei_umax_pp_getastra () != 1600))
9934     {
9935       DBG (2, "moveToOrigin() detected a 1600P");
9936       sanei_umax_pp_setastra (1600);
9937     }
9938   edge = edgePosition (w, h, buffer);
9939   /* rounded to lowest integer, since upping origin might lead */
9940   /* to bump in the other side if doing a full size preview    */
9941   val = (int) (edge);
9942 
9943   delta += val;
9944   DBG (64, "Edge=%f, val=%d, delta=%d\n", edge, val, delta);
9945 
9946   /* move back to y-coordinate origin */
9947   if (sanei_umax_pp_getastra () < 1220)
9948     {
9949       MOVE (delta, PRECISION_OFF, NULL);
9950     }
9951   else
9952     {
9953       MOVE (delta, PRECISION_ON, NULL);
9954     }
9955 
9956   /* head successfully set to the origin */
9957   return 1;
9958 }
9959 
9960 
9961 /* park head: returns 1 on success, 0 otherwise  */
9962 int
sanei_umax_pp_park(void)9963 sanei_umax_pp_park (void)
9964 {
9965   int header610[17] = {
9966     0x01, 0x00, 0x01, 0x40, 0x30, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00,
9967     0x00, 0x80, 0xF4, 0x00, -1
9968   };
9969   int body610[35] = {
9970     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80,
9971     0x00, 0x20, 0x02, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00,
9972     0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x1B, -1
9973   };
9974 
9975   int header[17] =
9976     { 0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x13, 0x05, 0x00, 0x00,
9977     0x00, 0x80, 0xF0, 0x00, -1
9978   };
9979   int body[37] =
9980     { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80,
9981     0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00,
9982     0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x1B, 0x1A, 0x00,
9983     -1
9984   };
9985 
9986   int status = 0x90;
9987 
9988   CMDSYNC (0x00);
9989 
9990   if (sanei_umax_pp_getastra () > 610)
9991     {
9992       CMDSETGET (0x02, 0x10, header);
9993       CMDSETGET (0x08, 0x24, body);
9994     }
9995   else
9996     {
9997       CMDSETGET (0x02, 0x10, header610);
9998       CMDSETGET (0x08, 0x22, body610);
9999     }
10000   CMDSYNC (0x40);
10001 
10002 
10003   status = sanei_umax_pp_scannerStatus ();
10004   DBG (16, "PARKING STATUS is 0x%02X (%s:%d)\n", status, __FILE__, __LINE__);
10005   DBG (1, "Park command issued ...\n");
10006   return 1;
10007 }
10008 
10009 
10010 /* calibrates CCD: returns 1 on success, 0 on failure */
10011 static int
shadingCalibration1220p(int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration)10012 shadingCalibration1220p (int color,
10013 			 int dcRed, int dcGreen, int dcBlue,
10014 			 int vgaRed, int vgaGreen, int vgaBlue,
10015 			 int *calibration)
10016 {
10017   int opsc32[17] =
10018     { 0x4A, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x17, 0x05, 0xA5, 0x08,
10019     0x00, 0x00, 0xAC, 0x00, -1
10020   };
10021   int opsc41[37] =
10022     { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
10023     0x00, 0x00, 0x04, 0x00, 0x6E, 0x90, 0xD0, 0x47, 0x06, 0x00, 0x00, 0xC4,
10024     0x5C, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1B, 0x00,
10025     -1
10026   };
10027   int opscnb[37] =
10028     { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
10029     0x00, 0x00, 0x04, 0x00, 0x6E, 0x90, 0xD0, 0x47, 0x06, 0x00, 0x00, 0xEC,
10030     0x54, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1A, 0x00,
10031     -1
10032   };
10033   int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 };
10034   int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 };
10035   int size;
10036   int width = 5100;		/* full usable CCD width */
10037   unsigned char buffer[0x105798];
10038 
10039   /* 1600P have a different CCD command block */
10040   if (sanei_umax_pp_getastra () == 1600)
10041     {
10042       opsc04[0] = 0x19;
10043       opsc04[1] = 0xD5;
10044       opsc04[4] = 0x1B;
10045 
10046       opsc41[29] = 0x1A;
10047       opsc41[30] = 0xEE;
10048     }
10049 
10050   /* step back by 67 ticks:                     */
10051   /* since we're going to scan 66 lines of data */
10052   /* which are going to be used as calibration  */
10053   /* data                                       */
10054   /* we are on the white area just before       */
10055   /* the user scan area                         */
10056   MOVE (-67, PRECISION_ON, NULL);
10057 
10058 
10059   CMDSYNC (0x00);
10060 
10061   /* get calibration data */
10062   /*
10063      if (sanei_umax_pp_getauto ())
10064      {                           auto settings doesn't use offset
10065      offset = 0x000;
10066      }
10067      else
10068      {                           manual settings
10069      gain = 0x777;
10070      offset = 0x000;
10071      }
10072    */
10073   encodeDC (dcRed, dcGreen, dcBlue, opsc32);
10074   encodeVGA (vgaRed, vgaGreen, vgaBlue, opsc32);
10075   if (sanei_umax_pp_getastra () == 1600)
10076     {
10077       opsc32[13] = 0x03;
10078     }
10079 
10080   /* 1220P/2000P shading calibration */
10081   if (color < RGB_MODE)
10082     {
10083       opsc32[0] -= 4;
10084       opsc32[13] = 0xC0;
10085     }
10086   CMDSETGET (2, 0x10, opsc32);
10087   if (DBG_LEVEL >= 64)
10088     {
10089       bloc2Decode (opsc32);
10090     }
10091   if (color < RGB_MODE)
10092     {
10093       CMDSETGET (8, 0x24, opscnb);
10094       if (DBG_LEVEL >= 64)
10095 	{
10096 	  bloc8Decode (opscnb);
10097 	}
10098       opsc04[6] = 0x85;
10099     }
10100   else
10101     {
10102       CMDSETGET (8, 0x24, opsc41);
10103       if (DBG_LEVEL >= 64)
10104 	{
10105 	  bloc8Decode (opsc41);
10106 	}
10107       opsc04[6] = 0x0F;
10108       if (sanei_umax_pp_getastra () == 1600)
10109 	opsc04[7] = 0xC0;
10110       else
10111 	opsc04[7] = 0x70;
10112     }
10113 
10114   /* BUG BW noisy here */
10115   CMDSETGET (1, 0x08, opsc04);
10116   CMDSYNC (0xC2);
10117   CMDSYNC (0x00);
10118   CMDSETGET (4, 0x08, commit);	/* opsc03 hangs it */
10119   COMPLETIONWAIT;
10120 
10121   opsc04[0] = 0x06;
10122   if (color >= RGB_MODE)
10123     size = 3 * width * 70;
10124   else
10125     size = width * 66;
10126   if (getEPPMode () == 32)
10127     {
10128       cmdGetBuffer32 (4, size, buffer);
10129     }
10130   else
10131     {
10132       CMDGETBUF (4, size, buffer);
10133     }
10134   if (DBG_LEVEL >= 128)
10135     {
10136       Dump (size, buffer, NULL);
10137       if (color >= RGB_MODE)
10138 	{
10139 	  DumpRVB (width, 66, buffer, NULL);
10140 	}
10141       else
10142 	{
10143 	  DumpNB (width, 66, buffer, NULL);
10144 	}
10145     }
10146   computeCalibrationData (color, width, buffer, calibration);
10147 
10148   DBG (1, "shadingCalibration1220p() done ...\n");
10149   return 1;
10150 }
10151 
10152 
10153 /* returns number of bytes read or 0 on failure */
10154 int
sanei_umax_pp_readBlock(long len, int window, int dpi, int last, unsigned char *buffer)10155 sanei_umax_pp_readBlock (long len, int window, int dpi, int last,
10156 			 unsigned char *buffer)
10157 {
10158   DBG (8, "readBlock(%ld,%d,%d,%d)\n", len, window, dpi, last);
10159   /* EPP block reading is available only when dpi >=600 */
10160   if ((dpi >= 600)
10161       && (gMode != UMAX_PP_PARPORT_ECP) && (sanei_umax_pp_getastra () > 610))
10162     {
10163       DBG (8, "cmdGetBlockBuffer(4,%ld,%d);\n", len, window);
10164       len = cmdGetBlockBuffer (4, len, window, buffer);
10165       if (len == 0)
10166 	{
10167 	  DBG (0, "cmdGetBlockBuffer(4,%ld,%d) failed (%s:%d)\n", len, window,
10168 	       __FILE__, __LINE__);
10169 	  gCancel = 1;
10170 	}
10171     }
10172   else
10173     {
10174       if ((sanei_umax_pp_getastra () < 1210) && (len > 0xFDCE))
10175 	{
10176 	  len = 0xFDCE;
10177 	  last = 0;
10178 	}
10179       DBG (8, "cmdGetBuffer(4,%ld);\n", len);
10180       if (cmdGetBuffer (4, len, buffer) != 1)
10181 	{
10182 	  DBG (0, "cmdGetBuffer(4,%ld) failed (%s:%d)\n", len, __FILE__,
10183 	       __LINE__);
10184 	  gCancel = 1;
10185 	}
10186     }
10187   if (!last)
10188     {
10189       /* sync with scanner */
10190       if (sanei_umax_pp_cmdSync (0xC2) == 0)
10191 	{
10192 	  DBG (0, "Warning cmdSync(0xC2) failed! (%s:%d)\n", __FILE__,
10193 	       __LINE__);
10194 	  DBG (0, "Trying again ...\n");
10195 	  if (sanei_umax_pp_cmdSync (0xC2) == 0)
10196 	    {
10197 	      DBG (0, " failed again! (%s:%d)\n", __FILE__, __LINE__);
10198 	      DBG (0, "Aborting ...\n");
10199 	      gCancel = 1;
10200 	    }
10201 	  else
10202 	    DBG (0, " success ...\n");
10203 	}
10204     }
10205   return len;
10206 }
10207 
10208 int
sanei_umax_pp_scan(int x, int y, int width, int height, int dpi, int color, int gain, int offset)10209 sanei_umax_pp_scan (int x, int y, int width, int height, int dpi, int color,
10210 		    int gain, int offset)
10211 {
10212 #ifdef HAVE_SYS_TIME_H
10213   struct timeval td, tf;
10214   float elapsed;
10215 #endif
10216   unsigned char *buffer;
10217   long int somme, len, read, blocksize;
10218   FILE *fout = NULL;
10219   int *dest = NULL;
10220   int bpl, hp;
10221   int th, tw, bpp;
10222   int nb;
10223   int bx, by, delta;
10224   int reserve, rc, remain, dataoffset;
10225 
10226   if (gain != 0 || offset != 0)
10227     sanei_umax_pp_setauto (0);
10228 
10229 
10230   /* colors don't come in sync, so we must increase y */
10231   /* to have extra lines to reorder data             */
10232   if (sanei_umax_pp_getastra () > 610)
10233     {
10234       switch (dpi)
10235 	{
10236 	case 1200:
10237 	  delta = 8;
10238 	  break;
10239 	case 600:
10240 	  delta = 4;
10241 	  break;
10242 	case 300:
10243 	  delta = 2;
10244 	  break;
10245 	case 150:
10246 	  delta = 1;
10247 	  break;
10248 	default:
10249 	  delta = 0;
10250 	  break;
10251 	}
10252     }
10253   else
10254     {
10255       if (color >= RGB_MODE)
10256 	{
10257 	  switch (dpi)
10258 	    {
10259 	    case 600:
10260 	      delta = 16;
10261 	      break;
10262 	    case 300:
10263 	      delta = 8;
10264 	      break;
10265 	    case 150:
10266 	      delta = 4;
10267 	      break;
10268 	    default:
10269 	      delta = 2;
10270 	      break;
10271 	    }
10272 	}
10273       else
10274 	delta = 0;
10275     }
10276 
10277   /* in color mode, we need extra lines to reorder data */
10278   if (color >= RGB_MODE)
10279     {
10280       if (sanei_umax_pp_getastra () <= 610)
10281 	dataoffset = 4 * delta;
10282       else
10283 	dataoffset = 2 * delta;
10284     }
10285   else
10286     dataoffset = 0;
10287 
10288   rc = sanei_umax_pp_startScan
10289     (x, y - dataoffset, width, height + dataoffset, dpi, color, gain,
10290      offset, &bpp, &tw, &th);
10291   if (rc == 1)
10292     {
10293       /* blocksize must be multiple of the number of bytes per line */
10294       /* max is 2096100                                             */
10295       /* so blocksize will hold a round number of lines, easing the */
10296       /* write data to file operation                               */
10297       bpl = bpp * tw;
10298       hp = 2096100 / bpl;
10299       blocksize = hp * bpl;
10300       nb = 0;
10301       somme = bpl * th;
10302       DBG (8, "Getting buffer %d*%d*%d=%ld=0x%lX    (%s:%d)  \n", bpp, tw, th,
10303 	   somme, somme, __FILE__, __LINE__);
10304 
10305       /* correct th to be usable scan height */
10306       th -= dataoffset;
10307 
10308       /* we need a 2 * delta lines reserve to reorder data */
10309       if (color >= RGB_MODE)
10310 	{
10311 	  reserve = 2 * delta * bpl;
10312 	  if (sanei_umax_pp_getastra () < 1210)
10313 	    dataoffset = reserve;
10314 	  else
10315 	    dataoffset = 0;
10316 	}
10317       else
10318 	{
10319 	  reserve = 0;
10320 	  dataoffset = 0;
10321 	}
10322 
10323       /* get scanned data */
10324 
10325       /* allocate memory */
10326       buffer = (unsigned char *) malloc (blocksize + reserve);
10327       if (buffer == NULL)
10328 	{
10329 	  DBG (0, "Failed to allocate %ld bytes, giving up....\n",
10330 	       blocksize + reserve);
10331 	  DBG (0, "Try to scan at lower resolution, or a smaller area.\n");
10332 	  gCancel = 1;
10333 	}
10334 
10335       /* open output file */
10336       fout = fopen ("out.pnm", "wb");
10337       if (fout == NULL)
10338 	{
10339 	  DBG (0, "Failed to open 'out.pnm', giving up....\n");
10340 	  gCancel = 1;
10341 	}
10342       else
10343 	{
10344 	  /* write pnm header */
10345 	  if (color >= RGB_MODE)
10346 	    fprintf (fout, "P6\n%d %d\n255\n", tw, th - 2 * delta);
10347 	  else
10348 	    fprintf (fout, "P5\n%d %d\n255\n", tw, th);
10349 	}
10350 
10351       /* read some line first until we got clean data */
10352       read = 0;
10353       remain = 0;
10354       while (read < dataoffset)
10355 	{
10356 	  if (read == 0)
10357 	    len = dataoffset;
10358 	  else
10359 	    len = dataoffset - read;
10360 	  len = sanei_umax_pp_readBlock (len, tw, dpi, 0, buffer + read);
10361 	  if (len == 0)
10362 	    {
10363 	      DBG (0,
10364 		   "sanei_umax_pp_readBlock failed, cancelling scan ...\n");
10365 	      gCancel = 1;
10366 	    }
10367 	  read += len;
10368 	}
10369 
10370       /* in color mode we have to fill the 'reserve' area
10371        * so that we can reorder data lines */
10372       while ((read - dataoffset < reserve) && (!gCancel))
10373 	{
10374 	  len = reserve - read + dataoffset;
10375 	  len =
10376 	    sanei_umax_pp_readBlock (len, tw, dpi, 0,
10377 				     buffer + read - dataoffset);
10378 	  if (len == 0)
10379 	    {
10380 	      DBG (0,
10381 		   "sanei_umax_pp_readBlock failed, cancelling scan ...\n");
10382 	      gCancel = 1;
10383 	    }
10384 	  read += len;
10385 	}
10386 
10387       /* data reading loop */
10388 #ifdef HAVE_SYS_TIME_H
10389       gettimeofday (&td, NULL);
10390 #endif
10391       while ((read < somme) && (!gCancel))
10392 	{
10393 	  /* 2096100 max */
10394 	  if (somme - read > blocksize - remain)
10395 	    len = blocksize - remain;
10396 	  else
10397 	    len = somme - read;
10398 	  len =
10399 	    sanei_umax_pp_readBlock (len, tw, dpi, (len < blocksize),
10400 				     buffer + reserve + remain);
10401 	  if (len == 0)
10402 	    {
10403 	      DBG (0,
10404 		   "sanei_umax_pp_readBlock failed, cancelling scan ...\n");
10405 	      gCancel = 1;
10406 	    }
10407 
10408 	  read += len;
10409 	  nb++;
10410 	  DBG (8, "Read %ld bytes out of %ld ...\n", read, somme);
10411 	  DBG (8, "Read %d blocks ... \n", nb);
10412 
10413 	  /* write partial buffer to file */
10414 	  if (len)
10415 	    {
10416 	      if (color >= RGB_MODE)
10417 		{
10418 		  /* using an image format that doesn't need   */
10419 		  /* reordering would speed up write operation */
10420 
10421 		  /* don't forget remaining bytes from previous block */
10422 		  hp = (len + remain) / bpl;
10423 		  remain = (len + remain) - hp * bpl;
10424 		  switch (sanei_umax_pp_getastra ())
10425 		    {
10426 		    case 610:
10427 		      /* first comes RED
10428 		       * then        BLUE
10429 		       * and finally GREEN */
10430 		      for (by = 0; by < hp; by++)
10431 			{
10432 			  for (bx = 0; bx < tw; bx++)
10433 			    {
10434 			      /* scanner data: red line, blue line then green line */
10435 			      /* red */
10436 			      fputc (buffer
10437 				     [3 * (by - 2 * delta) * tw + bx +
10438 				      reserve], fout);
10439 			      /* green */
10440 			      fputc (buffer
10441 				     [3 * by * tw + 2 * tw +
10442 				      bx + reserve], fout);
10443 			      /* blue */
10444 			      fputc (buffer
10445 				     [3 * (by - delta) * tw + tw + bx +
10446 				      reserve], fout);
10447 			    }
10448 			}
10449 		      /* copy tail lines for next block */
10450 		      /* memcpy (buffer,
10451 		       *         (buffer + reserve) + (hp * bpl - reserve),
10452 		       *         reserve + remain); */
10453 		      memcpy (buffer, buffer + hp * bpl, reserve + remain);
10454 		      break;
10455 		    case 1600:
10456 		      for (by = 0; by < hp; by++)
10457 			{
10458 			  for (bx = 0; bx < tw; bx++)
10459 			    {
10460 			      fputc (buffer[3 * by * tw + 2 * tw + bx], fout);
10461 			      fputc (buffer[3 * by * tw + bx], fout);
10462 			      fputc (buffer[3 * by * tw + tw + bx], fout);
10463 			    }
10464 			}
10465 		      break;
10466 		    default:
10467 		      for (by = 0; by < hp; by++)
10468 			{
10469 			  for (bx = 0; bx < tw; bx++)
10470 			    {
10471 			      fputc (buffer[3 * by * tw + 2 * tw + bx], fout);
10472 			      fputc (buffer[3 * by * tw + tw + bx], fout);
10473 			      fputc (buffer[3 * by * tw + bx], fout);
10474 			    }
10475 			}
10476 		      /* put remaining partial lines at start of buffer */
10477 		      memcpy (buffer, buffer + hp * bpl, remain);
10478 		      break;
10479 		    }
10480 		}
10481 	      else
10482 		fwrite (buffer, len, 1, fout);
10483 	    }
10484 	}
10485 
10486 #ifdef HAVE_SYS_TIME_H
10487       gettimeofday (&tf, NULL);
10488 
10489       /* scan time are high enough to forget about usec */
10490       elapsed = tf.tv_sec - td.tv_sec;
10491       DBG (8, "%ld bytes transferred in %f seconds ( %.2f Kb/s)\n", somme,
10492 	   elapsed, (somme / elapsed) / 1024.0);
10493 #endif
10494 
10495       /* release resources */
10496       if (fout != NULL)
10497 	fclose (fout);
10498       free (dest);
10499       free (buffer);
10500     }				/* if start scan OK */
10501   else
10502     {
10503       DBG (0, "startScan failed..... \n");
10504     }
10505 
10506   /* terminate any pending command */
10507   if (sanei_umax_pp_cmdSync (0x00) == 0)
10508     {
10509       DBG (0, "Warning cmdSync(0x00) failed! (%s:%d)\n", __FILE__, __LINE__);
10510       DBG (0, "Trying again ... ");
10511       if (sanei_umax_pp_cmdSync (0x00) == 0)
10512 	{
10513 	  DBG (0, " failed again! (%s:%d)\n", __FILE__, __LINE__);
10514 	  DBG (0, "Blindly going on ...\n");
10515 	}
10516       else
10517 	DBG (0, " success ...\n");
10518 
10519     }
10520 
10521   /* parking */
10522   if (sanei_umax_pp_park () == 0)
10523     DBG (0, "Park failed !!! (%s:%d)\n", __FILE__, __LINE__);
10524 
10525 
10526   /* end ... */
10527   DBG (16, "Scan done ...\n");
10528   return 1;
10529 }
10530 
10531 
10532 
10533 
10534 
10535 /*
10536  * returns 0 on error, 1 on success: ie head parked
10537  */
10538 int
sanei_umax_pp_parkWait(void)10539 sanei_umax_pp_parkWait (void)
10540 {
10541   int status;
10542 
10543   /* check if head is at home */
10544   DBG (16, "entering parkWait ...\n");
10545   do
10546     {
10547       usleep (1000);
10548       CMDSYNC (0x40);
10549       status = sanei_umax_pp_scannerStatus ();
10550     }
10551   while ((status & MOTOR_BIT) == 0x00);
10552   DBG (16, "parkWait done ...\n");
10553   return 1;
10554 }
10555 
10556 
10557 
10558 
10559 
10560 
10561 /* starts scan: return 1 on success */
10562 int
sanei_umax_pp_startScan(int x, int y, int width, int height, int dpi, int color, int gain, int offset, int *rbpp, int *rtw, int *rth)10563 sanei_umax_pp_startScan (int x, int y, int width, int height, int dpi,
10564 			 int color, int gain, int offset, int *rbpp,
10565 			 int *rtw, int *rth)
10566 {
10567   unsigned char *buffer;
10568   int rc = 0;
10569   int calibration[3 * 5100 + 768 + 2 + 1];
10570   int xdpi, ydpi, h;
10571   int th, tw, bpp;
10572   int hwdpi = 600;		/* CCD hardware dpi */
10573   /* DC offsets */
10574   int dcRed, dcGreen, dcBlue;
10575   int vgaRed, vgaGreen, vgaBlue;
10576   int len, delta;
10577 
10578   int lm9811[9] = {
10579     0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00,
10580     -1
10581   };
10582 
10583   int motor[17] = {
10584     0xA4, 0x80, 0x07, 0x50, 0xEC, 0x03, 0x00, 0x2F,
10585     0x17, 0x07, 0x84, 0x08, 0x90, 0x00, 0xAC, 0x00,
10586     -1
10587   };
10588 
10589   int ccd[37] =
10590     { 0x00, 0x00, 0xB0, 0x4F, 0xD8, 0xE7, 0xFA, 0x10, 0xEF, 0xC4, 0x3C, 0x71,
10591     0x0F, 0x00, 0x04, 0x00, 0x6E, 0x61, 0xA1, 0x24, 0xC4, 0x7E, 0x00, 0xAE,
10592     0x41, 0xA0, 0x0A, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x33, 0x1A, 0x00,
10593     -1
10594   };
10595 
10596 
10597 #ifdef UMAX_PP_DANGEROUS_EXPERIMENT
10598   FILE *f = NULL;
10599   char line[1024], *ptr;
10600   int *base = NULL;
10601   int channel;
10602   int max = 0;
10603 #endif
10604 
10605 
10606   if (sanei_umax_pp_getastra () == 610)
10607     {
10608       hwdpi = 300;
10609       len = 0x22;
10610 
10611       lm9811[0] = 0x88;
10612       lm9811[1] = 0xE6;
10613       lm9811[2] = 0xFD;
10614       lm9811[3] = 0x8E;
10615       lm9811[4] = 0x30;
10616       lm9811[5] = 0x00;
10617       lm9811[6] = 0x8F;
10618       lm9811[7] = 0x80;
10619 
10620       motor[3] = 0x30;
10621       motor[4] = 0x0E;
10622       motor[5] = 0x02;
10623       motor[12] = 0xAA;
10624 
10625       ccd[0] = 0x00;
10626       ccd[1] = 0x00;
10627       ccd[2] = 0xD8;
10628       ccd[3] = 0x27;
10629       ccd[4] = 0xEC;
10630       ccd[5] = 0x53;
10631       ccd[6] = 0x7D;
10632       ccd[7] = 0x8A;
10633       ccd[8] = 0x77;
10634       ccd[9] = 0xE2;
10635       ccd[10] = 0x9E;
10636       ccd[11] = 0xF8;
10637       ccd[12] = 0x07;
10638       ccd[13] = 0x20;
10639       ccd[14] = 0x02;
10640       ccd[15] = 0x00;
10641       ccd[16] = 0x76;
10642       ccd[17] = 0x5D;
10643       ccd[18] = 0xE0;
10644       ccd[19] = 0x13;
10645       ccd[20] = 0xE2;
10646       ccd[21] = 0x20;
10647       ccd[22] = 0x00;
10648       ccd[23] = 0xA8;
10649       ccd[24] = 0x41;
10650       ccd[25] = 0xA0;
10651       ccd[26] = 0x0A;
10652       ccd[27] = 0x8B;
10653       ccd[28] = 0x4D;
10654       ccd[29] = 0x4B;
10655       ccd[30] = 0xD0;
10656       ccd[31] = 0x68;
10657       ccd[32] = 0xDF;
10658       ccd[33] = 0x13;
10659     }
10660   else
10661     {
10662       len = 0x24;
10663       hwdpi = 600;
10664     }
10665   DBG (8, "startScan(%d,%d,%d,%d,%d,%d,%X);\n", x, y, width, height, dpi,
10666        color, gain);
10667   buffer = (unsigned char *) malloc (2096100);
10668   if (buffer == NULL)
10669     {
10670       DBG (0, "Failed to allocate 2096100 bytes... (%s:%d)\n", __FILE__,
10671 	   __LINE__);
10672       return 0;
10673     }
10674 
10675   /* 1600P have a different CCD command block */
10676   if (sanei_umax_pp_getastra () == 1600)
10677     {
10678       lm9811[0] = 0x19;
10679       lm9811[1] = 0xD5;
10680       lm9811[4] = 0x1B;
10681       lm9811[7] = 0x70;
10682 
10683       ccd[29] = 0x1A;
10684       ccd[30] = 0xEE;
10685 
10686       motor[13] = 0x03;		/* may be blur filter */
10687     }
10688 
10689   /* matches intTransport610P */
10690   /* get scanner status */
10691   rc = inquire ();
10692   if (rc == 0)
10693     {
10694       DBG (0, "inquire() failed ! (%s:%d) \n", __FILE__, __LINE__);
10695       return 0;
10696     }
10697   DBG (16, "inquire() passed ... (%s:%d)\n", __FILE__, __LINE__);
10698 
10699   rc = loadDefaultTables ();
10700   if (rc == 0)
10701     {
10702       DBG (0, "loadDefaultTables() failed ! (%s:%d) \n", __FILE__, __LINE__);
10703       return 0;
10704     }
10705   DBG (16, "loadDefaultTables() passed ... (%s:%d)\n", __FILE__, __LINE__);
10706 
10707   /* find and move to zero */
10708   if (moveToOrigin () == 0)
10709     {
10710       DBG (0, "moveToOrigin() failed ... (%s:%d)\n", __FILE__, __LINE__);
10711     }
10712   else
10713     {
10714       DBG (16, "moveToOrigin() passed ... (%s:%d)\n", __FILE__, __LINE__);
10715     }
10716 
10717   /* 1600P have a different CCD command block */
10718   if (sanei_umax_pp_getastra () == 1600)
10719     {
10720       lm9811[0] = 0x19;
10721       lm9811[1] = 0xD5;
10722       lm9811[4] = 0x1B;
10723       lm9811[7] = 0x70;
10724 
10725       ccd[29] = 0x1A;
10726       ccd[30] = 0xEE;
10727 
10728       motor[13] = 0x03;		/* may be blur filter */
10729     }
10730 
10731   /* XXX STEF XXX : done even is manual settings, some day skip it
10732    * and move head the right amount */
10733   if (offsetCalibration (color, &dcRed, &dcGreen, &dcBlue) == 0)
10734     {
10735       DBG (0, "offsetCalibration failed !!! (%s:%d)\n", __FILE__, __LINE__);
10736       return 0;
10737     }
10738   DBG (16, "offsetCalibration(%d=>%d,%d,%d) passed ... (%s:%d)\n",
10739        color, dcRed, dcGreen, dcBlue, __FILE__, __LINE__);
10740 
10741   if (coarseGainCalibration
10742       (color, dcRed, dcGreen, dcBlue, &vgaRed, &vgaGreen, &vgaBlue) == 0)
10743     {
10744       DBG (0, "coarseGainCalibration failed !!! (%s:%d)\n", __FILE__,
10745 	   __LINE__);
10746       return 0;
10747     }
10748   DBG (16,
10749        "coarseGainCalibration(%d,%d,%d,%d=>%d,%d,%d) passed ... (%s:%d)\n",
10750        color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue,
10751        __FILE__, __LINE__);
10752 
10753   /* manual setting overrides evaluated values */
10754   if (!sanei_umax_pp_getauto ())
10755     {
10756       dcRed = (offset & 0xF00) >> 8;
10757       dcGreen = (offset & 0x0F0) >> 4;
10758       dcBlue = offset & 0x00F;
10759       vgaRed = (gain & 0xF00) >> 8;
10760       vgaGreen = (gain & 0x0F0) >> 4;
10761       vgaBlue = gain & 0x00F;
10762     }
10763 
10764   /* ccd calibration is always done */
10765   /* with final dc and vga */
10766   if (shadingCalibration
10767       (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue,
10768        calibration) == 0)
10769     {
10770       DBG (0, "shadingCalibration failed !!! (%s:%d)\n", __FILE__, __LINE__);
10771       return 0;
10772     }
10773   DBG (16,
10774        "shadingCalibration(%d,%d,%d,%d,%d,%d,%d) passed ... (%s:%d)\n",
10775        color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, __FILE__,
10776        __LINE__);
10777 
10778   /* gamma or left shading calibration ? */
10779   if (sanei_umax_pp_getastra () <= 610)
10780     {
10781       if (leftShadingCalibration610p
10782 	  (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue,
10783 	   calibration) == 0)
10784 	{
10785 	  DBG (0, "leftShadingCalibration610p failed !!! (%s:%d)\n", __FILE__,
10786 	       __LINE__);
10787 	  return 0;
10788 	}
10789       DBG (16,
10790 	   "leftShadingCalibration610p(%d,%d,%d,%d,%d,%d,%d) passed ... (%s:%d)\n",
10791 	   color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, __FILE__,
10792 	   __LINE__);
10793     }
10794 
10795   /* 1220P: x dpi is from 75 to 600 max, any modes */
10796   /*  610P: x dpi is from 75 to 300 max, any modes */
10797   if (dpi > hwdpi)
10798     xdpi = hwdpi;
10799   else
10800     xdpi = dpi;
10801 
10802 
10803   /* EPPRead32Buffer does not work                         */
10804   /* with length not multiple of four bytes, so we enlarge */
10805   /* width to meet this criteria ...                       */
10806   if ((getEPPMode () == 32) && (xdpi >= 600) && (width & 0x03)
10807       && (sanei_umax_pp_getastra () > 610))
10808     {
10809       width += (4 - (width & 0x03));
10810       /* in case we go too far on the right */
10811       if (x + width > 5100)
10812 	{
10813 	  x = 5100 - width;
10814 	}
10815     }
10816 
10817   /* compute target size */
10818   th = (height * dpi) / hwdpi;
10819   tw = (width * xdpi) / hwdpi;
10820 
10821   /* corrects y to match exact scan area start
10822    * and lets room for a leading zone so that
10823    * we can reorder data */
10824   switch (sanei_umax_pp_getastra ())
10825     {
10826     case 610:
10827       if (color >= RGB_MODE)
10828 	switch (dpi)
10829 	  {
10830 	  case 600:
10831 	    y += 64;
10832 	    break;
10833 	  case 300:
10834 	    y += 32;
10835 	    break;
10836 	  case 150:
10837 	    y += 16;
10838 	    break;
10839 	  case 75:
10840 	    y += 8;
10841 	    break;
10842 	  }
10843       else
10844 	y += 80;
10845       // fall through
10846     default:
10847       y += 8;
10848       break;
10849     }
10850 
10851   /* for 1220P/2000P move fast to scan target if possible */
10852   /* it is faster to move at low resolution, then scan */
10853   /* than scan & move at high resolution               */
10854   if ((sanei_umax_pp_getastra () > 610 && (dpi > 300)) && (y > 100))
10855     {
10856       /* move at 150 dpi resolution */
10857       move (y / 2, PRECISION_OFF, NULL);
10858 
10859       /* keep the remainder for scan */
10860       y = y % 4;
10861     }
10862 
10863   /* build final scan command */
10864 
10865   /* round width and height */
10866   width = (tw * hwdpi) / xdpi;
10867   height = (th * hwdpi) / dpi;
10868 
10869   ydpi = dpi;
10870   if (ydpi < 300)
10871     {
10872       if ((color >= RGB_MODE) && (sanei_umax_pp_getastra () > 610))
10873 	{
10874 	  if (dpi < 150)
10875 	    ydpi = 150;
10876 	}
10877       else
10878 	ydpi = 300;
10879     }
10880   if ((color < RGB_MODE) && (sanei_umax_pp_getastra () <= 610))
10881     ydpi = 600;
10882 
10883   /* at maximum resolution                      */
10884   if (color >= RGB_MODE)
10885     {
10886       h = ((height * ydpi) / hwdpi) + 8;
10887       bpp = 3;
10888     }
10889   else
10890     {
10891       h = ((height * ydpi) / hwdpi) + 4;
10892       if (sanei_umax_pp_getastra () <= 610)
10893 	h += 16;
10894       bpp = 1;
10895     }
10896 
10897   /* sets y resolution */
10898   switch (ydpi)
10899     {
10900     case 1200:
10901       motor[6] = 0x60;
10902       motor[8] = 0x5E;		/* *WORKING* value */
10903       motor[8] = 0x5F;		/* 5F gives wrong colors ? */
10904       motor[8] = 0x58;
10905       motor[9] = 0x05;
10906       /* XXX test value XXX motor[14] = motor[14] & 0xF0;  ~ 0x08 -> scan AND move */
10907       /* XXX test value XXX motor[14] = (motor[14] & 0xF0) | 0x04;         -> 600 dpi ? */
10908       /* XXX test value XXX motor[14] = (motor[14] & 0xF0) | 0x0C; */
10909       motor[14] = motor[14] & 0xF0;	/* *WORKING* 1200 dpi */
10910       break;
10911 
10912     case 600:
10913       if (sanei_umax_pp_getastra () <= 610)
10914 	{
10915 	  motor[6] = 0xC0;
10916 	  motor[7] = 0x2F;
10917 	  motor[14] = motor[14] & 0xF0;
10918 	  /* if (color >= RGB_MODE)
10919 	     motor[14] |= 0x04; XXX STEF XXX */
10920 	}
10921       else
10922 	{
10923 	  motor[6] = 0x60;
10924 	  motor[14] = (motor[14] & 0xF0) | 0x04;
10925 	}
10926       motor[8] = 0x2F;
10927       motor[9] = 0x05;
10928       break;
10929 
10930     case 300:
10931       if (sanei_umax_pp_getastra () <= 610)
10932 	{
10933 	  motor[6] = 0xC0;
10934 	  motor[14] = motor[14] & 0xF0;
10935 	  if (color >= RGB_MODE)
10936 	    motor[14] |= 0x04;
10937 	}
10938       else
10939 	{
10940 	  motor[6] = 0x00;
10941 	  motor[14] = (motor[14] & 0xF0) | 0x0C;
10942 	}
10943       motor[8] = 0x17;
10944       motor[9] = 0x05;
10945 
10946       /* si | 0C h=2*w, si | 04 h=w ? */
10947 
10948       break;
10949 
10950     case 150:
10951       if (sanei_umax_pp_getastra () <= 610)
10952 	{
10953 	  motor[6] = 0xC0;
10954 	  motor[9] = 0x05;
10955 	  motor[14] = motor[14] & 0xF0;
10956 	  if (color >= RGB_MODE)
10957 	    motor[14] |= 0x04;
10958 	}
10959       else
10960 	{
10961 	  motor[6] = 0x00;
10962 	  motor[9] = 0x07;
10963 	  motor[14] = (motor[14] & 0xF0) | 0x0C;
10964 	}
10965       motor[8] = 0x17;
10966       break;
10967     }
10968 
10969   /* different values for 610P in B&W */
10970   if ((sanei_umax_pp_getastra () <= 610) && (color < RGB_MODE))
10971     {
10972       motor[7] = 0xC8;
10973       motor[8] = 0x2F;
10974       motor[9] = 0x05;
10975     }
10976 
10977   /* y start -1 */
10978   y = (y * ydpi) / hwdpi;
10979 
10980   if (color >= RGB_MODE)
10981     {
10982       /* 00 seems to give better results ?     */
10983       /* 80 some more gain, lamp power level ? */
10984       /* 8x does not make much difference      */
10985       lm9811[6] = 0x8F;
10986       switch (sanei_umax_pp_getastra ())
10987 	{
10988 	case 610:
10989 	  lm9811[7] = 0x80;
10990 	  motor[13] = 0x20;
10991 	  break;
10992 	case 1600:
10993 	  lm9811[7] = 0x70;
10994 	  motor[13] = 0x03;
10995 	  break;
10996 	default:
10997 	  lm9811[7] = 0xF0;
10998 	  motor[13] = 0x09;
10999 	}
11000     }
11001   else
11002     {
11003       motor[13] = 0xC0;
11004       lm9811[6] = 0x80 | vgaGreen;
11005       switch (sanei_umax_pp_getastra ())
11006 	{
11007 	case 610:
11008 	  lm9811[7] = 0xA0;
11009 	  lm9811[6] = lm9811[6] | 0x40;
11010 	  motor[13] = 0x6F;
11011 	  break;
11012 	case 1600:
11013 	  lm9811[7] = 0x20;
11014 	  motor[13] = 0xC3;
11015 	  break;
11016 	default:
11017 	  lm9811[7] = 0xA0;
11018 	  motor[13] = 0xC9;
11019 	}
11020     }
11021 
11022   encodeCoefficient (color, dpi, calibration);
11023   encodeWX (width, x, dpi, color, ccd, 0);
11024   encodeHY (h, y, motor);
11025   encodeDC (dcRed, dcGreen, dcBlue, motor);
11026   encodeVGA (vgaRed, vgaGreen, vgaBlue, motor);
11027 
11028 #ifdef UMAX_PP_DANGEROUS_EXPERIMENT
11029   /*motor[13] = 0x80;           B&W bit */
11030   /*motor[13] = 0x40;           green bit */
11031   /*motor[13] = 0x20;           red bit */
11032   /*motor[13] = 0x10;           blue bit */
11033   /* with cmd 01, may be use to do 3 pass scanning ? */
11034   /* bits 0 to 3 seem related to sharpness */
11035   f = fopen ("/tmp/dangerous.params", "rb");
11036   if (f != NULL)
11037     {
11038       fgets (line, 1024, f);
11039       while (!feof (f))
11040 	{
11041 	  channel = 0;
11042 	  if (sscanf (line, "CMD%1d", &channel) != 1)
11043 	    channel = 0;
11044 	  switch (channel)
11045 	    {
11046 	    case 0:
11047 	      break;
11048 	    case 1:
11049 	      base = lm9811;
11050 	      max = 8;
11051 	      break;
11052 	    case 2:
11053 	      base = motor;
11054 	      max = 16;
11055 	      break;
11056 	    case 8:
11057 	      base = ccd;
11058 	      max = 36;
11059 	      break;
11060 	    default:
11061 	      channel = 0;
11062 	    }
11063 	  printf ("CMD%d BEFORE: ", channel);
11064 	  for (i = 0; i < max; i++)
11065 	    printf ("%02X ", base[i]);
11066 	  printf ("\n");
11067 	  if (channel > 0)
11068 	    {
11069 	      ptr = line + 6;
11070 	      for (i = 0; (i < max) && ((ptr - line) < strlen (line)); i++)
11071 		{
11072 		  if (ptr[0] != '-')
11073 		    {
11074 		      sscanf (ptr, "%X", base + i);
11075 		    }
11076 		  ptr += 3;
11077 		}
11078 	    }
11079 	  printf ("CMD%d AFTER : ", channel);
11080 	  for (i = 0; i < max; i++)
11081 	    printf ("%02X ", base[i]);
11082 	  printf ("\n");
11083 	  fgets (line, 1024, f);
11084 	}
11085       fclose (f);
11086     }
11087 #endif
11088 
11089   if (DBG_LEVEL >= 64)
11090     {
11091       bloc2Decode (motor);
11092       bloc8Decode (ccd);
11093     }
11094 
11095   CMDSYNC (0x00);
11096   CMDSETGET (2, 0x10, motor);
11097   CMDSETGET (8, len, ccd);
11098   CMDSETGET (1, 0x08, lm9811);
11099   CMDSYNC (0xC2);
11100 
11101   /* 3 ccd lines + 3 gamma tables + end tag */
11102   if (sanei_umax_pp_getastra () <= 610)
11103     {
11104       /* XXX STEF XXX : there is a 4 pixels shift to the right
11105        * the first shading correction value applies to the forth
11106        * pixel of scan (at 300 dpi), we already shift to the left
11107        * when doing shadingCalibration, but now we have to move coeffs
11108        * to match x coordinate */
11109       delta = x - sanei_umax_pp_getLeft ();
11110       if (delta)
11111 	{
11112 	  memcpy (calibration,
11113 		  calibration + delta, (7650 - delta) * sizeof (int));
11114 	}
11115       CMDSET (4, 0x20E4, calibration);
11116     }
11117   else
11118     {
11119       CMDSET (4, 0x3EC6, calibration);
11120     }
11121 
11122   COMPLETIONWAIT;
11123 
11124   *rbpp = bpp;
11125   *rtw = tw;
11126   *rth = th;
11127 
11128   free (buffer);
11129   return 1;
11130 }
11131 
11132 /*
11133  * check the scanner model. Return 1220 for
11134  * a 1220P, or 2000 for a 2000P.
11135  * and 610 for a 610p
11136  * values less than 610 are errors
11137  */
11138 int
sanei_umax_pp_checkModel(void)11139 sanei_umax_pp_checkModel (void)
11140 {
11141   int *dest = NULL;
11142   int state[16];
11143   int err = 0;
11144   int i;
11145 
11146   int opsc35[37] =
11147     { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80,
11148     0x00, 0x00, 0x04, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
11149     0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00,
11150     -1
11151   };
11152 
11153   /* if we have already detected a scanner different from */
11154   /* default type, no need to check again                 */
11155   if (sanei_umax_pp_getastra ())
11156     return sanei_umax_pp_getastra ();
11157 
11158   /* get scanner status */
11159   CMDGET (0x02, 16, state);
11160   CMDSETGET (0x08, 36, opsc35);
11161   CMDSYNC (0xC2);
11162 
11163   dest = (int *) malloc (65536 * sizeof (int));
11164   if (dest == NULL)
11165     {
11166       DBG (0, "%s:%d failed to allocate 256 Ko !\n", __FILE__, __LINE__);
11167       return 0;
11168     }
11169 
11170   /* init some buffer : default calibration data ? */
11171   dest[0] = 0x00;
11172   dest[1] = 0x00;
11173   dest[2] = 0x00;
11174   for (i = 0; i < 768; i++)
11175     dest[i + 3] = i % 256;
11176   dest[768 + 3] = 0xAA;
11177   dest[768 + 4] = 0xAA;
11178   dest[768 + 5] = -1;
11179   CMDSETGET (0x04, 768 + 5, dest);
11180 
11181 
11182   /* check buffer returned */
11183   for (i = 0; i < 768; i++)
11184     {
11185       if (dest[i + 3] != (i % 256))
11186 	{
11187 	  DBG
11188 	    (0,
11189 	     "Error data altered: byte %d=0x%02X, should be 0x%02X !    (%s:%d)\n",
11190 	     i, dest[i + 3], i % 256, __FILE__, __LINE__);
11191 	  err = 1;
11192 	}
11193     }
11194   if (err)
11195     return 0;
11196 
11197 
11198   /* new part of buffer ... */
11199   for (i = 0; i < 256; i++)
11200     {
11201       dest[i * 2] = i;
11202       dest[i * 2 + 1] = 0x00;
11203     }
11204   CMDSETGET (0x08, 36, opsc35);
11205   CMDSYNC (0xC2);
11206   CMDSET (0x04, 512, dest);
11207 
11208   /* another new part ... */
11209   for (i = 0; i < 256; i++)
11210     {
11211       dest[i * 2] = i;
11212       dest[i * 2 + 1] = 0x04;	/* instead of 0x00 */
11213     }
11214   opsc35[2] = 0x06;		/* instead of 0x04, write flag ? */
11215   CMDSETGET (0x08, 36, opsc35);
11216   CMDSYNC (0xC2);
11217   CMDSET (0x04, 512, dest);
11218 
11219   opsc35[2] = 0x04;		/* return to initial value, read flag? */
11220   CMDSETGET (0x08, 36, opsc35);
11221   CMDGET (0x04, 512, dest);
11222 
11223   /* check buffer returned */
11224   /* if 0x4 are still 0x04, we got a 1220P, else it is a 2000P */
11225   for (i = 0; i < 256; i++)
11226     {
11227       if ((dest[2 * i] != i)
11228 	  || ((dest[2 * i + 1] != 0x04) && (dest[2 * i + 1] != 0x00)))
11229 	{
11230 	  DBG
11231 	    (0,
11232 	     "Error data altered: expected %d=(0x%02X,0x04), found (0x%02X,0x%02X) !    (%s:%d)\n",
11233 	     i, i, dest[i * 2], dest[i * 2 + 1], __FILE__, __LINE__);
11234 	  err = 0;
11235 	}
11236     }
11237 
11238   /* if buffer unchanged, we have a 1600P, or a 1220P */
11239   /* if data has turned into 0, we have a 2000P       */
11240   if (dest[1] == 0x00)
11241     {
11242       sanei_umax_pp_setastra (2000);
11243       err = 2000;
11244     }
11245   else
11246     {
11247       /* detects 1600  by finding black scans */
11248       /* we defaults to 1220 */
11249       sanei_umax_pp_setastra (1220);
11250       moveToOrigin ();
11251       err = sanei_umax_pp_getastra ();
11252 
11253       /* parking */
11254       CMDSYNC (0xC2);
11255       CMDSYNC (0x00);
11256       if (sanei_umax_pp_park () == 0)
11257 	DBG (0, "Park failed !!! (%s:%d)\n", __FILE__, __LINE__);
11258 
11259       /* poll parking */
11260       do
11261 	{
11262 	  sleep (1);
11263 	  CMDSYNC (0x40);
11264 	}
11265       while ((sanei_umax_pp_scannerStatus () & MOTOR_BIT) == 0x00);
11266     }
11267 
11268   /* return guessed model number */
11269   CMDSYNC (0x00);
11270   return err;
11271 }
11272 
11273 
11274 
11275 /* sets, resets gamma tables */
11276 
11277 void
sanei_umax_pp_gamma(int *red, int *green, int *blue)11278 sanei_umax_pp_gamma (int *red, int *green, int *blue)
11279 {
11280   if (red != NULL)
11281     {
11282       ggRed = red;
11283     }
11284   else
11285     {
11286       ggRed = ggamma;
11287     }
11288 
11289   if (green != NULL)
11290     {
11291       ggGreen = green;
11292     }
11293   else
11294     {
11295       ggGreen = ggamma;
11296     }
11297 
11298   if (blue != NULL)
11299     {
11300       ggBlue = blue;
11301     }
11302   else
11303     {
11304       ggBlue = ggamma;
11305     }
11306 }
11307 
11308 /* initialize scanner by loading default transformation table */
11309 /* O: failure
11310  * 1: OK
11311  */
11312 int
loadDefaultTables(void)11313 loadDefaultTables (void)
11314 {
11315   int cmd01[36] = {
11316     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11317     0x00, 0x03, 0xC1, 0x80, 0x60, 0x20, 0x00, 0x00,
11318     0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
11319     0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11320     0x00, 0xF0, 0x13, -1
11321   };
11322   int opsc35[37] = {
11323     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11324     0x00, 0x03, 0xC1, 0x80, 0x00, 0x00, 0x04, 0x00,
11325     0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
11326     0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68,
11327     0xDF, 0x13, 0x1A, 0x00,
11328     -1
11329   };
11330   int i, len, *cmd, err;
11331   int buffer[774];
11332   int rc = 1;
11333 
11334 
11335   /* 1600P have a different CCD command block */
11336   if (sanei_umax_pp_getastra () == 1600)
11337     {
11338       opsc35[29] = 0x1A;
11339       opsc35[30] = 0xEE;
11340     }
11341 
11342   if (sanei_umax_pp_getastra () <= 610)
11343     {
11344       len = 0x22;
11345       cmd = cmd01;
11346       /* XXX STEF XXX if we send F0, we get 0x10 back */
11347       cmd[0x21] = 0x10;
11348     }
11349   else
11350     {
11351       len = 0x24;
11352       cmd = opsc35;
11353     }
11354 
11355   /* set and reread first table */
11356   /* since 1660P seems to have another type of CCD
11357    * this table is not sent/needed
11358    */
11359   err = 0;
11360   if (sanei_umax_pp_getastra () != 1600)
11361     {
11362       CMDSETGET (8, len, cmd);
11363       CMDSYNC (0xC2);
11364       buffer[0] = 0x00;
11365       buffer[1] = 0x00;
11366       buffer[2] = 0x00;
11367       for (i = 0; i < 768; i++)
11368 	buffer[i + 3] = i % 256;
11369       if (sanei_umax_pp_getastra () <= 610)
11370 	{
11371 	  buffer[768 + 3] = 0xFF;
11372 	  buffer[768 + 4] = 0xFF;
11373 	}
11374       else
11375 	{
11376 	  buffer[768 + 3] = 0xAA;
11377 	  buffer[768 + 4] = 0xAA;
11378 	}
11379       buffer[768 + 5] = -1;
11380       CMDSETGET (4, 0x305, buffer);
11381 
11382 
11383       /* check buffer returned */
11384       for (i = 0; i < 768; i++)
11385 	{
11386 	  if (buffer[i + 3] != (i % 256))
11387 	    {
11388 	      DBG
11389 		(0,
11390 		 "Error data altered: byte %d=0x%02X, should be 0x%02X !    (%s:%d)\n",
11391 		 i, buffer[i + 3], i % 256, __FILE__, __LINE__);
11392 	      err = 1;
11393 	    }
11394 	}
11395       if (err)
11396 	return 0;
11397     }
11398 
11399   /* second table ... */
11400   for (i = 0; i < 256; i++)
11401     {
11402       buffer[i * 2] = i;
11403       buffer[i * 2 + 1] = 0;
11404     }
11405   CMDSETGET (8, len, cmd);
11406   CMDSYNC (0xC2);
11407   CMDSET (4, 0x200, buffer);
11408 
11409   /* third table ... */
11410   if (sanei_umax_pp_getastra () <= 610)
11411     {
11412       for (i = 0; i < 256; i++)
11413 	{
11414 	  buffer[i * 2] = i;
11415 	  buffer[i * 2 + 1] = 0x01;	/* instead of 0x00 */
11416 	}
11417     }
11418   else
11419     {
11420       for (i = 0; i < 256; i++)
11421 	{
11422 	  buffer[i * 2] = i;
11423 	  buffer[i * 2 + 1] = 0x04;	/* instead of 0x00 */
11424 	}
11425     }
11426   opsc35[2] = 0x06;
11427   cmd01[1] = 0x80;
11428   CMDSETGET (8, len, cmd);
11429   CMDSYNC (0xC2);
11430   CMDSET (4, 0x200, buffer);
11431 
11432   opsc35[2] = 0x04;
11433   cmd01[1] = 0x00;
11434   CMDSETGET (8, len, cmd);
11435   CMDGET (4, 0x200, buffer);
11436   /* check buffer returned */
11437   /* if 0x4 are still 0x0 (hum..), we got a 1220P, else it is a 2000P */
11438   for (i = 0; i < 256; i++)
11439     {
11440       if ((buffer[2 * i] != i)
11441 	  || ((buffer[2 * i + 1] != 0x04) && (buffer[2 * i + 1] != 0x01)
11442 	      && (buffer[2 * i + 1] != 0x00)))
11443 	{
11444 	  DBG
11445 	    (0,
11446 	     "Error data altered: expected %d=(0x%02X,0x04), found (0x%02X,0x%02X) !    (%s:%d)\n",
11447 	     i, i, buffer[i * 2], buffer[i * 2 + 1], __FILE__, __LINE__);
11448 	  err = 1;
11449 	}
11450     }
11451   if (err)
11452     return 0;
11453 
11454   return rc;
11455 }
11456 
11457 /* inquire scanner status
11458  * O: failure
11459  * 1: OK
11460  * 2: first scanner init, needs re-homing
11461  */
11462 int
inquire(void)11463 inquire (void)
11464 {
11465   int cmd01[36] = {
11466     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11467     0x00, 0x03, 0xC1, 0x80, 0x60, 0x20, 0x00, 0x00,
11468     0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
11469     0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11470     0x00, 0xF0, 0x1B, -1
11471   };
11472   int buffer[37];
11473   int rc = 1, first, i;
11474   char str[106];
11475 
11476 
11477   /* inquiry: ask for RAM, CCD, ... */
11478   CMDSET (8, 0x23, cmd01);
11479   CMDGET (8, 0x23, buffer);
11480 
11481   if (DBG_LEVEL > 8)
11482     {
11483       for (i = 0; i < 35; i++)
11484 	sprintf (str + 3 * i, "%02X ", buffer[i]);
11485       str[105] = 0x00;
11486       DBG (8, "SCANNER INFORMATION=%s\n", str);
11487     }
11488 
11489   /* get state */
11490   CMDGET (2, 0x10, buffer);
11491   first = 1;
11492   for (i = 0; i < 14; i++)
11493     {
11494       if (buffer[i] != 0)
11495 	first = 0;
11496     }
11497   if (buffer[15] != 0)
11498     first = 0;
11499   if (first)
11500     rc = 2;
11501 
11502   if (DBG_LEVEL > 8)
11503     {
11504       for (i = 0; i < 16; i++)
11505 	sprintf (str + 3 * i, "%02X ", buffer[i]);
11506       str[48] = 0x00;
11507       DBG (8, "SCANNER STATE=%s\n", str);
11508     }
11509 
11510   return rc;
11511 }
11512 
11513 /*
11514  * computes DC offset to have black pixel really black out of
11515  * CCD ie black gives 0
11516  * 1220P implements the method described in LM9811 datasheet
11517  * returns 1 and DC offsets in the corresponding vars on success .
11518  * On failure, returns 0.
11519  */
11520 static int
offsetCalibration1220p(int color, int *offRed, int *offGreen, int *offBlue)11521 offsetCalibration1220p (int color, int *offRed, int *offGreen, int *offBlue)
11522 {
11523   unsigned char buffer[5300];
11524   int i, val;
11525   int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 };
11526   int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 };
11527   int opsc38[37] =
11528     { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
11529     0x00, 0x00, 0x04, 0x00, 0x6E, 0x18, 0x10, 0x03, 0x06, 0x00, 0x00, 0x00,
11530     0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00,
11531     -1
11532   };
11533   int opsc48[17] =
11534     { 0x09, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0x00, 0x00,
11535     0x00, 0x40, 0xA4, 0x00, -1
11536   };
11537   float low, high;
11538   DBG (16, "entering offsetCalibration1220p() ... (%s:%d)\n", __FILE__,
11539        __LINE__);
11540 
11541   /* really dirty hack: something is buggy in BW mode   */
11542   /* we override mode with color until the bug is found */
11543   /* color = RGB_MODE; */
11544 
11545   /* 1600P have a different CCD command block */
11546   if (sanei_umax_pp_getastra () == 1600)
11547     {
11548       opsc04[0] = 0x19;
11549       opsc04[1] = 0xD5;
11550       opsc04[4] = 0x1B;
11551       opsc04[7] = 0x20;
11552 
11553       opsc48[8] = 0x2B;
11554       opsc48[11] = 0x20;
11555       opsc48[12] = 0x08;
11556       opsc48[13] = 0x42;
11557     }
11558 
11559   /* offset calibration, scan 24 bytes of black in each color */
11560   /* component see section 5.1 of LM9811 datasheet */
11561   if (color >= RGB_MODE)
11562     {
11563       CMDSETGET (2, 0x10, opsc48);
11564       CMDSETGET (8, 0x24, opsc38);
11565       CMDSETGET (1, 0x08, opsc04);	/* scan std, no 'enhancing' */
11566       CMDSYNC (0xC2);
11567       if (sanei_umax_pp_scannerStatus () & 0x80)
11568 	{
11569 	  CMDSYNC (0x00);
11570 	}
11571       CMDSETGET (4, 0x08, commit);	/* commit ? */
11572       COMPLETIONWAIT;
11573       CMDGETBUF (4, 0x18, buffer);
11574       if (DBG_LEVEL >= 128)
11575 	Dump (0x18, buffer, NULL);
11576       val = 0;
11577       for (i = 0; i < 24; i++)
11578 	val += buffer[i];
11579       low = (float) val / i;	/* Vadc1 */
11580 
11581 
11582       CMDSYNC (0x00);
11583       opsc04[7] = opsc04[7] | 0x10;	/* enhanced ? */
11584       CMDSETGET (1, 0x08, opsc04);
11585       COMPLETIONWAIT;
11586       CMDGETBUF (4, 0x18, buffer);
11587       val = 0;
11588       for (i = 0; i < 24; i++)
11589 	val += buffer[i];
11590       high = (float) val / i;	/* Vadc2 */
11591       if (DBG_LEVEL >= 128)
11592 	Dump (0x18, buffer, NULL);
11593       *offRed = 15.0 - ((high - low) * 2);
11594 
11595       /* block that repeats */
11596       /* must be monochrome since hscan=1 */
11597       opsc48[0] = 0x01;
11598       if (sanei_umax_pp_getastra () == 1600)
11599 	{
11600 	  opsc48[12] = 0x0C;
11601 	  opsc48[13] = 0x82;
11602 	}
11603       else
11604 	{
11605 	  opsc48[12] = 0x04;
11606 	  opsc48[13] = 0x80;
11607 	}
11608       CMDSETGET (2, 0x10, opsc48);
11609       CMDSETGET (8, 0x24, opsc38);
11610       opsc04[7] = opsc04[7] & 0x20;
11611       CMDSETGET (1, 0x08, opsc04);
11612       CMDSYNC (0xC2);
11613       if (sanei_umax_pp_scannerStatus () & 0x80)
11614 	{
11615 	  CMDSYNC (0x00);
11616 	}
11617       CMDSETGET (4, 0x08, commit);
11618       COMPLETIONWAIT;
11619       CMDGETBUF (4, 0x18, buffer);
11620       if (DBG_LEVEL >= 128)
11621 	Dump (0x18, buffer, NULL);
11622       val = 0;
11623       for (i = 0; i < 24; i++)
11624 	val += buffer[i];
11625       low = (float) val / i;
11626 
11627       CMDSYNC (0x00);
11628       opsc04[7] = opsc04[7] | 0x10;	/* gain ? */
11629       CMDSETGET (1, 0x08, opsc04);
11630       COMPLETIONWAIT;
11631       CMDGETBUF (4, 0x18, buffer);
11632       if (DBG_LEVEL >= 128)
11633 	Dump (0x18, buffer, NULL);
11634       val = 0;
11635       for (i = 0; i < 24; i++)
11636 	val += buffer[i];
11637       high = (float) val / i;
11638 
11639       *offBlue = 15.0 - ((high - low) * 2);
11640     }
11641 
11642   /* block that repeats */
11643   if (color < RGB_MODE)
11644     {
11645       opsc48[0] = 0x05;		/* B&H height is 5 */
11646       opsc48[13] = 0xC0;	/* B&W mode */
11647     }
11648   else
11649     {
11650       opsc48[0] = 0x05;		/* color height is 5 (+4 ?) */
11651       opsc48[13] = 0xC1;	/* some strange mode ? */
11652     }
11653   if (sanei_umax_pp_getastra () == 1600)
11654     opsc48[13] = opsc48[13] | 0x02;
11655   CMDSETGET (2, 0x10, opsc48);
11656   CMDSETGET (8, 0x24, opsc38);
11657   opsc04[7] = opsc04[7] & 0x20;
11658   CMDSETGET (1, 0x08, opsc04);
11659   CMDSYNC (0xC2);
11660   if (sanei_umax_pp_scannerStatus () & 0x80)
11661     {
11662       CMDSYNC (0x00);
11663     }
11664   CMDSETGET (4, 0x08, commit);
11665   COMPLETIONWAIT;
11666   CMDGETBUF (4, 0x18, buffer);
11667   if (DBG_LEVEL >= 128)
11668     Dump (0x18, buffer, NULL);
11669   val = 0;
11670   for (i = 0; i < 24; i++)
11671     val += buffer[i];
11672   low = (float) val / i;
11673 
11674   CMDSYNC (0x00);
11675   opsc04[7] = opsc04[7] | 0x10;
11676   CMDSETGET (1, 0x08, opsc04);
11677   COMPLETIONWAIT;
11678   CMDGETBUF (4, 0x18, buffer);
11679   if (DBG_LEVEL >= 128)
11680     Dump (0x18, buffer, NULL);
11681   val = 0;
11682   for (i = 0; i < 24; i++)
11683     val += buffer[i];
11684   high = (float) val / i;
11685 
11686   *offGreen = 15.0 - ((high - low) * 2);
11687 
11688   /*DBG (1, "STEF: offsets(RED,GREEN,BLUE=(%d,%d,%d)\n", *offRed, *offGreen,
11689    *offBlue);*/
11690   DBG (16, "offsetCalibration1220p() done ...\n");
11691   return 1;
11692 }
11693 
11694 /*
11695  * computes DC offset to have black pixel really black out of
11696  * CCD ie black gives 0
11697  * 610P doesn't implement method described in LM9811 datasheet
11698  * but scan a black line with decreasing offsets until the
11699  * scanned data reach a 'good black level'.
11700  * returns 1 and DC offsets in the corresponding vars on success .
11701  * On failure, returns 0.
11702  */
11703 static int
offsetCalibration610p(int color, int *offRed, int *offGreen, int *offBlue)11704 offsetCalibration610p (int color, int *offRed, int *offGreen, int *offBlue)
11705 {
11706   int motor[17] = {
11707     0x11, 0x00, 0x00, 0x70, 0x00, 0x00, 0xC0, 0x2F,
11708     0x17, 0x00, 0x00, 0xF0, 0x7D, 0x5F, 0xA4, 0x00,
11709     -1
11710   };
11711 
11712   int ccd[37] = {
11713     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11714     0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00,
11715     0x76, 0x12, 0xB0, 0x03, 0x06, 0x00, 0x00, 0x00,
11716     0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
11717     0xDF, 0x13, 0x1A, 0x00,
11718     -1
11719   };
11720 
11721   int lm9811[9] = {
11722     0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x40, 0xF0,
11723     -1
11724   };
11725 
11726   int commit[9] = {
11727     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
11728     -1
11729   };
11730 
11731 
11732   int offset;
11733   int level;
11734   unsigned char data[40];
11735   int i;
11736   int len;
11737   int w;
11738 
11739   DBG (16, "entering offsetCalibration610P() ... (%s:%d)\n", __FILE__,
11740        __LINE__);
11741 
11742   if (sanei_umax_pp_getastra () < 1220)
11743     {
11744       len = 0x22;
11745       w = 40;
11746     }
11747   else
11748     {
11749       len = 0x24;
11750       w = 40;
11751     }
11752 
11753   *offRed = 0;
11754   *offGreen = 0;
11755   *offBlue = 0;
11756 
11757   /* first color channel: used both in color and b&w modes */
11758   /* offset to the max */
11759   /* supposed to be green component */
11760   offset = 0x10;
11761   do
11762     {
11763       offset--;
11764 
11765       /* 7D: 0111 1101 */
11766       /* sets for the current offset */
11767       motor[12] = (offset << 2) | 0x40 | 0x01;
11768       lm9811[7] = offset << 4;
11769 
11770       /* sends commands */
11771       CMDSYNC (0x00);
11772       CMDSETGET (2, 0x10, motor);
11773       CMDSETGET (8, len, ccd);
11774       CMDSETGET (1, 0x08, lm9811);
11775       CMDSYNC (0xC2);
11776       CMDSETGET (4, 0x08, commit);
11777       COMPLETIONWAIT;
11778       CMDGETBUF (4, w, data);
11779       if (DBG_LEVEL > 128)
11780 	{
11781 	  DumpNB (w, 1, data, NULL);
11782 	}
11783       level = 0;
11784       for (i = 0; i < w; i++)
11785 	level += data[i];
11786     }
11787   /* loop while average >0.5 */
11788   while ((offset > 0) && ((level * 2) / w > 1));
11789   *offGreen = offset;
11790 
11791   /* offset calibration for the two other channels when in color */
11792   if (color >= RGB_MODE)
11793     {
11794       motor[0] = 0x01;
11795 
11796       offset = 0x10;
11797       do
11798 	{
11799 	  offset--;
11800 
11801 	  /* sets for the current offset */
11802 	  motor[13] = 0x90 | offset;
11803 	  lm9811[7] = offset << 4;
11804 
11805 	  /* sends commands */
11806 	  CMDSYNC (0x00);
11807 	  CMDSETGET (2, 0x10, motor);
11808 	  CMDSETGET (8, len, ccd);
11809 	  CMDSETGET (1, 0x08, lm9811);
11810 	  CMDSYNC (0xC2);
11811 	  CMDSETGET (4, 0x08, commit);
11812 	  COMPLETIONWAIT;
11813 	  CMDGETBUF (4, w, data);
11814 	  if (DBG_LEVEL > 128)
11815 	    {
11816 	      DumpNB (w, 1, data, NULL);
11817 	    }
11818 	  level = 0;
11819 	  for (i = 0; i < w; i++)
11820 	    level += data[i];
11821 	}
11822       /* loop while average >0.5 */
11823       while ((offset > 0) && ((level * 2) / w > 1));
11824       *offBlue = offset;
11825 
11826       /* last color component */
11827       motor[0] = 0x09;
11828       ccd[13] = 0xD0 | (ccd[13] & 0x0F);
11829 
11830       offset = 0x10;
11831       do
11832 	{
11833 	  offset--;
11834 
11835 	  /* sets for the current offset */
11836 	  motor[11] = offset << 4;
11837 	  lm9811[7] = offset << 4;
11838 
11839 	  /* sends commands */
11840 	  CMDSYNC (0x00);
11841 	  CMDSETGET (2, 0x10, motor);
11842 	  CMDSETGET (8, len, ccd);
11843 	  CMDSETGET (1, 0x08, lm9811);
11844 	  CMDSYNC (0xC2);
11845 	  CMDSYNC (0x00);
11846 	  CMDSETGET (4, 0x08, commit);
11847 
11848 	  COMPLETIONWAIT;
11849 	  CMDGETBUF (4, w, data);
11850 	  if (gMode == UMAX_PP_PARPORT_EPP)
11851 	    {
11852 	      CMDSYNC (0x00);
11853 	    }
11854 	  if (DBG_LEVEL > 128)
11855 	    {
11856 	      DumpNB (w, 1, data, NULL);
11857 	    }
11858 	  level = 0;
11859 	  for (i = 0; i < w; i++)
11860 	    level += data[i];
11861 	}
11862       /* loop while average >0.5 */
11863       while ((offset > 0) && ((level * 2) / w > 1));
11864       *offRed = offset;
11865     }
11866   else
11867     {
11868       *offRed = 0x0F;
11869       *offBlue = 0x0F;
11870     }
11871 
11872   return 1;
11873 }
11874 
11875 /*
11876  * generic offset calibration function
11877  */
11878 static int
offsetCalibration(int color, int *dcRed, int *dcGreen, int *dcBlue)11879 offsetCalibration (int color, int *dcRed, int *dcGreen, int *dcBlue)
11880 {
11881   if (sanei_umax_pp_getastra () <= 610)
11882     {
11883       if (offsetCalibration610p (color, dcRed, dcGreen, dcBlue) == 0)
11884 	{
11885 	  DBG (0, "offsetCalibration610p failed !!! (%s:%d)\n", __FILE__,
11886 	       __LINE__);
11887 	  return 0;
11888 	}
11889       DBG (16, "offsetCalibration610p(%d=>%d,%d,%d) passed ... (%s:%d)\n",
11890 	   color, *dcRed, *dcGreen, *dcBlue, __FILE__, __LINE__);
11891     }
11892   else
11893     {
11894       if (offsetCalibration1220p (color, dcRed, dcGreen, dcBlue) == 0)
11895 	{
11896 	  DBG (0, "offsetCalibration1220p failed !!! (%s:%d)\n", __FILE__,
11897 	       __LINE__);
11898 	  return 0;
11899 	}
11900       DBG (16, "offsetCalibration1220p(%d=>%d,%d,%d) passed ... (%s:%d)\n",
11901 	   color, *dcRed, *dcGreen, *dcBlue, __FILE__, __LINE__);
11902     }
11903   return 1;
11904 }
11905 
11906 /*
11907  * computes Video Gain Amplifier : LM9811 can corrects up to 3dB of
11908  * light variation. So we must adjust VGA so that dynamic range is
11909  * within 3db. It is achieved when min white pixel >= max white pixel / 2.8
11910  * So we scan a white area and decrease gain until this condition is met.
11911  * returns 1 and VGA values in the corresponding vars on success .
11912  * On failure, returns 0.
11913  */
11914 static int
coarseGainCalibration610p(int color, int dcRed, int dcGreen, int dcBlue, int *vgaRed, int *vgaGreen, int *vgaBlue)11915 coarseGainCalibration610p (int color, int dcRed, int dcGreen, int dcBlue,
11916 			   int *vgaRed, int *vgaGreen, int *vgaBlue)
11917 {
11918   int motor[17] = {
11919     0x11, 0x00, 0x00, 0x70, 0x00, 0x00, 0xC0, 0x2F,
11920     0x17, 0x00, 0xFF, 0xAF, 0xAA, 0x6A, 0xA4, 0x00,
11921     -1
11922   };
11923 
11924   int ccd[37] = {
11925     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11926     0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00,
11927     0x76, 0x41, 0xE0, 0xAC, 0x06, 0x00, 0x00, 0x9C,
11928     0x4A, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
11929     0xDF, 0x13, 0x1A, 0x00,
11930     -1
11931   };
11932 
11933   /*
11934    * lm9811[7]= VGA << 4
11935    * lm9811[6]= 0x40 | DC offset
11936    */
11937   int lm9811[9] = {
11938     0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x40, 0xF0,
11939     -1
11940   };
11941 
11942   int commit[9] = {
11943     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
11944     -1
11945   };
11946 
11947   unsigned char data[5400];
11948   int i, len;
11949   int w, xstart, xend;
11950   int min, max;
11951 
11952   TRACE (16, "entering coarseGainCalibration610p ...\n");
11953   if (sanei_umax_pp_getastra () < 1220)
11954     {
11955       w = 2700;
11956       len = 0x22;
11957     }
11958   else
11959     {
11960       w = 5400;
11961       len = 0x24;
11962     }
11963 
11964   /* move back to desired area */
11965   MOVE (-69, PRECISION_OFF, NULL);
11966 
11967   /* first scan : taking a reference full width scan to
11968    * find usable full width of the CCD
11969    */
11970   *vgaRed = 0x08;
11971   *vgaGreen = 0x00;
11972   *vgaBlue = 0x00;
11973 
11974   /* scanning red component -> h=1 */
11975   motor[0] = 0x01;
11976   motor[13] = 0xAA;		/* will be 6A below */
11977 
11978   encodeDC (dcRed, dcGreen, dcBlue, motor);
11979   encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor);
11980 
11981   lm9811[7] = dcRed << 4;
11982   lm9811[6] = 0x40 | *vgaRed;
11983 
11984   CMDSYNC (0x00);
11985   CMDSETGET (2, 0x10, motor);
11986   CMDSETGET (8, len, ccd);
11987   CMDSETGET (1, 0x08, lm9811);
11988   CMDSYNC (0xC2);
11989   CMDSETGET (4, 0x08, commit);
11990 
11991   COMPLETIONWAIT;
11992   CMDGETBUF (4, w, data);
11993   if (gMode == UMAX_PP_PARPORT_EPP)
11994     {
11995       CMDSYNC (0x00);
11996     }
11997   if (DBG_LEVEL > 128)
11998     {
11999       DumpNB (w, 1, data, NULL);
12000     }
12001 
12002   /* find usable CCD area */
12003   i = 0;
12004   while ((i < w) && (data[i] <= (targetCode * 2) / 5))
12005     i++;
12006   xstart = i;
12007   i = w - 1;
12008   while ((i > 0) && (data[i] <= (targetCode * 2) / 5))
12009     i--;
12010   xend = i;
12011   DBG (32, "coarseGainCalibration610p: xstart=%d, xend=%d ->left=%d\n",
12012        xstart, xend, ((xend + xstart - w) / 2));
12013   /* choose best 'left' position */
12014   sanei_umax_pp_setLeft ((xend + xstart - w) / 2);
12015 
12016   /* now do VGA calibration for green (=B&W channel) */
12017   motor[0] = 0x11;
12018   motor[13] = 0x60 | (motor[13] & 0x0F);
12019 
12020   *vgaRed = 0x0F;
12021   *vgaGreen = 0x0F;
12022   *vgaBlue = 0x0F;
12023 
12024   for (*vgaGreen = 0x0F; *vgaGreen > 0; (*vgaGreen)--)
12025     {
12026       encodeDC (dcRed, dcGreen, dcBlue, motor);
12027       encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor);
12028 
12029       lm9811[7] = dcGreen << 4;
12030       lm9811[6] = 0x40 | *vgaGreen;
12031 
12032       CMDSETGET (2, 0x10, motor);
12033       CMDSETGET (8, len, ccd);
12034       CMDSETGET (1, 0x08, lm9811);
12035       CMDSYNC (0xC2);
12036       CMDSYNC (0x00);
12037       CMDSETGET (4, 0x08, commit);
12038 
12039       COMPLETIONWAIT;
12040       CMDGETBUF (4, w, data);
12041       if (gMode == UMAX_PP_PARPORT_EPP)
12042 	{
12043 	  CMDSYNC (0x00);
12044 	}
12045 
12046       if (DBG_LEVEL > 128)
12047 	{
12048 	  DumpNB (w, 1, data, NULL);
12049 	}
12050 
12051       min = 0xFF;
12052       max = 0x00;
12053       for (i = xstart; i <= xend; i++)
12054 	{
12055 	  if (data[i] < min)
12056 	    min = data[i];
12057 	  if (data[i] > max)
12058 	    max = data[i];
12059 	}
12060       if ((max <= targetCode) && (min > (((float) targetCode) / 2.8)))
12061 	break;
12062       DBG (32, "coarseGainCalibration610p, target/2.8=%f\n",
12063 	   (((float) targetCode) / 2.8));
12064       DBG (32, "coarseGainCalibration610p, green: min=%d, max=%d\n", min,
12065 	   max);
12066     }
12067 
12068   if (color >= RGB_MODE)
12069     {
12070       motor[0] = 0x01;
12071       motor[13] = 0xA0 | (motor[13] & 0x0F);
12072 
12073       for (*vgaBlue = 0x0F; *vgaBlue > 0; (*vgaBlue)--)
12074 	{
12075 	  encodeDC (dcRed, dcGreen, dcBlue, motor);
12076 	  encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor);
12077 
12078 	  lm9811[7] = dcBlue << 4;
12079 	  lm9811[6] = 0x40 | *vgaBlue;
12080 
12081 	  CMDSETGET (2, 0x10, motor);
12082 	  CMDSETGET (8, len, ccd);
12083 	  CMDSETGET (1, 0x08, lm9811);
12084 	  CMDSYNC (0xC2);
12085 	  CMDSYNC (0x00);
12086 	  CMDSETGET (4, 0x08, commit);
12087 
12088 	  COMPLETIONWAIT;
12089 	  CMDGETBUF (4, w, data);
12090 	  if (gMode == UMAX_PP_PARPORT_EPP)
12091 	    {
12092 	      CMDSYNC (0x00);
12093 	    }
12094 
12095 	  if (DBG_LEVEL > 128)
12096 	    {
12097 	      DumpNB (w, 1, data, NULL);
12098 	    }
12099 
12100 	  min = 0xFF;
12101 	  max = 0x00;
12102 	  for (i = xstart; i <= xend; i++)
12103 	    {
12104 	      if (data[i] < min)
12105 		min = data[i];
12106 	      if (data[i] > max)
12107 		max = data[i];
12108 	    }
12109 	  if ((max <= targetCode) && (min > (((float) targetCode) / 2.8)))
12110 	    break;
12111 	  DBG (32, "coarseGainCalibration610p, blue: min=%d, max=%d\n", min,
12112 	       max);
12113 	}
12114 
12115       motor[0] = 0x09;
12116       motor[13] = 0xE0 | (motor[13] & 0x0F);
12117 
12118       for (*vgaRed = 0x0F; *vgaRed > 0; (*vgaRed)--)
12119 	{
12120 	  encodeDC (dcRed, dcGreen, dcBlue, motor);
12121 	  encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor);
12122 
12123 	  lm9811[7] = dcRed << 4;
12124 	  lm9811[6] = 0x40 | *vgaRed;
12125 
12126 	  CMDSETGET (2, 0x10, motor);
12127 	  CMDSETGET (8, len, ccd);
12128 	  CMDSETGET (1, 0x08, lm9811);
12129 	  CMDSYNC (0xC2);
12130 	  CMDSYNC (0x00);
12131 	  CMDSETGET (4, 0x08, commit);
12132 
12133 	  COMPLETIONWAIT;
12134 	  CMDGETBUF (4, w, data);
12135 	  if (gMode == UMAX_PP_PARPORT_EPP)
12136 	    {
12137 	      CMDSYNC (0x00);
12138 	    }
12139 
12140 	  if (DBG_LEVEL > 128)
12141 	    {
12142 	      DumpNB (w, 1, data, NULL);
12143 	    }
12144 
12145 	  min = 0xFF;
12146 	  max = 0x00;
12147 	  for (i = xstart; i <= xend; i++)
12148 	    {
12149 	      if (data[i] < min)
12150 		min = data[i];
12151 	      if (data[i] > max)
12152 		max = data[i];
12153 	    }
12154 	  if ((max <= targetCode) && (min > (((float) targetCode) / 2.8)))
12155 	    break;
12156 	  DBG (32, "coarseGainCalibration610p, red: min=%d, max=%d\n", min,
12157 	       max);
12158 	}
12159     }
12160   else
12161     {
12162       *vgaRed = 0x0F;
12163       *vgaBlue = 0x0F;
12164     }
12165 
12166   TRACE (16, "coarseGainCalibration610p end ...\n");
12167   return 1;
12168 }
12169 
12170 /* same as above, but for 1220P/1600P/200P */
12171 static int
coarseGainCalibration1220p(int color, int dcRed, int dcGreen, int dcBlue, int *vgaRed, int *vgaGreen, int *vgaBlue)12172 coarseGainCalibration1220p (int color, int dcRed, int dcGreen,
12173 			    int dcBlue, int *vgaRed, int *vgaGreen,
12174 			    int *vgaBlue)
12175 {
12176   unsigned char buffer[5300];
12177   int i;
12178   double sum;
12179   int xstart = 540;
12180   int xend = 5100;
12181   int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 };
12182   int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 };
12183   int opsc10[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x08, 0x00, -1 };
12184   int opsc18[17] =
12185     { 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0x88, 0x08,
12186     0x00, 0x80, 0xA4, 0x00, -1
12187   };
12188   int opsc39[37] =
12189     { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
12190     0x00, 0x00, 0x04, 0x00, 0x6E, 0x41, 0x20, 0x24, 0x06, 0x00, 0x00, 0x00,
12191     0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00,
12192     -1
12193   };
12194   int opsc40[37] =
12195     { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
12196     0x00, 0x00, 0x04, 0x00, 0x6E, 0x41, 0x60, 0x4F, 0x06, 0x00, 0x00, 0x00,
12197     0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1A, 0x00,
12198     -1
12199   };
12200   int motor[17] =
12201     { 0x09, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0xA5, 0x09,
12202     0x00, 0x40, 0xA4, 0x00, -1
12203   };
12204 
12205   DBG (16, "entering coarseGainCalibration1220p() ... (%s:%d) \n", __FILE__,
12206        __LINE__);
12207 
12208   /* temporary workaround */
12209   color = RGB_MODE;
12210 
12211   /* initialize VGA components */
12212   *vgaGreen = 0;
12213   *vgaRed = 2;
12214   *vgaBlue = 2;
12215 
12216   CMDSETGET (2, 0x10, opsc18);
12217   CMDSETGET (8, 0x24, opsc39);
12218   opsc04[7] = opsc04[7] & 0x20;
12219   opsc04[6] = 0x06;		/* one channel gain value */
12220   CMDSETGET (1, 0x08, opsc10);	/* was opsc04, extraneaous string */
12221   /* that prevents using move .... */
12222   CMDSYNC (0xC2);
12223   CMDSYNC (0x00);
12224   CMDSETGET (4, 0x08, commit);
12225   COMPLETIONWAIT;
12226   CMDGETBUF (4, 0x200, buffer);
12227   if (DBG_LEVEL >= 128)
12228     Dump (0x200, buffer, NULL);
12229 
12230 
12231   /* auto correction of gain levels */
12232   /* first color component X        */
12233   if (color >= RGB_MODE)
12234     {
12235       if (sanei_umax_pp_getastra () == 1600)
12236 	{
12237 	  motor[11] |= 0x20;
12238 	  motor[12] = 0x08;
12239 	  motor[13] |= 0x02;
12240 
12241 	  opsc04[7] |= 0x20;
12242 	}
12243       encodeDC (dcRed, dcGreen, dcBlue, motor);
12244       encodeVGA (*vgaRed, 0, 0, motor);
12245       CMDSETGET (2, 0x10, motor);
12246       CMDSETGET (8, 0x24, opsc40);
12247       if (DBG_LEVEL >= 128)
12248 	{
12249 	  bloc2Decode (motor);
12250 	  bloc8Decode (opsc40);
12251 	}
12252       opsc04[6] = *vgaRed;
12253       CMDSETGET (1, 0x08, opsc04);
12254       CMDSYNC (0xC2);
12255       CMDSYNC (0x00);
12256       CMDSETGET (4, 0x08, commit);
12257       COMPLETIONWAIT;
12258       CMDGETBUF (4, 0x14B4, buffer);
12259       if (DBG_LEVEL >= 128)
12260 	Dump (0x14B4, buffer, NULL);
12261       sum = 0;
12262       for (i = xstart; i < xend; i++)
12263 	sum += buffer[i];
12264       sum = sum / (xend - xstart);
12265       while ((opsc04[6] < 0x0F) && (sum < 140))
12266 	{
12267 	  CMDSYNC (0x00);
12268 	  opsc04[6]++;
12269 	  CMDSETGET (1, 0x000008, opsc04);
12270 	  COMPLETIONWAIT;
12271 	  CMDGETBUF (4, 0x0014B4, buffer);
12272 	  if (DBG_LEVEL >= 128)
12273 	    Dump (0x14B4, buffer, NULL);
12274 	  sum = 0;
12275 	  for (i = xstart; i < xend; i++)
12276 	    sum += buffer[i];
12277 	  sum = sum / (xend - xstart);
12278 	}
12279       *vgaRed = opsc04[6];
12280 
12281       /* blue */
12282       encodeDC (dcRed, dcGreen, dcBlue, motor);
12283       encodeVGA (0, 0, *vgaBlue, motor);
12284       if (sanei_umax_pp_getastra () == 1600)
12285 	{
12286 	  motor[11] |= 0x20;
12287 	  motor[12] = 0x08;
12288 	  motor[13] |= 0x02;
12289 
12290 	  opsc04[7] |= 0x20;
12291 	}
12292       CMDSETGET (2, 0x10, motor);
12293       CMDSETGET (8, 0x24, opsc40);
12294       opsc04[6] = *vgaBlue;
12295       CMDSETGET (1, 0x08, opsc04);
12296       CMDSYNC (0xC2);
12297       CMDSYNC (0x00);
12298       CMDSETGET (4, 0x08, commit);
12299       COMPLETIONWAIT;
12300       CMDGETBUF (4, 0x14B4, buffer);
12301       if (DBG_LEVEL >= 128)
12302 	Dump (0x14B4, buffer, NULL);
12303       sum = 0;
12304       for (i = xstart; i < xend; i++)
12305 	sum += buffer[i];
12306       sum = sum / (xend - xstart);
12307       while ((opsc04[6] < 0x0F) && (sum < 140))
12308 	{
12309 	  CMDSYNC (0x00);
12310 	  opsc04[6]++;
12311 	  CMDSETGET (1, 0x08, opsc04);
12312 	  COMPLETIONWAIT;
12313 	  CMDGETBUF (4, 0x14B4, buffer);
12314 	  if (DBG_LEVEL >= 128)
12315 	    Dump (0x14B4, buffer, NULL);
12316 	  sum = 0;
12317 	  for (i = xstart; i < xend; i++)
12318 	    sum += buffer[i];
12319 	  sum = sum / (xend - xstart);
12320 	}
12321       *vgaBlue = opsc04[6];
12322     }
12323 
12324 
12325   /* component Z: B&W component (green ...) */
12326   encodeDC (dcRed, dcGreen, dcBlue, motor);
12327   encodeVGA (0, *vgaGreen, 0, motor);
12328   if (color < RGB_MODE)
12329     motor[0] = 0x01;		/* in BW, scan zone doesn't have an extra 4 points */
12330   else
12331     motor[0] = 0x05;		/*  extra 4 points */
12332   motor[13] = 0xC0;		/* B&W */
12333   if (sanei_umax_pp_getastra () == 1600)
12334     {
12335       motor[11] |= 0x20;
12336       motor[12] = 0x08;
12337       motor[13] |= 0x02;
12338 
12339       opsc04[7] |= 0x20;
12340     }
12341   CMDSETGET (2, 0x10, motor);
12342   if (DBG_LEVEL >= 128)
12343     {
12344       bloc2Decode (motor);
12345     }
12346   CMDSETGET (8, 0x24, opsc40);
12347   opsc04[6] = *vgaGreen;
12348   CMDSETGET (1, 0x08, opsc04);
12349   CMDSYNC (0xC2);
12350   CMDSYNC (0x00);
12351   CMDSETGET (4, 0x08, commit);
12352   COMPLETIONWAIT;
12353   /* B&W hangs here XXX STEF XXX */
12354   CMDGETBUF (4, 0x14B4, buffer);
12355   if (DBG_LEVEL >= 128)
12356     Dump (0x14B4, buffer, NULL);
12357   sum = 0;
12358   for (i = xstart; i < xend; i++)
12359     sum += buffer[i];
12360   sum = sum / (xend - xstart);
12361   while ((opsc04[6] < 0x07) && (sum < 110))
12362     {
12363       CMDSYNC (0x00);
12364       opsc04[6]++;
12365       CMDSETGET (1, 0x08, opsc04);
12366       COMPLETIONWAIT;
12367       CMDGETBUF (4, 0x0014B4, buffer);
12368       if (DBG_LEVEL >= 128)
12369 	Dump (0x14B4, buffer, NULL);
12370       sum = 0;
12371       for (i = xstart; i < xend; i++)
12372 	sum += buffer[i];
12373       sum = sum / (xend - xstart);
12374     }
12375   *vgaGreen = opsc04[6];
12376   DBG (1, "coarseGainCalibration1220p()=%d,%d,%d done ...\n", *vgaRed,
12377        *vgaGreen, *vgaBlue);
12378   return 1;
12379 }
12380 
12381 /*
12382  * generic function
12383  */
12384 static int
coarseGainCalibration(int color, int dcRed, int dcGreen, int dcBlue, int *vgaRed, int *vgaGreen, int *vgaBlue)12385 coarseGainCalibration (int color, int dcRed, int dcGreen, int dcBlue,
12386 		       int *vgaRed, int *vgaGreen, int *vgaBlue)
12387 {
12388   if (sanei_umax_pp_getastra () <= 610)
12389     {
12390       if (coarseGainCalibration610p
12391 	  (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue) == 0)
12392 	{
12393 	  DBG (0, "coarseGainCalibration610p failed !!! (%s:%d)\n", __FILE__,
12394 	       __LINE__);
12395 	  return 0;
12396 	}
12397       DBG (16,
12398 	   "coarseGainCalibration610p passed ... (%s:%d)\n", __FILE__,
12399 	   __LINE__);
12400     }
12401   else
12402     {
12403       if (coarseGainCalibration1220p
12404 	  (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue) == 0)
12405 	{
12406 	  DBG (0, "coarseGainCalibration1220p failed !!! (%s:%d)\n", __FILE__,
12407 	       __LINE__);
12408 	  return 0;
12409 	}
12410       DBG (16,
12411 	   "coarseGainCalibration1220p passed ... (%s:%d)\n", __FILE__,
12412 	   __LINE__);
12413     }
12414   return 1;
12415 }
12416 
12417 /*
12418  * computes PGA offset for each pixel of the ccd.
12419  * We scan a white area with PGA=0 and computes the
12420  * offset to push the result in the correctable range
12421  * returns 1 and PGA values in 'calibration' var on success .
12422  * On failure, returns 0.
12423  */
12424 static int
shadingCalibration610p(int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration)12425 shadingCalibration610p (int color, int dcRed, int dcGreen, int dcBlue,
12426 			int vgaRed, int vgaGreen, int vgaBlue,
12427 			int *calibration)
12428 {
12429   int motor[17] = {
12430     0x5A, 0x80, 0x02, 0x70, 0x00, 0x00, 0xC0, 0x00,
12431     0x17, 0x05, 0x6C, 0xAB, 0xAA, 0x2A, 0xA4, 0x00,
12432     -1
12433   };
12434 
12435   int ccd[37] = {
12436     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
12437     0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00,
12438     0x76, 0x5D, 0x40, 0xA5, 0x06, 0x00, 0x00, 0xE2,
12439     0x5E, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
12440     0xDF, 0x13, 0x1A, 0x00,
12441     -1
12442   };
12443 
12444   /*
12445    * lm9811[7]= VGA << 4
12446    * lm9811[6]= 0x40 | DC offset
12447    */
12448   int lm9811[9] = {
12449     0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x0F, 0x80,
12450     -1
12451   };
12452 
12453   int commit[9] = {
12454     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
12455     -1
12456   };
12457 
12458   int len, dpi, size;
12459   int bpp = 3;			/* defaults to color scan value */
12460   int w, h, x, y;
12461   int sum, i;
12462   float avg, pct, coeff = 0;
12463   unsigned char *data = NULL;
12464   int top, bottom;
12465 
12466   TRACE (16, "entering shadingCalibration610p ...\n");
12467   len = 0x22;
12468   w = 2550;
12469   y = 10;
12470   dpi = 300;
12471   h = 90;
12472   top = 8;
12473   bottom = 8;
12474 
12475   /* move back first */
12476   MOVE (-31, PRECISION_OFF, NULL);
12477 
12478   /* gray scanning handling */
12479   if (color < RGB_MODE)
12480     {
12481       lm9811[7] = dcGreen << 4;
12482       lm9811[6] = 0x40 | vgaGreen;
12483       bpp = 1;
12484 
12485       motor[13] = 0x6F;
12486     }
12487 
12488   data = (unsigned char *) malloc (w * h * bpp);
12489   if (data == NULL)
12490     {
12491       DBG (0, "shadingCalibration610p: failed to allocate memory (%s:%d)\n",
12492 	   __FILE__, __LINE__);
12493       return 0;
12494     }
12495   memset (data, 0x00, w * h * bpp);
12496 
12497   /* prepare scan command */
12498   x = sanei_umax_pp_getLeft ();
12499   encodeWX (w, x, dpi, color, ccd, bpp * w);
12500   encodeHY (h, y, motor);
12501   encodeDC (dcRed, dcGreen, dcBlue, motor);
12502   encodeVGA (vgaRed, vgaGreen, vgaBlue, motor);
12503   if (DBG_LEVEL > 128)
12504     {
12505       bloc2Decode (motor);
12506       bloc8Decode (ccd);
12507     }
12508 
12509   CMDSYNC (0x00);
12510   CMDSETGET (2, 0x10, motor);
12511   CMDSETGET (8, len, ccd);
12512   CMDSETGET (1, 0x08, lm9811);
12513   CMDSYNC (0xC2);
12514   CMDSETGET (4, 0x08, commit);
12515   COMPLETIONWAIT;
12516 
12517   /* picture height is scan area height minus y          */
12518   /* then we subtract 14 or 6 lines that aren't scanned  */
12519   if (color < RGB_MODE)
12520     h = h - y - 14;
12521   else
12522     h = h - y - 6;
12523   size = w * bpp * h;
12524 
12525   DBG (128,
12526        "shadingCalibration610p: trying to read 0x%06X bytes ... (%s:%d)\n",
12527        size, __FILE__, __LINE__);
12528   /* since we know that each scan line matches CCD width, we signals
12529    * that data reading doesn't need to sync on each byte, but at each
12530    * row end
12531    */
12532   sanei_umax_pp_setfull (1);
12533   CMDGETBUF (4, size, data);
12534   sanei_umax_pp_setfull (0);
12535 
12536   /* computes correction here ... */
12537   /* debug image files */
12538   /* data is in R B G order */
12539   if (DBG_LEVEL > 128)
12540     DumpNB (w * bpp, h, data, NULL);
12541 
12542   /* zeroes all shading coefficients first */
12543   memset (calibration, 0x00, 3 * w * sizeof (int));
12544 
12545   /* in gray scans, we have only green component (i=3) */
12546   if (color < RGB_MODE)
12547     {
12548 
12549       /* build green only coefficients */
12550       for (x = 4; x < w; x++)
12551 	{
12552 	  sum = 0;
12553 	  for (y = top; y < h - bottom; y++)
12554 	    sum += data[(y * bpp) * w + x];
12555 	  avg = ((float) (sum)) / ((float) (h - (top + bottom)));
12556 	  /* XXX ICI XXX avg=128==>2 */
12557 	  /*coeff = (256.0 * (targetCode / avg - 1.0)) / 2.00;*/
12558 	  coeff = (256.0 * (targetCode / avg - 1.0)) / ((avg*3.5)/targetCode);
12559 	  if (coeff < 0)
12560 	    coeff = 0;
12561 	  if (coeff > 255)
12562 	    coeff = 255;
12563 	  calibration[x + 2 * w - 4] = (int) (coeff + 0.5);
12564 	}
12565     }
12566   else
12567     {
12568       for (i = 0; i < 3; i++)
12569 	{
12570 	  for (x = 4; x < w; x++)
12571 	    {
12572 	      sum = 0;
12573 	      for (y = top; y < h - bottom; y++)
12574 		sum += data[(y * bpp + i) * w + x];
12575 	      avg = ((float) (sum)) / ((float) (h - (top + bottom)));
12576 	      /* one step increase means a 0.71% increase of the final
12577 	         pixel */
12578 	      pct = 100.0 - (avg * 100.0) / targetCode;
12579 	      switch (i)
12580 		{
12581 		case 0:	/* RED  1.80 */
12582 		case 1:	/* BLUE : 2.10 */
12583 		  coeff = (int) (pct / 0.57 + 0.5);
12584 		  break;
12585 		case 2:	/* GREEN 1.50 */
12586 		  coeff = (int) (pct / 0.45 + 0.5);
12587 		  break;
12588 		}
12589 	      if (coeff < 0)
12590 		coeff = 0;
12591 	      if (coeff > 255)
12592 		coeff = 255;
12593 	      calibration[x + i * w - 4] = (int) (coeff + 0.5);
12594 	    }
12595 	  /* 100 in coeffs -> +104 on picture */
12596 	}
12597     }
12598 
12599   /* use default color tables */
12600   for (x = 0; x < 256; x++)
12601     {
12602       calibration[3 * w + x] = ggRed[x];
12603       calibration[3 * w + x + 256] = ggGreen[x];
12604       calibration[3 * w + x + 512] = ggBlue[x];
12605     }
12606 
12607   if (DBG_LEVEL > 128)
12608     {
12609       DumpNB (w * bpp, h, data, NULL);
12610       DumpNB (w, h * bpp, data, NULL);
12611     }
12612 
12613   free (data);
12614   TRACE (16, "shadingCalibration610p end ...\n");
12615   return 1;
12616 }
12617 
12618 /*
12619  * build CCD correction: a white area below the top is scanned without
12620  * correction, and the data are used to compute the coefficients needed
12621  * to correct the light/CCD variations
12622  */
12623 static int
shadingCalibration(int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration)12624 shadingCalibration (int color, int dcRed, int dcGreen, int dcBlue,
12625 		    int vgaRed, int vgaGreen, int vgaBlue, int *calibration)
12626 {
12627   if (sanei_umax_pp_getastra () < 1220)
12628     return shadingCalibration610p (color, dcRed, dcGreen, dcBlue, vgaRed,
12629 				   vgaGreen, vgaBlue, calibration);
12630   return shadingCalibration1220p (color, dcRed, dcGreen, dcBlue, vgaRed,
12631 				  vgaGreen, vgaBlue, calibration);
12632 }
12633 
12634 
12635 /*
12636  * this is certainly gamma calibration
12637  * We scan a white area with PGA=0 and computes the
12638  * offset to push the result in the correctable range
12639  * returns 1 and PGA values in 'calibration' var on success .
12640  * On failure, returns 0.
12641  */
12642 static int
leftShadingCalibration610p(int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration)12643 leftShadingCalibration610p (int color, int dcRed, int dcGreen, int dcBlue,
12644 			    int vgaRed, int vgaGreen, int vgaBlue,
12645 			    int *calibration)
12646 {
12647   int motor[17] = {
12648     0x14, 0x80, 0x02, 0x60, 0xDE, 0x01, 0xC0, 0x2F,
12649     0x17, 0x00, 0x6C, 0xAB, 0xAA, 0x2A, 0xA4, 0x00,
12650     -1
12651   };
12652 
12653   int ccd[37] = {
12654     0x00, 0x00, 0xD8, 0x27, 0xEC, 0x53, 0x7D, 0x8A,
12655     0x77, 0xE3, 0x1D, 0x79, 0x07, 0x20, 0x02, 0x00,
12656     0x76, 0x41, 0x80, 0xA3, 0xE5, 0x1D, 0x00, 0xF2,
12657     0x5D, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
12658     0xDF, 0x13, 0x1A, 0x00,
12659     -1
12660   };
12661 
12662   /*
12663    * lm9811[7]= VGA << 4
12664    * lm9811[6]= 0x40 | DC offset
12665    * lm9811[6].bit7 = use shading data
12666    */
12667   int lm9811[9] = {
12668     0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x8F, 0x80,
12669     -1
12670   };
12671 
12672   int *commit = NULL;
12673 
12674   int len, dpi, size;
12675   int w, h, x, y;
12676   int ofst;
12677   unsigned char *data = NULL;
12678 
12679   TRACE (16, "entering leftShadingCalibration610p ...\n");
12680   if (sanei_umax_pp_getastra () < 1220)
12681     {
12682       len = 0x22;
12683       ofst = 28;
12684       w = 2550;
12685       x = 94 - ofst;		/* left shift compared to shading calibration */
12686       y = 10;
12687       dpi = 75;
12688       h = 20;
12689     }
12690   else
12691     {
12692       len = 0x24;
12693       ofst = 28;
12694       w = 5100;
12695       x = 180;
12696       y = 10;
12697       dpi = 600;
12698       h = 67;
12699     }
12700 
12701   commit = (int *) malloc ((w * 3 + 5) * sizeof (int));
12702   if (commit == NULL)
12703     {
12704       DBG (0,
12705 	   "leftShadingCalibration610p: failed to allocate memory (%s:%d)\n",
12706 	   __FILE__, __LINE__);
12707       return 0;
12708     }
12709 
12710   data = (unsigned char *) malloc (w * h * 3);
12711   if (data == NULL)
12712     {
12713       DBG (0,
12714 	   "leftShadingCalibration610p: failed to allocate memory (%s:%d)\n",
12715 	   __FILE__, __LINE__);
12716       free (commit);
12717       return 0;
12718     }
12719 
12720   /* prepare scan command */
12721   encodeWX (w, x, dpi, color, ccd, 7410);
12722   encodeHY (h, y, motor);
12723   encodeDC (dcRed, dcGreen, dcBlue, motor);
12724   encodeVGA (vgaRed, vgaGreen, vgaBlue, motor);
12725   if (DBG_LEVEL > 128)
12726     {
12727       bloc2Decode (motor);
12728       bloc8Decode (ccd);
12729     }
12730 
12731   /* build shading calibration data */
12732   memset (commit, 0x00, (3 * w + 5) * sizeof (int));
12733   for (x = ofst; x < w; x++)
12734     {
12735       commit[x] = calibration[x - ofst];
12736       commit[x + w] = calibration[x - ofst + w];
12737       commit[x + 2 * w] = calibration[x - ofst + 2 * w];
12738     }
12739   /* image data cropping coefficient  */
12740   commit[3 * w + 3] = 0xFF;
12741   commit[3 * w + 4] = 0xFF;
12742 
12743   CMDSYNC (0x00);
12744   CMDSETGET (2, 0x10, motor);
12745   CMDSETGET (8, len, ccd);
12746   CMDSETGET (1, 0x08, lm9811);
12747   CMDSYNC (0xC2);
12748   CMDSETGET (4, 3 * w + 5, commit);
12749   free (commit);
12750   COMPLETIONWAIT;
12751 
12752   if (color >= RGB_MODE)
12753     {
12754       /* picture height is scan area height minus y    */
12755       h = h - y;
12756       size = w * 3 * h;
12757     }
12758   else
12759     {
12760       h = h - y - 1;
12761       size = w * h;
12762     }
12763   DBG (128,
12764        "leftShadingCalibration610p: trying to read 0x%06X bytes ... (%s:%d)\n",
12765        size, __FILE__, __LINE__);
12766   CMDGETBUF (4, size, data);
12767   if (DBG_LEVEL > 128)
12768     DumpNB (3 * w, h, data, NULL);
12769 
12770   /* XXX STEF XXX */
12771   /* build coefficients for the 25 left pixels */
12772   /* and compute gamma correction ?            */
12773 
12774   free (data);
12775   TRACE (16, "leftShadingCalibration610p end ...\n");
12776   return 1;
12777 }
12778