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