1141cc406Sopenharmony_ci/**
2141cc406Sopenharmony_ci   Copyright (C) 2001-2012 Stéphane Voltz <stef.dev@free.fr>
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
38141cc406Sopenharmony_ci
39141cc406Sopenharmony_ci   This file implements a SANE backend for Umax PP flatbed scanners.  */
40141cc406Sopenharmony_ci
41141cc406Sopenharmony_ci#undef BACKEND_NAME
42141cc406Sopenharmony_ci#define BACKEND_NAME umax_pp_low
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci#include "../include/sane/config.h"
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci#include <stdio.h>
47141cc406Sopenharmony_ci#include <stdlib.h>
48141cc406Sopenharmony_ci#include <string.h>
49141cc406Sopenharmony_ci#include <math.h>
50141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
51141cc406Sopenharmony_ci#include <sys/time.h>
52141cc406Sopenharmony_ci#endif
53141cc406Sopenharmony_ci#ifdef HAVE_SYS_TYPES_H
54141cc406Sopenharmony_ci#include <sys/types.h>
55141cc406Sopenharmony_ci#endif
56141cc406Sopenharmony_ci#include "../include/sane/sanei_directio.h"
57141cc406Sopenharmony_ci#ifdef HAVE_UNISTD_H
58141cc406Sopenharmony_ci#include <unistd.h>
59141cc406Sopenharmony_ci#endif
60141cc406Sopenharmony_ci#ifdef HAVE_FCNTL_H
61141cc406Sopenharmony_ci#include <fcntl.h>
62141cc406Sopenharmony_ci#endif
63141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h"
64141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
65141cc406Sopenharmony_ci#include <errno.h>
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_ci#ifdef HAVE_DEV_PPBUS_PPI_H
68141cc406Sopenharmony_ci#include <dev/ppbus/ppi.h>
69141cc406Sopenharmony_ci#include <dev/ppbus/ppbconf.h>
70141cc406Sopenharmony_ci#endif
71141cc406Sopenharmony_ci
72141cc406Sopenharmony_ci#ifdef HAVE_MACHINE_CPUFUNC_H
73141cc406Sopenharmony_ci#include <machine/cpufunc.h>
74141cc406Sopenharmony_ci#endif
75141cc406Sopenharmony_ci
76141cc406Sopenharmony_ci#ifdef HAVE_I386_SET_IOPERM
77141cc406Sopenharmony_ci#include <machine/sysarch.h>
78141cc406Sopenharmony_ci#endif
79141cc406Sopenharmony_ci
80141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
81141cc406Sopenharmony_ci#include <sys/ioctl.h>
82141cc406Sopenharmony_ci#include <linux/parport.h>
83141cc406Sopenharmony_ci#include <linux/ppdev.h>
84141cc406Sopenharmony_ci#endif
85141cc406Sopenharmony_ci
86141cc406Sopenharmony_ci#include "umax_pp_low.h"
87141cc406Sopenharmony_ci
88141cc406Sopenharmony_ci#ifdef DMALLOC
89141cc406Sopenharmony_ci#include "dmalloc.h"
90141cc406Sopenharmony_ci#endif
91141cc406Sopenharmony_ci
92141cc406Sopenharmony_ci#ifndef __IO__
93141cc406Sopenharmony_ci#define __IO__
94141cc406Sopenharmony_ci
95141cc406Sopenharmony_ci#define DATA                   gPort+0x00
96141cc406Sopenharmony_ci#define STATUS                 gPort+0x01
97141cc406Sopenharmony_ci#define CONTROL                gPort+0x02
98141cc406Sopenharmony_ci#define EPPADDR                 gPort+0x03
99141cc406Sopenharmony_ci#define EPPDATA                gPort+0x04
100141cc406Sopenharmony_ci
101141cc406Sopenharmony_ci#define ECPDATA                gPort+0x400
102141cc406Sopenharmony_ci#define ECR		       gPort+0x402
103141cc406Sopenharmony_ci
104141cc406Sopenharmony_ci#define FIFO_WAIT	      1000
105141cc406Sopenharmony_ci#endif
106141cc406Sopenharmony_ci
107141cc406Sopenharmony_cistatic int fonc001 (void);
108141cc406Sopenharmony_cistatic int foncSendWord (int *cmd);
109141cc406Sopenharmony_ci
110141cc406Sopenharmony_cistatic void setEPPMode (int mode);
111141cc406Sopenharmony_cistatic int getEPPMode (void);
112141cc406Sopenharmony_cistatic void setModel (int model);
113141cc406Sopenharmony_cistatic int getModel (void);
114141cc406Sopenharmony_cistatic int ringScanner (int count, unsigned long delay);
115141cc406Sopenharmony_cistatic int testVersion (int no);
116141cc406Sopenharmony_ci
117141cc406Sopenharmony_cistatic int probePS2 (unsigned char *dest);
118141cc406Sopenharmony_cistatic int probeEPP (unsigned char *dest);
119141cc406Sopenharmony_cistatic int probeECP (unsigned char *dest);
120141cc406Sopenharmony_ci
121141cc406Sopenharmony_cistatic int sendCommand (int cmd);
122141cc406Sopenharmony_cistatic void SPPResetLPT (void);
123141cc406Sopenharmony_cistatic int sendWord (int *cmd);
124141cc406Sopenharmony_cistatic int sendData (int *cmd, int len);
125141cc406Sopenharmony_cistatic int receiveData (int *cmd, int len);
126141cc406Sopenharmony_cistatic int sendLength (int *cmd, int len);
127141cc406Sopenharmony_ci
128141cc406Sopenharmony_cistatic int waitAck (void);
129141cc406Sopenharmony_cistatic void init001 (void);
130141cc406Sopenharmony_cistatic int init002 (int arg);
131141cc406Sopenharmony_cistatic int init005 (int arg);
132141cc406Sopenharmony_ci
133141cc406Sopenharmony_ci/* 610p comm functions */
134141cc406Sopenharmony_cistatic int putByte610p (int data);
135141cc406Sopenharmony_cistatic int EPPputByte610p (int data);
136141cc406Sopenharmony_cistatic int sendLength610p (int *cmd);
137141cc406Sopenharmony_cistatic int sendData610p (int *cmd, int len);
138141cc406Sopenharmony_cistatic int receiveData610p (int *cmd, int len);
139141cc406Sopenharmony_cistatic int connect610p (void);
140141cc406Sopenharmony_cistatic int sync610p (void);
141141cc406Sopenharmony_cistatic int cmdSync610p (int cmd);
142141cc406Sopenharmony_cistatic int EPPcmdSync610p (int cmd);
143141cc406Sopenharmony_cistatic int getStatus610p (void);
144141cc406Sopenharmony_cistatic int EPPgetStatus610p (void);
145141cc406Sopenharmony_cistatic int disconnect610p (void);
146141cc406Sopenharmony_cistatic int EPPsendWord610p (int *cmd);
147141cc406Sopenharmony_cistatic int SPPsendWord610p (int *cmd);
148141cc406Sopenharmony_cistatic int cmdSet610p (int cmd, int len, int *buffer);
149141cc406Sopenharmony_cistatic int cmdGet610p (int cmd, int len, int *buffer);
150141cc406Sopenharmony_cistatic int EPPcmdSet610p (int cmd, int len, int *buffer);
151141cc406Sopenharmony_cistatic int EPPcmdGet610p (int cmd, int len, int *buffer);
152141cc406Sopenharmony_cistatic int initScanner610p (int recover);
153141cc406Sopenharmony_cistatic int cmdGetBuffer610p (int cmd, int len, unsigned char *buffer);
154141cc406Sopenharmony_ci
155141cc406Sopenharmony_ci
156141cc406Sopenharmony_ci/* parport mode setting */
157141cc406Sopenharmony_cistatic void compatMode (void);
158141cc406Sopenharmony_cistatic void byteMode (void);
159141cc406Sopenharmony_cistatic void ECPFifoMode (void);
160141cc406Sopenharmony_ci
161141cc406Sopenharmony_ci/* block transfer init */
162141cc406Sopenharmony_cistatic void ECPSetBuffer (int size);
163141cc406Sopenharmony_ci
164141cc406Sopenharmony_ci/* mode dependent operations */
165141cc406Sopenharmony_cistatic int PS2Something (int reg);
166141cc406Sopenharmony_cistatic void PS2bufferRead (int size, unsigned char *dest);
167141cc406Sopenharmony_cistatic void PS2bufferWrite (int size, unsigned char *source);
168141cc406Sopenharmony_cistatic int PS2registerRead (int reg);
169141cc406Sopenharmony_cistatic void PS2registerWrite (int reg, int value);
170141cc406Sopenharmony_ci
171141cc406Sopenharmony_cistatic int EPPconnect (void);
172141cc406Sopenharmony_cistatic int EPPregisterRead (int reg);
173141cc406Sopenharmony_cistatic void EPPregisterWrite (int reg, int value);
174141cc406Sopenharmony_cistatic void EPPbufferRead (int size, unsigned char *dest);
175141cc406Sopenharmony_cistatic void EPPbufferWrite (int size, unsigned char *source);
176141cc406Sopenharmony_cistatic void EPPRead32Buffer (int size, unsigned char *dest);
177141cc406Sopenharmony_cistatic void EPPWrite32Buffer (int size, unsigned char *source);
178141cc406Sopenharmony_ci
179141cc406Sopenharmony_cistatic int ECPconnect (void);
180141cc406Sopenharmony_cistatic void ECPdisconnect (void);
181141cc406Sopenharmony_cistatic int ECPregisterRead (int reg);
182141cc406Sopenharmony_cistatic void ECPregisterWrite (int reg, int value);
183141cc406Sopenharmony_cistatic int ECPbufferRead (int size, unsigned char *dest);
184141cc406Sopenharmony_cistatic void ECPbufferWrite (int size, unsigned char *source);
185141cc406Sopenharmony_cistatic int waitFifoEmpty (void);
186141cc406Sopenharmony_cistatic int waitFifoNotEmpty (void);
187141cc406Sopenharmony_cistatic int waitFifoFull (void);
188141cc406Sopenharmony_ci
189141cc406Sopenharmony_ci/* generic operations */
190141cc406Sopenharmony_cistatic int connect (void);
191141cc406Sopenharmony_cistatic void disconnect (void);
192141cc406Sopenharmony_cistatic void bufferRead (int size, unsigned char *dest);
193141cc406Sopenharmony_cistatic void bufferWrite (int size, unsigned char *source);
194141cc406Sopenharmony_cistatic int pausedBufferRead (int size, unsigned char *dest);
195141cc406Sopenharmony_ci
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_cistatic void ClearRegister (int reg);
198141cc406Sopenharmony_ci
199141cc406Sopenharmony_cistatic int connect_epat (int r08);
200141cc406Sopenharmony_cistatic int prologue (int r08);
201141cc406Sopenharmony_cistatic int epilogue (void);
202141cc406Sopenharmony_ci
203141cc406Sopenharmony_cistatic int cmdSet (int cmd, int len, int *buffer);
204141cc406Sopenharmony_cistatic int cmdGet (int cmd, int len, int *buffer);
205141cc406Sopenharmony_cistatic int cmdSetGet (int cmd, int len, int *buffer);
206141cc406Sopenharmony_ci
207141cc406Sopenharmony_ci
208141cc406Sopenharmony_cistatic int cmdGetBuffer (int cmd, int len, unsigned char *buffer);
209141cc406Sopenharmony_cistatic int cmdGetBuffer32 (int cmd, int len, unsigned char *buffer);
210141cc406Sopenharmony_cistatic int cmdGetBlockBuffer (int cmd, int len, int window,
211141cc406Sopenharmony_ci			      unsigned char *buffer);
212141cc406Sopenharmony_ci
213141cc406Sopenharmony_cistatic void bloc2Decode (int *op);
214141cc406Sopenharmony_cistatic void bloc8Decode (int *op);
215141cc406Sopenharmony_ci/*
216141cc406Sopenharmony_ci * high level operations
217141cc406Sopenharmony_ci */
218141cc406Sopenharmony_cistatic int loadDefaultTables (void);
219141cc406Sopenharmony_cistatic int inquire (void);
220141cc406Sopenharmony_cistatic int offsetCalibration (int color, int *offRed, int *offGreen,
221141cc406Sopenharmony_ci			      int *offBlue);
222141cc406Sopenharmony_cistatic int coarseGainCalibration (int color, int dcRed, int dcGreen,
223141cc406Sopenharmony_ci				  int dcBlue, int *vgaRed, int *vgaGreen,
224141cc406Sopenharmony_ci				  int *vgaBlue);
225141cc406Sopenharmony_cistatic int
226141cc406Sopenharmony_cishadingCalibration (int color, int dcRed, int dcGreen, int dcBlue,
227141cc406Sopenharmony_ci		    int vgaRed, int vgaGreen, int vgaBlue, int *calibration);
228141cc406Sopenharmony_cistatic int leftShadingCalibration610p (int color, int dcRed, int dcGreen,
229141cc406Sopenharmony_ci				       int dcBlue, int vgaRed, int vgaGreen,
230141cc406Sopenharmony_ci				       int vgaBlue, int *calibration);
231141cc406Sopenharmony_ci
232141cc406Sopenharmony_ci#define WRITESLOW(x,y) \
233141cc406Sopenharmony_ci        PS2registerWrite((x),(y)); \
234141cc406Sopenharmony_ci        DBG(16,"PS2registerWrite(0x%X,0x%X) passed...   (%s:%d)\n",(x),(y),__FILE__,__LINE__);
235141cc406Sopenharmony_ci#define SLOWNIBBLEREGISTERREAD(x,y) \
236141cc406Sopenharmony_ci        tmp=PS2registerRead(x);\
237141cc406Sopenharmony_ci        if(tmp!=y)\
238141cc406Sopenharmony_ci        {\
239141cc406Sopenharmony_ci                DBG(0,"PS2registerRead: found 0x%X expected 0x%X (%s:%d)\n",tmp,y,__FILE__,__LINE__);\
240141cc406Sopenharmony_ci                /*return 0;*/ \
241141cc406Sopenharmony_ci        }\
242141cc406Sopenharmony_ci        DBG(16,"PS2registerRead(0x%X)=0x%X passed... (%s:%d)\n",x,y,__FILE__,__LINE__);
243141cc406Sopenharmony_ci#define REGISTERWRITE(x,y) \
244141cc406Sopenharmony_ci        registerWrite((x),(y)); \
245141cc406Sopenharmony_ci        DBG(16,"registerWrite(0x%X,0x%X) passed...   (%s:%d)\n",(x),(y),__FILE__,__LINE__);
246141cc406Sopenharmony_ci#define REGISTERREAD(x,y) \
247141cc406Sopenharmony_ci        tmp=registerRead(x);\
248141cc406Sopenharmony_ci        if(tmp!=y)\
249141cc406Sopenharmony_ci        {\
250141cc406Sopenharmony_ci                DBG(0,"registerRead, found 0x%X expected 0x%X (%s:%d)\n",tmp,y,__FILE__,__LINE__);\
251141cc406Sopenharmony_ci                return 0;\
252141cc406Sopenharmony_ci        }\
253141cc406Sopenharmony_ci        DBG(16,"registerRead(0x%X)=0x%X passed... (%s:%d)\n",x,y,__FILE__,__LINE__);
254141cc406Sopenharmony_ci#define TRACE(level,msg)        DBG(level, msg"  (%s:%d)\n",__FILE__,__LINE__);
255141cc406Sopenharmony_ci#define CMDSYNC(x)        if(sanei_umax_pp_cmdSync(x)!=1)\
256141cc406Sopenharmony_ci                        {\
257141cc406Sopenharmony_ci                                DBG(0,"cmdSync(0x%02X) failed (%s:%d)\n",x,__FILE__,__LINE__);\
258141cc406Sopenharmony_ci                                return 0;\
259141cc406Sopenharmony_ci                        }\
260141cc406Sopenharmony_ci                        DBG(16,"cmdSync(0x%02X)=%02X passed ... (%s:%d)\n",x,sanei_umax_pp_scannerStatus(),__FILE__,__LINE__)
261141cc406Sopenharmony_ci#define CMDSETGET(cmd,len,sent) if(cmdSetGet(cmd,len,sent)!=1)\
262141cc406Sopenharmony_ci                                {\
263141cc406Sopenharmony_ci                                        DBG(0,"cmdSetGet(0x%02X,%d,sent) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\
264141cc406Sopenharmony_ci                                        return 0;\
265141cc406Sopenharmony_ci                                }\
266141cc406Sopenharmony_ci                                TRACE(16,"cmdSetGet() passed ...")
267141cc406Sopenharmony_ci#define YOFFSET                40
268141cc406Sopenharmony_ci#define YOFFSET1220P        40
269141cc406Sopenharmony_ci#define YOFFSET2000P        40
270141cc406Sopenharmony_ci#define COMPLETIONWAIT        if(completionWait()==0)\
271141cc406Sopenharmony_ci                        {\
272141cc406Sopenharmony_ci                                DBG(0,"completionWait() failed (%s:%d)\n",__FILE__,__LINE__);\
273141cc406Sopenharmony_ci                                return 0;\
274141cc406Sopenharmony_ci                        }\
275141cc406Sopenharmony_ci                        TRACE(16,"completionWait() passed ...")
276141cc406Sopenharmony_ci#define MOVE(x,y,t)        if(move(x,y,t)==0)\
277141cc406Sopenharmony_ci                        {\
278141cc406Sopenharmony_ci                                DBG(0,"move(%d,%d,buffer) failed (%s:%d)\n",x,y,__FILE__,__LINE__);\
279141cc406Sopenharmony_ci                                return 0;\
280141cc406Sopenharmony_ci                        }\
281141cc406Sopenharmony_ci                        TRACE(16,"move() passed ...")
282141cc406Sopenharmony_ci#define CMDGETBUF(cmd,len,sent) if(cmdGetBuffer(cmd,len,sent)!=1)\
283141cc406Sopenharmony_ci                                {\
284141cc406Sopenharmony_ci                                        DBG(0,"cmdGetBuffer(0x%02X,%ld,buffer) failed (%s:%d)\n",cmd,(long)len,__FILE__,__LINE__);\
285141cc406Sopenharmony_ci                                        return 0;\
286141cc406Sopenharmony_ci                                }\
287141cc406Sopenharmony_ci                                DBG(16,"cmdGetBuffer(%ld) passed ... (%s:%d)\n",(long)len,__FILE__,__LINE__);
288141cc406Sopenharmony_ci#define CMDGETBUF32(cmd,len,sent) if(cmdGetBuffer32(cmd,len,sent)!=1)\
289141cc406Sopenharmony_ci                                {\
290141cc406Sopenharmony_ci                                        DBG(0,"cmdGetBuffer32(0x%02X,%ld,buffer) failed (%s:%d)\n",cmd,(long)len,__FILE__,__LINE__);\
291141cc406Sopenharmony_ci                                        return 0;\
292141cc406Sopenharmony_ci                                }\
293141cc406Sopenharmony_ci                                TRACE(16,"cmdGetBuffer32() passed ...")
294141cc406Sopenharmony_ci#define CMDSET(cmd,len,sent) if(cmdSet(cmd,len,sent)!=1)\
295141cc406Sopenharmony_ci                                {\
296141cc406Sopenharmony_ci                                        DBG(0,"cmdSet(0x%02X,%d,sent) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\
297141cc406Sopenharmony_ci                                        return 0;\
298141cc406Sopenharmony_ci                                }\
299141cc406Sopenharmony_ci                                TRACE(16,"cmdSet() passed ...")
300141cc406Sopenharmony_ci#define CMDGET(cmd,len,sent) if(cmdGet(cmd,len,sent)!=1)\
301141cc406Sopenharmony_ci                                {\
302141cc406Sopenharmony_ci                                        DBG(0,"cmdGet(0x%02X,%d,read) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\
303141cc406Sopenharmony_ci                                        return 0;\
304141cc406Sopenharmony_ci                                }\
305141cc406Sopenharmony_ci                                TRACE(16,"cmdGet() passed ...")
306141cc406Sopenharmony_cistatic int gPort = 0x378;
307141cc406Sopenharmony_cistatic float targetCode = 250.0;
308141cc406Sopenharmony_ci
309141cc406Sopenharmony_ci/* global control vars */
310141cc406Sopenharmony_cistatic int gControl = 0;
311141cc406Sopenharmony_cistatic int gData = 0;
312141cc406Sopenharmony_cistatic int g674 = 0;		/* semble indiquer qu'on utilise les IRQ */
313141cc406Sopenharmony_cistatic int g67D = 0;
314141cc406Sopenharmony_cistatic int g67E = 0;
315141cc406Sopenharmony_cistatic int gEPAT = 0;		/* signals fast mode ? */
316141cc406Sopenharmony_cistatic int g6FE = 0;
317141cc406Sopenharmony_cistatic int gECP = 0;
318141cc406Sopenharmony_ci
319141cc406Sopenharmony_cistatic int gLeft = 144;		/* default value for 1220P */
320141cc406Sopenharmony_ci
321141cc406Sopenharmony_ci/* default gamma translation table */
322141cc406Sopenharmony_cistatic int ggamma[256] =
323141cc406Sopenharmony_ci  { 0x00, 0x06, 0x0A, 0x0D, 0x10, 0x12, 0x14, 0x17, 0x19, 0x1B, 0x1D,
324141cc406Sopenharmony_ci  0x1F,
325141cc406Sopenharmony_ci  0x21, 0x23, 0x24, 0x26, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x30, 0x31, 0x33,
326141cc406Sopenharmony_ci  0x34, 0x36, 0x37, 0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x40, 0x41, 0x42, 0x43,
327141cc406Sopenharmony_ci  0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4F, 0x50, 0x51, 0x52,
328141cc406Sopenharmony_ci  0x53, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5E, 0x5F, 0x60,
329141cc406Sopenharmony_ci  0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
330141cc406Sopenharmony_ci  0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
331141cc406Sopenharmony_ci  0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84,
332141cc406Sopenharmony_ci  0x85, 0x86, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
333141cc406Sopenharmony_ci  0x90, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99,
334141cc406Sopenharmony_ci  0x9A, 0x9B, 0x9C, 0x9D, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA2, 0xA3,
335141cc406Sopenharmony_ci  0xA4, 0xA5, 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAC, 0xAD,
336141cc406Sopenharmony_ci  0xAE, 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB4, 0xB5, 0xB6, 0xB7,
337141cc406Sopenharmony_ci  0xB8, 0xB8, 0xB9, 0xBA, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBF, 0xC0,
338141cc406Sopenharmony_ci  0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC8, 0xC9,
339141cc406Sopenharmony_ci  0xCA, 0xCB, 0xCB, 0xCC, 0xCD, 0xCE, 0xCE, 0xCF, 0xD0, 0xD1, 0xD1, 0xD2,
340141cc406Sopenharmony_ci  0xD3, 0xD4, 0xD4, 0xD5, 0xD6, 0xD6, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDB,
341141cc406Sopenharmony_ci  0xDC, 0xDC, 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE3,
342141cc406Sopenharmony_ci  0xE4, 0xE5, 0xE6, 0xE6, 0xE7, 0xE8, 0xE8, 0xE9, 0xEA, 0xEA, 0xEB, 0xEC,
343141cc406Sopenharmony_ci  0xEC, 0xED, 0xEE, 0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF3, 0xF4,
344141cc406Sopenharmony_ci  0xF5, 0xF5, 0xF6, 0xF7, 0xF7, 0xF8, 0xF9, 0xF9, 0xFA, 0xFB, 0xFB, 0xFC,
345141cc406Sopenharmony_ci  0xFD, 0xFE, 0xFE, 0xFF
346141cc406Sopenharmony_ci};
347141cc406Sopenharmony_ci
348141cc406Sopenharmony_ci
349141cc406Sopenharmony_ci/* default gamma translation table */
350141cc406Sopenharmony_cistatic int *ggGreen = ggamma;
351141cc406Sopenharmony_cistatic int *ggBlue = ggamma;
352141cc406Sopenharmony_cistatic int *ggRed = ggamma;
353141cc406Sopenharmony_cistatic int gParport = 0;
354141cc406Sopenharmony_cistatic int gCancel = 0;
355141cc406Sopenharmony_cistatic int gAutoSettings = 1;
356141cc406Sopenharmony_ci
357141cc406Sopenharmony_ci
358141cc406Sopenharmony_ci/*****************************************************************************/
359141cc406Sopenharmony_ci/*                    output one byte on given port                          */
360141cc406Sopenharmony_ci/*****************************************************************************/
361141cc406Sopenharmony_cistatic void Outb (int port, int value);
362141cc406Sopenharmony_ci
363141cc406Sopenharmony_ci/*****************************************************************************/
364141cc406Sopenharmony_ci/*         output 'size' bytes stored in 'source' on given port              */
365141cc406Sopenharmony_ci/*****************************************************************************/
366141cc406Sopenharmony_cistatic void Outsb (int port, unsigned char *source, int size);
367141cc406Sopenharmony_ci
368141cc406Sopenharmony_ci/*****************************************************************************/
369141cc406Sopenharmony_ci/*       output 'size' 32 bits words stored in 'source' on given port        */
370141cc406Sopenharmony_ci/*****************************************************************************/
371141cc406Sopenharmony_cistatic void Outsw (int port, unsigned char *source, int size);
372141cc406Sopenharmony_ci
373141cc406Sopenharmony_ci
374141cc406Sopenharmony_ci/*****************************************************************************/
375141cc406Sopenharmony_ci/*                   input one byte from given port                          */
376141cc406Sopenharmony_ci/*****************************************************************************/
377141cc406Sopenharmony_cistatic int Inb (int port);
378141cc406Sopenharmony_ci
379141cc406Sopenharmony_ci/*****************************************************************************/
380141cc406Sopenharmony_ci/*       input 'size' bytes from given port and store them in 'dest'         */
381141cc406Sopenharmony_ci/*****************************************************************************/
382141cc406Sopenharmony_cistatic void Insb (int port, unsigned char *dest, int size);
383141cc406Sopenharmony_ci
384141cc406Sopenharmony_ci/*****************************************************************************/
385141cc406Sopenharmony_ci/*     input 'size' 32 bits word from given port and store them in 'dest'    */
386141cc406Sopenharmony_ci/*****************************************************************************/
387141cc406Sopenharmony_cistatic void Insw (int port, unsigned char *dest, int size);
388141cc406Sopenharmony_ci
389141cc406Sopenharmony_ci
390141cc406Sopenharmony_ci
391141cc406Sopenharmony_cichar **
392141cc406Sopenharmony_cisanei_parport_find_port (void)
393141cc406Sopenharmony_ci{
394141cc406Sopenharmony_ci  char **ports = NULL;
395141cc406Sopenharmony_ci#ifdef ENABLE_PARPORT_DIRECTIO
396141cc406Sopenharmony_ci  int i, addr, ecpaddr;
397141cc406Sopenharmony_ci  int found = 0;
398141cc406Sopenharmony_ci  char name[80], buffer[80];
399141cc406Sopenharmony_ci  FILE *fic = NULL;
400141cc406Sopenharmony_ci
401141cc406Sopenharmony_ci  /* direct I/O detection */
402141cc406Sopenharmony_ci  /* linux 2.4 + 2.6 with proc support */
403141cc406Sopenharmony_ci  for (i = 0; i < 4; i++)
404141cc406Sopenharmony_ci    {
405141cc406Sopenharmony_ci      /* try to ensure loading of lp module */
406141cc406Sopenharmony_ci      sprintf (name, "/dev/lp%d", i);
407141cc406Sopenharmony_ci      fic = fopen (name, "wb");
408141cc406Sopenharmony_ci      if (fic != NULL)
409141cc406Sopenharmony_ci	fclose (fic);
410141cc406Sopenharmony_ci      sprintf (name, "/proc/sys/dev/parport/parport%d/base-addr", i);
411141cc406Sopenharmony_ci      fic = fopen (name, "rb");
412141cc406Sopenharmony_ci      if (fic != NULL)
413141cc406Sopenharmony_ci	{
414141cc406Sopenharmony_ci	  fread (buffer, 64, 1, fic);
415141cc406Sopenharmony_ci	  fclose (fic);
416141cc406Sopenharmony_ci	  if (sscanf (buffer, "%d %d", &addr, &ecpaddr) > 0)
417141cc406Sopenharmony_ci	    {
418141cc406Sopenharmony_ci	      DBG (16, "parport at 0x%X\n", addr);
419141cc406Sopenharmony_ci	      ports =
420141cc406Sopenharmony_ci		(char **) realloc (ports, (found + 2) * sizeof (char *));
421141cc406Sopenharmony_ci	      ports[found] = (char *) malloc (19);
422141cc406Sopenharmony_ci	      sprintf (ports[found], "0x%X", addr);
423141cc406Sopenharmony_ci	      found++;
424141cc406Sopenharmony_ci	      ports[found] = NULL;
425141cc406Sopenharmony_ci	    }
426141cc406Sopenharmony_ci	}
427141cc406Sopenharmony_ci    }
428141cc406Sopenharmony_ci#endif
429141cc406Sopenharmony_ci  return ports;
430141cc406Sopenharmony_ci}
431141cc406Sopenharmony_ci
432141cc406Sopenharmony_ci
433141cc406Sopenharmony_cichar **
434141cc406Sopenharmony_cisanei_parport_find_device (void)
435141cc406Sopenharmony_ci{
436141cc406Sopenharmony_ci  char *devices[] = {
437141cc406Sopenharmony_ci    /* FreeBSD */
438141cc406Sopenharmony_ci    "/dev/ppi0",
439141cc406Sopenharmony_ci    "/dev/ppi1",
440141cc406Sopenharmony_ci    "/dev/ppi2",
441141cc406Sopenharmony_ci    "/dev/ppi3",
442141cc406Sopenharmony_ci    /* linux ppdev with devfs */
443141cc406Sopenharmony_ci    "/dev/parports/0",
444141cc406Sopenharmony_ci    "/dev/parports/1",
445141cc406Sopenharmony_ci    "/dev/parports/2",
446141cc406Sopenharmony_ci    "/dev/parports/3",
447141cc406Sopenharmony_ci    /* linux ppdev */
448141cc406Sopenharmony_ci    "/dev/parport0",
449141cc406Sopenharmony_ci    "/dev/parport1",
450141cc406Sopenharmony_ci    "/dev/parport2",
451141cc406Sopenharmony_ci    "/dev/parport3",
452141cc406Sopenharmony_ci    NULL
453141cc406Sopenharmony_ci  };
454141cc406Sopenharmony_ci  int i, file;
455141cc406Sopenharmony_ci  int rc = 0;
456141cc406Sopenharmony_ci  int found = 0;
457141cc406Sopenharmony_ci  char **ports = NULL;
458141cc406Sopenharmony_ci
459141cc406Sopenharmony_ci
460141cc406Sopenharmony_ci  /* device finding */
461141cc406Sopenharmony_ci  i = 0;
462141cc406Sopenharmony_ci  while (devices[i] != NULL)
463141cc406Sopenharmony_ci    {
464141cc406Sopenharmony_ci      DBG (16, "Controlling %s: ", devices[i]);
465141cc406Sopenharmony_ci      file = open (devices[i], O_RDWR);
466141cc406Sopenharmony_ci      if (file < 0)
467141cc406Sopenharmony_ci	{
468141cc406Sopenharmony_ci	  switch (errno)
469141cc406Sopenharmony_ci	    {
470141cc406Sopenharmony_ci	    case ENOENT:
471141cc406Sopenharmony_ci#ifdef ENIO
472141cc406Sopenharmony_ci	    case ENXIO:
473141cc406Sopenharmony_ci#endif
474141cc406Sopenharmony_ci#ifdef ENODEV
475141cc406Sopenharmony_ci	    case ENODEV:
476141cc406Sopenharmony_ci#endif
477141cc406Sopenharmony_ci	      DBG (16, "no %s device ...\n", devices[i]);
478141cc406Sopenharmony_ci	      break;
479141cc406Sopenharmony_ci	    case EACCES:
480141cc406Sopenharmony_ci	      DBG (16, "current user cannot use existing %s device ...\n",
481141cc406Sopenharmony_ci		   devices[i]);
482141cc406Sopenharmony_ci	      break;
483141cc406Sopenharmony_ci	    default:
484141cc406Sopenharmony_ci	      perror (devices[i]);
485141cc406Sopenharmony_ci	    }
486141cc406Sopenharmony_ci	}
487141cc406Sopenharmony_ci      else
488141cc406Sopenharmony_ci	{
489141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
490141cc406Sopenharmony_ci	  /* on kernel < 2.4.23, you have to CLAIM the device
491141cc406Sopenharmony_ci	   * to check it really exists
492141cc406Sopenharmony_ci	   * we may hang if another program already claimed it
493141cc406Sopenharmony_ci	   */
494141cc406Sopenharmony_ci	  rc = ioctl (file, PPCLAIM);
495141cc406Sopenharmony_ci	  if (rc)
496141cc406Sopenharmony_ci	    {
497141cc406Sopenharmony_ci	      switch (errno)
498141cc406Sopenharmony_ci		{
499141cc406Sopenharmony_ci		case ENOENT:
500141cc406Sopenharmony_ci#ifdef ENXIO
501141cc406Sopenharmony_ci		case ENXIO:
502141cc406Sopenharmony_ci#endif
503141cc406Sopenharmony_ci#ifdef ENODEV
504141cc406Sopenharmony_ci		case ENODEV:
505141cc406Sopenharmony_ci#endif
506141cc406Sopenharmony_ci		  DBG (16, "no %s device ...\n", devices[i]);
507141cc406Sopenharmony_ci		  break;
508141cc406Sopenharmony_ci		case EACCES:
509141cc406Sopenharmony_ci		  DBG (16, "current user cannot use existing %s device ...\n",
510141cc406Sopenharmony_ci		       devices[i]);
511141cc406Sopenharmony_ci		  break;
512141cc406Sopenharmony_ci		default:
513141cc406Sopenharmony_ci		  DBG (16, "errno=%d\n", errno);
514141cc406Sopenharmony_ci		  perror (devices[i]);
515141cc406Sopenharmony_ci		}
516141cc406Sopenharmony_ci	    }
517141cc406Sopenharmony_ci	  else
518141cc406Sopenharmony_ci	    {
519141cc406Sopenharmony_ci	      rc = ioctl (file, PPRELEASE);
520141cc406Sopenharmony_ci	    }
521141cc406Sopenharmony_ci#endif /* HAVE_LINUX_PPDEV_H */
522141cc406Sopenharmony_ci	  close (file);
523141cc406Sopenharmony_ci	  if (!rc)
524141cc406Sopenharmony_ci	    {
525141cc406Sopenharmony_ci	      DBG (16, "adding %s to valid devices ...\n", devices[i]);
526141cc406Sopenharmony_ci	      ports =
527141cc406Sopenharmony_ci		(char **) realloc (ports, (found + 2) * sizeof (char *));
528141cc406Sopenharmony_ci	      ports[found] = strdup (devices[i]);
529141cc406Sopenharmony_ci	      found++;
530141cc406Sopenharmony_ci	      ports[found] = NULL;
531141cc406Sopenharmony_ci	    }
532141cc406Sopenharmony_ci	}
533141cc406Sopenharmony_ci
534141cc406Sopenharmony_ci      /* suite */
535141cc406Sopenharmony_ci      i++;
536141cc406Sopenharmony_ci    }
537141cc406Sopenharmony_ci  return ports;
538141cc406Sopenharmony_ci}
539141cc406Sopenharmony_ci
540141cc406Sopenharmony_ci
541141cc406Sopenharmony_ci
542141cc406Sopenharmony_ci/*
543141cc406Sopenharmony_ci * gain direct access to IO port, and set parport to the 'right' mode
544141cc406Sopenharmony_ci * returns 1 on success, 0 an failure
545141cc406Sopenharmony_ci */
546141cc406Sopenharmony_ci
547141cc406Sopenharmony_ci
548141cc406Sopenharmony_ciint
549141cc406Sopenharmony_cisanei_umax_pp_initPort (int port, const char *name)
550141cc406Sopenharmony_ci{
551141cc406Sopenharmony_ci#ifndef IO_SUPPORT_MISSING
552141cc406Sopenharmony_ci# ifdef HAVE_LINUX_PPDEV_H
553141cc406Sopenharmony_ci  int found = 0;
554141cc406Sopenharmony_ci  int fd;
555141cc406Sopenharmony_ci  int mode, modes, rc;
556141cc406Sopenharmony_ci#  ifdef PPGETMODES
557141cc406Sopenharmony_ci  char strmodes[160];
558141cc406Sopenharmony_ci#  endif
559141cc406Sopenharmony_ci# endif
560141cc406Sopenharmony_ci# ifdef HAVE_DEV_PPBUS_PPI_H
561141cc406Sopenharmony_ci  int found = 0;
562141cc406Sopenharmony_ci  int fd;
563141cc406Sopenharmony_ci# endif
564141cc406Sopenharmony_ci# ifdef HAVE_IOPERM
565141cc406Sopenharmony_ci  int ectr;
566141cc406Sopenharmony_ci# endif
567141cc406Sopenharmony_ci#endif
568141cc406Sopenharmony_ci
569141cc406Sopenharmony_ci  /* since this function must be called before */
570141cc406Sopenharmony_ci  /* any other, we put debug init here         */
571141cc406Sopenharmony_ci  DBG_INIT ();
572141cc406Sopenharmony_ci  DBG (1, "SANE_INB level %d\n", SANE_INB);
573141cc406Sopenharmony_ci
574141cc406Sopenharmony_ci  /* sets global vars */
575141cc406Sopenharmony_ci  ggGreen = ggamma;
576141cc406Sopenharmony_ci  ggBlue = ggamma;
577141cc406Sopenharmony_ci  ggRed = ggamma;
578141cc406Sopenharmony_ci  gParport = 0;
579141cc406Sopenharmony_ci  gCancel = 0;
580141cc406Sopenharmony_ci  gAutoSettings = 1;
581141cc406Sopenharmony_ci  gControl = 0;
582141cc406Sopenharmony_ci  gData = 0;
583141cc406Sopenharmony_ci  g674 = 0;
584141cc406Sopenharmony_ci  g67D = 0;
585141cc406Sopenharmony_ci  g67E = 0;
586141cc406Sopenharmony_ci  gEPAT = 0;
587141cc406Sopenharmony_ci  g6FE = 0;
588141cc406Sopenharmony_ci  sanei_umax_pp_setparport (0);
589141cc406Sopenharmony_ci
590141cc406Sopenharmony_ci
591141cc406Sopenharmony_ci  DBG (1, "sanei_umax_pp_InitPort(0x%X,%s)\n", port, name);
592141cc406Sopenharmony_ci#ifndef ENABLE_PARPORT_DIRECTIO
593141cc406Sopenharmony_ci  if ((name == NULL) || ((name != NULL) && (strlen (name) < 4)))
594141cc406Sopenharmony_ci    {
595141cc406Sopenharmony_ci      DBG (0, "sanei_umax_pp_InitPort cannot use direct hardware access\n");
596141cc406Sopenharmony_ci      DBG (0, "if not compiled with --enable-parport-directio\n");
597141cc406Sopenharmony_ci      return 0;
598141cc406Sopenharmony_ci    }
599141cc406Sopenharmony_ci#endif
600141cc406Sopenharmony_ci
601141cc406Sopenharmony_ci
602141cc406Sopenharmony_ci  /* init global var holding port value */
603141cc406Sopenharmony_ci  gPort = port;
604141cc406Sopenharmony_ci
605141cc406Sopenharmony_ci#ifdef IO_SUPPORT_MISSING
606141cc406Sopenharmony_ci  DBG (1, "*** Direct I/O or ppdev unavailable, giving up ***\n");
607141cc406Sopenharmony_ci  return 0;
608141cc406Sopenharmony_ci#else
609141cc406Sopenharmony_ci
610141cc406Sopenharmony_ci
611141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
612141cc406Sopenharmony_ci  if (name != NULL)
613141cc406Sopenharmony_ci    {
614141cc406Sopenharmony_ci      if (strlen (name) > 3)
615141cc406Sopenharmony_ci	{
616141cc406Sopenharmony_ci	  /* ppdev opening and configuration                               */
617141cc406Sopenharmony_ci	  found = 0;
618141cc406Sopenharmony_ci	  fd = open (name, O_RDWR | O_NOCTTY | O_NONBLOCK);
619141cc406Sopenharmony_ci	  if (fd < 0)
620141cc406Sopenharmony_ci	    {
621141cc406Sopenharmony_ci	      switch (errno)
622141cc406Sopenharmony_ci		{
623141cc406Sopenharmony_ci		case ENOENT:
624141cc406Sopenharmony_ci		  DBG (1, "umax_pp: '%s' does not exist \n", name);
625141cc406Sopenharmony_ci		  break;
626141cc406Sopenharmony_ci		case EACCES:
627141cc406Sopenharmony_ci		  DBG (1,
628141cc406Sopenharmony_ci		       "umax_pp: current user has not R/W permissions on '%s' \n",
629141cc406Sopenharmony_ci		       name);
630141cc406Sopenharmony_ci		  break;
631141cc406Sopenharmony_ci		}
632141cc406Sopenharmony_ci	      return 0;
633141cc406Sopenharmony_ci
634141cc406Sopenharmony_ci	    }
635141cc406Sopenharmony_ci	  /* claim port */
636141cc406Sopenharmony_ci	  if (ioctl (fd, PPCLAIM))
637141cc406Sopenharmony_ci	    {
638141cc406Sopenharmony_ci	      DBG (1, "umax_pp: cannot claim port '%s'\n", name);
639141cc406Sopenharmony_ci	    }
640141cc406Sopenharmony_ci	  else
641141cc406Sopenharmony_ci	    {
642141cc406Sopenharmony_ci	      /* we check if parport does EPP or ECP */
643141cc406Sopenharmony_ci#ifdef PPGETMODES
644141cc406Sopenharmony_ci	      if (ioctl (fd, PPGETMODES, &modes))
645141cc406Sopenharmony_ci		{
646141cc406Sopenharmony_ci		  DBG (16,
647141cc406Sopenharmony_ci		       "umax_pp: ppdev couldn't gave modes for port '%s'\n",
648141cc406Sopenharmony_ci		       name);
649141cc406Sopenharmony_ci		}
650141cc406Sopenharmony_ci	      else
651141cc406Sopenharmony_ci		{
652141cc406Sopenharmony_ci		  snprintf(strmodes, sizeof(strmodes),
653141cc406Sopenharmony_ci			   "\n%s%s%s%s%s%s",
654141cc406Sopenharmony_ci			   (modes & PARPORT_MODE_PCSPP)? "\t\tPARPORT_MODE_PCSPP\n": "",
655141cc406Sopenharmony_ci			   (modes & PARPORT_MODE_TRISTATE)? "\t\tPARPORT_MODE_TRISTATE\n": "",
656141cc406Sopenharmony_ci			   (modes & PARPORT_MODE_EPP)? "\t\tPARPORT_MODE_EPP\n": "",
657141cc406Sopenharmony_ci			   (modes & PARPORT_MODE_ECP)? "\t\tPARPORT_MODE_ECP\n": "",
658141cc406Sopenharmony_ci			   (modes & PARPORT_MODE_COMPAT)? "\t\tPARPORT_MODE_COMPAT\n": "",
659141cc406Sopenharmony_ci			   (modes & PARPORT_MODE_DMA)? "\t\tPARPORT_MODE_DMA\n": "");
660141cc406Sopenharmony_ci
661141cc406Sopenharmony_ci		  if (modes & PARPORT_MODE_ECP)
662141cc406Sopenharmony_ci		    {
663141cc406Sopenharmony_ci		      gECP = 1;
664141cc406Sopenharmony_ci		    }
665141cc406Sopenharmony_ci
666141cc406Sopenharmony_ci		  DBG (32, "parport modes: %X\n", modes);
667141cc406Sopenharmony_ci		  DBG (32, "parport modes: %s\n", strmodes);
668141cc406Sopenharmony_ci		  if (!(modes & PARPORT_MODE_EPP)
669141cc406Sopenharmony_ci		      && !(modes & PARPORT_MODE_ECP))
670141cc406Sopenharmony_ci		    {
671141cc406Sopenharmony_ci		      DBG (1,
672141cc406Sopenharmony_ci			   "port 0x%X does not have EPP or ECP, giving up ...\n",
673141cc406Sopenharmony_ci			   port);
674141cc406Sopenharmony_ci		      mode = IEEE1284_MODE_COMPAT;
675141cc406Sopenharmony_ci		      ioctl (fd, PPSETMODE, &mode);
676141cc406Sopenharmony_ci		      ioctl (fd, PPRELEASE);
677141cc406Sopenharmony_ci		      close (fd);
678141cc406Sopenharmony_ci		      return 0;
679141cc406Sopenharmony_ci		    }
680141cc406Sopenharmony_ci		}
681141cc406Sopenharmony_ci
682141cc406Sopenharmony_ci#else
683141cc406Sopenharmony_ci	      DBG (16,
684141cc406Sopenharmony_ci		   "umax_pp: ppdev used to build SANE doesn't have PPGETMODES.\n");
685141cc406Sopenharmony_ci	      /* faking result */
686141cc406Sopenharmony_ci	      modes = 0xFFFFFFFF;
687141cc406Sopenharmony_ci#endif
688141cc406Sopenharmony_ci	      mode = 0;
689141cc406Sopenharmony_ci
690141cc406Sopenharmony_ci	      /* preferred mode is EPP */
691141cc406Sopenharmony_ci	      if (modes & PARPORT_MODE_EPP)
692141cc406Sopenharmony_ci		{
693141cc406Sopenharmony_ci		  mode = IEEE1284_MODE_EPP;
694141cc406Sopenharmony_ci
695141cc406Sopenharmony_ci		  /* negot always fail here ... */
696141cc406Sopenharmony_ci		  rc = ioctl (fd, PPNEGOT, &mode);
697141cc406Sopenharmony_ci		  if (rc)
698141cc406Sopenharmony_ci		    {
699141cc406Sopenharmony_ci		      DBG (16,
700141cc406Sopenharmony_ci			   "umax_pp: ppdev couldn't negotiate mode IEEE1284_MODE_EPP for '%s' (ignored)\n",
701141cc406Sopenharmony_ci			   name);
702141cc406Sopenharmony_ci		    }
703141cc406Sopenharmony_ci		  if (ioctl (fd, PPSETMODE, &mode))
704141cc406Sopenharmony_ci		    {
705141cc406Sopenharmony_ci		      DBG (16,
706141cc406Sopenharmony_ci			   "umax_pp: ppdev couldn't set mode to IEEE1284_MODE_EPP for '%s'\n",
707141cc406Sopenharmony_ci			   name);
708141cc406Sopenharmony_ci		      /* signal failure for ECP test */
709141cc406Sopenharmony_ci		      mode = 0;
710141cc406Sopenharmony_ci		    }
711141cc406Sopenharmony_ci		  else
712141cc406Sopenharmony_ci		    {
713141cc406Sopenharmony_ci		      DBG (16,
714141cc406Sopenharmony_ci			   "umax_pp: mode set to PARPORT_MODE_EPP for '%s'\n",
715141cc406Sopenharmony_ci			   name);
716141cc406Sopenharmony_ci		    }
717141cc406Sopenharmony_ci		}
718141cc406Sopenharmony_ci
719141cc406Sopenharmony_ci	      if ((modes & PARPORT_MODE_ECP) && (mode == 0))
720141cc406Sopenharmony_ci		{
721141cc406Sopenharmony_ci		  mode = IEEE1284_MODE_ECP;
722141cc406Sopenharmony_ci		  rc = ioctl (fd, PPNEGOT, &mode);
723141cc406Sopenharmony_ci		  if (rc)
724141cc406Sopenharmony_ci		    {
725141cc406Sopenharmony_ci		      DBG (16,
726141cc406Sopenharmony_ci			   "umax_pp: ppdev couldn't negotiate mode IEEE1284_MODE_ECP for '%s' (ignored)\n",
727141cc406Sopenharmony_ci			   name);
728141cc406Sopenharmony_ci		    }
729141cc406Sopenharmony_ci		  if (ioctl (fd, PPSETMODE, &mode))
730141cc406Sopenharmony_ci		    {
731141cc406Sopenharmony_ci		      DBG (16,
732141cc406Sopenharmony_ci			   "umax_pp: ppdev couldn't set mode to IEEE1284_MODE_ECP for '%s'\n",
733141cc406Sopenharmony_ci			   name);
734141cc406Sopenharmony_ci		      DBG (1,
735141cc406Sopenharmony_ci			   "port 0x%X can't be set to EPP or ECP, giving up ...\n",
736141cc406Sopenharmony_ci			   port);
737141cc406Sopenharmony_ci
738141cc406Sopenharmony_ci		      mode = IEEE1284_MODE_COMPAT;
739141cc406Sopenharmony_ci		      ioctl (fd, PPSETMODE, &mode);
740141cc406Sopenharmony_ci		      ioctl (fd, PPRELEASE);
741141cc406Sopenharmony_ci		      close (fd);
742141cc406Sopenharmony_ci		      return 0;
743141cc406Sopenharmony_ci		    }
744141cc406Sopenharmony_ci		  else
745141cc406Sopenharmony_ci		    {
746141cc406Sopenharmony_ci		      gECP = 1;
747141cc406Sopenharmony_ci		      DBG (16,
748141cc406Sopenharmony_ci			   "umax_pp: mode set to PARPORT_MODE_ECP for '%s'\n",
749141cc406Sopenharmony_ci			   name);
750141cc406Sopenharmony_ci		    }
751141cc406Sopenharmony_ci		}
752141cc406Sopenharmony_ci
753141cc406Sopenharmony_ci
754141cc406Sopenharmony_ci	      /* always start in compat mode (for probe) */
755141cc406Sopenharmony_ci	      mode = IEEE1284_MODE_COMPAT;
756141cc406Sopenharmony_ci	      rc = ioctl (fd, PPSETMODE, &mode);
757141cc406Sopenharmony_ci	      if (rc)
758141cc406Sopenharmony_ci		DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
759141cc406Sopenharmony_ci		     strerror (errno), __FILE__, __LINE__);
760141cc406Sopenharmony_ci	      mode = 0;		/* data forward */
761141cc406Sopenharmony_ci	      rc = ioctl (fd, PPDATADIR, &mode);
762141cc406Sopenharmony_ci	      if (rc)
763141cc406Sopenharmony_ci		DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
764141cc406Sopenharmony_ci		     strerror (errno), __FILE__, __LINE__);
765141cc406Sopenharmony_ci	      mode = 1;		/* FW IDLE */
766141cc406Sopenharmony_ci	      rc = ioctl (fd, PPSETPHASE, &mode);
767141cc406Sopenharmony_ci	      if (rc)
768141cc406Sopenharmony_ci		DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
769141cc406Sopenharmony_ci		     strerror (errno), __FILE__, __LINE__);
770141cc406Sopenharmony_ci	      found = 1;
771141cc406Sopenharmony_ci
772141cc406Sopenharmony_ci	    }
773141cc406Sopenharmony_ci
774141cc406Sopenharmony_ci	  if (!found)
775141cc406Sopenharmony_ci	    {
776141cc406Sopenharmony_ci	      DBG (1, "device %s does not fit ...\n", name);
777141cc406Sopenharmony_ci	    }
778141cc406Sopenharmony_ci	  else
779141cc406Sopenharmony_ci	    {
780141cc406Sopenharmony_ci	      DBG (1, "Using %s ...\n", name);
781141cc406Sopenharmony_ci	      sanei_umax_pp_setparport (fd);
782141cc406Sopenharmony_ci	      return 1;
783141cc406Sopenharmony_ci	    }
784141cc406Sopenharmony_ci	}
785141cc406Sopenharmony_ci    }
786141cc406Sopenharmony_ci#endif /* HAVE_LINUX_PPDEV_H */
787141cc406Sopenharmony_ci
788141cc406Sopenharmony_ci
789141cc406Sopenharmony_ci#ifdef HAVE_DEV_PPBUS_PPI_H
790141cc406Sopenharmony_ci/* the ppi device let user access to parallel port on freebsd */
791141cc406Sopenharmony_ci  if (name != NULL)
792141cc406Sopenharmony_ci    {
793141cc406Sopenharmony_ci      if (strlen (name) > 3)
794141cc406Sopenharmony_ci	{
795141cc406Sopenharmony_ci	  /* ppi opening and configuration                               */
796141cc406Sopenharmony_ci	  found = 0;
797141cc406Sopenharmony_ci	  fd = open (name, O_RDONLY);
798141cc406Sopenharmony_ci	  if (fd < 0)
799141cc406Sopenharmony_ci	    {
800141cc406Sopenharmony_ci	      switch (errno)
801141cc406Sopenharmony_ci		{
802141cc406Sopenharmony_ci		case ENOENT:
803141cc406Sopenharmony_ci		  DBG (1, "umax_pp: '%s' does not exist \n", name);
804141cc406Sopenharmony_ci		  break;
805141cc406Sopenharmony_ci		case EACCES:
806141cc406Sopenharmony_ci		  DBG (1,
807141cc406Sopenharmony_ci		       "umax_pp: current user has not read permissions on '%s' \n",
808141cc406Sopenharmony_ci		       name);
809141cc406Sopenharmony_ci		  break;
810141cc406Sopenharmony_ci		}
811141cc406Sopenharmony_ci	      return 0;
812141cc406Sopenharmony_ci	    }
813141cc406Sopenharmony_ci	  else
814141cc406Sopenharmony_ci	    {
815141cc406Sopenharmony_ci	      DBG (1, "Using %s ...\n", name);
816141cc406Sopenharmony_ci	      sanei_umax_pp_setparport (fd);
817141cc406Sopenharmony_ci	      return 1;
818141cc406Sopenharmony_ci	    }
819141cc406Sopenharmony_ci	}
820141cc406Sopenharmony_ci    }
821141cc406Sopenharmony_ci#endif /* HAVE_DEV_PPBUS_PPI_H */
822141cc406Sopenharmony_ci
823141cc406Sopenharmony_ci  if (port < 0x400)
824141cc406Sopenharmony_ci    {
825141cc406Sopenharmony_ci      if (sanei_ioperm (port, 8, 1) != 0)
826141cc406Sopenharmony_ci	{
827141cc406Sopenharmony_ci	  DBG (1, "sanei_ioperm() could not gain access to 0x%X\n", port);
828141cc406Sopenharmony_ci	  return 0;
829141cc406Sopenharmony_ci	}
830141cc406Sopenharmony_ci      DBG (1, "sanei_ioperm(0x%X, 8, 1) OK ...\n", port);
831141cc406Sopenharmony_ci    }
832141cc406Sopenharmony_ci
833141cc406Sopenharmony_ci#ifdef HAVE_IOPERM
834141cc406Sopenharmony_ci  /* ECP i/o range */
835141cc406Sopenharmony_ci  if (iopl (3) != 0)
836141cc406Sopenharmony_ci    {
837141cc406Sopenharmony_ci      DBG (1, "iopl could not raise IO permission to level 3\n");
838141cc406Sopenharmony_ci      DBG (1, "*NO* ECP support\n");
839141cc406Sopenharmony_ci
840141cc406Sopenharmony_ci    }
841141cc406Sopenharmony_ci  else
842141cc406Sopenharmony_ci    {
843141cc406Sopenharmony_ci      /* any ECP out there ? */
844141cc406Sopenharmony_ci      ectr = Inb (ECR);
845141cc406Sopenharmony_ci      if (ectr != 0xFF)
846141cc406Sopenharmony_ci	{
847141cc406Sopenharmony_ci	  gECP = 1;
848141cc406Sopenharmony_ci
849141cc406Sopenharmony_ci	}
850141cc406Sopenharmony_ci    }
851141cc406Sopenharmony_ci#endif
852141cc406Sopenharmony_ci
853141cc406Sopenharmony_ci
854141cc406Sopenharmony_ci
855141cc406Sopenharmony_ci#endif /* IO_SUPPORT_MISSING */
856141cc406Sopenharmony_ci  return 1;
857141cc406Sopenharmony_ci}
858141cc406Sopenharmony_ci
859141cc406Sopenharmony_ci
860141cc406Sopenharmony_ci
861141cc406Sopenharmony_ci
862141cc406Sopenharmony_ci
863141cc406Sopenharmony_ci
864141cc406Sopenharmony_cistatic void
865141cc406Sopenharmony_ciOutb (int port, int value)
866141cc406Sopenharmony_ci{
867141cc406Sopenharmony_ci#ifndef IO_SUPPORT_MISSING
868141cc406Sopenharmony_ci
869141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
870141cc406Sopenharmony_ci  int fd, rc, mode, exmode;
871141cc406Sopenharmony_ci  unsigned char val;
872141cc406Sopenharmony_ci
873141cc406Sopenharmony_ci
874141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
875141cc406Sopenharmony_ci  val = (unsigned char) value;
876141cc406Sopenharmony_ci  if (fd > 0)
877141cc406Sopenharmony_ci    {
878141cc406Sopenharmony_ci      /* there should be ECR that doesn't go through ppdev */
879141cc406Sopenharmony_ci      /* it will leave when all the I/O will be done with ppdev   */
880141cc406Sopenharmony_ci      switch (port - gPort)
881141cc406Sopenharmony_ci	{
882141cc406Sopenharmony_ci	case 0:
883141cc406Sopenharmony_ci	  rc = ioctl (fd, PPWDATA, &val);
884141cc406Sopenharmony_ci	  if (rc)
885141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
886141cc406Sopenharmony_ci		 __FILE__, __LINE__);
887141cc406Sopenharmony_ci#ifdef IOLOG
888141cc406Sopenharmony_ci	  DBG (0, "outb DATA,%02X\n", value);
889141cc406Sopenharmony_ci#endif
890141cc406Sopenharmony_ci	  return;
891141cc406Sopenharmony_ci	case 2:
892141cc406Sopenharmony_ci	  mode = val & 0x20;
893141cc406Sopenharmony_ci	  rc = ioctl (fd, PPDATADIR, &mode);
894141cc406Sopenharmony_ci	  if (rc)
895141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
896141cc406Sopenharmony_ci		 strerror (errno), __FILE__, __LINE__);
897141cc406Sopenharmony_ci	  val = val & 0xDF;
898141cc406Sopenharmony_ci	  rc = ioctl (fd, PPWCONTROL, &val);
899141cc406Sopenharmony_ci	  if (rc)
900141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
901141cc406Sopenharmony_ci		 strerror (errno), __FILE__, __LINE__);
902141cc406Sopenharmony_ci#ifdef IOLOG
903141cc406Sopenharmony_ci	  DBG (0, "outb CONTROL,%02X\n", value);
904141cc406Sopenharmony_ci#endif
905141cc406Sopenharmony_ci	  return;
906141cc406Sopenharmony_ci	case 4:
907141cc406Sopenharmony_ci	  rc = ioctl (fd, PPGETMODE, &exmode);
908141cc406Sopenharmony_ci	  if (rc)
909141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
910141cc406Sopenharmony_ci		 __FILE__, __LINE__);
911141cc406Sopenharmony_ci	  mode = 0;		/* data forward */
912141cc406Sopenharmony_ci	  rc = ioctl (fd, PPDATADIR, &mode);
913141cc406Sopenharmony_ci	  if (rc)
914141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
915141cc406Sopenharmony_ci		 __FILE__, __LINE__);
916141cc406Sopenharmony_ci	  mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
917141cc406Sopenharmony_ci	  rc = ioctl (fd, PPSETMODE, &mode);
918141cc406Sopenharmony_ci	  if (rc)
919141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
920141cc406Sopenharmony_ci		 __FILE__, __LINE__);
921141cc406Sopenharmony_ci	  rc = write (fd, &val, 1);
922141cc406Sopenharmony_ci	  if (rc != 1)
923141cc406Sopenharmony_ci	    DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
924141cc406Sopenharmony_ci	  rc = ioctl (fd, PPSETMODE, &exmode);
925141cc406Sopenharmony_ci	  if (rc)
926141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
927141cc406Sopenharmony_ci		 __FILE__, __LINE__);
928141cc406Sopenharmony_ci#ifdef IOLOG
929141cc406Sopenharmony_ci	  DBG (0, "outb EPPDATA,%02X\n", value);
930141cc406Sopenharmony_ci#endif
931141cc406Sopenharmony_ci	  return;
932141cc406Sopenharmony_ci	case 3:
933141cc406Sopenharmony_ci	  rc = ioctl (fd, PPGETMODE, &exmode);
934141cc406Sopenharmony_ci	  if (rc)
935141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
936141cc406Sopenharmony_ci		 __FILE__, __LINE__);
937141cc406Sopenharmony_ci	  mode = 0;		/* data forward */
938141cc406Sopenharmony_ci	  rc = ioctl (fd, PPDATADIR, &mode);
939141cc406Sopenharmony_ci	  if (rc)
940141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
941141cc406Sopenharmony_ci		 __FILE__, __LINE__);
942141cc406Sopenharmony_ci	  mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
943141cc406Sopenharmony_ci	  rc = ioctl (fd, PPSETMODE, &mode);
944141cc406Sopenharmony_ci	  if (rc)
945141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
946141cc406Sopenharmony_ci		 __FILE__, __LINE__);
947141cc406Sopenharmony_ci	  rc = write (fd, &val, 1);
948141cc406Sopenharmony_ci	  if (rc != 1)
949141cc406Sopenharmony_ci	    DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
950141cc406Sopenharmony_ci	  rc = ioctl (fd, PPSETMODE, &exmode);
951141cc406Sopenharmony_ci	  if (rc)
952141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
953141cc406Sopenharmony_ci		 __FILE__, __LINE__);
954141cc406Sopenharmony_ci	  return;
955141cc406Sopenharmony_ci	case 0x400:
956141cc406Sopenharmony_ci	case 0x402:
957141cc406Sopenharmony_ci	  break;
958141cc406Sopenharmony_ci	default:
959141cc406Sopenharmony_ci	  DBG (16, "Outb(0x%03X,0x%02X) escaped ppdev\n", port, value);
960141cc406Sopenharmony_ci	  return;
961141cc406Sopenharmony_ci	}
962141cc406Sopenharmony_ci    }
963141cc406Sopenharmony_ci#endif /* HAVE_LINUX_PPDEV_H */
964141cc406Sopenharmony_ci
965141cc406Sopenharmony_ci
966141cc406Sopenharmony_ci#ifdef HAVE_DEV_PPBUS_PPI_H
967141cc406Sopenharmony_ci  int fd, rc;
968141cc406Sopenharmony_ci  unsigned char val;
969141cc406Sopenharmony_ci
970141cc406Sopenharmony_ci
971141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
972141cc406Sopenharmony_ci  val = (unsigned char) value;
973141cc406Sopenharmony_ci  if (fd > 0)
974141cc406Sopenharmony_ci    {
975141cc406Sopenharmony_ci      switch (port - gPort)
976141cc406Sopenharmony_ci	{
977141cc406Sopenharmony_ci	case 0:
978141cc406Sopenharmony_ci	  rc = ioctl (fd, PPISDATA, &val);
979141cc406Sopenharmony_ci	  if (rc)
980141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
981141cc406Sopenharmony_ci		 __FILE__, __LINE__);
982141cc406Sopenharmony_ci	  return;
983141cc406Sopenharmony_ci	case 1:
984141cc406Sopenharmony_ci	  rc = ioctl (fd, PPISSTATUS, &val);
985141cc406Sopenharmony_ci	  if (rc)
986141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
987141cc406Sopenharmony_ci		 __FILE__, __LINE__);
988141cc406Sopenharmony_ci	  return;
989141cc406Sopenharmony_ci	case 2:
990141cc406Sopenharmony_ci	  rc = ioctl (fd, PPISCTRL, &val);
991141cc406Sopenharmony_ci	  if (rc)
992141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
993141cc406Sopenharmony_ci		 __FILE__, __LINE__);
994141cc406Sopenharmony_ci	  return;
995141cc406Sopenharmony_ci	case 3:
996141cc406Sopenharmony_ci	  rc = ioctl (fd, PPISEPPA, &val);
997141cc406Sopenharmony_ci	  if (rc)
998141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
999141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1000141cc406Sopenharmony_ci	  return;
1001141cc406Sopenharmony_ci	case 4:
1002141cc406Sopenharmony_ci	  rc = ioctl (fd, PPISEPPD, &val);
1003141cc406Sopenharmony_ci	  if (rc)
1004141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1005141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1006141cc406Sopenharmony_ci	  return;
1007141cc406Sopenharmony_ci	case 0x402:
1008141cc406Sopenharmony_ci	  rc = ioctl (fd, PPISECR, &val);
1009141cc406Sopenharmony_ci	  if (rc)
1010141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1011141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1012141cc406Sopenharmony_ci	  return;
1013141cc406Sopenharmony_ci	default:
1014141cc406Sopenharmony_ci	  DBG (16, "Outb(0x%03X,0x%02X) escaped ppi\n", port, value);
1015141cc406Sopenharmony_ci	  return;
1016141cc406Sopenharmony_ci	}
1017141cc406Sopenharmony_ci    }
1018141cc406Sopenharmony_ci#endif /* HAVE_DEV_PPBUS_PPI_H */
1019141cc406Sopenharmony_ci
1020141cc406Sopenharmony_ci  sanei_outb (port, value);
1021141cc406Sopenharmony_ci
1022141cc406Sopenharmony_ci#endif /* IO_SUPPORT_MISSING */
1023141cc406Sopenharmony_ci}
1024141cc406Sopenharmony_ci
1025141cc406Sopenharmony_ci
1026141cc406Sopenharmony_ci
1027141cc406Sopenharmony_ci
1028141cc406Sopenharmony_ci
1029141cc406Sopenharmony_cistatic int
1030141cc406Sopenharmony_ciInb (int port)
1031141cc406Sopenharmony_ci{
1032141cc406Sopenharmony_ci  int res = 0xFF;
1033141cc406Sopenharmony_ci#ifndef IO_SUPPORT_MISSING
1034141cc406Sopenharmony_ci
1035141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
1036141cc406Sopenharmony_ci  int fd, rc, mode;
1037141cc406Sopenharmony_ci  unsigned char val;
1038141cc406Sopenharmony_ci
1039141cc406Sopenharmony_ci
1040141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
1041141cc406Sopenharmony_ci  if (fd > 0)
1042141cc406Sopenharmony_ci    {
1043141cc406Sopenharmony_ci      /* there should be ECR that doesn't go through ppdev */
1044141cc406Sopenharmony_ci      /* it will leave when all the I/O will be done with ppdev   */
1045141cc406Sopenharmony_ci      switch (port - gPort)
1046141cc406Sopenharmony_ci	{
1047141cc406Sopenharmony_ci	case 0:
1048141cc406Sopenharmony_ci	  rc = ioctl (fd, PPRDATA, &val);
1049141cc406Sopenharmony_ci	  if (rc)
1050141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1051141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1052141cc406Sopenharmony_ci	  res = val;
1053141cc406Sopenharmony_ci#ifdef IOLOG
1054141cc406Sopenharmony_ci	  DBG (0, "inb  DATA,%02X\n", res);
1055141cc406Sopenharmony_ci#endif
1056141cc406Sopenharmony_ci	  return res;
1057141cc406Sopenharmony_ci
1058141cc406Sopenharmony_ci	case 1:
1059141cc406Sopenharmony_ci	  rc = ioctl (fd, PPRSTATUS, &val);
1060141cc406Sopenharmony_ci	  if (rc)
1061141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1062141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1063141cc406Sopenharmony_ci	  res = val;
1064141cc406Sopenharmony_ci#ifdef IOLOG
1065141cc406Sopenharmony_ci	  DBG (0, "inb  STATUS,%02X\n", res);
1066141cc406Sopenharmony_ci#endif
1067141cc406Sopenharmony_ci	  return res;
1068141cc406Sopenharmony_ci
1069141cc406Sopenharmony_ci	case 2:
1070141cc406Sopenharmony_ci	  rc = ioctl (fd, PPRCONTROL, &val);
1071141cc406Sopenharmony_ci	  if (rc)
1072141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1073141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1074141cc406Sopenharmony_ci	  res = val;
1075141cc406Sopenharmony_ci#ifdef IOLOG
1076141cc406Sopenharmony_ci	  DBG (0, "inb  CONTROL,%02X\n", res);
1077141cc406Sopenharmony_ci#endif
1078141cc406Sopenharmony_ci	  return res;
1079141cc406Sopenharmony_ci
1080141cc406Sopenharmony_ci	case 4:
1081141cc406Sopenharmony_ci	  mode = 1;		/* data_reverse */
1082141cc406Sopenharmony_ci	  rc = ioctl (fd, PPDATADIR, &mode);
1083141cc406Sopenharmony_ci	  if (rc)
1084141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1085141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1086141cc406Sopenharmony_ci	  mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
1087141cc406Sopenharmony_ci	  rc = ioctl (fd, PPSETMODE, &mode);
1088141cc406Sopenharmony_ci	  if (rc)
1089141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1090141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1091141cc406Sopenharmony_ci	  rc = read (fd, &val, 1);
1092141cc406Sopenharmony_ci	  if (rc != 1)
1093141cc406Sopenharmony_ci	    DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__);
1094141cc406Sopenharmony_ci	  mode = 0;		/* data_forward */
1095141cc406Sopenharmony_ci	  rc = ioctl (fd, PPDATADIR, &mode);
1096141cc406Sopenharmony_ci	  if (rc)
1097141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1098141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1099141cc406Sopenharmony_ci	  res = val;
1100141cc406Sopenharmony_ci#ifdef IOLOG
1101141cc406Sopenharmony_ci	  DBG (0, "inb  EPPDATA,%02X\n", res);
1102141cc406Sopenharmony_ci#endif
1103141cc406Sopenharmony_ci	  return res;
1104141cc406Sopenharmony_ci	case 0x400:
1105141cc406Sopenharmony_ci	case 0x402:
1106141cc406Sopenharmony_ci	default:
1107141cc406Sopenharmony_ci	  DBG (16, "Inb(0x%03X) escaped ppdev\n", port);
1108141cc406Sopenharmony_ci	  return 0xFF;
1109141cc406Sopenharmony_ci	}
1110141cc406Sopenharmony_ci    }
1111141cc406Sopenharmony_ci#endif /* HAVE_LINUX_PPDEV_H */
1112141cc406Sopenharmony_ci
1113141cc406Sopenharmony_ci
1114141cc406Sopenharmony_ci#ifdef HAVE_DEV_PPBUS_PPI_H
1115141cc406Sopenharmony_ci  int fd, rc;
1116141cc406Sopenharmony_ci  unsigned char val;
1117141cc406Sopenharmony_ci
1118141cc406Sopenharmony_ci
1119141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
1120141cc406Sopenharmony_ci  if (fd > 0)
1121141cc406Sopenharmony_ci    {
1122141cc406Sopenharmony_ci      switch (port - gPort)
1123141cc406Sopenharmony_ci	{
1124141cc406Sopenharmony_ci	case 0:
1125141cc406Sopenharmony_ci	  rc = ioctl (fd, PPIGDATA, &val);
1126141cc406Sopenharmony_ci	  if (rc)
1127141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1128141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1129141cc406Sopenharmony_ci	  res = val;
1130141cc406Sopenharmony_ci	  return res;
1131141cc406Sopenharmony_ci	case 1:
1132141cc406Sopenharmony_ci	  rc = ioctl (fd, PPIGSTATUS, &val);
1133141cc406Sopenharmony_ci	  if (rc)
1134141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1135141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1136141cc406Sopenharmony_ci	  res = val;
1137141cc406Sopenharmony_ci	  return res;
1138141cc406Sopenharmony_ci	case 2:
1139141cc406Sopenharmony_ci	  rc = ioctl (fd, PPIGCTRL, &val);
1140141cc406Sopenharmony_ci	  if (rc)
1141141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1142141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1143141cc406Sopenharmony_ci	  res = val;
1144141cc406Sopenharmony_ci	  return res;
1145141cc406Sopenharmony_ci	case 3:
1146141cc406Sopenharmony_ci	  rc = ioctl (fd, PPIGEPPA, &val);
1147141cc406Sopenharmony_ci	  if (rc)
1148141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1149141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1150141cc406Sopenharmony_ci	  res = val;
1151141cc406Sopenharmony_ci	  return res;
1152141cc406Sopenharmony_ci	case 4:
1153141cc406Sopenharmony_ci	  rc = ioctl (fd, PPIGEPPD, &val);
1154141cc406Sopenharmony_ci	  if (rc)
1155141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1156141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1157141cc406Sopenharmony_ci	  res = val;
1158141cc406Sopenharmony_ci	  return res;
1159141cc406Sopenharmony_ci	case 0x402:
1160141cc406Sopenharmony_ci	  rc = ioctl (fd, PPIGECR, &val);
1161141cc406Sopenharmony_ci	  if (rc)
1162141cc406Sopenharmony_ci	    DBG (0, "ppi ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1163141cc406Sopenharmony_ci		 __FILE__, __LINE__);
1164141cc406Sopenharmony_ci	  res = val;
1165141cc406Sopenharmony_ci	  return res;
1166141cc406Sopenharmony_ci	default:
1167141cc406Sopenharmony_ci	  DBG (16, "Inb(0x%03X) escaped ppi\n", port);
1168141cc406Sopenharmony_ci	  return 0xFF;
1169141cc406Sopenharmony_ci	}
1170141cc406Sopenharmony_ci    }
1171141cc406Sopenharmony_ci#endif /* HAVE_DEV_PPBUS_PPI_H */
1172141cc406Sopenharmony_ci
1173141cc406Sopenharmony_ci  res = sanei_inb (port);
1174141cc406Sopenharmony_ci
1175141cc406Sopenharmony_ci#endif /* IO_SUPPORT_MISSING */
1176141cc406Sopenharmony_ci  return res;
1177141cc406Sopenharmony_ci}
1178141cc406Sopenharmony_ci
1179141cc406Sopenharmony_ci
1180141cc406Sopenharmony_cistatic void
1181141cc406Sopenharmony_ciInsb (int port, unsigned char *dest, int size)
1182141cc406Sopenharmony_ci{
1183141cc406Sopenharmony_ci#ifndef IO_SUPPORT_MISSING
1184141cc406Sopenharmony_ci
1185141cc406Sopenharmony_ci#ifdef HAVE_DEV_PPBUS_PPI_H
1186141cc406Sopenharmony_ci  int i;
1187141cc406Sopenharmony_ci  if (sanei_umax_pp_getparport () > 0)
1188141cc406Sopenharmony_ci    {
1189141cc406Sopenharmony_ci      for (i = 0; i < size; i++)
1190141cc406Sopenharmony_ci	dest[i] = Inb (port);
1191141cc406Sopenharmony_ci      return;
1192141cc406Sopenharmony_ci    }
1193141cc406Sopenharmony_ci#endif /* HAVE_DEV_PPBUS_PPI_H */
1194141cc406Sopenharmony_ci  sanei_insb (port, dest, size);
1195141cc406Sopenharmony_ci
1196141cc406Sopenharmony_ci#endif
1197141cc406Sopenharmony_ci}
1198141cc406Sopenharmony_ci
1199141cc406Sopenharmony_cistatic void
1200141cc406Sopenharmony_ciOutsb (int port, unsigned char *source, int size)
1201141cc406Sopenharmony_ci{
1202141cc406Sopenharmony_ci#ifndef IO_SUPPORT_MISSING
1203141cc406Sopenharmony_ci
1204141cc406Sopenharmony_ci#ifdef HAVE_DEV_PPBUS_PPI_H
1205141cc406Sopenharmony_ci  int i;
1206141cc406Sopenharmony_ci
1207141cc406Sopenharmony_ci  if (sanei_umax_pp_getparport () > 0)
1208141cc406Sopenharmony_ci    {
1209141cc406Sopenharmony_ci      for (i = 0; i < size; i++)
1210141cc406Sopenharmony_ci	Outb (port, source[i]);
1211141cc406Sopenharmony_ci      return;
1212141cc406Sopenharmony_ci    }
1213141cc406Sopenharmony_ci#endif /* HAVE_DEV_PPBUS_PPI_H */
1214141cc406Sopenharmony_ci
1215141cc406Sopenharmony_ci  sanei_outsb (port, source, size);
1216141cc406Sopenharmony_ci
1217141cc406Sopenharmony_ci#endif
1218141cc406Sopenharmony_ci}
1219141cc406Sopenharmony_ci
1220141cc406Sopenharmony_ci
1221141cc406Sopenharmony_ci
1222141cc406Sopenharmony_ci/* size = nb words */
1223141cc406Sopenharmony_cistatic void
1224141cc406Sopenharmony_ciInsw (int port, unsigned char *dest, int size)
1225141cc406Sopenharmony_ci{
1226141cc406Sopenharmony_ci#ifndef IO_SUPPORT_MISSING
1227141cc406Sopenharmony_ci
1228141cc406Sopenharmony_ci#ifdef HAVE_DEV_PPBUS_PPI_H
1229141cc406Sopenharmony_ci  int i;
1230141cc406Sopenharmony_ci
1231141cc406Sopenharmony_ci  if (sanei_umax_pp_getparport () > 0)
1232141cc406Sopenharmony_ci    {
1233141cc406Sopenharmony_ci      for (i = 0; i < size * 4; i++)
1234141cc406Sopenharmony_ci	dest[i] = Inb (port);
1235141cc406Sopenharmony_ci      return;
1236141cc406Sopenharmony_ci    }
1237141cc406Sopenharmony_ci#endif /* HAVE_DEV_PPBUS_PPI_H */
1238141cc406Sopenharmony_ci
1239141cc406Sopenharmony_ci  sanei_insl (port, dest, size);
1240141cc406Sopenharmony_ci
1241141cc406Sopenharmony_ci#endif
1242141cc406Sopenharmony_ci}
1243141cc406Sopenharmony_ci
1244141cc406Sopenharmony_cistatic void
1245141cc406Sopenharmony_ciOutsw (int port, unsigned char *source, int size)
1246141cc406Sopenharmony_ci{
1247141cc406Sopenharmony_ci#ifndef IO_SUPPORT_MISSING
1248141cc406Sopenharmony_ci
1249141cc406Sopenharmony_ci#ifdef HAVE_DEV_PPBUS_PPI_H
1250141cc406Sopenharmony_ci  int i;
1251141cc406Sopenharmony_ci
1252141cc406Sopenharmony_ci  if (sanei_umax_pp_getparport () > 0)
1253141cc406Sopenharmony_ci    {
1254141cc406Sopenharmony_ci      for (i = 0; i < size * 4; i++)
1255141cc406Sopenharmony_ci	Outb (port, source[i]);
1256141cc406Sopenharmony_ci      return;
1257141cc406Sopenharmony_ci    }
1258141cc406Sopenharmony_ci#endif /* HAVE_DEV_PPBUS_PPI_H */
1259141cc406Sopenharmony_ci
1260141cc406Sopenharmony_ci  sanei_outsl (port, source, size);
1261141cc406Sopenharmony_ci
1262141cc406Sopenharmony_ci#endif
1263141cc406Sopenharmony_ci}
1264141cc406Sopenharmony_ci
1265141cc406Sopenharmony_ci
1266141cc406Sopenharmony_ci/* we're trying to gather information on the scanner here, */
1267141cc406Sopenharmony_ci/* and published it through an easy interface              */
1268141cc406Sopenharmony_ci/* will turn it into a struct when 610P code will be done  */
1269141cc406Sopenharmony_cistatic int scannerStatus = 0;
1270141cc406Sopenharmony_cistatic time_t gTime = 0;
1271141cc406Sopenharmony_cistatic time_t gDelay = 0;
1272141cc406Sopenharmony_cistatic int epp32 = 1;
1273141cc406Sopenharmony_cistatic int gMode = 0;
1274141cc406Sopenharmony_cistatic int gprobed = 0;
1275141cc406Sopenharmony_cistatic int model = 0x15;
1276141cc406Sopenharmony_cistatic int astra = 0;
1277141cc406Sopenharmony_cistatic int hasUTA = 0;
1278141cc406Sopenharmony_ci
1279141cc406Sopenharmony_ci/* signals that scan width matches full ccd width */
1280141cc406Sopenharmony_cistatic int fullCCDWidth = 0;
1281141cc406Sopenharmony_ci
1282141cc406Sopenharmony_ciint
1283141cc406Sopenharmony_cisanei_umax_pp_getfull (void)
1284141cc406Sopenharmony_ci{
1285141cc406Sopenharmony_ci  return fullCCDWidth;
1286141cc406Sopenharmony_ci}
1287141cc406Sopenharmony_ci
1288141cc406Sopenharmony_civoid
1289141cc406Sopenharmony_cisanei_umax_pp_setfull (int mod)
1290141cc406Sopenharmony_ci{
1291141cc406Sopenharmony_ci  fullCCDWidth = mod;
1292141cc406Sopenharmony_ci}
1293141cc406Sopenharmony_ci
1294141cc406Sopenharmony_ci
1295141cc406Sopenharmony_ciint
1296141cc406Sopenharmony_cisanei_umax_pp_UTA (void)
1297141cc406Sopenharmony_ci{
1298141cc406Sopenharmony_ci  return hasUTA;
1299141cc406Sopenharmony_ci}
1300141cc406Sopenharmony_ci
1301141cc406Sopenharmony_ciint
1302141cc406Sopenharmony_cisanei_umax_pp_scannerStatus (void)
1303141cc406Sopenharmony_ci{
1304141cc406Sopenharmony_ci  struct timeval tv;
1305141cc406Sopenharmony_ci
1306141cc406Sopenharmony_ci  /* the 610P ASIC needs some time to settle down after probe */
1307141cc406Sopenharmony_ci  if ((gTime > 0) && (gDelay > 0))
1308141cc406Sopenharmony_ci    {
1309141cc406Sopenharmony_ci      gettimeofday (&tv, NULL);
1310141cc406Sopenharmony_ci      /* delay elapsed ? */
1311141cc406Sopenharmony_ci      if (tv.tv_sec - gTime < gDelay)
1312141cc406Sopenharmony_ci	/* still waiting */
1313141cc406Sopenharmony_ci	return ASIC_BIT;
1314141cc406Sopenharmony_ci      /* wait finished */
1315141cc406Sopenharmony_ci      gDelay = 0;
1316141cc406Sopenharmony_ci      gTime = 0;
1317141cc406Sopenharmony_ci    }
1318141cc406Sopenharmony_ci
1319141cc406Sopenharmony_ci  /* 0x07 variant returns status with bit 0 or 1 always set to 1 */
1320141cc406Sopenharmony_ci  /* so we mask it out                                            */
1321141cc406Sopenharmony_ci  return scannerStatus & 0xFC;
1322141cc406Sopenharmony_ci}
1323141cc406Sopenharmony_ci
1324141cc406Sopenharmony_cistatic int
1325141cc406Sopenharmony_cigetEPPMode (void)
1326141cc406Sopenharmony_ci{
1327141cc406Sopenharmony_ci  if (epp32)
1328141cc406Sopenharmony_ci    return 32;
1329141cc406Sopenharmony_ci  return 8;
1330141cc406Sopenharmony_ci}
1331141cc406Sopenharmony_ci
1332141cc406Sopenharmony_cistatic void
1333141cc406Sopenharmony_cisetEPPMode (int mode)
1334141cc406Sopenharmony_ci{
1335141cc406Sopenharmony_ci  if (mode == 8)
1336141cc406Sopenharmony_ci    epp32 = 0;
1337141cc406Sopenharmony_ci  else
1338141cc406Sopenharmony_ci    epp32 = 1;
1339141cc406Sopenharmony_ci}
1340141cc406Sopenharmony_ci
1341141cc406Sopenharmony_cistatic int
1342141cc406Sopenharmony_cigetModel (void)
1343141cc406Sopenharmony_ci{
1344141cc406Sopenharmony_ci  return model;
1345141cc406Sopenharmony_ci}
1346141cc406Sopenharmony_ci
1347141cc406Sopenharmony_cistatic void
1348141cc406Sopenharmony_cisetModel (int mod)
1349141cc406Sopenharmony_ci{
1350141cc406Sopenharmony_ci  model = mod;
1351141cc406Sopenharmony_ci}
1352141cc406Sopenharmony_ci
1353141cc406Sopenharmony_ci
1354141cc406Sopenharmony_ciint
1355141cc406Sopenharmony_cisanei_umax_pp_getparport (void)
1356141cc406Sopenharmony_ci{
1357141cc406Sopenharmony_ci  return gParport;
1358141cc406Sopenharmony_ci}
1359141cc406Sopenharmony_ci
1360141cc406Sopenharmony_civoid
1361141cc406Sopenharmony_cisanei_umax_pp_setparport (int fd)
1362141cc406Sopenharmony_ci{
1363141cc406Sopenharmony_ci  gParport = fd;
1364141cc406Sopenharmony_ci}
1365141cc406Sopenharmony_ci
1366141cc406Sopenharmony_ciint
1367141cc406Sopenharmony_cisanei_umax_pp_getport (void)
1368141cc406Sopenharmony_ci{
1369141cc406Sopenharmony_ci  return gPort;
1370141cc406Sopenharmony_ci}
1371141cc406Sopenharmony_ci
1372141cc406Sopenharmony_civoid
1373141cc406Sopenharmony_cisanei_umax_pp_setport (int port)
1374141cc406Sopenharmony_ci{
1375141cc406Sopenharmony_ci  gPort = port;
1376141cc406Sopenharmony_ci}
1377141cc406Sopenharmony_ci
1378141cc406Sopenharmony_ciint
1379141cc406Sopenharmony_cisanei_umax_pp_getastra (void)
1380141cc406Sopenharmony_ci{
1381141cc406Sopenharmony_ci  return astra;
1382141cc406Sopenharmony_ci}
1383141cc406Sopenharmony_ci
1384141cc406Sopenharmony_civoid
1385141cc406Sopenharmony_cisanei_umax_pp_setastra (int mod)
1386141cc406Sopenharmony_ci{
1387141cc406Sopenharmony_ci  astra = mod;
1388141cc406Sopenharmony_ci}
1389141cc406Sopenharmony_ci
1390141cc406Sopenharmony_ciint
1391141cc406Sopenharmony_cisanei_umax_pp_getLeft (void)
1392141cc406Sopenharmony_ci{
1393141cc406Sopenharmony_ci  switch (sanei_umax_pp_getastra ())
1394141cc406Sopenharmony_ci    {
1395141cc406Sopenharmony_ci    case 610:
1396141cc406Sopenharmony_ci      return 92;
1397141cc406Sopenharmony_ci    default:
1398141cc406Sopenharmony_ci      return 144;
1399141cc406Sopenharmony_ci    }
1400141cc406Sopenharmony_ci}
1401141cc406Sopenharmony_ci
1402141cc406Sopenharmony_civoid
1403141cc406Sopenharmony_cisanei_umax_pp_setLeft (int mod)
1404141cc406Sopenharmony_ci{
1405141cc406Sopenharmony_ci  gLeft = mod;
1406141cc406Sopenharmony_ci}
1407141cc406Sopenharmony_ci
1408141cc406Sopenharmony_ciint
1409141cc406Sopenharmony_cisanei_umax_pp_getauto (void)
1410141cc406Sopenharmony_ci{
1411141cc406Sopenharmony_ci  return gAutoSettings;
1412141cc406Sopenharmony_ci}
1413141cc406Sopenharmony_ci
1414141cc406Sopenharmony_civoid
1415141cc406Sopenharmony_cisanei_umax_pp_setauto (int autoset)
1416141cc406Sopenharmony_ci{
1417141cc406Sopenharmony_ci  gAutoSettings = autoset;
1418141cc406Sopenharmony_ci}
1419141cc406Sopenharmony_ci
1420141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
1421141cc406Sopenharmony_ci/* set to the parallel port needed using ppdev
1422141cc406Sopenharmony_ci * returns 1 if ok, 0 else
1423141cc406Sopenharmony_ci */
1424141cc406Sopenharmony_cistatic int
1425141cc406Sopenharmony_cippdev_set_mode (int mode)
1426141cc406Sopenharmony_ci{
1427141cc406Sopenharmony_ci  int fd, rc;
1428141cc406Sopenharmony_ci
1429141cc406Sopenharmony_ci  /* check we have ppdev working */
1430141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
1431141cc406Sopenharmony_ci  if (fd > 0)
1432141cc406Sopenharmony_ci    {
1433141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
1434141cc406Sopenharmony_ci      if (rc)
1435141cc406Sopenharmony_ci	{
1436141cc406Sopenharmony_ci	  DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
1437141cc406Sopenharmony_ci	       __FILE__, __LINE__);
1438141cc406Sopenharmony_ci	  return 0;
1439141cc406Sopenharmony_ci	}
1440141cc406Sopenharmony_ci      return 1;
1441141cc406Sopenharmony_ci    }
1442141cc406Sopenharmony_ci  return 0;
1443141cc406Sopenharmony_ci}
1444141cc406Sopenharmony_ci#endif
1445141cc406Sopenharmony_ci
1446141cc406Sopenharmony_ci/* set parallel port mode to 'compatible'*/
1447141cc406Sopenharmony_cistatic void
1448141cc406Sopenharmony_cicompatMode (void)
1449141cc406Sopenharmony_ci{
1450141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
1451141cc406Sopenharmony_ci  if (ppdev_set_mode (IEEE1284_MODE_COMPAT))
1452141cc406Sopenharmony_ci    return;
1453141cc406Sopenharmony_ci#endif
1454141cc406Sopenharmony_ci  if (!gECP)
1455141cc406Sopenharmony_ci    return;
1456141cc406Sopenharmony_ci  Outb (ECR, 0x15);
1457141cc406Sopenharmony_ci}
1458141cc406Sopenharmony_ci
1459141cc406Sopenharmony_ci/* set parallel port mode to 'bidirectionel'*/
1460141cc406Sopenharmony_cistatic void
1461141cc406Sopenharmony_cibyteMode (void)
1462141cc406Sopenharmony_ci{
1463141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
1464141cc406Sopenharmony_ci  if (ppdev_set_mode (IEEE1284_MODE_BYTE))
1465141cc406Sopenharmony_ci    return;
1466141cc406Sopenharmony_ci#endif
1467141cc406Sopenharmony_ci  if (!gECP)
1468141cc406Sopenharmony_ci    return;
1469141cc406Sopenharmony_ci  Outb (ECR, 0x35);		/* or 0x34 */
1470141cc406Sopenharmony_ci}
1471141cc406Sopenharmony_ci
1472141cc406Sopenharmony_ci/* set parallel port mode to 'fifo'*/
1473141cc406Sopenharmony_cistatic void
1474141cc406Sopenharmony_ciECPFifoMode (void)
1475141cc406Sopenharmony_ci{
1476141cc406Sopenharmony_ci  /* bits 7:5 :
1477141cc406Sopenharmony_ci     000 Standard Mode
1478141cc406Sopenharmony_ci     001 Byte Mode
1479141cc406Sopenharmony_ci     010 Parallel Port FIFO Mode
1480141cc406Sopenharmony_ci     011 ECP FIFO Mode
1481141cc406Sopenharmony_ci     100 EPP Mode
1482141cc406Sopenharmony_ci     101 Reserved
1483141cc406Sopenharmony_ci     110 FIFO Test Mode
1484141cc406Sopenharmony_ci     111 Configuration Mode
1485141cc406Sopenharmony_ci   */
1486141cc406Sopenharmony_ci  /* logged as 74/75 */
1487141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
1488141cc406Sopenharmony_ci  if (ppdev_set_mode (IEEE1284_MODE_ECP))
1489141cc406Sopenharmony_ci    return;
1490141cc406Sopenharmony_ci#endif
1491141cc406Sopenharmony_ci  if (!gECP)
1492141cc406Sopenharmony_ci    return;
1493141cc406Sopenharmony_ci  Outb (ECR, 0x75);
1494141cc406Sopenharmony_ci}
1495141cc406Sopenharmony_ci
1496141cc406Sopenharmony_ci/* wait for ack bit */
1497141cc406Sopenharmony_ci/* return 1 on success, 0 on error */
1498141cc406Sopenharmony_cistatic int
1499141cc406Sopenharmony_ciwaitAck ()
1500141cc406Sopenharmony_ci{
1501141cc406Sopenharmony_ci  unsigned char breg = 0;
1502141cc406Sopenharmony_ci  int i = 0;
1503141cc406Sopenharmony_ci
1504141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);		/* select printer + initialize printer */
1505141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
1506141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
1507141cc406Sopenharmony_ci  breg = Inb (STATUS) & 0xF8;
1508141cc406Sopenharmony_ci  while ((i < 1024) && ((breg & 0x04) == 0))
1509141cc406Sopenharmony_ci    {
1510141cc406Sopenharmony_ci      Outb (CONTROL, 0x0E);	/* autolinefeed ?.. */
1511141cc406Sopenharmony_ci      Outb (CONTROL, 0x0E);
1512141cc406Sopenharmony_ci      Outb (CONTROL, 0x0E);
1513141cc406Sopenharmony_ci      breg = Inb (STATUS) & 0xF8;
1514141cc406Sopenharmony_ci      i++;
1515141cc406Sopenharmony_ci      usleep (1000);
1516141cc406Sopenharmony_ci    }
1517141cc406Sopenharmony_ci  if (i == 1024)
1518141cc406Sopenharmony_ci    {
1519141cc406Sopenharmony_ci      DBG (1, "waitAck failed, time-out waiting for Ack (%s:%d)\n",
1520141cc406Sopenharmony_ci	   __FILE__, __LINE__);
1521141cc406Sopenharmony_ci      /* return 0; seems to be non-blocking ... */
1522141cc406Sopenharmony_ci    }
1523141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);		/* printer reset */
1524141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1525141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1526141cc406Sopenharmony_ci  return 1;
1527141cc406Sopenharmony_ci}
1528141cc406Sopenharmony_ci
1529141cc406Sopenharmony_cistatic int
1530141cc406Sopenharmony_ciwaitFifoEmpty (void)
1531141cc406Sopenharmony_ci{
1532141cc406Sopenharmony_ci  int i;
1533141cc406Sopenharmony_ci  unsigned char breg;
1534141cc406Sopenharmony_ci
1535141cc406Sopenharmony_ci  breg = Inb (ECR);
1536141cc406Sopenharmony_ci  i = 0;
1537141cc406Sopenharmony_ci  while ((i < FIFO_WAIT) && ((breg & 0x01) == 0))
1538141cc406Sopenharmony_ci    {
1539141cc406Sopenharmony_ci      breg = Inb (ECR);
1540141cc406Sopenharmony_ci      i++;
1541141cc406Sopenharmony_ci    }
1542141cc406Sopenharmony_ci  if (i == FIFO_WAIT)
1543141cc406Sopenharmony_ci    {
1544141cc406Sopenharmony_ci      DBG (0, "waitFifoEmpty failed, time-out waiting for FIFO (%s:%d)\n",
1545141cc406Sopenharmony_ci	   __FILE__, __LINE__);
1546141cc406Sopenharmony_ci      return 0;
1547141cc406Sopenharmony_ci    }
1548141cc406Sopenharmony_ci  return 1;
1549141cc406Sopenharmony_ci}
1550141cc406Sopenharmony_ci
1551141cc406Sopenharmony_cistatic int
1552141cc406Sopenharmony_ciwaitFifoNotEmpty (void)
1553141cc406Sopenharmony_ci{
1554141cc406Sopenharmony_ci  int i;
1555141cc406Sopenharmony_ci  unsigned char breg;
1556141cc406Sopenharmony_ci
1557141cc406Sopenharmony_ci  breg = Inb (ECR);
1558141cc406Sopenharmony_ci  i = 0;
1559141cc406Sopenharmony_ci  while ((i < FIFO_WAIT) && ((breg & 0x01) != 0))
1560141cc406Sopenharmony_ci    {
1561141cc406Sopenharmony_ci      breg = Inb (ECR);
1562141cc406Sopenharmony_ci      i++;
1563141cc406Sopenharmony_ci      /* usleep (2000); */
1564141cc406Sopenharmony_ci    }
1565141cc406Sopenharmony_ci  if (i == FIFO_WAIT)
1566141cc406Sopenharmony_ci    {
1567141cc406Sopenharmony_ci      DBG (0, "waitFifoNotEmpty failed, time-out waiting for FIFO (%s:%d)\n",
1568141cc406Sopenharmony_ci	   __FILE__, __LINE__);
1569141cc406Sopenharmony_ci      return 0;
1570141cc406Sopenharmony_ci    }
1571141cc406Sopenharmony_ci  return 1;
1572141cc406Sopenharmony_ci}
1573141cc406Sopenharmony_ci
1574141cc406Sopenharmony_ci
1575141cc406Sopenharmony_cistatic int
1576141cc406Sopenharmony_ciwaitFifoFull (void)
1577141cc406Sopenharmony_ci{
1578141cc406Sopenharmony_ci  int i;
1579141cc406Sopenharmony_ci  unsigned char breg;
1580141cc406Sopenharmony_ci
1581141cc406Sopenharmony_ci  breg = Inb (ECR);
1582141cc406Sopenharmony_ci
1583141cc406Sopenharmony_ci  /* two wait loop */
1584141cc406Sopenharmony_ci  /* the first apply to fast data transfer (ie when no scaaning is undergoing) */
1585141cc406Sopenharmony_ci  /* and we fallback to the second in case the scanner is answering slowly */
1586141cc406Sopenharmony_ci  i = 0;
1587141cc406Sopenharmony_ci  while ((i < FIFO_WAIT) && ((breg & 0x02) == 0))
1588141cc406Sopenharmony_ci    {
1589141cc406Sopenharmony_ci      breg = Inb (ECR);
1590141cc406Sopenharmony_ci      i++;
1591141cc406Sopenharmony_ci    }
1592141cc406Sopenharmony_ci  /* don't need to wait any longer */
1593141cc406Sopenharmony_ci  if (i < FIFO_WAIT)
1594141cc406Sopenharmony_ci    return 1;
1595141cc406Sopenharmony_ci  i = 0;
1596141cc406Sopenharmony_ci  while ((i < FIFO_WAIT) && ((breg & 0x02) == 0))
1597141cc406Sopenharmony_ci    {
1598141cc406Sopenharmony_ci      breg = Inb (ECR);
1599141cc406Sopenharmony_ci      i++;
1600141cc406Sopenharmony_ci      usleep (500);
1601141cc406Sopenharmony_ci    }
1602141cc406Sopenharmony_ci  if (i == FIFO_WAIT)
1603141cc406Sopenharmony_ci    {
1604141cc406Sopenharmony_ci      DBG (0, "waitFifoFull failed, time-out waiting for FIFO (%s:%d)\n",
1605141cc406Sopenharmony_ci	   __FILE__, __LINE__);
1606141cc406Sopenharmony_ci      return 0;
1607141cc406Sopenharmony_ci    }
1608141cc406Sopenharmony_ci  return 1;
1609141cc406Sopenharmony_ci}
1610141cc406Sopenharmony_ci
1611141cc406Sopenharmony_ci/*
1612141cc406Sopenharmony_ci * surely some register reading in PS2 mode
1613141cc406Sopenharmony_ci * only one nibble is accessed, may be
1614141cc406Sopenharmony_ci * PS2RegisterLowNibbleRead(reg)
1615141cc406Sopenharmony_ci */
1616141cc406Sopenharmony_cistatic int
1617141cc406Sopenharmony_ciPS2Something (int reg)
1618141cc406Sopenharmony_ci{
1619141cc406Sopenharmony_ci  unsigned char breg, low, high = 0;
1620141cc406Sopenharmony_ci
1621141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1622141cc406Sopenharmony_ci  Outb (DATA, reg);		/* register number ? */
1623141cc406Sopenharmony_ci  Outb (CONTROL, 0x06);
1624141cc406Sopenharmony_ci  Outb (CONTROL, 0x06);
1625141cc406Sopenharmony_ci  Outb (CONTROL, 0x06);
1626141cc406Sopenharmony_ci  breg = Inb (STATUS) & 0xF8;
1627141cc406Sopenharmony_ci  low = breg;
1628141cc406Sopenharmony_ci  breg = breg & 0x08;
1629141cc406Sopenharmony_ci  /* surely means register(0x10)=0x0B */
1630141cc406Sopenharmony_ci  /* since reg & 0x08 != 0, high and low nibble
1631141cc406Sopenharmony_ci   * differ, but we don't care, since we surely expect it
1632141cc406Sopenharmony_ci   * to be 0
1633141cc406Sopenharmony_ci   */
1634141cc406Sopenharmony_ci  if (breg != 0x08)
1635141cc406Sopenharmony_ci    {
1636141cc406Sopenharmony_ci      DBG (0, "PS2Something failed, expecting 0x08, got 0x%02X (%s:%d)\n",
1637141cc406Sopenharmony_ci	   breg, __FILE__, __LINE__);
1638141cc406Sopenharmony_ci    }
1639141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
1640141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
1641141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
1642141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
1643141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
1644141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1645141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1646141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1647141cc406Sopenharmony_ci  if (breg != 0x08)
1648141cc406Sopenharmony_ci    high = Inb (STATUS) & 0xF0;
1649141cc406Sopenharmony_ci  return high + ((low & 0xF0) >> 4);
1650141cc406Sopenharmony_ci}
1651141cc406Sopenharmony_ci
1652141cc406Sopenharmony_cistatic int
1653141cc406Sopenharmony_ciPS2Read (void)
1654141cc406Sopenharmony_ci{
1655141cc406Sopenharmony_ci  int res;
1656141cc406Sopenharmony_ci  int tmp;
1657141cc406Sopenharmony_ci
1658141cc406Sopenharmony_ci  res = Inb (STATUS);
1659141cc406Sopenharmony_ci  res = Inb (STATUS);
1660141cc406Sopenharmony_ci  res = res & 0xF0;
1661141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1662141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1663141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1664141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1665141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1666141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1667141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1668141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1669141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1670141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1671141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1672141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1673141cc406Sopenharmony_ci
1674141cc406Sopenharmony_ci  tmp = Inb (STATUS);
1675141cc406Sopenharmony_ci  tmp = Inb (STATUS);
1676141cc406Sopenharmony_ci  tmp = (tmp & 0xF0) >> 4;
1677141cc406Sopenharmony_ci  res = res | tmp;
1678141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1679141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1680141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1681141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1682141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1683141cc406Sopenharmony_ci  Outb (CONTROL, 5);
1684141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1685141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1686141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1687141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1688141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1689141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1690141cc406Sopenharmony_ci
1691141cc406Sopenharmony_ci  return res;
1692141cc406Sopenharmony_ci}
1693141cc406Sopenharmony_ci
1694141cc406Sopenharmony_ci
1695141cc406Sopenharmony_ci/******************************************************************************/
1696141cc406Sopenharmony_ci/* PS2registerWrite: write value in register, slow method                            */
1697141cc406Sopenharmony_ci/******************************************************************************/
1698141cc406Sopenharmony_cistatic void
1699141cc406Sopenharmony_ciPS2registerWrite (int reg, int value)
1700141cc406Sopenharmony_ci{
1701141cc406Sopenharmony_ci  /* select register */
1702141cc406Sopenharmony_ci  Outb (DATA, reg | 0x60);
1703141cc406Sopenharmony_ci  Outb (DATA, reg | 0x60);
1704141cc406Sopenharmony_ci  Outb (CONTROL, 0x01);
1705141cc406Sopenharmony_ci  Outb (CONTROL, 0x01);
1706141cc406Sopenharmony_ci  Outb (CONTROL, 0x01);
1707141cc406Sopenharmony_ci
1708141cc406Sopenharmony_ci  /* send value */
1709141cc406Sopenharmony_ci  Outb (DATA, value);
1710141cc406Sopenharmony_ci  Outb (DATA, value);
1711141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1712141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1713141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1714141cc406Sopenharmony_ci}
1715141cc406Sopenharmony_ci
1716141cc406Sopenharmony_ci
1717141cc406Sopenharmony_ci
1718141cc406Sopenharmony_ci/*****************************************************************************/
1719141cc406Sopenharmony_ci/* Send command returns 0 on failure, 1 on success                           */
1720141cc406Sopenharmony_ci/*****************************************************************************/
1721141cc406Sopenharmony_cistatic int
1722141cc406Sopenharmony_cisendCommand (int cmd)
1723141cc406Sopenharmony_ci{
1724141cc406Sopenharmony_ci  int control;
1725141cc406Sopenharmony_ci  int tmp;
1726141cc406Sopenharmony_ci  int val;
1727141cc406Sopenharmony_ci  int i;
1728141cc406Sopenharmony_ci
1729141cc406Sopenharmony_ci  if (g674 != 0)
1730141cc406Sopenharmony_ci    {
1731141cc406Sopenharmony_ci      DBG (0, "No scanner attached, sendCommand(0x%X) failed\n", cmd);
1732141cc406Sopenharmony_ci      return 0;
1733141cc406Sopenharmony_ci    }
1734141cc406Sopenharmony_ci
1735141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x3F;
1736141cc406Sopenharmony_ci  tmp = cmd & 0xF8;
1737141cc406Sopenharmony_ci
1738141cc406Sopenharmony_ci
1739141cc406Sopenharmony_ci  if ((g67D != 1) && (tmp != 0xE0) && (tmp != 0x20) && (tmp != 0x40)
1740141cc406Sopenharmony_ci      && (tmp != 0xD0) && (tmp != 0x08) && (tmp != 0x48))
1741141cc406Sopenharmony_ci    {
1742141cc406Sopenharmony_ci      Outb (CONTROL, 4);	/* reset printer */
1743141cc406Sopenharmony_ci    }
1744141cc406Sopenharmony_ci  else
1745141cc406Sopenharmony_ci    {
1746141cc406Sopenharmony_ci      val = control & 0x1F;
1747141cc406Sopenharmony_ci      if (g67D != 1)
1748141cc406Sopenharmony_ci	val = val & 0xF;	/* no IRQ */
1749141cc406Sopenharmony_ci      val = val | 0x4;
1750141cc406Sopenharmony_ci      Outb (CONTROL, val);
1751141cc406Sopenharmony_ci      Outb (CONTROL, val);
1752141cc406Sopenharmony_ci    }
1753141cc406Sopenharmony_ci
1754141cc406Sopenharmony_ci  /* send sequence */
1755141cc406Sopenharmony_ci  Outb (DATA, 0x22);
1756141cc406Sopenharmony_ci  Outb (DATA, 0x22);
1757141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
1758141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
1759141cc406Sopenharmony_ci  Outb (DATA, 0x55);
1760141cc406Sopenharmony_ci  Outb (DATA, 0x55);
1761141cc406Sopenharmony_ci  Outb (DATA, 0x00);
1762141cc406Sopenharmony_ci  Outb (DATA, 0x00);
1763141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
1764141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
1765141cc406Sopenharmony_ci  Outb (DATA, 0x87);
1766141cc406Sopenharmony_ci  Outb (DATA, 0x87);
1767141cc406Sopenharmony_ci  Outb (DATA, 0x78);
1768141cc406Sopenharmony_ci  Outb (DATA, 0x78);
1769141cc406Sopenharmony_ci  Outb (DATA, cmd);
1770141cc406Sopenharmony_ci  Outb (DATA, cmd);
1771141cc406Sopenharmony_ci
1772141cc406Sopenharmony_ci  cmd = cmd & 0xF8;
1773141cc406Sopenharmony_ci
1774141cc406Sopenharmony_ci  if ((g67D == 1) && (cmd == 0xE0))
1775141cc406Sopenharmony_ci    {
1776141cc406Sopenharmony_ci      val = Inb (CONTROL);
1777141cc406Sopenharmony_ci      val = (val & 0xC) | 0x01;
1778141cc406Sopenharmony_ci      Outb (CONTROL, val);
1779141cc406Sopenharmony_ci      Outb (CONTROL, val);
1780141cc406Sopenharmony_ci      val = val & 0xC;
1781141cc406Sopenharmony_ci      Outb (CONTROL, val);
1782141cc406Sopenharmony_ci      Outb (CONTROL, val);
1783141cc406Sopenharmony_ci      goto sendCommandEnd;
1784141cc406Sopenharmony_ci    }
1785141cc406Sopenharmony_ci
1786141cc406Sopenharmony_ci  if ((cmd != 8) && (cmd != 0x48))
1787141cc406Sopenharmony_ci    {
1788141cc406Sopenharmony_ci      tmp = Inb (CONTROL);
1789141cc406Sopenharmony_ci      tmp = Inb (CONTROL);
1790141cc406Sopenharmony_ci      tmp = tmp & 0x1E;
1791141cc406Sopenharmony_ci      if (g67D != 1)
1792141cc406Sopenharmony_ci	tmp = tmp & 0xE;
1793141cc406Sopenharmony_ci      Outb (CONTROL, tmp);
1794141cc406Sopenharmony_ci      Outb (CONTROL, tmp);
1795141cc406Sopenharmony_ci    }
1796141cc406Sopenharmony_ci
1797141cc406Sopenharmony_ci  if (cmd == 0x10)
1798141cc406Sopenharmony_ci    {
1799141cc406Sopenharmony_ci      tmp = PS2Read ();
1800141cc406Sopenharmony_ci      tmp = tmp * 256 + PS2Read ();
1801141cc406Sopenharmony_ci      goto sendCommandEnd;
1802141cc406Sopenharmony_ci    }
1803141cc406Sopenharmony_ci
1804141cc406Sopenharmony_ci  if (cmd == 8)
1805141cc406Sopenharmony_ci    {
1806141cc406Sopenharmony_ci      if (g67D == 1)
1807141cc406Sopenharmony_ci	{
1808141cc406Sopenharmony_ci	  i = 0;
1809141cc406Sopenharmony_ci	  while (i < g67E)
1810141cc406Sopenharmony_ci	    {
1811141cc406Sopenharmony_ci	      tmp = Inb (CONTROL);
1812141cc406Sopenharmony_ci	      tmp = Inb (CONTROL);
1813141cc406Sopenharmony_ci	      tmp = (tmp & 0x1E) | 0x1;
1814141cc406Sopenharmony_ci	      Outb (CONTROL, tmp);
1815141cc406Sopenharmony_ci	      Outb (CONTROL, tmp);
1816141cc406Sopenharmony_ci	      Inb (STATUS);
1817141cc406Sopenharmony_ci	      tmp = tmp & 0x1E;
1818141cc406Sopenharmony_ci	      Outb (CONTROL, tmp);
1819141cc406Sopenharmony_ci	      Outb (CONTROL, tmp);
1820141cc406Sopenharmony_ci
1821141cc406Sopenharmony_ci	      /* next read */
1822141cc406Sopenharmony_ci	      i++;
1823141cc406Sopenharmony_ci	      if (i < g67E)
1824141cc406Sopenharmony_ci		{
1825141cc406Sopenharmony_ci		  Outb (DATA, i | 8);
1826141cc406Sopenharmony_ci		  Outb (DATA, i | 8);
1827141cc406Sopenharmony_ci		}
1828141cc406Sopenharmony_ci	    }
1829141cc406Sopenharmony_ci	  goto sendCommandEnd;
1830141cc406Sopenharmony_ci	}
1831141cc406Sopenharmony_ci      else
1832141cc406Sopenharmony_ci	{
1833141cc406Sopenharmony_ci	  DBG (0, "UNEXPLORED BRANCH %s:%d\n", __FILE__, __LINE__);
1834141cc406Sopenharmony_ci	  return 0;
1835141cc406Sopenharmony_ci	}
1836141cc406Sopenharmony_ci    }
1837141cc406Sopenharmony_ci
1838141cc406Sopenharmony_ci  /*  */
1839141cc406Sopenharmony_ci  if (cmd == 0)
1840141cc406Sopenharmony_ci    {
1841141cc406Sopenharmony_ci      i = 0;
1842141cc406Sopenharmony_ci      do
1843141cc406Sopenharmony_ci	{
1844141cc406Sopenharmony_ci	  tmp = Inb (CONTROL);
1845141cc406Sopenharmony_ci	  tmp = (tmp & 0xE) | 0x1;
1846141cc406Sopenharmony_ci	  Outb (CONTROL, tmp);
1847141cc406Sopenharmony_ci	  Outb (CONTROL, tmp);
1848141cc406Sopenharmony_ci	  tmp = tmp & 0xE;
1849141cc406Sopenharmony_ci	  Outb (CONTROL, tmp);
1850141cc406Sopenharmony_ci	  Outb (CONTROL, tmp);
1851141cc406Sopenharmony_ci
1852141cc406Sopenharmony_ci	  i++;
1853141cc406Sopenharmony_ci	  if (i < g67E)
1854141cc406Sopenharmony_ci	    {
1855141cc406Sopenharmony_ci	      Outb (DATA, i);
1856141cc406Sopenharmony_ci	      Outb (DATA, i);
1857141cc406Sopenharmony_ci	    }
1858141cc406Sopenharmony_ci	}
1859141cc406Sopenharmony_ci      while (i < g67E);
1860141cc406Sopenharmony_ci      goto sendCommandEnd;
1861141cc406Sopenharmony_ci    }
1862141cc406Sopenharmony_ci
1863141cc406Sopenharmony_ci  if (cmd == 0x48)
1864141cc406Sopenharmony_ci    {
1865141cc406Sopenharmony_ci      /* this case is unneeded, should fit with the rest */
1866141cc406Sopenharmony_ci      tmp = Inb (CONTROL) & 0x1E;
1867141cc406Sopenharmony_ci      if (g67D != 1)
1868141cc406Sopenharmony_ci	tmp = tmp & 0xE;
1869141cc406Sopenharmony_ci      Outb (CONTROL, tmp | 0x1);
1870141cc406Sopenharmony_ci      Outb (CONTROL, tmp | 0x1);
1871141cc406Sopenharmony_ci      Outb (CONTROL, tmp);
1872141cc406Sopenharmony_ci      Outb (CONTROL, tmp);
1873141cc406Sopenharmony_ci      goto sendCommandEnd;
1874141cc406Sopenharmony_ci    }
1875141cc406Sopenharmony_ci
1876141cc406Sopenharmony_ci  /*  */
1877141cc406Sopenharmony_ci  tmp = Inb (CONTROL) & 0x1E;
1878141cc406Sopenharmony_ci  if (g67D != 1)
1879141cc406Sopenharmony_ci    tmp = tmp & 0xE;
1880141cc406Sopenharmony_ci  Outb (CONTROL, tmp | 0x1);
1881141cc406Sopenharmony_ci  Outb (CONTROL, tmp | 0x1);
1882141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
1883141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
1884141cc406Sopenharmony_ci
1885141cc406Sopenharmony_ci  /* success */
1886141cc406Sopenharmony_cisendCommandEnd:
1887141cc406Sopenharmony_ci
1888141cc406Sopenharmony_ci  if (cmd == 0x48)
1889141cc406Sopenharmony_ci    Outb (CONTROL, (control & 0xF) | 0x4);
1890141cc406Sopenharmony_ci  if (cmd == 0x30)
1891141cc406Sopenharmony_ci    Outb (CONTROL, (gControl & 0xF) | 0x4);
1892141cc406Sopenharmony_ci
1893141cc406Sopenharmony_ci  /* end signature */
1894141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
1895141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
1896141cc406Sopenharmony_ci
1897141cc406Sopenharmony_ci  if (cmd == 8)
1898141cc406Sopenharmony_ci    {
1899141cc406Sopenharmony_ci      Outb (CONTROL, control);
1900141cc406Sopenharmony_ci      return 1;
1901141cc406Sopenharmony_ci    }
1902141cc406Sopenharmony_ci
1903141cc406Sopenharmony_ci  if (cmd == 0x30)
1904141cc406Sopenharmony_ci    {
1905141cc406Sopenharmony_ci      Outb (CONTROL, gControl);
1906141cc406Sopenharmony_ci      return 1;
1907141cc406Sopenharmony_ci    }
1908141cc406Sopenharmony_ci
1909141cc406Sopenharmony_ci  if (cmd != 0xE0)
1910141cc406Sopenharmony_ci    Outb (CONTROL, control);
1911141cc406Sopenharmony_ci
1912141cc406Sopenharmony_ci  return 1;
1913141cc406Sopenharmony_ci}
1914141cc406Sopenharmony_ci
1915141cc406Sopenharmony_ci
1916141cc406Sopenharmony_cistatic void
1917141cc406Sopenharmony_ciClearRegister (int reg)
1918141cc406Sopenharmony_ci{
1919141cc406Sopenharmony_ci
1920141cc406Sopenharmony_ci  /* choose register */
1921141cc406Sopenharmony_ci  Outb (DATA, reg);
1922141cc406Sopenharmony_ci  Outb (DATA, reg);
1923141cc406Sopenharmony_ci  Outb (CONTROL, 1);
1924141cc406Sopenharmony_ci  Outb (CONTROL, 1);
1925141cc406Sopenharmony_ci  if ((g6FE == 0) || (g674 != 0))
1926141cc406Sopenharmony_ci    {
1927141cc406Sopenharmony_ci      Outb (CONTROL, 1);
1928141cc406Sopenharmony_ci      Outb (CONTROL, 1);
1929141cc406Sopenharmony_ci      Outb (CONTROL, 1);
1930141cc406Sopenharmony_ci      Outb (CONTROL, 1);
1931141cc406Sopenharmony_ci    }
1932141cc406Sopenharmony_ci
1933141cc406Sopenharmony_ci  /* clears it by not sending new value */
1934141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1935141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1936141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1937141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1938141cc406Sopenharmony_ci}
1939141cc406Sopenharmony_ci
1940141cc406Sopenharmony_cistatic void
1941141cc406Sopenharmony_ciSPPResetLPT (void)
1942141cc406Sopenharmony_ci{
1943141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
1944141cc406Sopenharmony_ci}
1945141cc406Sopenharmony_ci
1946141cc406Sopenharmony_ci
1947141cc406Sopenharmony_cistatic int
1948141cc406Sopenharmony_ciPS2registerRead (int reg)
1949141cc406Sopenharmony_ci{
1950141cc406Sopenharmony_ci  int low, high;
1951141cc406Sopenharmony_ci
1952141cc406Sopenharmony_ci
1953141cc406Sopenharmony_ci  /* send register number */
1954141cc406Sopenharmony_ci  Outb (DATA, reg);
1955141cc406Sopenharmony_ci  Outb (DATA, reg);
1956141cc406Sopenharmony_ci
1957141cc406Sopenharmony_ci  /* get low nibble */
1958141cc406Sopenharmony_ci  Outb (CONTROL, 1);
1959141cc406Sopenharmony_ci  Outb (CONTROL, 3);
1960141cc406Sopenharmony_ci  Outb (CONTROL, 3);
1961141cc406Sopenharmony_ci  Outb (CONTROL, 3);
1962141cc406Sopenharmony_ci  Outb (CONTROL, 3);
1963141cc406Sopenharmony_ci  low = Inb (STATUS);
1964141cc406Sopenharmony_ci  low = Inb (STATUS);
1965141cc406Sopenharmony_ci
1966141cc406Sopenharmony_ci  /* get high nibble */
1967141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1968141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1969141cc406Sopenharmony_ci  Outb (CONTROL, 4);
1970141cc406Sopenharmony_ci  high = Inb (STATUS);
1971141cc406Sopenharmony_ci  high = Inb (STATUS);
1972141cc406Sopenharmony_ci
1973141cc406Sopenharmony_ci  /* merge nibbles and return */
1974141cc406Sopenharmony_ci  high = (high & 0xF0) | ((low & 0xF0) >> 4);
1975141cc406Sopenharmony_ci  return high;
1976141cc406Sopenharmony_ci}
1977141cc406Sopenharmony_ci
1978141cc406Sopenharmony_ci
1979141cc406Sopenharmony_cistatic void
1980141cc406Sopenharmony_ciPS2bufferRead (int size, unsigned char *dest)
1981141cc406Sopenharmony_ci{
1982141cc406Sopenharmony_ci  int high;
1983141cc406Sopenharmony_ci  int low;
1984141cc406Sopenharmony_ci  int i;
1985141cc406Sopenharmony_ci  int count;
1986141cc406Sopenharmony_ci  int bytel, byteh;
1987141cc406Sopenharmony_ci
1988141cc406Sopenharmony_ci  /* init transfer */
1989141cc406Sopenharmony_ci  Outb (DATA, 7);
1990141cc406Sopenharmony_ci  Outb (DATA, 7);
1991141cc406Sopenharmony_ci  Outb (CONTROL, 1);
1992141cc406Sopenharmony_ci  Outb (CONTROL, 1);
1993141cc406Sopenharmony_ci  Outb (CONTROL, 3);
1994141cc406Sopenharmony_ci  Outb (CONTROL, 3);
1995141cc406Sopenharmony_ci  Outb (CONTROL, 3);
1996141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
1997141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
1998141cc406Sopenharmony_ci  count = (size - 2) / 2;
1999141cc406Sopenharmony_ci  i = 0;
2000141cc406Sopenharmony_ci  bytel = 0x06;			/* signals low byte of word  */
2001141cc406Sopenharmony_ci  byteh = 0x07;			/* signals high byte of word */
2002141cc406Sopenharmony_ci
2003141cc406Sopenharmony_ci  /* read loop */
2004141cc406Sopenharmony_ci  while (count > 0)
2005141cc406Sopenharmony_ci    {
2006141cc406Sopenharmony_ci      /* low nibble byte 0 */
2007141cc406Sopenharmony_ci      Outb (CONTROL, bytel);
2008141cc406Sopenharmony_ci      Outb (CONTROL, bytel);
2009141cc406Sopenharmony_ci      Outb (CONTROL, bytel);
2010141cc406Sopenharmony_ci      low = Inb (STATUS);
2011141cc406Sopenharmony_ci      if ((low & 0x08) == 0)
2012141cc406Sopenharmony_ci	{
2013141cc406Sopenharmony_ci	  /* high nibble <> low nibble */
2014141cc406Sopenharmony_ci	  Outb (CONTROL, bytel & 0x05);
2015141cc406Sopenharmony_ci	  Outb (CONTROL, bytel & 0x05);
2016141cc406Sopenharmony_ci	  Outb (CONTROL, bytel & 0x05);
2017141cc406Sopenharmony_ci	  high = Inb (STATUS);
2018141cc406Sopenharmony_ci	}
2019141cc406Sopenharmony_ci      else
2020141cc406Sopenharmony_ci	{
2021141cc406Sopenharmony_ci	  high = low;
2022141cc406Sopenharmony_ci	}
2023141cc406Sopenharmony_ci      low = low & 0xF0;
2024141cc406Sopenharmony_ci      high = high & 0xF0;
2025141cc406Sopenharmony_ci      dest[i] = (unsigned char) (high | (low >> 4));
2026141cc406Sopenharmony_ci      i++;
2027141cc406Sopenharmony_ci
2028141cc406Sopenharmony_ci      /* low nibble byte 1 */
2029141cc406Sopenharmony_ci      Outb (CONTROL, byteh);
2030141cc406Sopenharmony_ci      Outb (CONTROL, byteh);
2031141cc406Sopenharmony_ci      Outb (CONTROL, byteh);
2032141cc406Sopenharmony_ci      low = Inb (STATUS);
2033141cc406Sopenharmony_ci      if ((low & 0x08) == 0)
2034141cc406Sopenharmony_ci	{
2035141cc406Sopenharmony_ci	  /* high nibble <> low nibble */
2036141cc406Sopenharmony_ci	  Outb (CONTROL, byteh & 0x05);
2037141cc406Sopenharmony_ci	  Outb (CONTROL, byteh & 0x05);
2038141cc406Sopenharmony_ci	  Outb (CONTROL, byteh & 0x05);
2039141cc406Sopenharmony_ci	  high = Inb (STATUS);
2040141cc406Sopenharmony_ci	}
2041141cc406Sopenharmony_ci      else
2042141cc406Sopenharmony_ci	{
2043141cc406Sopenharmony_ci	  high = low;
2044141cc406Sopenharmony_ci	}
2045141cc406Sopenharmony_ci      low = low & 0xF0;
2046141cc406Sopenharmony_ci      high = high & 0xF0;
2047141cc406Sopenharmony_ci      dest[i] = (unsigned char) (high | (low >> 4));
2048141cc406Sopenharmony_ci      i++;
2049141cc406Sopenharmony_ci
2050141cc406Sopenharmony_ci      /* next read */
2051141cc406Sopenharmony_ci      count--;
2052141cc406Sopenharmony_ci    }
2053141cc406Sopenharmony_ci
2054141cc406Sopenharmony_ci  /* final read        */
2055141cc406Sopenharmony_ci  /* low nibble byte 0 */
2056141cc406Sopenharmony_ci  Outb (CONTROL, bytel);
2057141cc406Sopenharmony_ci  Outb (CONTROL, bytel);
2058141cc406Sopenharmony_ci  Outb (CONTROL, bytel);
2059141cc406Sopenharmony_ci  low = Inb (STATUS);
2060141cc406Sopenharmony_ci  if ((low & 0x08) == 0)
2061141cc406Sopenharmony_ci    {
2062141cc406Sopenharmony_ci      /* high nibble <> low nibble */
2063141cc406Sopenharmony_ci      Outb (CONTROL, bytel & 0x05);
2064141cc406Sopenharmony_ci      Outb (CONTROL, bytel & 0x05);
2065141cc406Sopenharmony_ci      Outb (CONTROL, bytel & 0x05);
2066141cc406Sopenharmony_ci      high = Inb (STATUS);
2067141cc406Sopenharmony_ci    }
2068141cc406Sopenharmony_ci  else
2069141cc406Sopenharmony_ci    {
2070141cc406Sopenharmony_ci      high = low;
2071141cc406Sopenharmony_ci    }
2072141cc406Sopenharmony_ci  low = low & 0xF0;
2073141cc406Sopenharmony_ci  high = high & 0xF0;
2074141cc406Sopenharmony_ci  dest[i] = (unsigned char) (high | (low >> 4));
2075141cc406Sopenharmony_ci  i++;
2076141cc406Sopenharmony_ci
2077141cc406Sopenharmony_ci  /* uneven size need an extra read */
2078141cc406Sopenharmony_ci  if ((size & 0x01) == 1)
2079141cc406Sopenharmony_ci    {
2080141cc406Sopenharmony_ci      /* low nibble byte 1 */
2081141cc406Sopenharmony_ci      Outb (CONTROL, byteh);
2082141cc406Sopenharmony_ci      Outb (CONTROL, byteh);
2083141cc406Sopenharmony_ci      Outb (CONTROL, byteh);
2084141cc406Sopenharmony_ci      low = Inb (STATUS);
2085141cc406Sopenharmony_ci      if ((low & 0x08) == 0)
2086141cc406Sopenharmony_ci	{
2087141cc406Sopenharmony_ci	  /* high nibble <> low nibble */
2088141cc406Sopenharmony_ci	  Outb (CONTROL, byteh & 0x05);
2089141cc406Sopenharmony_ci	  Outb (CONTROL, byteh & 0x05);
2090141cc406Sopenharmony_ci	  Outb (CONTROL, byteh & 0x05);
2091141cc406Sopenharmony_ci	  high = Inb (STATUS);
2092141cc406Sopenharmony_ci	}
2093141cc406Sopenharmony_ci      else
2094141cc406Sopenharmony_ci	{
2095141cc406Sopenharmony_ci	  high = low;
2096141cc406Sopenharmony_ci	}
2097141cc406Sopenharmony_ci      low = low & 0xF0;
2098141cc406Sopenharmony_ci      high = high & 0xF0;
2099141cc406Sopenharmony_ci      dest[i] = (unsigned char) (high | (low >> 4));
2100141cc406Sopenharmony_ci      i++;
2101141cc406Sopenharmony_ci
2102141cc406Sopenharmony_ci      /* swap high/low word */
2103141cc406Sopenharmony_ci      count = bytel;
2104141cc406Sopenharmony_ci      bytel = byteh;
2105141cc406Sopenharmony_ci      byteh = count;
2106141cc406Sopenharmony_ci    }
2107141cc406Sopenharmony_ci
2108141cc406Sopenharmony_ci  /* final byte ... */
2109141cc406Sopenharmony_ci  Outb (DATA, 0xFD);
2110141cc406Sopenharmony_ci  Outb (DATA, 0xFD);
2111141cc406Sopenharmony_ci  Outb (DATA, 0xFD);
2112141cc406Sopenharmony_ci
2113141cc406Sopenharmony_ci  /* low nibble */
2114141cc406Sopenharmony_ci  Outb (CONTROL, byteh);
2115141cc406Sopenharmony_ci  Outb (CONTROL, byteh);
2116141cc406Sopenharmony_ci  Outb (CONTROL, byteh);
2117141cc406Sopenharmony_ci  low = Inb (STATUS);
2118141cc406Sopenharmony_ci  if ((low & 0x08) == 0)
2119141cc406Sopenharmony_ci    {
2120141cc406Sopenharmony_ci      /* high nibble <> low nibble */
2121141cc406Sopenharmony_ci      Outb (CONTROL, byteh & 0x05);
2122141cc406Sopenharmony_ci      Outb (CONTROL, byteh & 0x05);
2123141cc406Sopenharmony_ci      Outb (CONTROL, byteh & 0x05);
2124141cc406Sopenharmony_ci      high = Inb (STATUS);
2125141cc406Sopenharmony_ci    }
2126141cc406Sopenharmony_ci  else
2127141cc406Sopenharmony_ci    {
2128141cc406Sopenharmony_ci      high = low;
2129141cc406Sopenharmony_ci    }
2130141cc406Sopenharmony_ci  low = low & 0xF0;
2131141cc406Sopenharmony_ci  high = high & 0xF0;
2132141cc406Sopenharmony_ci  dest[i] = (unsigned char) (high | (low >> 4));
2133141cc406Sopenharmony_ci  i++;
2134141cc406Sopenharmony_ci
2135141cc406Sopenharmony_ci  /* reset port */
2136141cc406Sopenharmony_ci  Outb (DATA, 0x00);
2137141cc406Sopenharmony_ci  Outb (DATA, 0x00);
2138141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2139141cc406Sopenharmony_ci}
2140141cc406Sopenharmony_ci
2141141cc406Sopenharmony_cistatic void
2142141cc406Sopenharmony_ciPS2bufferWrite (int size, unsigned char *source)
2143141cc406Sopenharmony_ci{
2144141cc406Sopenharmony_ci  int i;
2145141cc406Sopenharmony_ci  int count;
2146141cc406Sopenharmony_ci  int val;
2147141cc406Sopenharmony_ci
2148141cc406Sopenharmony_ci  /* init buffer write */
2149141cc406Sopenharmony_ci  i = 0;
2150141cc406Sopenharmony_ci  count = size / 2;
2151141cc406Sopenharmony_ci  Outb (DATA, 0x67);
2152141cc406Sopenharmony_ci  Outb (CONTROL, 0x01);
2153141cc406Sopenharmony_ci  Outb (CONTROL, 0x01);
2154141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
2155141cc406Sopenharmony_ci
2156141cc406Sopenharmony_ci  /* write loop */
2157141cc406Sopenharmony_ci  while (count > 0)
2158141cc406Sopenharmony_ci    {
2159141cc406Sopenharmony_ci      /* low byte of word */
2160141cc406Sopenharmony_ci      val = source[i];
2161141cc406Sopenharmony_ci      i++;
2162141cc406Sopenharmony_ci      Outb (DATA, val);
2163141cc406Sopenharmony_ci      Outb (DATA, val);
2164141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
2165141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
2166141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
2167141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
2168141cc406Sopenharmony_ci
2169141cc406Sopenharmony_ci      /* high byte of word */
2170141cc406Sopenharmony_ci      val = source[i];
2171141cc406Sopenharmony_ci      i++;
2172141cc406Sopenharmony_ci      Outb (DATA, val);
2173141cc406Sopenharmony_ci      Outb (DATA, val);
2174141cc406Sopenharmony_ci      Outb (CONTROL, 0x05);
2175141cc406Sopenharmony_ci      Outb (CONTROL, 0x05);
2176141cc406Sopenharmony_ci      Outb (CONTROL, 0x05);
2177141cc406Sopenharmony_ci      Outb (CONTROL, 0x05);
2178141cc406Sopenharmony_ci
2179141cc406Sopenharmony_ci      /* next write */
2180141cc406Sopenharmony_ci      count--;
2181141cc406Sopenharmony_ci    }
2182141cc406Sopenharmony_ci
2183141cc406Sopenharmony_ci  /* termination sequence */
2184141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
2185141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
2186141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
2187141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
2188141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
2189141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
2190141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
2191141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
2192141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2193141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2194141cc406Sopenharmony_ci}
2195141cc406Sopenharmony_ci
2196141cc406Sopenharmony_ci
2197141cc406Sopenharmony_ci
2198141cc406Sopenharmony_ci
2199141cc406Sopenharmony_cistatic void
2200141cc406Sopenharmony_ciinit001 (void)
2201141cc406Sopenharmony_ci{
2202141cc406Sopenharmony_ci  int i;
2203141cc406Sopenharmony_ci  int val;
2204141cc406Sopenharmony_ci  int status;
2205141cc406Sopenharmony_ci
2206141cc406Sopenharmony_ci  ClearRegister (0);
2207141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
2208141cc406Sopenharmony_ci  if (g674 != 0)
2209141cc406Sopenharmony_ci    {
2210141cc406Sopenharmony_ci      Outb (CONTROL, 0x0C);
2211141cc406Sopenharmony_ci      Outb (CONTROL, 0x0C);
2212141cc406Sopenharmony_ci      Outb (CONTROL, 0x0C);
2213141cc406Sopenharmony_ci    }
2214141cc406Sopenharmony_ci  Outb (DATA, 0x40);
2215141cc406Sopenharmony_ci  if (g674 != 0)
2216141cc406Sopenharmony_ci    {
2217141cc406Sopenharmony_ci      Outb (DATA, 0x40);
2218141cc406Sopenharmony_ci      Outb (DATA, 0x40);
2219141cc406Sopenharmony_ci      Outb (DATA, 0x40);
2220141cc406Sopenharmony_ci    }
2221141cc406Sopenharmony_ci  Outb (CONTROL, 0x06);
2222141cc406Sopenharmony_ci  Outb (CONTROL, 0x06);
2223141cc406Sopenharmony_ci  Outb (CONTROL, 0x06);
2224141cc406Sopenharmony_ci  if (g674 != 0)
2225141cc406Sopenharmony_ci    {
2226141cc406Sopenharmony_ci      Outb (CONTROL, 0x06);
2227141cc406Sopenharmony_ci      Outb (CONTROL, 0x06);
2228141cc406Sopenharmony_ci      Outb (CONTROL, 0x06);
2229141cc406Sopenharmony_ci    }
2230141cc406Sopenharmony_ci
2231141cc406Sopenharmony_ci  /* sync loop */
2232141cc406Sopenharmony_ci  i = 256;
2233141cc406Sopenharmony_ci  do
2234141cc406Sopenharmony_ci    {
2235141cc406Sopenharmony_ci      status = Inb (STATUS);
2236141cc406Sopenharmony_ci      i--;
2237141cc406Sopenharmony_ci    }
2238141cc406Sopenharmony_ci  while ((i > 0) && ((status & 0x40)));
2239141cc406Sopenharmony_ci  val = 0x0C;
2240141cc406Sopenharmony_ci  if (i > 0)
2241141cc406Sopenharmony_ci    {
2242141cc406Sopenharmony_ci      Outb (CONTROL, 0x07);
2243141cc406Sopenharmony_ci      Outb (CONTROL, 0x07);
2244141cc406Sopenharmony_ci      Outb (CONTROL, 0x07);
2245141cc406Sopenharmony_ci      if (g674 != 0)
2246141cc406Sopenharmony_ci	{
2247141cc406Sopenharmony_ci	  Outb (CONTROL, 0x07);
2248141cc406Sopenharmony_ci	  Outb (CONTROL, 0x07);
2249141cc406Sopenharmony_ci	  Outb (CONTROL, 0x07);
2250141cc406Sopenharmony_ci	}
2251141cc406Sopenharmony_ci      val = 0x04;
2252141cc406Sopenharmony_ci      Outb (CONTROL, val);
2253141cc406Sopenharmony_ci      Outb (CONTROL, val);
2254141cc406Sopenharmony_ci      Outb (CONTROL, val);
2255141cc406Sopenharmony_ci      if (g674 != 0)
2256141cc406Sopenharmony_ci	{
2257141cc406Sopenharmony_ci	  Outb (CONTROL, val);
2258141cc406Sopenharmony_ci	  Outb (CONTROL, val);
2259141cc406Sopenharmony_ci	  Outb (CONTROL, val);
2260141cc406Sopenharmony_ci	}
2261141cc406Sopenharmony_ci    }
2262141cc406Sopenharmony_ci  val = val | 0x0C;
2263141cc406Sopenharmony_ci  Outb (CONTROL, val);
2264141cc406Sopenharmony_ci  Outb (CONTROL, val);
2265141cc406Sopenharmony_ci  Outb (CONTROL, val);
2266141cc406Sopenharmony_ci  if (g674 != 0)
2267141cc406Sopenharmony_ci    {
2268141cc406Sopenharmony_ci      Outb (CONTROL, val);
2269141cc406Sopenharmony_ci      Outb (CONTROL, val);
2270141cc406Sopenharmony_ci      Outb (CONTROL, val);
2271141cc406Sopenharmony_ci    }
2272141cc406Sopenharmony_ci  val = val & 0xF7;
2273141cc406Sopenharmony_ci  Outb (CONTROL, val);
2274141cc406Sopenharmony_ci  Outb (CONTROL, val);
2275141cc406Sopenharmony_ci  Outb (CONTROL, val);
2276141cc406Sopenharmony_ci  if (g674 != 0)
2277141cc406Sopenharmony_ci    {
2278141cc406Sopenharmony_ci      Outb (CONTROL, val);
2279141cc406Sopenharmony_ci      Outb (CONTROL, val);
2280141cc406Sopenharmony_ci      Outb (CONTROL, val);
2281141cc406Sopenharmony_ci    }
2282141cc406Sopenharmony_ci}
2283141cc406Sopenharmony_ci
2284141cc406Sopenharmony_ci/* SPP register reading */
2285141cc406Sopenharmony_cistatic int
2286141cc406Sopenharmony_ciinit002 (int arg)
2287141cc406Sopenharmony_ci{
2288141cc406Sopenharmony_ci  int data;
2289141cc406Sopenharmony_ci
2290141cc406Sopenharmony_ci  if (arg == 1)
2291141cc406Sopenharmony_ci    return 0;
2292141cc406Sopenharmony_ci  Outb (DATA, 0x0B);
2293141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2294141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2295141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2296141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
2297141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
2298141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
2299141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2300141cc406Sopenharmony_ci  Outb (CONTROL, 0x24);
2301141cc406Sopenharmony_ci  Outb (CONTROL, 0x24);
2302141cc406Sopenharmony_ci  Outb (CONTROL, 0x26);
2303141cc406Sopenharmony_ci  Outb (CONTROL, 0x26);
2304141cc406Sopenharmony_ci
2305141cc406Sopenharmony_ci  data = Inb (DATA);
2306141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2307141cc406Sopenharmony_ci  if (data == gEPAT)
2308141cc406Sopenharmony_ci    {
2309141cc406Sopenharmony_ci      return 1;
2310141cc406Sopenharmony_ci    }
2311141cc406Sopenharmony_ci  return 0;
2312141cc406Sopenharmony_ci}
2313141cc406Sopenharmony_ci
2314141cc406Sopenharmony_ci/*
2315141cc406Sopenharmony_ci * connecct to the EPAT chip, and
2316141cc406Sopenharmony_ci * prepare command sending
2317141cc406Sopenharmony_ci */
2318141cc406Sopenharmony_cistatic int
2319141cc406Sopenharmony_ciECPconnect (void)
2320141cc406Sopenharmony_ci{
2321141cc406Sopenharmony_ci  int ret, control;
2322141cc406Sopenharmony_ci
2323141cc406Sopenharmony_ci  /* these 3 lines set to 'inital mode' */
2324141cc406Sopenharmony_ci  byteMode ();			/*Outb (ECR, 0x20); */
2325141cc406Sopenharmony_ci  Outb (DATA, 0x04);		/* gData */
2326141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);		/* gControl */
2327141cc406Sopenharmony_ci
2328141cc406Sopenharmony_ci  Inb (ECR);			/* 0x35 */
2329141cc406Sopenharmony_ci  byteMode ();			/*Outb (ECR, 0x20); */
2330141cc406Sopenharmony_ci  byteMode ();			/*Outb (ECR, 0x20); */
2331141cc406Sopenharmony_ci
2332141cc406Sopenharmony_ci  gData = Inb (DATA);
2333141cc406Sopenharmony_ci  gControl = Inb (CONTROL);
2334141cc406Sopenharmony_ci
2335141cc406Sopenharmony_ci  Inb (DATA);
2336141cc406Sopenharmony_ci  control = Inb (CONTROL);
2337141cc406Sopenharmony_ci  Outb (CONTROL, control & 0x1F);
2338141cc406Sopenharmony_ci  control = Inb (CONTROL);
2339141cc406Sopenharmony_ci  Outb (CONTROL, control & 0x1F);
2340141cc406Sopenharmony_ci  sendCommand (0xE0);
2341141cc406Sopenharmony_ci
2342141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
2343141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
2344141cc406Sopenharmony_ci  ClearRegister (0);
2345141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
2346141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2347141cc406Sopenharmony_ci  ClearRegister (0);
2348141cc406Sopenharmony_ci  ret = PS2Something (0x10);
2349141cc406Sopenharmony_ci  if (ret != 0x0B)
2350141cc406Sopenharmony_ci    {
2351141cc406Sopenharmony_ci      DBG (16,
2352141cc406Sopenharmony_ci	   "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", ret,
2353141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2354141cc406Sopenharmony_ci    }
2355141cc406Sopenharmony_ci  return 1;
2356141cc406Sopenharmony_ci}
2357141cc406Sopenharmony_ci
2358141cc406Sopenharmony_cistatic void
2359141cc406Sopenharmony_ciEPPdisconnect (void)
2360141cc406Sopenharmony_ci{
2361141cc406Sopenharmony_ci  if (getModel () != 0x07)
2362141cc406Sopenharmony_ci    sendCommand (40);
2363141cc406Sopenharmony_ci  sendCommand (30);
2364141cc406Sopenharmony_ci  Outb (DATA, gData);
2365141cc406Sopenharmony_ci  Outb (CONTROL, gControl);
2366141cc406Sopenharmony_ci}
2367141cc406Sopenharmony_ci
2368141cc406Sopenharmony_cistatic void
2369141cc406Sopenharmony_ciECPdisconnect (void)
2370141cc406Sopenharmony_ci{
2371141cc406Sopenharmony_ci  int control;
2372141cc406Sopenharmony_ci
2373141cc406Sopenharmony_ci  if (getModel () != 0x07)	/* guessed */
2374141cc406Sopenharmony_ci    sendCommand (40);		/* guessed */
2375141cc406Sopenharmony_ci  sendCommand (0x30);
2376141cc406Sopenharmony_ci  control = Inb (CONTROL) | 0x01;
2377141cc406Sopenharmony_ci  Outb (CONTROL, control);
2378141cc406Sopenharmony_ci  Outb (CONTROL, control);
2379141cc406Sopenharmony_ci  control = control & 0x04;
2380141cc406Sopenharmony_ci  Outb (CONTROL, control);
2381141cc406Sopenharmony_ci  Outb (CONTROL, control);
2382141cc406Sopenharmony_ci  control = control | 0x08;
2383141cc406Sopenharmony_ci  Outb (CONTROL, control);
2384141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
2385141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
2386141cc406Sopenharmony_ci  Outb (CONTROL, control);
2387141cc406Sopenharmony_ci}
2388141cc406Sopenharmony_ci
2389141cc406Sopenharmony_cistatic int
2390141cc406Sopenharmony_ciECPregisterRead (int reg)
2391141cc406Sopenharmony_ci{
2392141cc406Sopenharmony_ci  unsigned char breg, value;
2393141cc406Sopenharmony_ci
2394141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2395141cc406Sopenharmony_ci  int rc, mode, fd;
2396141cc406Sopenharmony_ci  unsigned char bval;
2397141cc406Sopenharmony_ci
2398141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
2399141cc406Sopenharmony_ci  if (fd > 0)
2400141cc406Sopenharmony_ci    {
2401141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
2402141cc406Sopenharmony_ci      ECPFifoMode ();
2403141cc406Sopenharmony_ci      Outb (DATA, reg);
2404141cc406Sopenharmony_ci      mode = 1;			/* data_reverse */
2405141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
2406141cc406Sopenharmony_ci      if (rc)
2407141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2408141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2409141cc406Sopenharmony_ci      rc = read (fd, &bval, 1);
2410141cc406Sopenharmony_ci      if (rc != 1)
2411141cc406Sopenharmony_ci	DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__);
2412141cc406Sopenharmony_ci      value = bval;
2413141cc406Sopenharmony_ci      breg = (Inb (CONTROL) & 0x3F);
2414141cc406Sopenharmony_ci      if (breg != 0x20)
2415141cc406Sopenharmony_ci	{
2416141cc406Sopenharmony_ci	  DBG (0,
2417141cc406Sopenharmony_ci	       "ECPregisterRead failed, expecting 0x20, got 0x%02X (%s:%d)\n",
2418141cc406Sopenharmony_ci	       breg, __FILE__, __LINE__);
2419141cc406Sopenharmony_ci	}
2420141cc406Sopenharmony_ci
2421141cc406Sopenharmony_ci      /* restore port state */
2422141cc406Sopenharmony_ci      mode = 0;			/* data_forward */
2423141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
2424141cc406Sopenharmony_ci      if (rc)
2425141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2426141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2427141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
2428141cc406Sopenharmony_ci      byteMode ();
2429141cc406Sopenharmony_ci      return value;
2430141cc406Sopenharmony_ci    }
2431141cc406Sopenharmony_ci#endif
2432141cc406Sopenharmony_ci
2433141cc406Sopenharmony_ci  Outb (CONTROL, 0x4);
2434141cc406Sopenharmony_ci
2435141cc406Sopenharmony_ci  /* ECP FIFO mode, interrupt bit, dma disabled,
2436141cc406Sopenharmony_ci     service bit, fifo full=0, fifo empty=0 */
2437141cc406Sopenharmony_ci  ECPFifoMode ();		/*Outb (ECR, 0x60); */
2438141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2439141cc406Sopenharmony_ci    {
2440141cc406Sopenharmony_ci      DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n",
2441141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2442141cc406Sopenharmony_ci    }
2443141cc406Sopenharmony_ci  breg = Inb (ECR);
2444141cc406Sopenharmony_ci
2445141cc406Sopenharmony_ci  Outb (DATA, reg);
2446141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2447141cc406Sopenharmony_ci    {
2448141cc406Sopenharmony_ci      DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n",
2449141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2450141cc406Sopenharmony_ci    }
2451141cc406Sopenharmony_ci  breg = Inb (ECR);
2452141cc406Sopenharmony_ci
2453141cc406Sopenharmony_ci  /* byte mode, interrupt bit, dma disabled,
2454141cc406Sopenharmony_ci     service bit, fifo full=0, fifo empty=0 */
2455141cc406Sopenharmony_ci  byteMode ();			/*Outb (ECR, 0x20); */
2456141cc406Sopenharmony_ci  Outb (CONTROL, 0x20);		/* data reverse */
2457141cc406Sopenharmony_ci
2458141cc406Sopenharmony_ci  /* ECP FIFO mode, interrupt bit, dma disabled,
2459141cc406Sopenharmony_ci     service bit, fifo full=0, fifo empty=0 */
2460141cc406Sopenharmony_ci  ECPFifoMode ();		/*Outb (ECR, 0x60); */
2461141cc406Sopenharmony_ci  if (waitFifoNotEmpty () == 0)
2462141cc406Sopenharmony_ci    {
2463141cc406Sopenharmony_ci      DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n",
2464141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2465141cc406Sopenharmony_ci    }
2466141cc406Sopenharmony_ci  breg = Inb (ECR);
2467141cc406Sopenharmony_ci  value = Inb (ECPDATA);
2468141cc406Sopenharmony_ci
2469141cc406Sopenharmony_ci  /* according to the spec bit 7 and 6 are unused */
2470141cc406Sopenharmony_ci  breg = (Inb (CONTROL) & 0x3F);
2471141cc406Sopenharmony_ci  if (breg != 0x20)
2472141cc406Sopenharmony_ci    {
2473141cc406Sopenharmony_ci      DBG (0, "ECPregisterRead failed, expecting 0x20, got 0x%02X (%s:%d)\n",
2474141cc406Sopenharmony_ci	   breg, __FILE__, __LINE__);
2475141cc406Sopenharmony_ci    }
2476141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2477141cc406Sopenharmony_ci  byteMode ();
2478141cc406Sopenharmony_ci  return value;
2479141cc406Sopenharmony_ci}
2480141cc406Sopenharmony_ci
2481141cc406Sopenharmony_cistatic int
2482141cc406Sopenharmony_ciEPPregisterRead (int reg)
2483141cc406Sopenharmony_ci{
2484141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2485141cc406Sopenharmony_ci  int fd, mode, rc;
2486141cc406Sopenharmony_ci  unsigned char breg, bval;
2487141cc406Sopenharmony_ci  int value;
2488141cc406Sopenharmony_ci#endif
2489141cc406Sopenharmony_ci  int control;
2490141cc406Sopenharmony_ci
2491141cc406Sopenharmony_ci
2492141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2493141cc406Sopenharmony_ci  /* check we have ppdev working */
2494141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
2495141cc406Sopenharmony_ci  if (fd > 0)
2496141cc406Sopenharmony_ci    {
2497141cc406Sopenharmony_ci      breg = (unsigned char) (reg);
2498141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2499141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2500141cc406Sopenharmony_ci      if (rc)
2501141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2502141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2503141cc406Sopenharmony_ci      rc = write (fd, &breg, 1);
2504141cc406Sopenharmony_ci      if (rc != 1)
2505141cc406Sopenharmony_ci	DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
2506141cc406Sopenharmony_ci
2507141cc406Sopenharmony_ci      mode = 1;			/* data_reverse */
2508141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
2509141cc406Sopenharmony_ci      if (rc)
2510141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2511141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2512141cc406Sopenharmony_ci
2513141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2514141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2515141cc406Sopenharmony_ci      if (rc)
2516141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2517141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2518141cc406Sopenharmony_ci      rc = read (fd, &bval, 1);
2519141cc406Sopenharmony_ci      if (rc != 1)
2520141cc406Sopenharmony_ci	DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__);
2521141cc406Sopenharmony_ci      value = bval;
2522141cc406Sopenharmony_ci
2523141cc406Sopenharmony_ci      mode = 0;			/* forward */
2524141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
2525141cc406Sopenharmony_ci      if (rc)
2526141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2527141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2528141cc406Sopenharmony_ci
2529141cc406Sopenharmony_ci      return value;
2530141cc406Sopenharmony_ci    }
2531141cc406Sopenharmony_ci  /* if not, direct hardware access */
2532141cc406Sopenharmony_ci#endif
2533141cc406Sopenharmony_ci
2534141cc406Sopenharmony_ci  Outb (EPPADDR, reg);
2535141cc406Sopenharmony_ci  control = Inb (CONTROL);
2536141cc406Sopenharmony_ci  control = (control & 0x1F) | 0x20;
2537141cc406Sopenharmony_ci  Outb (CONTROL, control);
2538141cc406Sopenharmony_ci  Inb (EPPDATA);
2539141cc406Sopenharmony_ci  control = Inb (CONTROL);
2540141cc406Sopenharmony_ci  control = control & 0x1F;
2541141cc406Sopenharmony_ci  Outb (CONTROL, control);
2542141cc406Sopenharmony_ci  return 0xFF;
2543141cc406Sopenharmony_ci  /* return value; */
2544141cc406Sopenharmony_ci}
2545141cc406Sopenharmony_ci
2546141cc406Sopenharmony_cistatic int
2547141cc406Sopenharmony_ciregisterRead (int reg)
2548141cc406Sopenharmony_ci{
2549141cc406Sopenharmony_ci  switch (gMode)
2550141cc406Sopenharmony_ci    {
2551141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_ECP:
2552141cc406Sopenharmony_ci      return ECPregisterRead (reg);
2553141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_BYTE:
2554141cc406Sopenharmony_ci      DBG (0, "STEF: gMode BYTE in registerRead !!\n");
2555141cc406Sopenharmony_ci      return 0xFF;
2556141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_EPP:
2557141cc406Sopenharmony_ci      return EPPregisterRead (reg);
2558141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_PS2:
2559141cc406Sopenharmony_ci      DBG (0, "STEF: gMode PS2 in registerRead !!\n");
2560141cc406Sopenharmony_ci      return PS2registerRead (reg);
2561141cc406Sopenharmony_ci    default:
2562141cc406Sopenharmony_ci      DBG (0, "STEF: gMode unset in registerRead !!\n");
2563141cc406Sopenharmony_ci      return 0xFF;
2564141cc406Sopenharmony_ci    }
2565141cc406Sopenharmony_ci}
2566141cc406Sopenharmony_ci
2567141cc406Sopenharmony_ci
2568141cc406Sopenharmony_cistatic void
2569141cc406Sopenharmony_ciECPregisterWrite (int reg, int value)
2570141cc406Sopenharmony_ci{
2571141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2572141cc406Sopenharmony_ci  unsigned char breg;
2573141cc406Sopenharmony_ci  int rc, fd;
2574141cc406Sopenharmony_ci
2575141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
2576141cc406Sopenharmony_ci  if (fd > 0)
2577141cc406Sopenharmony_ci    {
2578141cc406Sopenharmony_ci      ECPFifoMode ();
2579141cc406Sopenharmony_ci      Outb (DATA, reg);
2580141cc406Sopenharmony_ci      breg = value;
2581141cc406Sopenharmony_ci      rc = write (fd, &breg, 1);
2582141cc406Sopenharmony_ci      if (rc != 1)
2583141cc406Sopenharmony_ci	DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
2584141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
2585141cc406Sopenharmony_ci      byteMode ();
2586141cc406Sopenharmony_ci      return;
2587141cc406Sopenharmony_ci    }
2588141cc406Sopenharmony_ci#endif
2589141cc406Sopenharmony_ci
2590141cc406Sopenharmony_ci  /* standard mode, interrupt bit, dma disabled,
2591141cc406Sopenharmony_ci     service bit, fifo full=0, fifo empty=0 */
2592141cc406Sopenharmony_ci  compatMode ();
2593141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);		/* reset ? */
2594141cc406Sopenharmony_ci
2595141cc406Sopenharmony_ci  /* ECP FIFO mode, interrupt bit, dma disabled,
2596141cc406Sopenharmony_ci     service bit, fifo full=0, fifo empty=0 */
2597141cc406Sopenharmony_ci  ECPFifoMode ();		/*Outb (ECR, 0x60); */
2598141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2599141cc406Sopenharmony_ci    {
2600141cc406Sopenharmony_ci      DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n",
2601141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2602141cc406Sopenharmony_ci      return;
2603141cc406Sopenharmony_ci    }
2604141cc406Sopenharmony_ci  Inb (ECR);
2605141cc406Sopenharmony_ci
2606141cc406Sopenharmony_ci  Outb (DATA, reg);
2607141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2608141cc406Sopenharmony_ci    {
2609141cc406Sopenharmony_ci      DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n",
2610141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2611141cc406Sopenharmony_ci      return;
2612141cc406Sopenharmony_ci    }
2613141cc406Sopenharmony_ci  Inb (ECR);
2614141cc406Sopenharmony_ci
2615141cc406Sopenharmony_ci  Outb (ECPDATA, value);
2616141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2617141cc406Sopenharmony_ci    {
2618141cc406Sopenharmony_ci      DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n",
2619141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2620141cc406Sopenharmony_ci      return;
2621141cc406Sopenharmony_ci    }
2622141cc406Sopenharmony_ci  Inb (ECR);
2623141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2624141cc406Sopenharmony_ci  byteMode ();
2625141cc406Sopenharmony_ci  return;
2626141cc406Sopenharmony_ci}
2627141cc406Sopenharmony_ci
2628141cc406Sopenharmony_cistatic void
2629141cc406Sopenharmony_ciEPPregisterWrite (int reg, int value)
2630141cc406Sopenharmony_ci{
2631141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2632141cc406Sopenharmony_ci  int fd, mode, rc;
2633141cc406Sopenharmony_ci  unsigned char breg, bval;
2634141cc406Sopenharmony_ci#endif
2635141cc406Sopenharmony_ci
2636141cc406Sopenharmony_ci  reg = reg | 0x40;
2637141cc406Sopenharmony_ci
2638141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2639141cc406Sopenharmony_ci  /* check we have ppdev working */
2640141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
2641141cc406Sopenharmony_ci  if (fd > 0)
2642141cc406Sopenharmony_ci    {
2643141cc406Sopenharmony_ci      breg = (unsigned char) (reg);
2644141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2645141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2646141cc406Sopenharmony_ci      if (rc)
2647141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2648141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2649141cc406Sopenharmony_ci      rc = write (fd, &breg, 1);
2650141cc406Sopenharmony_ci      if (rc != 1)
2651141cc406Sopenharmony_ci	DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__);
2652141cc406Sopenharmony_ci
2653141cc406Sopenharmony_ci      bval = (unsigned char) (value);
2654141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2655141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2656141cc406Sopenharmony_ci      if (rc)
2657141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2658141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2659141cc406Sopenharmony_ci      rc = write (fd, &bval, 1);
2660141cc406Sopenharmony_ci
2661141cc406Sopenharmony_ci      return;
2662141cc406Sopenharmony_ci    }
2663141cc406Sopenharmony_ci  /* if not, direct hardware access */
2664141cc406Sopenharmony_ci#endif
2665141cc406Sopenharmony_ci  Outb (EPPADDR, reg);
2666141cc406Sopenharmony_ci  Outb (EPPDATA, value);
2667141cc406Sopenharmony_ci}
2668141cc406Sopenharmony_ci
2669141cc406Sopenharmony_cistatic void
2670141cc406Sopenharmony_ciregisterWrite (int reg, int value)
2671141cc406Sopenharmony_ci{
2672141cc406Sopenharmony_ci  switch (gMode)
2673141cc406Sopenharmony_ci    {
2674141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_PS2:
2675141cc406Sopenharmony_ci      PS2registerWrite (reg, value);
2676141cc406Sopenharmony_ci      DBG (0, "STEF: gMode PS2 in registerWrite !!\n");
2677141cc406Sopenharmony_ci      break;
2678141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_ECP:
2679141cc406Sopenharmony_ci      ECPregisterWrite (reg, value);
2680141cc406Sopenharmony_ci      break;
2681141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_EPP:
2682141cc406Sopenharmony_ci      EPPregisterWrite (reg, value);
2683141cc406Sopenharmony_ci      break;
2684141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_BYTE:
2685141cc406Sopenharmony_ci      DBG (0, "STEF: gMode BYTE in registerWrite !!\n");
2686141cc406Sopenharmony_ci      break;
2687141cc406Sopenharmony_ci    default:
2688141cc406Sopenharmony_ci      DBG (0, "STEF: gMode unset in registerWrite !!\n");
2689141cc406Sopenharmony_ci      break;
2690141cc406Sopenharmony_ci    }
2691141cc406Sopenharmony_ci}
2692141cc406Sopenharmony_ci
2693141cc406Sopenharmony_cistatic void
2694141cc406Sopenharmony_ciEPPBlockMode (int flag)
2695141cc406Sopenharmony_ci{
2696141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2697141cc406Sopenharmony_ci  int fd, mode, rc;
2698141cc406Sopenharmony_ci  unsigned char bval;
2699141cc406Sopenharmony_ci
2700141cc406Sopenharmony_ci  /* check we have ppdev working */
2701141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
2702141cc406Sopenharmony_ci  if (fd > 0)
2703141cc406Sopenharmony_ci    {
2704141cc406Sopenharmony_ci      bval = (unsigned char) (flag);
2705141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2706141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2707141cc406Sopenharmony_ci      if (rc)
2708141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2709141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2710141cc406Sopenharmony_ci      rc = write (fd, &bval, 1);
2711141cc406Sopenharmony_ci      return;
2712141cc406Sopenharmony_ci    }
2713141cc406Sopenharmony_ci#endif
2714141cc406Sopenharmony_ci  Outb (EPPADDR, flag);
2715141cc406Sopenharmony_ci}
2716141cc406Sopenharmony_ci
2717141cc406Sopenharmony_cistatic void
2718141cc406Sopenharmony_ciEPPbufferRead (int size, unsigned char *dest)
2719141cc406Sopenharmony_ci{
2720141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2721141cc406Sopenharmony_ci  int fd, mode, rc, nb;
2722141cc406Sopenharmony_ci  unsigned char bval;
2723141cc406Sopenharmony_ci#endif
2724141cc406Sopenharmony_ci  int control;
2725141cc406Sopenharmony_ci
2726141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2727141cc406Sopenharmony_ci  /* check we have ppdev working */
2728141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
2729141cc406Sopenharmony_ci  if (fd > 0)
2730141cc406Sopenharmony_ci    {
2731141cc406Sopenharmony_ci
2732141cc406Sopenharmony_ci      bval = 0x80;
2733141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2734141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2735141cc406Sopenharmony_ci      if (rc)
2736141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2737141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2738141cc406Sopenharmony_ci      rc = write (fd, &bval, 1);
2739141cc406Sopenharmony_ci
2740141cc406Sopenharmony_ci      mode = 1;			/* data_reverse */
2741141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
2742141cc406Sopenharmony_ci      if (rc)
2743141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2744141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2745141cc406Sopenharmony_ci#ifdef PPSETFLAGS
2746141cc406Sopenharmony_ci      mode = PP_FASTREAD;
2747141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETFLAGS, &mode);
2748141cc406Sopenharmony_ci      if (rc)
2749141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2750141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2751141cc406Sopenharmony_ci#endif
2752141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2753141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2754141cc406Sopenharmony_ci      if (rc)
2755141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2756141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2757141cc406Sopenharmony_ci      nb = 0;
2758141cc406Sopenharmony_ci      while (nb < size - 1)
2759141cc406Sopenharmony_ci	{
2760141cc406Sopenharmony_ci	  rc = read (fd, dest + nb, size - 1 - nb);
2761141cc406Sopenharmony_ci	  nb += rc;
2762141cc406Sopenharmony_ci	}
2763141cc406Sopenharmony_ci
2764141cc406Sopenharmony_ci      mode = 0;			/* forward */
2765141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
2766141cc406Sopenharmony_ci      if (rc)
2767141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2768141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2769141cc406Sopenharmony_ci      bval = 0xA0;
2770141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2771141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2772141cc406Sopenharmony_ci      if (rc)
2773141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2774141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2775141cc406Sopenharmony_ci      rc = write (fd, &bval, 1);
2776141cc406Sopenharmony_ci
2777141cc406Sopenharmony_ci      mode = 1;			/* data_reverse */
2778141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
2779141cc406Sopenharmony_ci      if (rc)
2780141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2781141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2782141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2783141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2784141cc406Sopenharmony_ci      if (rc)
2785141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2786141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2787141cc406Sopenharmony_ci      rc = read (fd, dest + size - 1, 1);
2788141cc406Sopenharmony_ci
2789141cc406Sopenharmony_ci      mode = 0;			/* forward */
2790141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
2791141cc406Sopenharmony_ci      if (rc)
2792141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2793141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2794141cc406Sopenharmony_ci
2795141cc406Sopenharmony_ci      return;
2796141cc406Sopenharmony_ci    }
2797141cc406Sopenharmony_ci  /* if not, direct hardware access */
2798141cc406Sopenharmony_ci#endif
2799141cc406Sopenharmony_ci
2800141cc406Sopenharmony_ci  EPPBlockMode (0x80);
2801141cc406Sopenharmony_ci  control = Inb (CONTROL);
2802141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F) | 0x20);	/* reverse */
2803141cc406Sopenharmony_ci  Insb (EPPDATA, dest, size - 1);
2804141cc406Sopenharmony_ci  control = Inb (CONTROL);
2805141cc406Sopenharmony_ci
2806141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F));	/* forward */
2807141cc406Sopenharmony_ci  EPPBlockMode (0xA0);
2808141cc406Sopenharmony_ci  control = Inb (CONTROL);
2809141cc406Sopenharmony_ci
2810141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F) | 0x20);	/* reverse */
2811141cc406Sopenharmony_ci  Insb (EPPDATA, (unsigned char *) (dest + size - 1), 1);
2812141cc406Sopenharmony_ci
2813141cc406Sopenharmony_ci  control = Inb (CONTROL);
2814141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F));	/* forward */
2815141cc406Sopenharmony_ci}
2816141cc406Sopenharmony_ci
2817141cc406Sopenharmony_ci
2818141cc406Sopenharmony_ci/* block transfer init */
2819141cc406Sopenharmony_cistatic void
2820141cc406Sopenharmony_ciECPSetBuffer (int size)
2821141cc406Sopenharmony_ci{
2822141cc406Sopenharmony_ci  static int last = 0;
2823141cc406Sopenharmony_ci
2824141cc406Sopenharmony_ci  /* routine XX */
2825141cc406Sopenharmony_ci  compatMode ();
2826141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);		/* reset ? */
2827141cc406Sopenharmony_ci
2828141cc406Sopenharmony_ci  /* we set size only if it has changed */
2829141cc406Sopenharmony_ci  /* from last time        */
2830141cc406Sopenharmony_ci  if (size == last)
2831141cc406Sopenharmony_ci    return;
2832141cc406Sopenharmony_ci  last = size;
2833141cc406Sopenharmony_ci
2834141cc406Sopenharmony_ci  /* mode and size setting */
2835141cc406Sopenharmony_ci  ECPFifoMode ();		/*Outb (ECR, 0x60);         */
2836141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2837141cc406Sopenharmony_ci    {
2838141cc406Sopenharmony_ci      DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2839141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2840141cc406Sopenharmony_ci      return;
2841141cc406Sopenharmony_ci    }
2842141cc406Sopenharmony_ci  Inb (ECR);
2843141cc406Sopenharmony_ci
2844141cc406Sopenharmony_ci  Outb (DATA, 0x0E);
2845141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2846141cc406Sopenharmony_ci    {
2847141cc406Sopenharmony_ci      DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2848141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2849141cc406Sopenharmony_ci      return;
2850141cc406Sopenharmony_ci    }
2851141cc406Sopenharmony_ci  Inb (ECR);
2852141cc406Sopenharmony_ci
2853141cc406Sopenharmony_ci  Outb (ECPDATA, 0x0B);		/* R0E=0x0B */
2854141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2855141cc406Sopenharmony_ci    {
2856141cc406Sopenharmony_ci      DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2857141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2858141cc406Sopenharmony_ci      return;
2859141cc406Sopenharmony_ci    }
2860141cc406Sopenharmony_ci  Inb (ECR);
2861141cc406Sopenharmony_ci
2862141cc406Sopenharmony_ci  Outb (DATA, 0x0F);		/* R0F=size MSB */
2863141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2864141cc406Sopenharmony_ci    {
2865141cc406Sopenharmony_ci      DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2866141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2867141cc406Sopenharmony_ci      return;
2868141cc406Sopenharmony_ci    }
2869141cc406Sopenharmony_ci  Inb (ECR);
2870141cc406Sopenharmony_ci
2871141cc406Sopenharmony_ci  Outb (ECPDATA, size / 256);
2872141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2873141cc406Sopenharmony_ci    {
2874141cc406Sopenharmony_ci      DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2875141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2876141cc406Sopenharmony_ci      return;
2877141cc406Sopenharmony_ci    }
2878141cc406Sopenharmony_ci  Inb (ECR);
2879141cc406Sopenharmony_ci
2880141cc406Sopenharmony_ci  Outb (DATA, 0x0B);		/* R0B=size LSB */
2881141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2882141cc406Sopenharmony_ci    {
2883141cc406Sopenharmony_ci      DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2884141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2885141cc406Sopenharmony_ci      return;
2886141cc406Sopenharmony_ci    }
2887141cc406Sopenharmony_ci  Inb (ECR);
2888141cc406Sopenharmony_ci
2889141cc406Sopenharmony_ci  Outb (ECPDATA, size % 256);
2890141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2891141cc406Sopenharmony_ci    {
2892141cc406Sopenharmony_ci      DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n",
2893141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2894141cc406Sopenharmony_ci      return;
2895141cc406Sopenharmony_ci    }
2896141cc406Sopenharmony_ci  Inb (ECR);
2897141cc406Sopenharmony_ci  DBG (16, "ECPSetBuffer(%d) passed ...\n", size);
2898141cc406Sopenharmony_ci}
2899141cc406Sopenharmony_ci
2900141cc406Sopenharmony_ci
2901141cc406Sopenharmony_ci
2902141cc406Sopenharmony_cistatic int
2903141cc406Sopenharmony_ciECPbufferRead (int size, unsigned char *dest)
2904141cc406Sopenharmony_ci{
2905141cc406Sopenharmony_ci  int n, idx, remain;
2906141cc406Sopenharmony_ci
2907141cc406Sopenharmony_ci  idx = 0;
2908141cc406Sopenharmony_ci  n = size / 16;
2909141cc406Sopenharmony_ci  remain = size - 16 * n;
2910141cc406Sopenharmony_ci
2911141cc406Sopenharmony_ci  /* block transfer */
2912141cc406Sopenharmony_ci  Inb (ECR);			/* 0x15,0x75 expected: fifo empty */
2913141cc406Sopenharmony_ci
2914141cc406Sopenharmony_ci  byteMode ();			/*Outb (ECR, 0x20);            byte mode */
2915141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
2916141cc406Sopenharmony_ci
2917141cc406Sopenharmony_ci  ECPFifoMode ();		/*Outb (ECR, 0x60); */
2918141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2919141cc406Sopenharmony_ci    {
2920141cc406Sopenharmony_ci      DBG (0, "ECPbufferRead failed, time-out waiting for FIFO (%s:%d)\n",
2921141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2922141cc406Sopenharmony_ci      return idx;
2923141cc406Sopenharmony_ci    }
2924141cc406Sopenharmony_ci  Inb (ECR);
2925141cc406Sopenharmony_ci
2926141cc406Sopenharmony_ci  Outb (DATA, 0x80);
2927141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
2928141cc406Sopenharmony_ci    {
2929141cc406Sopenharmony_ci      DBG (0, "ECPbufferRead failed, time-out waiting for FIFO (%s:%d)\n",
2930141cc406Sopenharmony_ci	   __FILE__, __LINE__);
2931141cc406Sopenharmony_ci      return idx;
2932141cc406Sopenharmony_ci    }
2933141cc406Sopenharmony_ci  Inb (ECR);			/* 0x75 expected */
2934141cc406Sopenharmony_ci
2935141cc406Sopenharmony_ci  byteMode ();			/*Outb (ECR, 0x20);            byte mode */
2936141cc406Sopenharmony_ci  Outb (CONTROL, 0x20);		/* data reverse */
2937141cc406Sopenharmony_ci  ECPFifoMode ();		/*Outb (ECR, 0x60); */
2938141cc406Sopenharmony_ci
2939141cc406Sopenharmony_ci  while (n > 0)
2940141cc406Sopenharmony_ci    {
2941141cc406Sopenharmony_ci      if (waitFifoFull () == 0)
2942141cc406Sopenharmony_ci	{
2943141cc406Sopenharmony_ci	  DBG (0,
2944141cc406Sopenharmony_ci	       "ECPbufferRead failed, time-out waiting for FIFO idx=%d (%s:%d)\n",
2945141cc406Sopenharmony_ci	       idx, __FILE__, __LINE__);
2946141cc406Sopenharmony_ci	  return idx;
2947141cc406Sopenharmony_ci	}
2948141cc406Sopenharmony_ci      Insb (ECPDATA, dest + idx, 16);
2949141cc406Sopenharmony_ci      idx += 16;
2950141cc406Sopenharmony_ci      n--;
2951141cc406Sopenharmony_ci    }
2952141cc406Sopenharmony_ci
2953141cc406Sopenharmony_ci  /* reading trailing bytes */
2954141cc406Sopenharmony_ci  while (remain > 0)
2955141cc406Sopenharmony_ci    {
2956141cc406Sopenharmony_ci      if (waitFifoNotEmpty () == 0)
2957141cc406Sopenharmony_ci	{
2958141cc406Sopenharmony_ci	  DBG (0, "ECPbufferRead failed, FIFO time-out (%s:%d)\n",
2959141cc406Sopenharmony_ci	       __FILE__, __LINE__);
2960141cc406Sopenharmony_ci	}
2961141cc406Sopenharmony_ci      dest[idx] = Inb (ECPDATA);
2962141cc406Sopenharmony_ci      idx++;
2963141cc406Sopenharmony_ci      remain--;
2964141cc406Sopenharmony_ci    }
2965141cc406Sopenharmony_ci
2966141cc406Sopenharmony_ci  return idx;
2967141cc406Sopenharmony_ci}
2968141cc406Sopenharmony_ci
2969141cc406Sopenharmony_cistatic void
2970141cc406Sopenharmony_ciEPPbufferWrite (int size, unsigned char *source)
2971141cc406Sopenharmony_ci{
2972141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2973141cc406Sopenharmony_ci  int fd, mode, rc;
2974141cc406Sopenharmony_ci  unsigned char bval;
2975141cc406Sopenharmony_ci#endif
2976141cc406Sopenharmony_ci
2977141cc406Sopenharmony_ci
2978141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
2979141cc406Sopenharmony_ci  /* check we have ppdev working */
2980141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
2981141cc406Sopenharmony_ci  if (fd > 0)
2982141cc406Sopenharmony_ci    {
2983141cc406Sopenharmony_ci      bval = 0xC0;
2984141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
2985141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2986141cc406Sopenharmony_ci      if (rc)
2987141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2988141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2989141cc406Sopenharmony_ci      rc = write (fd, &bval, 1);
2990141cc406Sopenharmony_ci
2991141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
2992141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
2993141cc406Sopenharmony_ci      if (rc)
2994141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
2995141cc406Sopenharmony_ci	     __FILE__, __LINE__);
2996141cc406Sopenharmony_ci      rc = write (fd, source, size);
2997141cc406Sopenharmony_ci      return;
2998141cc406Sopenharmony_ci    }
2999141cc406Sopenharmony_ci  /* if not, direct hardware access */
3000141cc406Sopenharmony_ci#endif
3001141cc406Sopenharmony_ci  EPPBlockMode (0xC0);
3002141cc406Sopenharmony_ci  Outsb (EPPDATA, source, size);
3003141cc406Sopenharmony_ci}
3004141cc406Sopenharmony_ci
3005141cc406Sopenharmony_cistatic void
3006141cc406Sopenharmony_ciECPbufferWrite (int size, unsigned char *source)
3007141cc406Sopenharmony_ci{
3008141cc406Sopenharmony_ci  unsigned char breg;
3009141cc406Sopenharmony_ci  int n, idx;
3010141cc406Sopenharmony_ci
3011141cc406Sopenharmony_ci  /* until we know to handle that case, fail */
3012141cc406Sopenharmony_ci  if (size % 16 != 0)
3013141cc406Sopenharmony_ci    {
3014141cc406Sopenharmony_ci      DBG (0, "ECPbufferWrite failed, size %%16 !=0 (%s:%d)\n",
3015141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3016141cc406Sopenharmony_ci      return;
3017141cc406Sopenharmony_ci    }
3018141cc406Sopenharmony_ci
3019141cc406Sopenharmony_ci  /* prepare actual transfer */
3020141cc406Sopenharmony_ci  compatMode ();
3021141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);		/* reset ? */
3022141cc406Sopenharmony_ci  breg = Inb (CONTROL);
3023141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);		/* data forward */
3024141cc406Sopenharmony_ci  ECPFifoMode ();		/*Outb (ECR, 0x60);         */
3025141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
3026141cc406Sopenharmony_ci    {
3027141cc406Sopenharmony_ci      DBG (0, "ECPWriteBuffer failed, time-out waiting for FIFO (%s:%d)\n",
3028141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3029141cc406Sopenharmony_ci      return;
3030141cc406Sopenharmony_ci    }
3031141cc406Sopenharmony_ci  breg = Inb (ECR);
3032141cc406Sopenharmony_ci  breg = (Inb (STATUS)) & 0xF8;
3033141cc406Sopenharmony_ci  n = 0;
3034141cc406Sopenharmony_ci  while ((n < 1024) && (breg != 0xF8))
3035141cc406Sopenharmony_ci    {
3036141cc406Sopenharmony_ci      breg = (Inb (STATUS)) & 0xF8;
3037141cc406Sopenharmony_ci      n++;
3038141cc406Sopenharmony_ci    }
3039141cc406Sopenharmony_ci  if (breg != 0xF8)
3040141cc406Sopenharmony_ci    {
3041141cc406Sopenharmony_ci      DBG (0,
3042141cc406Sopenharmony_ci	   "ECPbufferWrite failed, expected status=0xF8, got 0x%02X (%s:%d)\n",
3043141cc406Sopenharmony_ci	   breg, __FILE__, __LINE__);
3044141cc406Sopenharmony_ci      return;
3045141cc406Sopenharmony_ci    }
3046141cc406Sopenharmony_ci
3047141cc406Sopenharmony_ci  /* wait for FIFO empty (bit 0) */
3048141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
3049141cc406Sopenharmony_ci    {
3050141cc406Sopenharmony_ci      DBG (0, "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n",
3051141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3052141cc406Sopenharmony_ci      return;
3053141cc406Sopenharmony_ci    }
3054141cc406Sopenharmony_ci  breg = Inb (ECR);
3055141cc406Sopenharmony_ci
3056141cc406Sopenharmony_ci  /* block transfer direction
3057141cc406Sopenharmony_ci   * 0x80 means from scanner to PC, 0xC0 means PC to scanner
3058141cc406Sopenharmony_ci   */
3059141cc406Sopenharmony_ci  Outb (DATA, 0xC0);
3060141cc406Sopenharmony_ci
3061141cc406Sopenharmony_ci  n = size / 16;
3062141cc406Sopenharmony_ci  idx = 0;
3063141cc406Sopenharmony_ci  while (n > 0)
3064141cc406Sopenharmony_ci    {
3065141cc406Sopenharmony_ci      /* wait for FIFO empty */
3066141cc406Sopenharmony_ci      if (waitFifoEmpty () == 0)
3067141cc406Sopenharmony_ci	{
3068141cc406Sopenharmony_ci	  DBG (0,
3069141cc406Sopenharmony_ci	       "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n",
3070141cc406Sopenharmony_ci	       __FILE__, __LINE__);
3071141cc406Sopenharmony_ci	  return;
3072141cc406Sopenharmony_ci	}
3073141cc406Sopenharmony_ci      breg = Inb (ECR);
3074141cc406Sopenharmony_ci
3075141cc406Sopenharmony_ci      Outsb (ECPDATA, source + idx * 16, 16);
3076141cc406Sopenharmony_ci      idx++;
3077141cc406Sopenharmony_ci      n--;
3078141cc406Sopenharmony_ci    }
3079141cc406Sopenharmony_ci
3080141cc406Sopenharmony_ci
3081141cc406Sopenharmony_ci  /* final FIFO check and go to Byte mode */
3082141cc406Sopenharmony_ci  if (waitFifoEmpty () == 0)
3083141cc406Sopenharmony_ci    {
3084141cc406Sopenharmony_ci      DBG (0, "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n",
3085141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3086141cc406Sopenharmony_ci      return;
3087141cc406Sopenharmony_ci    }
3088141cc406Sopenharmony_ci  breg = Inb (ECR);
3089141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
3090141cc406Sopenharmony_ci  byteMode ();
3091141cc406Sopenharmony_ci}
3092141cc406Sopenharmony_ci
3093141cc406Sopenharmony_cistatic void
3094141cc406Sopenharmony_cibufferWrite (int size, unsigned char *source)
3095141cc406Sopenharmony_ci{
3096141cc406Sopenharmony_ci  switch (gMode)
3097141cc406Sopenharmony_ci    {
3098141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_PS2:
3099141cc406Sopenharmony_ci      PS2bufferWrite (size, source);
3100141cc406Sopenharmony_ci      DBG (0, "STEF: gMode PS2 in bufferWrite !!\n");
3101141cc406Sopenharmony_ci      break;
3102141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_ECP:
3103141cc406Sopenharmony_ci      ECPbufferWrite (size, source);
3104141cc406Sopenharmony_ci      break;
3105141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_EPP:
3106141cc406Sopenharmony_ci      switch (getEPPMode ())
3107141cc406Sopenharmony_ci	{
3108141cc406Sopenharmony_ci	case 32:
3109141cc406Sopenharmony_ci	  EPPWrite32Buffer (size, source);
3110141cc406Sopenharmony_ci	  break;
3111141cc406Sopenharmony_ci	default:
3112141cc406Sopenharmony_ci	  EPPbufferWrite (size, source);
3113141cc406Sopenharmony_ci	  break;
3114141cc406Sopenharmony_ci	}
3115141cc406Sopenharmony_ci      break;
3116141cc406Sopenharmony_ci    default:
3117141cc406Sopenharmony_ci      DBG (0, "STEF: gMode PS2 in bufferWrite !!\n");
3118141cc406Sopenharmony_ci      break;
3119141cc406Sopenharmony_ci    }
3120141cc406Sopenharmony_ci  return;
3121141cc406Sopenharmony_ci}
3122141cc406Sopenharmony_ci
3123141cc406Sopenharmony_cistatic void
3124141cc406Sopenharmony_cibufferRead (int size, unsigned char *dest)
3125141cc406Sopenharmony_ci{
3126141cc406Sopenharmony_ci  switch (gMode)
3127141cc406Sopenharmony_ci    {
3128141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_PS2:
3129141cc406Sopenharmony_ci      PS2bufferRead (size, dest);
3130141cc406Sopenharmony_ci      DBG (0, "STEF: gMode PS2 in bufferRead !!\n");
3131141cc406Sopenharmony_ci      break;
3132141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_ECP:
3133141cc406Sopenharmony_ci      ECPbufferRead (size, dest);
3134141cc406Sopenharmony_ci      break;
3135141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_EPP:
3136141cc406Sopenharmony_ci      switch (getEPPMode ())
3137141cc406Sopenharmony_ci	{
3138141cc406Sopenharmony_ci	case 32:
3139141cc406Sopenharmony_ci	  EPPRead32Buffer (size, dest);
3140141cc406Sopenharmony_ci	  break;
3141141cc406Sopenharmony_ci	default:
3142141cc406Sopenharmony_ci	  EPPbufferRead (size, dest);
3143141cc406Sopenharmony_ci	  break;
3144141cc406Sopenharmony_ci	}
3145141cc406Sopenharmony_ci      break;
3146141cc406Sopenharmony_ci    default:
3147141cc406Sopenharmony_ci      DBG (0, "STEF: gMode unset in bufferRead !!\n");
3148141cc406Sopenharmony_ci      break;
3149141cc406Sopenharmony_ci    }
3150141cc406Sopenharmony_ci  return;
3151141cc406Sopenharmony_ci}
3152141cc406Sopenharmony_ci
3153141cc406Sopenharmony_cistatic int
3154141cc406Sopenharmony_ciconnect (void)
3155141cc406Sopenharmony_ci{
3156141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
3157141cc406Sopenharmony_ci    return connect610p ();
3158141cc406Sopenharmony_ci
3159141cc406Sopenharmony_ci  switch (gMode)
3160141cc406Sopenharmony_ci    {
3161141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_PS2:
3162141cc406Sopenharmony_ci      DBG (0, "STEF: unimplemented gMode PS2 in connect() !!\n");
3163141cc406Sopenharmony_ci      return 0;
3164141cc406Sopenharmony_ci      break;
3165141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_ECP:
3166141cc406Sopenharmony_ci      return ECPconnect ();
3167141cc406Sopenharmony_ci      break;
3168141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_BYTE:
3169141cc406Sopenharmony_ci      DBG (0, "STEF: unimplemented gMode BYTE in connect() !!\n");
3170141cc406Sopenharmony_ci      return 0;
3171141cc406Sopenharmony_ci      break;
3172141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_EPP:
3173141cc406Sopenharmony_ci      return EPPconnect ();
3174141cc406Sopenharmony_ci    default:
3175141cc406Sopenharmony_ci      DBG (0, "STEF: gMode unset in connect() !!\n");
3176141cc406Sopenharmony_ci      break;
3177141cc406Sopenharmony_ci    }
3178141cc406Sopenharmony_ci  return 0;
3179141cc406Sopenharmony_ci}
3180141cc406Sopenharmony_ci
3181141cc406Sopenharmony_ci
3182141cc406Sopenharmony_cistatic void
3183141cc406Sopenharmony_cidisconnect (void)
3184141cc406Sopenharmony_ci{
3185141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
3186141cc406Sopenharmony_ci    disconnect610p ();
3187141cc406Sopenharmony_ci  switch (gMode)
3188141cc406Sopenharmony_ci    {
3189141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_PS2:
3190141cc406Sopenharmony_ci      DBG (0, "STEF: unimplemented gMode PS2 in disconnect() !!\n");
3191141cc406Sopenharmony_ci      break;
3192141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_ECP:
3193141cc406Sopenharmony_ci      ECPdisconnect ();
3194141cc406Sopenharmony_ci      break;
3195141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_BYTE:
3196141cc406Sopenharmony_ci      DBG (0, "STEF: unimplemented gMode BYTE in disconnect() !!\n");
3197141cc406Sopenharmony_ci      break;
3198141cc406Sopenharmony_ci    case UMAX_PP_PARPORT_EPP:
3199141cc406Sopenharmony_ci      EPPdisconnect ();
3200141cc406Sopenharmony_ci      break;
3201141cc406Sopenharmony_ci    default:
3202141cc406Sopenharmony_ci      DBG (0, "STEF: gMode unset in disconnect() !!\n");
3203141cc406Sopenharmony_ci      break;
3204141cc406Sopenharmony_ci    }
3205141cc406Sopenharmony_ci}
3206141cc406Sopenharmony_ci
3207141cc406Sopenharmony_ci
3208141cc406Sopenharmony_ci/* returns 0 if mode OK, else -1 */
3209141cc406Sopenharmony_cistatic int
3210141cc406Sopenharmony_cicheckEPAT (void)
3211141cc406Sopenharmony_ci{
3212141cc406Sopenharmony_ci  int version;
3213141cc406Sopenharmony_ci
3214141cc406Sopenharmony_ci  version = registerRead (0x0B);
3215141cc406Sopenharmony_ci  if (version == 0xC7)
3216141cc406Sopenharmony_ci    return 0;
3217141cc406Sopenharmony_ci  DBG (0, "checkEPAT: expected EPAT version 0xC7, got 0x%X! (%s:%d)\n",
3218141cc406Sopenharmony_ci       version, __FILE__, __LINE__);
3219141cc406Sopenharmony_ci  return -1;
3220141cc406Sopenharmony_ci
3221141cc406Sopenharmony_ci}
3222141cc406Sopenharmony_ci
3223141cc406Sopenharmony_cistatic int
3224141cc406Sopenharmony_ciinit005 (int arg)
3225141cc406Sopenharmony_ci{
3226141cc406Sopenharmony_ci  int count = 5;
3227141cc406Sopenharmony_ci  int res;
3228141cc406Sopenharmony_ci
3229141cc406Sopenharmony_ci  while (count > 0)
3230141cc406Sopenharmony_ci    {
3231141cc406Sopenharmony_ci      registerWrite (0x0A, arg);
3232141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
3233141cc406Sopenharmony_ci      res = registerRead (0x0A);
3234141cc406Sopenharmony_ci
3235141cc406Sopenharmony_ci      /* failed ? */
3236141cc406Sopenharmony_ci      if (res != arg)
3237141cc406Sopenharmony_ci	return 1;
3238141cc406Sopenharmony_ci
3239141cc406Sopenharmony_ci      /* ror arg */
3240141cc406Sopenharmony_ci      res = arg & 0x01;
3241141cc406Sopenharmony_ci      arg = arg / 2;
3242141cc406Sopenharmony_ci      if (res == 1)
3243141cc406Sopenharmony_ci	arg = arg | 0x80;
3244141cc406Sopenharmony_ci
3245141cc406Sopenharmony_ci      /* next loop */
3246141cc406Sopenharmony_ci      count--;
3247141cc406Sopenharmony_ci    }
3248141cc406Sopenharmony_ci  return 0;
3249141cc406Sopenharmony_ci}
3250141cc406Sopenharmony_ci
3251141cc406Sopenharmony_ci/* write 1 byte in EPP mode, returning scnner's status */
3252141cc406Sopenharmony_cistatic int
3253141cc406Sopenharmony_ciEPPputByte610p (int data)
3254141cc406Sopenharmony_ci{
3255141cc406Sopenharmony_ci  int status, control;
3256141cc406Sopenharmony_ci
3257141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
3258141cc406Sopenharmony_ci  if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0))
3259141cc406Sopenharmony_ci    {
3260141cc406Sopenharmony_ci      DBG (0,
3261141cc406Sopenharmony_ci	   "EPPputByte610p failed, expected 0xC8, 0xD0 or 0xC0 got 0x%02X ! (%s:%d)\n",
3262141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
3263141cc406Sopenharmony_ci      return 0;
3264141cc406Sopenharmony_ci    }
3265141cc406Sopenharmony_ci  control = (Inb (CONTROL) & 0x44) | 0x44;	/* data forward, bit 5 cleared (!!) */
3266141cc406Sopenharmony_ci  Outb (CONTROL, control);
3267141cc406Sopenharmony_ci  Outb (EPPDATA, data);
3268141cc406Sopenharmony_ci  return status;
3269141cc406Sopenharmony_ci}
3270141cc406Sopenharmony_ci
3271141cc406Sopenharmony_cistatic int
3272141cc406Sopenharmony_ciputByte610p (int data)
3273141cc406Sopenharmony_ci{
3274141cc406Sopenharmony_ci  int status, control, j;
3275141cc406Sopenharmony_ci
3276141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_EPP)
3277141cc406Sopenharmony_ci    return EPPputByte610p (data);
3278141cc406Sopenharmony_ci  j = 0;
3279141cc406Sopenharmony_ci  do
3280141cc406Sopenharmony_ci    {
3281141cc406Sopenharmony_ci      status = Inb (STATUS) & 0xF8;
3282141cc406Sopenharmony_ci      j++;
3283141cc406Sopenharmony_ci    }
3284141cc406Sopenharmony_ci  while ((j < 20) && (status & 0x08));
3285141cc406Sopenharmony_ci
3286141cc406Sopenharmony_ci  if ((status != 0xC8) && (status != 0xC0))
3287141cc406Sopenharmony_ci    {
3288141cc406Sopenharmony_ci      DBG (0,
3289141cc406Sopenharmony_ci	   "putByte610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n",
3290141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
3291141cc406Sopenharmony_ci      return 0;
3292141cc406Sopenharmony_ci    }
3293141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x1F;	/* data forward */
3294141cc406Sopenharmony_ci  Outb (CONTROL, control);
3295141cc406Sopenharmony_ci
3296141cc406Sopenharmony_ci  Outb (DATA, data);
3297141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
3298141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
3299141cc406Sopenharmony_ci  if ((status != 0x48) && (status != 0x40))
3300141cc406Sopenharmony_ci    {
3301141cc406Sopenharmony_ci      DBG (0,
3302141cc406Sopenharmony_ci	   "putByte610p failed, expected 0x48 or 0x40 got 0x%02X ! (%s:%d)\n",
3303141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
3304141cc406Sopenharmony_ci      return 0;
3305141cc406Sopenharmony_ci    }
3306141cc406Sopenharmony_ci
3307141cc406Sopenharmony_ci
3308141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
3309141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
3310141cc406Sopenharmony_ci  Outb (CONTROL, control);
3311141cc406Sopenharmony_ci  return status;
3312141cc406Sopenharmony_ci}
3313141cc406Sopenharmony_ci
3314141cc406Sopenharmony_ci
3315141cc406Sopenharmony_ci/* 1 OK, 0 failure */
3316141cc406Sopenharmony_cistatic int
3317141cc406Sopenharmony_cisync610p (void)
3318141cc406Sopenharmony_ci{
3319141cc406Sopenharmony_ci  int status;
3320141cc406Sopenharmony_ci
3321141cc406Sopenharmony_ci  Outb (DATA, 0x40);
3322141cc406Sopenharmony_ci  Outb (CONTROL, 0x06);
3323141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
3324141cc406Sopenharmony_ci  if (status != 0x38)
3325141cc406Sopenharmony_ci    {
3326141cc406Sopenharmony_ci      DBG (0, "sync610p failed (got 0x%02X expected 0x38)! (%s:%d)\n",
3327141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
3328141cc406Sopenharmony_ci      return 0;
3329141cc406Sopenharmony_ci    }
3330141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
3331141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
3332141cc406Sopenharmony_ci  if (status != 0x38)
3333141cc406Sopenharmony_ci    {
3334141cc406Sopenharmony_ci      DBG (0, "sync610p failed (got 0x%02X expected 0x38)! (%s:%d)\n",
3335141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
3336141cc406Sopenharmony_ci      return 0;
3337141cc406Sopenharmony_ci    }
3338141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
3339141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
3340141cc406Sopenharmony_ci  if (status != 0xF8)
3341141cc406Sopenharmony_ci    {
3342141cc406Sopenharmony_ci      DBG (0, "sync610p failed (got 0x%02X expected 0xF8)! (%s:%d)\n",
3343141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
3344141cc406Sopenharmony_ci      return 0;
3345141cc406Sopenharmony_ci    }
3346141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
3347141cc406Sopenharmony_ci  Inb (CONTROL);		/* 0x05 expected */
3348141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
3349141cc406Sopenharmony_ci  return 1;
3350141cc406Sopenharmony_ci}
3351141cc406Sopenharmony_ci
3352141cc406Sopenharmony_cistatic int
3353141cc406Sopenharmony_ciEPPcmdSync610p (int cmd)
3354141cc406Sopenharmony_ci{
3355141cc406Sopenharmony_ci  int word[5];
3356141cc406Sopenharmony_ci  int status;
3357141cc406Sopenharmony_ci  int i;
3358141cc406Sopenharmony_ci
3359141cc406Sopenharmony_ci  word[0] = 0;
3360141cc406Sopenharmony_ci  word[1] = 0;
3361141cc406Sopenharmony_ci  word[2] = 0;
3362141cc406Sopenharmony_ci  word[3] = cmd;
3363141cc406Sopenharmony_ci
3364141cc406Sopenharmony_ci  connect610p ();
3365141cc406Sopenharmony_ci  sync610p ();
3366141cc406Sopenharmony_ci
3367141cc406Sopenharmony_ci  /* sends magic seal 55 AA */
3368141cc406Sopenharmony_ci  status = EPPputByte610p (0x55);
3369141cc406Sopenharmony_ci  if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0))
3370141cc406Sopenharmony_ci    {
3371141cc406Sopenharmony_ci      DBG (1,
3372141cc406Sopenharmony_ci	   "EPPcmdSync610p: Found 0x%X expected 0xC8, 0xC0 or 0xD0 (%s:%d)\n",
3373141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
3374141cc406Sopenharmony_ci      return 0;
3375141cc406Sopenharmony_ci    }
3376141cc406Sopenharmony_ci  status = EPPputByte610p (0xAA);
3377141cc406Sopenharmony_ci  if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0))
3378141cc406Sopenharmony_ci    {
3379141cc406Sopenharmony_ci      DBG (1,
3380141cc406Sopenharmony_ci	   "EPPcmdSync610p: Found 0x%X expected 0xC8, 0xC0 or 0xD0 (%s:%d)\n",
3381141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
3382141cc406Sopenharmony_ci      return 0;
3383141cc406Sopenharmony_ci    }
3384141cc406Sopenharmony_ci
3385141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
3386141cc406Sopenharmony_ci  if (status == 0xC0)
3387141cc406Sopenharmony_ci    for (i = 0; i < 10; i++)
3388141cc406Sopenharmony_ci      status = Inb (STATUS) & 0xF8;
3389141cc406Sopenharmony_ci  if (status != 0xC8)
3390141cc406Sopenharmony_ci    {
3391141cc406Sopenharmony_ci      DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC8 (%s:%d)\n", status,
3392141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3393141cc406Sopenharmony_ci      /*return 0; */
3394141cc406Sopenharmony_ci    }
3395141cc406Sopenharmony_ci
3396141cc406Sopenharmony_ci  /* sends 4 bytes of data */
3397141cc406Sopenharmony_ci  for (i = 0; i < 4; i++)
3398141cc406Sopenharmony_ci    {
3399141cc406Sopenharmony_ci      status = EPPputByte610p (word[i]);
3400141cc406Sopenharmony_ci    }
3401141cc406Sopenharmony_ci  if (status != 0xC8)
3402141cc406Sopenharmony_ci    {
3403141cc406Sopenharmony_ci      DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC8 (%s:%d)\n", status,
3404141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3405141cc406Sopenharmony_ci      /*return 0; */
3406141cc406Sopenharmony_ci    }
3407141cc406Sopenharmony_ci
3408141cc406Sopenharmony_ci  /* tests status */
3409141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
3410141cc406Sopenharmony_ci  if (cmd == 0xC2)
3411141cc406Sopenharmony_ci    {
3412141cc406Sopenharmony_ci      status = EPPgetStatus610p ();
3413141cc406Sopenharmony_ci      if (status != 0xC0)
3414141cc406Sopenharmony_ci	{
3415141cc406Sopenharmony_ci	  DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC0 (%s:%d)\n",
3416141cc406Sopenharmony_ci	       status, __FILE__, __LINE__);
3417141cc406Sopenharmony_ci	  /*return 0; */
3418141cc406Sopenharmony_ci	}
3419141cc406Sopenharmony_ci    }
3420141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
3421141cc406Sopenharmony_ci  if (status != 0xC0)
3422141cc406Sopenharmony_ci    {
3423141cc406Sopenharmony_ci      DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC0 (%s:%d)\n", status,
3424141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3425141cc406Sopenharmony_ci      /*return 0; */
3426141cc406Sopenharmony_ci    }
3427141cc406Sopenharmony_ci  disconnect610p ();
3428141cc406Sopenharmony_ci  return 1;
3429141cc406Sopenharmony_ci}
3430141cc406Sopenharmony_ci
3431141cc406Sopenharmony_cistatic int
3432141cc406Sopenharmony_cicmdSync610p (int cmd)
3433141cc406Sopenharmony_ci{
3434141cc406Sopenharmony_ci  int word[5];
3435141cc406Sopenharmony_ci  int status;
3436141cc406Sopenharmony_ci
3437141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_EPP)
3438141cc406Sopenharmony_ci    return EPPcmdSync610p (cmd);
3439141cc406Sopenharmony_ci
3440141cc406Sopenharmony_ci  word[0] = 0;
3441141cc406Sopenharmony_ci  word[1] = 0;
3442141cc406Sopenharmony_ci  word[2] = 0;
3443141cc406Sopenharmony_ci  word[3] = cmd;
3444141cc406Sopenharmony_ci
3445141cc406Sopenharmony_ci  connect610p ();
3446141cc406Sopenharmony_ci  sync610p ();
3447141cc406Sopenharmony_ci  if (sendLength610p (word) == 0)
3448141cc406Sopenharmony_ci    {
3449141cc406Sopenharmony_ci      DBG (0, "sendLength610p() failed... (%s:%d)\n", __FILE__, __LINE__);
3450141cc406Sopenharmony_ci      return 0;
3451141cc406Sopenharmony_ci    }
3452141cc406Sopenharmony_ci  if (cmd == 0xC2)
3453141cc406Sopenharmony_ci    {
3454141cc406Sopenharmony_ci      status = getStatus610p ();
3455141cc406Sopenharmony_ci      if (status != 0xC0)
3456141cc406Sopenharmony_ci	{
3457141cc406Sopenharmony_ci	  DBG (1, "Found 0x%X expected 0xC0  (%s:%d)\n", status, __FILE__,
3458141cc406Sopenharmony_ci	       __LINE__);
3459141cc406Sopenharmony_ci	  return 0;
3460141cc406Sopenharmony_ci	}
3461141cc406Sopenharmony_ci    }
3462141cc406Sopenharmony_ci  status = getStatus610p ();
3463141cc406Sopenharmony_ci  if (status != 0xC0)
3464141cc406Sopenharmony_ci    {
3465141cc406Sopenharmony_ci      DBG (1, "Found 0x%X expected 0xC0  (%s:%d)\n", status, __FILE__,
3466141cc406Sopenharmony_ci	   __LINE__);
3467141cc406Sopenharmony_ci      return 0;
3468141cc406Sopenharmony_ci    }
3469141cc406Sopenharmony_ci  disconnect610p ();
3470141cc406Sopenharmony_ci  return 1;
3471141cc406Sopenharmony_ci}
3472141cc406Sopenharmony_ci
3473141cc406Sopenharmony_cistatic int
3474141cc406Sopenharmony_ciEPPgetStatus610p (void)
3475141cc406Sopenharmony_ci{
3476141cc406Sopenharmony_ci  int data, status, control, i;
3477141cc406Sopenharmony_ci
3478141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0xA4;
3479141cc406Sopenharmony_ci  control = control | 0xE0;
3480141cc406Sopenharmony_ci  Outb (CONTROL, control);
3481141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
3482141cc406Sopenharmony_ci  if (status & 0x08)
3483141cc406Sopenharmony_ci    {
3484141cc406Sopenharmony_ci      for (i = 1; i < 10; i++)
3485141cc406Sopenharmony_ci	status = Inb (STATUS) & 0xF8;
3486141cc406Sopenharmony_ci    }
3487141cc406Sopenharmony_ci  else
3488141cc406Sopenharmony_ci    {
3489141cc406Sopenharmony_ci      data = Inb (EPPDATA);
3490141cc406Sopenharmony_ci      scannerStatus = data;
3491141cc406Sopenharmony_ci    }
3492141cc406Sopenharmony_ci  return status;
3493141cc406Sopenharmony_ci}
3494141cc406Sopenharmony_ci
3495141cc406Sopenharmony_cistatic int
3496141cc406Sopenharmony_cigetStatus610p (void)
3497141cc406Sopenharmony_ci{
3498141cc406Sopenharmony_ci  int data, status;
3499141cc406Sopenharmony_ci
3500141cc406Sopenharmony_ci  byteMode ();
3501141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
3502141cc406Sopenharmony_ci  Outb (CONTROL, 0x26);		/* data reverse */
3503141cc406Sopenharmony_ci  data = Inb (DATA);
3504141cc406Sopenharmony_ci  scannerStatus = data;
3505141cc406Sopenharmony_ci  Outb (CONTROL, 0x24);
3506141cc406Sopenharmony_ci  return status;
3507141cc406Sopenharmony_ci}
3508141cc406Sopenharmony_ci
3509141cc406Sopenharmony_ci
3510141cc406Sopenharmony_ciint
3511141cc406Sopenharmony_cisendLength610p (int *cmd)
3512141cc406Sopenharmony_ci{
3513141cc406Sopenharmony_ci  int ret, i, wait;
3514141cc406Sopenharmony_ci/* 55,AA,x,y,z,t */
3515141cc406Sopenharmony_ci
3516141cc406Sopenharmony_ci  byteMode ();
3517141cc406Sopenharmony_ci  wait = putByte610p (0x55);
3518141cc406Sopenharmony_ci  if ((wait != 0xC8) && (wait != 0xC0))
3519141cc406Sopenharmony_ci    {
3520141cc406Sopenharmony_ci      DBG (0,
3521141cc406Sopenharmony_ci	   "sendLength610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n",
3522141cc406Sopenharmony_ci	   wait, __FILE__, __LINE__);
3523141cc406Sopenharmony_ci      return 0;
3524141cc406Sopenharmony_ci    }
3525141cc406Sopenharmony_ci  wait = putByte610p (0xAA);
3526141cc406Sopenharmony_ci  if ((wait != 0xC8) && (wait != 0xC0))
3527141cc406Sopenharmony_ci    {
3528141cc406Sopenharmony_ci      DBG (0,
3529141cc406Sopenharmony_ci	   "sendLength610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n",
3530141cc406Sopenharmony_ci	   wait, __FILE__, __LINE__);
3531141cc406Sopenharmony_ci      return 0;
3532141cc406Sopenharmony_ci    }
3533141cc406Sopenharmony_ci
3534141cc406Sopenharmony_ci  /* if wait=C0, we have to ... wait */
3535141cc406Sopenharmony_ci  if (wait == 0xC0)
3536141cc406Sopenharmony_ci    {
3537141cc406Sopenharmony_ci      byteMode ();
3538141cc406Sopenharmony_ci      wait = Inb (STATUS);	/* C0 expected */
3539141cc406Sopenharmony_ci      Outb (CONTROL, 0x26);
3540141cc406Sopenharmony_ci      ret = Inb (DATA);		/* 88 expected */
3541141cc406Sopenharmony_ci      Outb (CONTROL, 0x24);
3542141cc406Sopenharmony_ci      for (i = 0; i < 10; i++)
3543141cc406Sopenharmony_ci	wait = Inb (STATUS);	/* C8 expected */
3544141cc406Sopenharmony_ci      byteMode ();
3545141cc406Sopenharmony_ci    }
3546141cc406Sopenharmony_ci
3547141cc406Sopenharmony_ci  for (i = 0; i < 3; i++)
3548141cc406Sopenharmony_ci    {
3549141cc406Sopenharmony_ci      ret = putByte610p (cmd[i]);
3550141cc406Sopenharmony_ci      if (ret != 0xC8)
3551141cc406Sopenharmony_ci	{
3552141cc406Sopenharmony_ci	  DBG (0,
3553141cc406Sopenharmony_ci	       "sendLength610p failed, expected 0xC8 got 0x%02X ! (%s:%d)\n",
3554141cc406Sopenharmony_ci	       ret, __FILE__, __LINE__);
3555141cc406Sopenharmony_ci	  return 0;
3556141cc406Sopenharmony_ci	}
3557141cc406Sopenharmony_ci    }
3558141cc406Sopenharmony_ci  ret = putByte610p (cmd[3]);
3559141cc406Sopenharmony_ci  if ((ret != 0xC0) && (ret != 0xD0))
3560141cc406Sopenharmony_ci    {
3561141cc406Sopenharmony_ci      DBG (0,
3562141cc406Sopenharmony_ci	   "sendLength610p failed, expected 0xC0 or 0xD0 got 0x%02X ! (%s:%d)\n",
3563141cc406Sopenharmony_ci	   ret, __FILE__, __LINE__);
3564141cc406Sopenharmony_ci      return 0;
3565141cc406Sopenharmony_ci    }
3566141cc406Sopenharmony_ci  return 1;
3567141cc406Sopenharmony_ci}
3568141cc406Sopenharmony_ci
3569141cc406Sopenharmony_ci/* 1 OK, 0 failure */
3570141cc406Sopenharmony_cistatic int
3571141cc406Sopenharmony_cidisconnect610p (void)
3572141cc406Sopenharmony_ci{
3573141cc406Sopenharmony_ci  int control, i;
3574141cc406Sopenharmony_ci
3575141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
3576141cc406Sopenharmony_ci  for (i = 0; i < 41; i++)
3577141cc406Sopenharmony_ci    {
3578141cc406Sopenharmony_ci      control = Inb (CONTROL) & 0x3F;
3579141cc406Sopenharmony_ci      if (control != 0x04)
3580141cc406Sopenharmony_ci	{
3581141cc406Sopenharmony_ci	  DBG (0, "disconnect610p failed (idx %d=%02X)! (%s:%d)\n",
3582141cc406Sopenharmony_ci	       i, control, __FILE__, __LINE__);
3583141cc406Sopenharmony_ci	  return 0;
3584141cc406Sopenharmony_ci	}
3585141cc406Sopenharmony_ci    }
3586141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
3587141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x3F;
3588141cc406Sopenharmony_ci  if (control != 0x0C)
3589141cc406Sopenharmony_ci    {
3590141cc406Sopenharmony_ci      DBG (0, "disconnect610p failed expected 0x0C got %02X (%s:%d)\n",
3591141cc406Sopenharmony_ci	   control, __FILE__, __LINE__);
3592141cc406Sopenharmony_ci      return 0;
3593141cc406Sopenharmony_ci    }
3594141cc406Sopenharmony_ci  /* XXX STEF XXX Outb (DATA, gData); */
3595141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
3596141cc406Sopenharmony_ci  return 1;
3597141cc406Sopenharmony_ci}
3598141cc406Sopenharmony_ci
3599141cc406Sopenharmony_ci/* 1 OK, 0 failure */
3600141cc406Sopenharmony_ci/* 0: short connect, 1 long connect */
3601141cc406Sopenharmony_cistatic int
3602141cc406Sopenharmony_ciconnect610p (void)
3603141cc406Sopenharmony_ci{
3604141cc406Sopenharmony_ci  int control;
3605141cc406Sopenharmony_ci
3606141cc406Sopenharmony_ci  gData = Inb (DATA);		/* to gDATA ? */
3607141cc406Sopenharmony_ci
3608141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
3609141cc406Sopenharmony_ci  Outb (CONTROL, 0x0E);
3610141cc406Sopenharmony_ci  control = Inb (CONTROL);	/* 0x0E expected */
3611141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x3F;
3612141cc406Sopenharmony_ci  if (control != 0x0E)
3613141cc406Sopenharmony_ci    {
3614141cc406Sopenharmony_ci      DBG (0, "connect610p control=%02X, expected 0x0E (%s:%d)\n", control,
3615141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3616141cc406Sopenharmony_ci    }
3617141cc406Sopenharmony_ci
3618141cc406Sopenharmony_ci  Outb (DATA, 0x00);
3619141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
3620141cc406Sopenharmony_ci  control = Inb (CONTROL);	/* 0x0C expected */
3621141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x3F;
3622141cc406Sopenharmony_ci  if (control != 0x0C)
3623141cc406Sopenharmony_ci    {
3624141cc406Sopenharmony_ci      DBG (0, "connect610p control=%02X, expected 0x0C (%s:%d)\n", control,
3625141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3626141cc406Sopenharmony_ci    }
3627141cc406Sopenharmony_ci
3628141cc406Sopenharmony_ci  Outb (DATA, 0x55);
3629141cc406Sopenharmony_ci  Outb (CONTROL, 0x0E);
3630141cc406Sopenharmony_ci  control = Inb (CONTROL);	/* 0x0E expected */
3631141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x3F;
3632141cc406Sopenharmony_ci  if (control != 0x0E)
3633141cc406Sopenharmony_ci    {
3634141cc406Sopenharmony_ci      DBG (0, "connect610p control=%02X, expected 0x0E (%s:%d)\n", control,
3635141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3636141cc406Sopenharmony_ci    }
3637141cc406Sopenharmony_ci
3638141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
3639141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
3640141cc406Sopenharmony_ci  control = Inb (CONTROL);	/* 0x0C expected */
3641141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x3F;
3642141cc406Sopenharmony_ci  if (control != 0x0C)
3643141cc406Sopenharmony_ci    {
3644141cc406Sopenharmony_ci      DBG (0, "connect610p control=%02X, expected 0x0C (%s:%d)\n", control,
3645141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3646141cc406Sopenharmony_ci    }
3647141cc406Sopenharmony_ci
3648141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
3649141cc406Sopenharmony_ci  control = Inb (CONTROL);	/* 0x04 expected */
3650141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x3F;
3651141cc406Sopenharmony_ci  if (control != 0x04)
3652141cc406Sopenharmony_ci    {
3653141cc406Sopenharmony_ci      DBG (0, "connect610p control=%02X, expected 0x04 (%s:%d)\n", control,
3654141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3655141cc406Sopenharmony_ci    }
3656141cc406Sopenharmony_ci  return 1;
3657141cc406Sopenharmony_ci}
3658141cc406Sopenharmony_ci
3659141cc406Sopenharmony_ci/* 1 OK, 0 failure */
3660141cc406Sopenharmony_cistatic int
3661141cc406Sopenharmony_ciEPPconnect (void)
3662141cc406Sopenharmony_ci{
3663141cc406Sopenharmony_ci  int control;
3664141cc406Sopenharmony_ci
3665141cc406Sopenharmony_ci  /* initial values, don't hardcode */
3666141cc406Sopenharmony_ci  Outb (DATA, 0x04);
3667141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
3668141cc406Sopenharmony_ci
3669141cc406Sopenharmony_ci  Inb (DATA);
3670141cc406Sopenharmony_ci  control = Inb (CONTROL);
3671141cc406Sopenharmony_ci  Outb (CONTROL, control & 0x1F);
3672141cc406Sopenharmony_ci  control = Inb (CONTROL);
3673141cc406Sopenharmony_ci  Outb (CONTROL, control & 0x1F);
3674141cc406Sopenharmony_ci
3675141cc406Sopenharmony_ci  if (sendCommand (0xE0) != 1)
3676141cc406Sopenharmony_ci    {
3677141cc406Sopenharmony_ci      DBG (0, "EPPconnect: sendCommand(0xE0) failed! (%s:%d)\n", __FILE__,
3678141cc406Sopenharmony_ci	   __LINE__);
3679141cc406Sopenharmony_ci      return 0;
3680141cc406Sopenharmony_ci    }
3681141cc406Sopenharmony_ci  ClearRegister (0);
3682141cc406Sopenharmony_ci  init001 ();
3683141cc406Sopenharmony_ci  return 1;
3684141cc406Sopenharmony_ci}
3685141cc406Sopenharmony_ci
3686141cc406Sopenharmony_ci
3687141cc406Sopenharmony_ci
3688141cc406Sopenharmony_cistatic void
3689141cc406Sopenharmony_ciEPPRead32Buffer (int size, unsigned char *dest)
3690141cc406Sopenharmony_ci{
3691141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
3692141cc406Sopenharmony_ci  int fd, mode, rc, nb;
3693141cc406Sopenharmony_ci  unsigned char bval;
3694141cc406Sopenharmony_ci#endif
3695141cc406Sopenharmony_ci  int control;
3696141cc406Sopenharmony_ci
3697141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
3698141cc406Sopenharmony_ci  /* check we have ppdev working */
3699141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
3700141cc406Sopenharmony_ci  if (fd > 0)
3701141cc406Sopenharmony_ci    {
3702141cc406Sopenharmony_ci
3703141cc406Sopenharmony_ci      bval = 0x80;
3704141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
3705141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
3706141cc406Sopenharmony_ci      if (rc)
3707141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3708141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3709141cc406Sopenharmony_ci      rc = write (fd, &bval, 1);
3710141cc406Sopenharmony_ci
3711141cc406Sopenharmony_ci      mode = 1;			/* data_reverse */
3712141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
3713141cc406Sopenharmony_ci      if (rc)
3714141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3715141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3716141cc406Sopenharmony_ci#ifdef PPSETFLAGS
3717141cc406Sopenharmony_ci      mode = PP_FASTREAD;
3718141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETFLAGS, &mode);
3719141cc406Sopenharmony_ci      if (rc)
3720141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3721141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3722141cc406Sopenharmony_ci#endif
3723141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
3724141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
3725141cc406Sopenharmony_ci      if (rc)
3726141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3727141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3728141cc406Sopenharmony_ci      nb = 0;
3729141cc406Sopenharmony_ci      while (nb < size - 4)
3730141cc406Sopenharmony_ci	{
3731141cc406Sopenharmony_ci	  rc = read (fd, dest + nb, size - 4 - nb);
3732141cc406Sopenharmony_ci	  nb += rc;
3733141cc406Sopenharmony_ci	}
3734141cc406Sopenharmony_ci
3735141cc406Sopenharmony_ci      rc = read (fd, dest + size - 4, 3);
3736141cc406Sopenharmony_ci
3737141cc406Sopenharmony_ci      mode = 0;			/* forward */
3738141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
3739141cc406Sopenharmony_ci      if (rc)
3740141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3741141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3742141cc406Sopenharmony_ci      bval = 0xA0;
3743141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
3744141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
3745141cc406Sopenharmony_ci      if (rc)
3746141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3747141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3748141cc406Sopenharmony_ci      rc = write (fd, &bval, 1);
3749141cc406Sopenharmony_ci
3750141cc406Sopenharmony_ci      mode = 1;			/* data_reverse */
3751141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
3752141cc406Sopenharmony_ci      if (rc)
3753141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3754141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3755141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
3756141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
3757141cc406Sopenharmony_ci      if (rc)
3758141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3759141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3760141cc406Sopenharmony_ci      rc = read (fd, dest + size - 1, 1);
3761141cc406Sopenharmony_ci
3762141cc406Sopenharmony_ci      mode = 0;			/* forward */
3763141cc406Sopenharmony_ci      rc = ioctl (fd, PPDATADIR, &mode);
3764141cc406Sopenharmony_ci      if (rc)
3765141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3766141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3767141cc406Sopenharmony_ci
3768141cc406Sopenharmony_ci      return;
3769141cc406Sopenharmony_ci    }
3770141cc406Sopenharmony_ci  /* if not, direct hardware access */
3771141cc406Sopenharmony_ci#endif
3772141cc406Sopenharmony_ci
3773141cc406Sopenharmony_ci  EPPBlockMode (0x80);
3774141cc406Sopenharmony_ci
3775141cc406Sopenharmony_ci  control = Inb (CONTROL);
3776141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F) | 0x20);
3777141cc406Sopenharmony_ci  Insw (EPPDATA, dest, size / 4 - 1);
3778141cc406Sopenharmony_ci
3779141cc406Sopenharmony_ci  Insb (EPPDATA, (unsigned char *) (dest + size - 4), 3);
3780141cc406Sopenharmony_ci  control = Inb (CONTROL);
3781141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F));
3782141cc406Sopenharmony_ci
3783141cc406Sopenharmony_ci  EPPBlockMode (0xA0);
3784141cc406Sopenharmony_ci  control = Inb (CONTROL);
3785141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F) | 0x20);
3786141cc406Sopenharmony_ci
3787141cc406Sopenharmony_ci  Insb (EPPDATA, (unsigned char *) (dest + size - 1), 1);
3788141cc406Sopenharmony_ci  control = Inb (CONTROL);
3789141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F));
3790141cc406Sopenharmony_ci}
3791141cc406Sopenharmony_ci
3792141cc406Sopenharmony_cistatic void
3793141cc406Sopenharmony_ciEPPWrite32Buffer (int size, unsigned char *source)
3794141cc406Sopenharmony_ci{
3795141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
3796141cc406Sopenharmony_ci  int fd, mode, rc;
3797141cc406Sopenharmony_ci  unsigned char bval;
3798141cc406Sopenharmony_ci#endif
3799141cc406Sopenharmony_ci
3800141cc406Sopenharmony_ci  if ((size % 4) != 0)
3801141cc406Sopenharmony_ci    {
3802141cc406Sopenharmony_ci      DBG (0, "EPPWrite32Buffer: size %% 4 != 0!! (%s:%d)\n", __FILE__,
3803141cc406Sopenharmony_ci	   __LINE__);
3804141cc406Sopenharmony_ci    }
3805141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
3806141cc406Sopenharmony_ci  /* check we have ppdev working */
3807141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
3808141cc406Sopenharmony_ci  if (fd > 0)
3809141cc406Sopenharmony_ci    {
3810141cc406Sopenharmony_ci
3811141cc406Sopenharmony_ci      bval = 0xC0;
3812141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
3813141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
3814141cc406Sopenharmony_ci      if (rc)
3815141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3816141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3817141cc406Sopenharmony_ci      rc = write (fd, &bval, 1);
3818141cc406Sopenharmony_ci
3819141cc406Sopenharmony_ci#ifdef PPSETFLAGS
3820141cc406Sopenharmony_ci      mode = PP_FASTWRITE;
3821141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETFLAGS, &mode);
3822141cc406Sopenharmony_ci      if (rc)
3823141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3824141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3825141cc406Sopenharmony_ci#endif
3826141cc406Sopenharmony_ci      mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
3827141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
3828141cc406Sopenharmony_ci      if (rc)
3829141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3830141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3831141cc406Sopenharmony_ci      rc = write (fd, source, size);
3832141cc406Sopenharmony_ci
3833141cc406Sopenharmony_ci      return;
3834141cc406Sopenharmony_ci    }
3835141cc406Sopenharmony_ci  /* if not, direct hardware access */
3836141cc406Sopenharmony_ci#endif
3837141cc406Sopenharmony_ci  EPPBlockMode (0xC0);
3838141cc406Sopenharmony_ci  Outsw (EPPDATA, source, size / 4);
3839141cc406Sopenharmony_ci}
3840141cc406Sopenharmony_ci
3841141cc406Sopenharmony_ci
3842141cc406Sopenharmony_ci
3843141cc406Sopenharmony_ci
3844141cc406Sopenharmony_ci
3845141cc406Sopenharmony_ci
3846141cc406Sopenharmony_ci/* returns 0 if ERROR cleared in STATUS within 1024 inb, else 1 */
3847141cc406Sopenharmony_cistatic int
3848141cc406Sopenharmony_ciWaitOnError (void)
3849141cc406Sopenharmony_ci{
3850141cc406Sopenharmony_ci  int c = 0;
3851141cc406Sopenharmony_ci  int count = 1024;
3852141cc406Sopenharmony_ci  int status;
3853141cc406Sopenharmony_ci
3854141cc406Sopenharmony_ci  do
3855141cc406Sopenharmony_ci    {
3856141cc406Sopenharmony_ci      do
3857141cc406Sopenharmony_ci	{
3858141cc406Sopenharmony_ci	  status = Inb (STATUS) & 0x08;
3859141cc406Sopenharmony_ci	  if (status != 0)
3860141cc406Sopenharmony_ci	    {
3861141cc406Sopenharmony_ci	      count--;
3862141cc406Sopenharmony_ci	      if (count == 0)
3863141cc406Sopenharmony_ci		c = 1;
3864141cc406Sopenharmony_ci	    }
3865141cc406Sopenharmony_ci	}
3866141cc406Sopenharmony_ci      while ((count > 0) && (status != 0));
3867141cc406Sopenharmony_ci      if (status == 0)
3868141cc406Sopenharmony_ci	{
3869141cc406Sopenharmony_ci	  status = Inb (STATUS) & 0x08;
3870141cc406Sopenharmony_ci	  if (status == 0)
3871141cc406Sopenharmony_ci	    c = 0;
3872141cc406Sopenharmony_ci	}
3873141cc406Sopenharmony_ci    }
3874141cc406Sopenharmony_ci  while ((status != 0) && (c == 0));
3875141cc406Sopenharmony_ci  return c;
3876141cc406Sopenharmony_ci}
3877141cc406Sopenharmony_ci
3878141cc406Sopenharmony_ci
3879141cc406Sopenharmony_ci
3880141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
3881141cc406Sopenharmony_ci/* read up to size bytes, returns bytes read */
3882141cc406Sopenharmony_cistatic int
3883141cc406Sopenharmony_ciParportpausedBufferRead (int size, unsigned char *dest)
3884141cc406Sopenharmony_ci{
3885141cc406Sopenharmony_ci  unsigned char status, bval;
3886141cc406Sopenharmony_ci  int error;
3887141cc406Sopenharmony_ci  int word;
3888141cc406Sopenharmony_ci  int bread;
3889141cc406Sopenharmony_ci  int c;
3890141cc406Sopenharmony_ci  int fd, rc, mode;
3891141cc406Sopenharmony_ci
3892141cc406Sopenharmony_ci  /* WIP check */
3893141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
3894141cc406Sopenharmony_ci    {
3895141cc406Sopenharmony_ci      DBG (0, "ECP access not implemented yet (WIP) ! (%s:%d)\n",
3896141cc406Sopenharmony_ci	   __FILE__, __LINE__);
3897141cc406Sopenharmony_ci    }
3898141cc406Sopenharmony_ci
3899141cc406Sopenharmony_ci  /* init */
3900141cc406Sopenharmony_ci  bread = 0;
3901141cc406Sopenharmony_ci  error = 0;
3902141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
3903141cc406Sopenharmony_ci
3904141cc406Sopenharmony_ci  mode = 1;			/* data_reverse */
3905141cc406Sopenharmony_ci  rc = ioctl (fd, PPDATADIR, &mode);
3906141cc406Sopenharmony_ci  if (rc)
3907141cc406Sopenharmony_ci    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3908141cc406Sopenharmony_ci	 __FILE__, __LINE__);
3909141cc406Sopenharmony_ci#ifdef PPSETFLAGS
3910141cc406Sopenharmony_ci  mode = PP_FASTREAD;
3911141cc406Sopenharmony_ci  rc = ioctl (fd, PPSETFLAGS, &mode);
3912141cc406Sopenharmony_ci  if (rc)
3913141cc406Sopenharmony_ci    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3914141cc406Sopenharmony_ci	 __FILE__, __LINE__);
3915141cc406Sopenharmony_ci#endif
3916141cc406Sopenharmony_ci  mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
3917141cc406Sopenharmony_ci  rc = ioctl (fd, PPSETMODE, &mode);
3918141cc406Sopenharmony_ci  if (rc)
3919141cc406Sopenharmony_ci    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3920141cc406Sopenharmony_ci	 __FILE__, __LINE__);
3921141cc406Sopenharmony_ci
3922141cc406Sopenharmony_ci  if ((size & 0x03) != 0)
3923141cc406Sopenharmony_ci    {
3924141cc406Sopenharmony_ci      while ((!error) && ((size & 0x03) != 0))
3925141cc406Sopenharmony_ci	{
3926141cc406Sopenharmony_ci	  rc = read (fd, dest, 1);
3927141cc406Sopenharmony_ci	  size--;
3928141cc406Sopenharmony_ci	  dest++;
3929141cc406Sopenharmony_ci	  bread++;
3930141cc406Sopenharmony_ci	  rc = ioctl (fd, PPRSTATUS, &status);
3931141cc406Sopenharmony_ci	  if (rc)
3932141cc406Sopenharmony_ci	    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3933141cc406Sopenharmony_ci		 __FILE__, __LINE__);
3934141cc406Sopenharmony_ci	  error = status & 0x08;
3935141cc406Sopenharmony_ci	}
3936141cc406Sopenharmony_ci      if (error)
3937141cc406Sopenharmony_ci	{
3938141cc406Sopenharmony_ci	  DBG (0, "Read error (%s:%d)\n", __FILE__, __LINE__);
3939141cc406Sopenharmony_ci	  return 0;
3940141cc406Sopenharmony_ci	}
3941141cc406Sopenharmony_ci    }
3942141cc406Sopenharmony_ci
3943141cc406Sopenharmony_ci  /* from here, we read 1 byte, then size/4-1 32 bits words, and then
3944141cc406Sopenharmony_ci     3 bytes, pausing on ERROR bit of STATUS */
3945141cc406Sopenharmony_ci  size -= 4;
3946141cc406Sopenharmony_ci
3947141cc406Sopenharmony_ci  /* sanity test, seems to be wrongly handled ... */
3948141cc406Sopenharmony_ci  if (size == 0)
3949141cc406Sopenharmony_ci    {
3950141cc406Sopenharmony_ci      DBG (0, "case not handled! (%s:%d)\n", __FILE__, __LINE__);
3951141cc406Sopenharmony_ci      return 0;
3952141cc406Sopenharmony_ci    }
3953141cc406Sopenharmony_ci
3954141cc406Sopenharmony_ci  word = 0;
3955141cc406Sopenharmony_ci  error = 0;
3956141cc406Sopenharmony_ci  bread += size;
3957141cc406Sopenharmony_ci  do
3958141cc406Sopenharmony_ci    {
3959141cc406Sopenharmony_ci      do
3960141cc406Sopenharmony_ci	{
3961141cc406Sopenharmony_ci	  rc = read (fd, dest, 1);
3962141cc406Sopenharmony_ci	  size--;
3963141cc406Sopenharmony_ci	  dest++;
3964141cc406Sopenharmony_ci	readstatus:
3965141cc406Sopenharmony_ci	  if (size > 0)
3966141cc406Sopenharmony_ci	    {
3967141cc406Sopenharmony_ci	      rc = ioctl (fd, PPRSTATUS, &status);
3968141cc406Sopenharmony_ci	      if (rc)
3969141cc406Sopenharmony_ci		DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
3970141cc406Sopenharmony_ci		     strerror (errno), __FILE__, __LINE__);
3971141cc406Sopenharmony_ci	      word = status & 0x10;
3972141cc406Sopenharmony_ci	      error = status & 0x08;
3973141cc406Sopenharmony_ci	    }
3974141cc406Sopenharmony_ci	}
3975141cc406Sopenharmony_ci      while ((size > 0) && (!error) && (!word));
3976141cc406Sopenharmony_ci    }
3977141cc406Sopenharmony_ci  while ((size < 4) && (!error) && (size > 0));
3978141cc406Sopenharmony_ci
3979141cc406Sopenharmony_ci  /* here size=0 or error=8 or word=0x10 */
3980141cc406Sopenharmony_ci  if ((word) && (!error) && (size))
3981141cc406Sopenharmony_ci    {
3982141cc406Sopenharmony_ci      rc = read (fd, dest, 4);
3983141cc406Sopenharmony_ci      dest += 4;
3984141cc406Sopenharmony_ci      size -= 4;
3985141cc406Sopenharmony_ci      if (size != 0)
3986141cc406Sopenharmony_ci	error = 0x08;
3987141cc406Sopenharmony_ci    }
3988141cc406Sopenharmony_ci  if (!error)
3989141cc406Sopenharmony_ci    {
3990141cc406Sopenharmony_ci      c = 0;
3991141cc406Sopenharmony_ci      rc = ioctl (fd, PPRSTATUS, &status);
3992141cc406Sopenharmony_ci      if (rc)
3993141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
3994141cc406Sopenharmony_ci	     __FILE__, __LINE__);
3995141cc406Sopenharmony_ci      error = status & 0x08;
3996141cc406Sopenharmony_ci      if (error)
3997141cc406Sopenharmony_ci	c = WaitOnError ();
3998141cc406Sopenharmony_ci    }
3999141cc406Sopenharmony_ci  else
4000141cc406Sopenharmony_ci    {				/* 8282 */
4001141cc406Sopenharmony_ci      c = WaitOnError ();
4002141cc406Sopenharmony_ci      if (c == 0)
4003141cc406Sopenharmony_ci	goto readstatus;
4004141cc406Sopenharmony_ci    }
4005141cc406Sopenharmony_ci  if (c == 1)
4006141cc406Sopenharmony_ci    {
4007141cc406Sopenharmony_ci      bread -= size;
4008141cc406Sopenharmony_ci    }
4009141cc406Sopenharmony_ci  else
4010141cc406Sopenharmony_ci    {
4011141cc406Sopenharmony_ci      bread += 3;
4012141cc406Sopenharmony_ci      size = 3;
4013141cc406Sopenharmony_ci      do
4014141cc406Sopenharmony_ci	{
4015141cc406Sopenharmony_ci	  do
4016141cc406Sopenharmony_ci	    {
4017141cc406Sopenharmony_ci	      rc = read (fd, dest, 1);
4018141cc406Sopenharmony_ci	      dest++;
4019141cc406Sopenharmony_ci	      size--;
4020141cc406Sopenharmony_ci	      if (size)
4021141cc406Sopenharmony_ci		{
4022141cc406Sopenharmony_ci		  rc = ioctl (fd, PPRSTATUS, &status);
4023141cc406Sopenharmony_ci		  if (rc)
4024141cc406Sopenharmony_ci		    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
4025141cc406Sopenharmony_ci			 strerror (errno), __FILE__, __LINE__);
4026141cc406Sopenharmony_ci		  error = status & 0x08;
4027141cc406Sopenharmony_ci		  if (!error)
4028141cc406Sopenharmony_ci		    {
4029141cc406Sopenharmony_ci		      rc = ioctl (fd, PPRSTATUS, &status);
4030141cc406Sopenharmony_ci		      if (rc)
4031141cc406Sopenharmony_ci			DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n",
4032141cc406Sopenharmony_ci			     strerror (errno), __FILE__, __LINE__);
4033141cc406Sopenharmony_ci		      error = status & 0x08;
4034141cc406Sopenharmony_ci		    }
4035141cc406Sopenharmony_ci		}
4036141cc406Sopenharmony_ci	    }
4037141cc406Sopenharmony_ci	  while ((size > 0) && (!error));
4038141cc406Sopenharmony_ci	  c = 0;
4039141cc406Sopenharmony_ci	  if (error)
4040141cc406Sopenharmony_ci	    c = WaitOnError ();
4041141cc406Sopenharmony_ci	}
4042141cc406Sopenharmony_ci      while ((size > 0) && (c == 0));
4043141cc406Sopenharmony_ci    }
4044141cc406Sopenharmony_ci
4045141cc406Sopenharmony_ci  /* end reading */
4046141cc406Sopenharmony_ci  mode = 0;			/* forward */
4047141cc406Sopenharmony_ci  rc = ioctl (fd, PPDATADIR, &mode);
4048141cc406Sopenharmony_ci  if (rc)
4049141cc406Sopenharmony_ci    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4050141cc406Sopenharmony_ci	 __FILE__, __LINE__);
4051141cc406Sopenharmony_ci  bval = 0xA0;
4052141cc406Sopenharmony_ci  mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
4053141cc406Sopenharmony_ci  rc = ioctl (fd, PPSETMODE, &mode);
4054141cc406Sopenharmony_ci  if (rc)
4055141cc406Sopenharmony_ci    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4056141cc406Sopenharmony_ci	 __FILE__, __LINE__);
4057141cc406Sopenharmony_ci  rc = write (fd, &bval, 1);
4058141cc406Sopenharmony_ci
4059141cc406Sopenharmony_ci  mode = 1;			/* data_reverse */
4060141cc406Sopenharmony_ci  rc = ioctl (fd, PPDATADIR, &mode);
4061141cc406Sopenharmony_ci  if (rc)
4062141cc406Sopenharmony_ci    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4063141cc406Sopenharmony_ci	 __FILE__, __LINE__);
4064141cc406Sopenharmony_ci  mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
4065141cc406Sopenharmony_ci  rc = ioctl (fd, PPSETMODE, &mode);
4066141cc406Sopenharmony_ci  if (rc)
4067141cc406Sopenharmony_ci    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4068141cc406Sopenharmony_ci	 __FILE__, __LINE__);
4069141cc406Sopenharmony_ci  rc = read (fd, dest, 1);
4070141cc406Sopenharmony_ci  bread++;
4071141cc406Sopenharmony_ci
4072141cc406Sopenharmony_ci  mode = 0;			/* forward */
4073141cc406Sopenharmony_ci  rc = ioctl (fd, PPDATADIR, &mode);
4074141cc406Sopenharmony_ci  if (rc)
4075141cc406Sopenharmony_ci    DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4076141cc406Sopenharmony_ci	 __FILE__, __LINE__);
4077141cc406Sopenharmony_ci  return bread;
4078141cc406Sopenharmony_ci}
4079141cc406Sopenharmony_ci#endif
4080141cc406Sopenharmony_ci
4081141cc406Sopenharmony_ci/* read up to size bytes, returns bytes read */
4082141cc406Sopenharmony_cistatic int
4083141cc406Sopenharmony_ciDirectpausedBufferRead (int size, unsigned char *dest)
4084141cc406Sopenharmony_ci{
4085141cc406Sopenharmony_ci  int control;
4086141cc406Sopenharmony_ci  int status;
4087141cc406Sopenharmony_ci  int error;
4088141cc406Sopenharmony_ci  int word;
4089141cc406Sopenharmony_ci  int read;
4090141cc406Sopenharmony_ci  int c;
4091141cc406Sopenharmony_ci
4092141cc406Sopenharmony_ci  /* init */
4093141cc406Sopenharmony_ci  read = 0;
4094141cc406Sopenharmony_ci  error = 0;
4095141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x1F;
4096141cc406Sopenharmony_ci  Outb (CONTROL, control | 0x20);
4097141cc406Sopenharmony_ci  if ((size & 0x03) != 0)
4098141cc406Sopenharmony_ci    {
4099141cc406Sopenharmony_ci      /* 8174 */
4100141cc406Sopenharmony_ci      while ((!error) && ((size & 0x03) != 0))
4101141cc406Sopenharmony_ci	{
4102141cc406Sopenharmony_ci	  Insb (EPPDATA, dest, 1);
4103141cc406Sopenharmony_ci	  size--;
4104141cc406Sopenharmony_ci	  dest++;
4105141cc406Sopenharmony_ci	  read++;
4106141cc406Sopenharmony_ci	  status = Inb (STATUS) & 0x1F;
4107141cc406Sopenharmony_ci	  error = status & 0x08;
4108141cc406Sopenharmony_ci	}
4109141cc406Sopenharmony_ci      if (error)
4110141cc406Sopenharmony_ci	{
4111141cc406Sopenharmony_ci	  DBG (0, "Read error (%s:%d)\n", __FILE__, __LINE__);
4112141cc406Sopenharmony_ci	  return 0;
4113141cc406Sopenharmony_ci	}
4114141cc406Sopenharmony_ci    }
4115141cc406Sopenharmony_ci
4116141cc406Sopenharmony_ci  /* from here, we read 1 byte, then size/4-1 32 bits words, and then
4117141cc406Sopenharmony_ci     3 bytes, pausing on ERROR bit of STATUS */
4118141cc406Sopenharmony_ci  size -= 4;
4119141cc406Sopenharmony_ci
4120141cc406Sopenharmony_ci  /* sanity test, seems to be wrongly handled ... */
4121141cc406Sopenharmony_ci  if (size == 0)
4122141cc406Sopenharmony_ci    {
4123141cc406Sopenharmony_ci      DBG (0, "case not handled! (%s:%d)\n", __FILE__, __LINE__);
4124141cc406Sopenharmony_ci      return 0;
4125141cc406Sopenharmony_ci    }
4126141cc406Sopenharmony_ci
4127141cc406Sopenharmony_ci  word = 0;
4128141cc406Sopenharmony_ci  error = 0;
4129141cc406Sopenharmony_ci  read += size;
4130141cc406Sopenharmony_ci  do
4131141cc406Sopenharmony_ci    {
4132141cc406Sopenharmony_ci      do
4133141cc406Sopenharmony_ci	{
4134141cc406Sopenharmony_ci	  Insb (EPPDATA, dest, 1);
4135141cc406Sopenharmony_ci	  size--;
4136141cc406Sopenharmony_ci	  dest++;
4137141cc406Sopenharmony_ci	readstatus:
4138141cc406Sopenharmony_ci	  if (size > 0)
4139141cc406Sopenharmony_ci	    {
4140141cc406Sopenharmony_ci	      status = Inb (STATUS) & 0x1F;
4141141cc406Sopenharmony_ci	      word = status & 0x10;
4142141cc406Sopenharmony_ci	      error = status & 0x08;
4143141cc406Sopenharmony_ci	    }
4144141cc406Sopenharmony_ci	}
4145141cc406Sopenharmony_ci      while ((size > 0) && (!error) && (!word));
4146141cc406Sopenharmony_ci    }
4147141cc406Sopenharmony_ci  while ((size < 4) && (!error) && (size > 0));
4148141cc406Sopenharmony_ci
4149141cc406Sopenharmony_ci  /* here size=0 or error=8 or word=0x10 */
4150141cc406Sopenharmony_ci  if ((word) && (!error) && (size))
4151141cc406Sopenharmony_ci    {
4152141cc406Sopenharmony_ci      if (epp32)
4153141cc406Sopenharmony_ci	Insw (EPPDATA, dest, 1);
4154141cc406Sopenharmony_ci      else
4155141cc406Sopenharmony_ci	Insb (EPPDATA, dest, 4);
4156141cc406Sopenharmony_ci      dest += 4;
4157141cc406Sopenharmony_ci      size -= 4;
4158141cc406Sopenharmony_ci      if (size != 0)
4159141cc406Sopenharmony_ci	error = 0x08;
4160141cc406Sopenharmony_ci    }
4161141cc406Sopenharmony_ci  if (!error)
4162141cc406Sopenharmony_ci    {
4163141cc406Sopenharmony_ci      c = 0;
4164141cc406Sopenharmony_ci      error = Inb (STATUS) & 0x08;
4165141cc406Sopenharmony_ci      if (error)
4166141cc406Sopenharmony_ci	c = WaitOnError ();
4167141cc406Sopenharmony_ci    }
4168141cc406Sopenharmony_ci  else
4169141cc406Sopenharmony_ci    {				/* 8282 */
4170141cc406Sopenharmony_ci      c = WaitOnError ();
4171141cc406Sopenharmony_ci      if (c == 0)
4172141cc406Sopenharmony_ci	goto readstatus;
4173141cc406Sopenharmony_ci    }
4174141cc406Sopenharmony_ci  if (c == 1)
4175141cc406Sopenharmony_ci    {
4176141cc406Sopenharmony_ci      read -= size;
4177141cc406Sopenharmony_ci    }
4178141cc406Sopenharmony_ci  else
4179141cc406Sopenharmony_ci    {
4180141cc406Sopenharmony_ci      read += 3;
4181141cc406Sopenharmony_ci      size = 3;
4182141cc406Sopenharmony_ci      do
4183141cc406Sopenharmony_ci	{
4184141cc406Sopenharmony_ci	  do
4185141cc406Sopenharmony_ci	    {
4186141cc406Sopenharmony_ci	      Insb (EPPDATA, dest, 1);
4187141cc406Sopenharmony_ci	      dest++;
4188141cc406Sopenharmony_ci	      size--;
4189141cc406Sopenharmony_ci	      if (size)
4190141cc406Sopenharmony_ci		{
4191141cc406Sopenharmony_ci		  error = Inb (STATUS) & 0x08;
4192141cc406Sopenharmony_ci		  if (!error)
4193141cc406Sopenharmony_ci		    error = Inb (STATUS) & 0x08;
4194141cc406Sopenharmony_ci		}
4195141cc406Sopenharmony_ci	    }
4196141cc406Sopenharmony_ci	  while ((size > 0) && (!error));
4197141cc406Sopenharmony_ci	  c = 0;
4198141cc406Sopenharmony_ci	  if (error)
4199141cc406Sopenharmony_ci	    c = WaitOnError ();
4200141cc406Sopenharmony_ci	}
4201141cc406Sopenharmony_ci      while ((size > 0) && (c == 0));
4202141cc406Sopenharmony_ci    }
4203141cc406Sopenharmony_ci
4204141cc406Sopenharmony_ci  /* end reading */
4205141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x1F;
4206141cc406Sopenharmony_ci  Outb (CONTROL, control);
4207141cc406Sopenharmony_ci  EPPBlockMode (0xA0);
4208141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x1F;
4209141cc406Sopenharmony_ci  Outb (CONTROL, control | 0x20);
4210141cc406Sopenharmony_ci  Insb (EPPDATA, dest, 1);
4211141cc406Sopenharmony_ci  read++;
4212141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x1F;
4213141cc406Sopenharmony_ci  Outb (CONTROL, control);
4214141cc406Sopenharmony_ci  return read;
4215141cc406Sopenharmony_ci}
4216141cc406Sopenharmony_ci
4217141cc406Sopenharmony_ci
4218141cc406Sopenharmony_ciint
4219141cc406Sopenharmony_cipausedBufferRead (int size, unsigned char *dest)
4220141cc406Sopenharmony_ci{
4221141cc406Sopenharmony_ci  EPPBlockMode (0x80);
4222141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
4223141cc406Sopenharmony_ci  if (sanei_umax_pp_getparport () > 0)
4224141cc406Sopenharmony_ci    return ParportpausedBufferRead (size, dest);
4225141cc406Sopenharmony_ci#endif
4226141cc406Sopenharmony_ci  /* only EPP hardware access for now */
4227141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_EPP)
4228141cc406Sopenharmony_ci    return DirectpausedBufferRead (size, dest);
4229141cc406Sopenharmony_ci  return 0;
4230141cc406Sopenharmony_ci}
4231141cc406Sopenharmony_ci
4232141cc406Sopenharmony_ci
4233141cc406Sopenharmony_ci
4234141cc406Sopenharmony_ci
4235141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
4236141cc406Sopenharmony_cistatic int
4237141cc406Sopenharmony_cisendWord1220P (int *cmd)
4238141cc406Sopenharmony_ci{
4239141cc406Sopenharmony_ci  int i;
4240141cc406Sopenharmony_ci  int reg;
4241141cc406Sopenharmony_ci  int try = 0;
4242141cc406Sopenharmony_ci
4243141cc406Sopenharmony_ci  /* send header */
4244141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
4245141cc406Sopenharmony_ciretry:
4246141cc406Sopenharmony_ci  registerWrite (0x1C, 0x55);
4247141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
4248141cc406Sopenharmony_ci
4249141cc406Sopenharmony_ci  registerWrite (0x1C, 0xAA);
4250141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
4251141cc406Sopenharmony_ci
4252141cc406Sopenharmony_ci  /* sync when needed */
4253141cc406Sopenharmony_ci  if ((reg & 0x08) == 0x00)
4254141cc406Sopenharmony_ci    {
4255141cc406Sopenharmony_ci      reg = registerRead (0x1C);
4256141cc406Sopenharmony_ci      DBG (16, "UTA: reg1C=0x%02X   (%s:%d)\n", reg, __FILE__, __LINE__);
4257141cc406Sopenharmony_ci      if (((reg & 0x10) != 0x10) && (reg != 0x6B) && (reg != 0xAB)
4258141cc406Sopenharmony_ci	  && (reg != 0x23))
4259141cc406Sopenharmony_ci	{
4260141cc406Sopenharmony_ci	  DBG (0, "sendWord failed (reg1C=0x%02X)   (%s:%d)\n", reg, __FILE__,
4261141cc406Sopenharmony_ci	       __LINE__);
4262141cc406Sopenharmony_ci	  return 0;
4263141cc406Sopenharmony_ci	}
4264141cc406Sopenharmony_ci      for (i = 0; i < 10; i++)
4265141cc406Sopenharmony_ci	{
4266141cc406Sopenharmony_ci	  usleep (1000);
4267141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
4268141cc406Sopenharmony_ci	  if (reg != 0xC8)
4269141cc406Sopenharmony_ci	    {
4270141cc406Sopenharmony_ci	      DBG (0, "Unexpected reg19=0x%2X  (%s:%d)\n", reg, __FILE__,
4271141cc406Sopenharmony_ci		   __LINE__);
4272141cc406Sopenharmony_ci	    }
4273141cc406Sopenharmony_ci	}
4274141cc406Sopenharmony_ci      do
4275141cc406Sopenharmony_ci	{
4276141cc406Sopenharmony_ci	  if ((reg != 0xC0) && (reg != 0xC8))
4277141cc406Sopenharmony_ci	    {
4278141cc406Sopenharmony_ci	      DBG (0, "Unexpected reg19=0x%2X  (%s:%d)\n", reg, __FILE__,
4279141cc406Sopenharmony_ci		   __LINE__);
4280141cc406Sopenharmony_ci	    }
4281141cc406Sopenharmony_ci	  /* 0xF0 certainly means error */
4282141cc406Sopenharmony_ci	  if ((reg == 0xC0) || (reg == 0xD0))
4283141cc406Sopenharmony_ci	    {
4284141cc406Sopenharmony_ci	      try++;
4285141cc406Sopenharmony_ci	      goto retry;
4286141cc406Sopenharmony_ci	    }
4287141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
4288141cc406Sopenharmony_ci	}
4289141cc406Sopenharmony_ci      while (reg != 0xC8);
4290141cc406Sopenharmony_ci    }
4291141cc406Sopenharmony_ci
4292141cc406Sopenharmony_ci  /* send word */
4293141cc406Sopenharmony_ci  i = 0;
4294141cc406Sopenharmony_ci  while ((reg == 0xC8) && (cmd[i] != -1))
4295141cc406Sopenharmony_ci    {
4296141cc406Sopenharmony_ci      registerWrite (0x1C, cmd[i]);
4297141cc406Sopenharmony_ci      i++;
4298141cc406Sopenharmony_ci      reg = registerRead (0x19) & 0xF8;
4299141cc406Sopenharmony_ci    }
4300141cc406Sopenharmony_ci  TRACE (16, "sendWord() passed ");
4301141cc406Sopenharmony_ci  if ((reg != 0xC0) && (reg != 0xD0))
4302141cc406Sopenharmony_ci    {
4303141cc406Sopenharmony_ci      DBG (0, "sendWord failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
4304141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
4305141cc406Sopenharmony_ci      DBG (0, "Blindly going on .....\n");
4306141cc406Sopenharmony_ci    }
4307141cc406Sopenharmony_ci  if (((reg == 0xC0) || (reg == 0xD0)) && (cmd[i] != -1))
4308141cc406Sopenharmony_ci    {
4309141cc406Sopenharmony_ci      DBG (0, "sendWord failed: short send  (%s:%d)\n", __FILE__, __LINE__);
4310141cc406Sopenharmony_ci      return 0;
4311141cc406Sopenharmony_ci    }
4312141cc406Sopenharmony_ci  reg = registerRead (0x1C);
4313141cc406Sopenharmony_ci  DBG (16, "sendWord, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
4314141cc406Sopenharmony_ci  /* model 0x07 has always the last bit set to 1, and even bit 1 */
4315141cc406Sopenharmony_ci  /* when UTA is present, we get 0x6B there */
4316141cc406Sopenharmony_ci  scannerStatus = reg & 0xFC;
4317141cc406Sopenharmony_ci  if (scannerStatus == 0x68)
4318141cc406Sopenharmony_ci    hasUTA = 1;
4319141cc406Sopenharmony_ci
4320141cc406Sopenharmony_ci  reg = reg & 0x10;
4321141cc406Sopenharmony_ci  if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8))
4322141cc406Sopenharmony_ci    {
4323141cc406Sopenharmony_ci      DBG (0, "sendWord failed: acknowledge not received (%s:%d)\n", __FILE__,
4324141cc406Sopenharmony_ci	   __LINE__);
4325141cc406Sopenharmony_ci      return 0;
4326141cc406Sopenharmony_ci    }
4327141cc406Sopenharmony_ci  if (try)
4328141cc406Sopenharmony_ci    {
4329141cc406Sopenharmony_ci      DBG (0, "sendWord retry success (retry %d time%s) ... (%s:%d)\n", try,
4330141cc406Sopenharmony_ci	   (try > 1) ? "s" : "", __FILE__, __LINE__);
4331141cc406Sopenharmony_ci    }
4332141cc406Sopenharmony_ci  return 1;
4333141cc406Sopenharmony_ci}
4334141cc406Sopenharmony_ci
4335141cc406Sopenharmony_ci
4336141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
4337141cc406Sopenharmony_cistatic int
4338141cc406Sopenharmony_ciSPPsendWord610p (int *cmd)
4339141cc406Sopenharmony_ci{
4340141cc406Sopenharmony_ci  int i, j;
4341141cc406Sopenharmony_ci  int tmp, status;
4342141cc406Sopenharmony_ci
4343141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
4344141cc406Sopenharmony_ci  int exmode, mode, rc, fd;
4345141cc406Sopenharmony_ci#endif
4346141cc406Sopenharmony_ci  connect610p ();
4347141cc406Sopenharmony_ci
4348141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
4349141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
4350141cc406Sopenharmony_ci  if (fd > 0)
4351141cc406Sopenharmony_ci    {
4352141cc406Sopenharmony_ci      rc = ioctl (fd, PPGETMODE, &exmode);
4353141cc406Sopenharmony_ci      if (rc)
4354141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4355141cc406Sopenharmony_ci	     __FILE__, __LINE__);
4356141cc406Sopenharmony_ci      mode = IEEE1284_MODE_COMPAT;
4357141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &mode);
4358141cc406Sopenharmony_ci      if (rc)
4359141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4360141cc406Sopenharmony_ci	     __FILE__, __LINE__);
4361141cc406Sopenharmony_ci    }
4362141cc406Sopenharmony_ci#endif
4363141cc406Sopenharmony_ci
4364141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4365141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
4366141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
4367141cc406Sopenharmony_ci  if (status != 0x88)
4368141cc406Sopenharmony_ci    {
4369141cc406Sopenharmony_ci      DBG (0, "SPPsendWord610p found 0x%02X expected 0x88  (%s:%d)\n", status,
4370141cc406Sopenharmony_ci	   __FILE__, __LINE__);
4371141cc406Sopenharmony_ci      return 0;
4372141cc406Sopenharmony_ci    }
4373141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
4374141cc406Sopenharmony_ci
4375141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4376141cc406Sopenharmony_ci  Outb (CONTROL, 0x05);
4377141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
4378141cc406Sopenharmony_ci  if (status != 0x88)
4379141cc406Sopenharmony_ci    {
4380141cc406Sopenharmony_ci      DBG (0, "SPPsendWord610p found 0x%02X expected 0x88  (%s:%d)\n", status,
4381141cc406Sopenharmony_ci	   __FILE__, __LINE__);
4382141cc406Sopenharmony_ci      return 0;
4383141cc406Sopenharmony_ci    }
4384141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
4385141cc406Sopenharmony_ci
4386141cc406Sopenharmony_ci  for (i = 0; i < 4; i++)
4387141cc406Sopenharmony_ci    {
4388141cc406Sopenharmony_ci      Outb (DATA, cmd[i]);
4389141cc406Sopenharmony_ci      Outb (CONTROL, 0x05);
4390141cc406Sopenharmony_ci      status = Inb (STATUS) & 0xF8;
4391141cc406Sopenharmony_ci      if (status != 0x88)
4392141cc406Sopenharmony_ci	{
4393141cc406Sopenharmony_ci	  DBG (0, "SPPsendWord610p found 0x%02X expected 0x88  (%s:%d)\n",
4394141cc406Sopenharmony_ci	       status, __FILE__, __LINE__);
4395141cc406Sopenharmony_ci	  return 0;
4396141cc406Sopenharmony_ci	}
4397141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
4398141cc406Sopenharmony_ci    }
4399141cc406Sopenharmony_ci
4400141cc406Sopenharmony_ci  Outb (CONTROL, 0x07);
4401141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4402141cc406Sopenharmony_ci  tmp = Inb (DATA);
4403141cc406Sopenharmony_ci  if (tmp != 0xFF)
4404141cc406Sopenharmony_ci    {
4405141cc406Sopenharmony_ci      DBG (0, "SPPsendWord610p found 0x%X expected 0xFF  (%s:%d)\n", tmp,
4406141cc406Sopenharmony_ci	   __FILE__, __LINE__);
4407141cc406Sopenharmony_ci      return 0;
4408141cc406Sopenharmony_ci    }
4409141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
4410141cc406Sopenharmony_ci  j = 0;
4411141cc406Sopenharmony_ci  while ((j < 256) && (status & 0x08))
4412141cc406Sopenharmony_ci    {
4413141cc406Sopenharmony_ci      j++;
4414141cc406Sopenharmony_ci      status = Inb (STATUS) & 0xF8;
4415141cc406Sopenharmony_ci    }
4416141cc406Sopenharmony_ci  if ((status != 0x80) && (status != 0xA0))
4417141cc406Sopenharmony_ci    {
4418141cc406Sopenharmony_ci      DBG (0, "SPPsendWord610p found 0x%X expected 0x80 or 0xA0 (%s:%d)\n",
4419141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
4420141cc406Sopenharmony_ci      return 0;
4421141cc406Sopenharmony_ci    }
4422141cc406Sopenharmony_ci  Outb (DATA, 0x7F);
4423141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
4424141cc406Sopenharmony_ci  if (status != 0xC0)
4425141cc406Sopenharmony_ci    {
4426141cc406Sopenharmony_ci      DBG (0, "SPPsendWord610p found 0x%X expected 0xC0  (%s:%d)\n", status,
4427141cc406Sopenharmony_ci	   __FILE__, __LINE__);
4428141cc406Sopenharmony_ci      return 0;
4429141cc406Sopenharmony_ci    }
4430141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4431141cc406Sopenharmony_ci  if (cmd[3] == 0xC2)
4432141cc406Sopenharmony_ci    {
4433141cc406Sopenharmony_ci      Outb (CONTROL, 0x07);
4434141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
4435141cc406Sopenharmony_ci      tmp = Inb (DATA);
4436141cc406Sopenharmony_ci      if (tmp != 0xFF)
4437141cc406Sopenharmony_ci	{
4438141cc406Sopenharmony_ci	  DBG (0, "SPPsendWord610p found 0x%X expected 0xFF  (%s:%d)\n", tmp,
4439141cc406Sopenharmony_ci	       __FILE__, __LINE__);
4440141cc406Sopenharmony_ci	  return 0;
4441141cc406Sopenharmony_ci	}
4442141cc406Sopenharmony_ci      status = Inb (STATUS) & 0xF8;
4443141cc406Sopenharmony_ci      if ((status != 0x80) && (status != 0xA0))
4444141cc406Sopenharmony_ci	{
4445141cc406Sopenharmony_ci	  DBG (0,
4446141cc406Sopenharmony_ci	       "SPPsendWord610p found 0x%X expected 0x80 or 0xA0 (%s:%d)\n",
4447141cc406Sopenharmony_ci	       status, __FILE__, __LINE__);
4448141cc406Sopenharmony_ci	  return 0;
4449141cc406Sopenharmony_ci	}
4450141cc406Sopenharmony_ci      Outb (DATA, 0x7F);
4451141cc406Sopenharmony_ci      status = Inb (STATUS) & 0xF8;
4452141cc406Sopenharmony_ci      if (status != 0xC0)
4453141cc406Sopenharmony_ci	{
4454141cc406Sopenharmony_ci	  DBG (0, "SPPsendWord610p found 0x%X expected 0xC0  (%s:%d)\n",
4455141cc406Sopenharmony_ci	       status, __FILE__, __LINE__);
4456141cc406Sopenharmony_ci	  return 0;
4457141cc406Sopenharmony_ci	}
4458141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
4459141cc406Sopenharmony_ci    }
4460141cc406Sopenharmony_ci
4461141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
4462141cc406Sopenharmony_ci  fd = sanei_umax_pp_getparport ();
4463141cc406Sopenharmony_ci  if (fd > 0)
4464141cc406Sopenharmony_ci    {
4465141cc406Sopenharmony_ci      rc = ioctl (fd, PPSETMODE, &exmode);
4466141cc406Sopenharmony_ci      if (rc)
4467141cc406Sopenharmony_ci	DBG (0, "ppdev ioctl returned <%s>  (%s:%d)\n", strerror (errno),
4468141cc406Sopenharmony_ci	     __FILE__, __LINE__);
4469141cc406Sopenharmony_ci    }
4470141cc406Sopenharmony_ci#endif
4471141cc406Sopenharmony_ci  disconnect610p ();
4472141cc406Sopenharmony_ci
4473141cc406Sopenharmony_ci  return 1;
4474141cc406Sopenharmony_ci}
4475141cc406Sopenharmony_ci
4476141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
4477141cc406Sopenharmony_cistatic int
4478141cc406Sopenharmony_ciEPPsendWord610p (int *cmd)
4479141cc406Sopenharmony_ci{
4480141cc406Sopenharmony_ci  int i;
4481141cc406Sopenharmony_ci  int tmp, control;
4482141cc406Sopenharmony_ci
4483141cc406Sopenharmony_ci  /* send magic tag */
4484141cc406Sopenharmony_ci  tmp = Inb (STATUS) & 0xF8;
4485141cc406Sopenharmony_ci  if (tmp != 0xC8)
4486141cc406Sopenharmony_ci    {
4487141cc406Sopenharmony_ci      DBG (0,
4488141cc406Sopenharmony_ci	   "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n",
4489141cc406Sopenharmony_ci	   tmp, __FILE__, __LINE__);
4490141cc406Sopenharmony_ci      return 0;
4491141cc406Sopenharmony_ci    }
4492141cc406Sopenharmony_ci
4493141cc406Sopenharmony_ci  /* sets to EPP, and get sure that data direction is forward */
4494141cc406Sopenharmony_ci  tmp = (Inb (CONTROL) & 0x44) | 0x44;	/* !! */
4495141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
4496141cc406Sopenharmony_ci  Outb (EPPDATA, 0x55);
4497141cc406Sopenharmony_ci
4498141cc406Sopenharmony_ci  /* bit0 is timeout bit in EPP mode, should we take care of it ? */
4499141cc406Sopenharmony_ci  tmp = Inb (STATUS) & 0xF8;
4500141cc406Sopenharmony_ci  if (tmp != 0xC8)
4501141cc406Sopenharmony_ci    {
4502141cc406Sopenharmony_ci      DBG (0,
4503141cc406Sopenharmony_ci	   "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n",
4504141cc406Sopenharmony_ci	   tmp, __FILE__, __LINE__);
4505141cc406Sopenharmony_ci      return 0;
4506141cc406Sopenharmony_ci    }
4507141cc406Sopenharmony_ci  tmp = (Inb (CONTROL) & 0x44) | 0x44;
4508141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
4509141cc406Sopenharmony_ci  Outb (EPPDATA, 0xAA);
4510141cc406Sopenharmony_ci
4511141cc406Sopenharmony_ci  control = (Inb (CONTROL) & 0xE0) | 0xE4;
4512141cc406Sopenharmony_ci  Outb (CONTROL, control);	/* bit 7 + data reverse + reset */
4513141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
4514141cc406Sopenharmony_ci    {
4515141cc406Sopenharmony_ci      tmp = Inb (STATUS) & 0xF8;
4516141cc406Sopenharmony_ci      if (tmp != 0xC8)
4517141cc406Sopenharmony_ci	{
4518141cc406Sopenharmony_ci	  DBG (0,
4519141cc406Sopenharmony_ci	       "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n",
4520141cc406Sopenharmony_ci	       tmp, __FILE__, __LINE__);
4521141cc406Sopenharmony_ci	  return 0;
4522141cc406Sopenharmony_ci	}
4523141cc406Sopenharmony_ci    }
4524141cc406Sopenharmony_ci
4525141cc406Sopenharmony_ci  i = 0;
4526141cc406Sopenharmony_ci  while ((tmp == 0xC8) && (cmd[i] != -1))
4527141cc406Sopenharmony_ci    {
4528141cc406Sopenharmony_ci      tmp = Inb (STATUS) & 0xF8;
4529141cc406Sopenharmony_ci      control = (Inb (CONTROL) & 0x44) | 0x44;	/* !! */
4530141cc406Sopenharmony_ci      Outb (CONTROL, control);
4531141cc406Sopenharmony_ci      Outb (EPPDATA, cmd[i]);
4532141cc406Sopenharmony_ci      i++;
4533141cc406Sopenharmony_ci    }
4534141cc406Sopenharmony_ci
4535141cc406Sopenharmony_ci  /* end */
4536141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4537141cc406Sopenharmony_ci  control = (Inb (CONTROL) & 0x44) | 0xE4;
4538141cc406Sopenharmony_ci  Outb (CONTROL, control);	/* data reverse + ????? */
4539141cc406Sopenharmony_ci  tmp = Inb (STATUS) & 0xF8;
4540141cc406Sopenharmony_ci  if (tmp == 0xC8)
4541141cc406Sopenharmony_ci    {
4542141cc406Sopenharmony_ci      for (i = 0; i < 9; i++)
4543141cc406Sopenharmony_ci	tmp = Inb (STATUS) & 0xF8;
4544141cc406Sopenharmony_ci      scannerStatus = tmp;
4545141cc406Sopenharmony_ci    }
4546141cc406Sopenharmony_ci  else
4547141cc406Sopenharmony_ci    {
4548141cc406Sopenharmony_ci      scannerStatus = Inb (EPPDATA);
4549141cc406Sopenharmony_ci    }
4550141cc406Sopenharmony_ci  if ((tmp != 0xC0) && (tmp != 0xD0))
4551141cc406Sopenharmony_ci    {
4552141cc406Sopenharmony_ci      DBG (0,
4553141cc406Sopenharmony_ci	   "EPPsendWord610p failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
4554141cc406Sopenharmony_ci	   tmp, __FILE__, __LINE__);
4555141cc406Sopenharmony_ci      return 0;
4556141cc406Sopenharmony_ci    }
4557141cc406Sopenharmony_ci  return 1;
4558141cc406Sopenharmony_ci}
4559141cc406Sopenharmony_ci
4560141cc406Sopenharmony_ci/*
4561141cc406Sopenharmony_ci * 0: failure
4562141cc406Sopenharmony_ci * 1: success
4563141cc406Sopenharmony_ci */
4564141cc406Sopenharmony_cistatic int
4565141cc406Sopenharmony_cisendWord (int *cmd)
4566141cc406Sopenharmony_ci{
4567141cc406Sopenharmony_ci  switch (sanei_umax_pp_getastra ())
4568141cc406Sopenharmony_ci    {
4569141cc406Sopenharmony_ci    case 610:
4570141cc406Sopenharmony_ci      return sendLength610p (cmd);
4571141cc406Sopenharmony_ci    case 1220:
4572141cc406Sopenharmony_ci    case 1600:
4573141cc406Sopenharmony_ci    case 2000:
4574141cc406Sopenharmony_ci    default:
4575141cc406Sopenharmony_ci      return sendWord1220P (cmd);
4576141cc406Sopenharmony_ci    }
4577141cc406Sopenharmony_ci}
4578141cc406Sopenharmony_ci
4579141cc406Sopenharmony_ci
4580141cc406Sopenharmony_ci
4581141cc406Sopenharmony_ci/******************************************************************************/
4582141cc406Sopenharmony_ci/* ringScanner: returns 1 if scanner present, else 0                          */
4583141cc406Sopenharmony_ci/******************************************************************************/
4584141cc406Sopenharmony_ci/*
4585141cc406Sopenharmony_ci * in fact this function is really close to CPP macro in
4586141cc406Sopenharmony_ci * /usr/src/linux/drivers/block/paride/epat.c .....
4587141cc406Sopenharmony_ci * we have almost CPP(8)
4588141cc406Sopenharmony_ci */
4589141cc406Sopenharmony_ci
4590141cc406Sopenharmony_cistatic int
4591141cc406Sopenharmony_ciringScanner (int count, unsigned long delay)
4592141cc406Sopenharmony_ci{
4593141cc406Sopenharmony_ci  int status;
4594141cc406Sopenharmony_ci  int data;
4595141cc406Sopenharmony_ci  int control;
4596141cc406Sopenharmony_ci  int ret = 1;
4597141cc406Sopenharmony_ci
4598141cc406Sopenharmony_ci  /* save state */
4599141cc406Sopenharmony_ci  data = Inb (DATA);
4600141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x1F;
4601141cc406Sopenharmony_ci
4602141cc406Sopenharmony_ci  /* send -irq,+reset */
4603141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0xF) | 0x4);
4604141cc406Sopenharmony_ci
4605141cc406Sopenharmony_ci  /* unhandled case */
4606141cc406Sopenharmony_ci  if (g674 == 1)
4607141cc406Sopenharmony_ci    {
4608141cc406Sopenharmony_ci      DBG (1, "OUCH! %s:%d\n", __FILE__, __LINE__);
4609141cc406Sopenharmony_ci      return 0;
4610141cc406Sopenharmony_ci    }
4611141cc406Sopenharmony_ci
4612141cc406Sopenharmony_ci  /* send ring string */
4613141cc406Sopenharmony_ci  Outb (DATA, 0x22);
4614141cc406Sopenharmony_ci  usleep (delay);
4615141cc406Sopenharmony_ci  Outb (DATA, 0x22);
4616141cc406Sopenharmony_ci  usleep (delay);
4617141cc406Sopenharmony_ci  if (count == 5)
4618141cc406Sopenharmony_ci    {
4619141cc406Sopenharmony_ci      Outb (DATA, 0x22);
4620141cc406Sopenharmony_ci      usleep (delay);
4621141cc406Sopenharmony_ci      Outb (DATA, 0x22);
4622141cc406Sopenharmony_ci      usleep (delay);
4623141cc406Sopenharmony_ci      Outb (DATA, 0x22);
4624141cc406Sopenharmony_ci      usleep (delay);
4625141cc406Sopenharmony_ci    }
4626141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4627141cc406Sopenharmony_ci  usleep (delay);
4628141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4629141cc406Sopenharmony_ci  usleep (delay);
4630141cc406Sopenharmony_ci  if (count == 5)
4631141cc406Sopenharmony_ci    {
4632141cc406Sopenharmony_ci      Outb (DATA, 0xAA);
4633141cc406Sopenharmony_ci      usleep (delay);
4634141cc406Sopenharmony_ci      Outb (DATA, 0xAA);
4635141cc406Sopenharmony_ci      usleep (delay);
4636141cc406Sopenharmony_ci      Outb (DATA, 0xAA);
4637141cc406Sopenharmony_ci      usleep (delay);
4638141cc406Sopenharmony_ci    }
4639141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4640141cc406Sopenharmony_ci  usleep (delay);
4641141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4642141cc406Sopenharmony_ci  usleep (delay);
4643141cc406Sopenharmony_ci  if (count == 5)
4644141cc406Sopenharmony_ci    {
4645141cc406Sopenharmony_ci      Outb (DATA, 0x55);
4646141cc406Sopenharmony_ci      usleep (delay);
4647141cc406Sopenharmony_ci      Outb (DATA, 0x55);
4648141cc406Sopenharmony_ci      usleep (delay);
4649141cc406Sopenharmony_ci      Outb (DATA, 0x55);
4650141cc406Sopenharmony_ci      usleep (delay);
4651141cc406Sopenharmony_ci    }
4652141cc406Sopenharmony_ci  Outb (DATA, 0x00);
4653141cc406Sopenharmony_ci  usleep (delay);
4654141cc406Sopenharmony_ci  Outb (DATA, 0x00);
4655141cc406Sopenharmony_ci  usleep (delay);
4656141cc406Sopenharmony_ci  if (count == 5)
4657141cc406Sopenharmony_ci    {
4658141cc406Sopenharmony_ci      Outb (DATA, 0x00);
4659141cc406Sopenharmony_ci      usleep (delay);
4660141cc406Sopenharmony_ci      Outb (DATA, 0x00);
4661141cc406Sopenharmony_ci      usleep (delay);
4662141cc406Sopenharmony_ci      Outb (DATA, 0x00);
4663141cc406Sopenharmony_ci      usleep (delay);
4664141cc406Sopenharmony_ci    }
4665141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4666141cc406Sopenharmony_ci  usleep (delay);
4667141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4668141cc406Sopenharmony_ci  usleep (delay);
4669141cc406Sopenharmony_ci  if (count == 5)
4670141cc406Sopenharmony_ci    {
4671141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
4672141cc406Sopenharmony_ci      usleep (delay);
4673141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
4674141cc406Sopenharmony_ci      usleep (delay);
4675141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
4676141cc406Sopenharmony_ci      usleep (delay);
4677141cc406Sopenharmony_ci    }
4678141cc406Sopenharmony_ci
4679141cc406Sopenharmony_ci  /* OK ? */
4680141cc406Sopenharmony_ci  status = Inb (STATUS) & 0xF8;
4681141cc406Sopenharmony_ci  usleep (delay);
4682141cc406Sopenharmony_ci  if ((status & 0xB8) != 0xB8)
4683141cc406Sopenharmony_ci    {
4684141cc406Sopenharmony_ci      DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__, __LINE__);
4685141cc406Sopenharmony_ci      ret = 0;
4686141cc406Sopenharmony_ci    }
4687141cc406Sopenharmony_ci
4688141cc406Sopenharmony_ci  /* if OK send 0x87 */
4689141cc406Sopenharmony_ci  if (ret)
4690141cc406Sopenharmony_ci    {
4691141cc406Sopenharmony_ci      Outb (DATA, 0x87);
4692141cc406Sopenharmony_ci      usleep (delay);
4693141cc406Sopenharmony_ci      Outb (DATA, 0x87);
4694141cc406Sopenharmony_ci      usleep (delay);
4695141cc406Sopenharmony_ci      if (count == 5)
4696141cc406Sopenharmony_ci	{
4697141cc406Sopenharmony_ci	  Outb (DATA, 0x87);
4698141cc406Sopenharmony_ci	  usleep (delay);
4699141cc406Sopenharmony_ci	  Outb (DATA, 0x87);
4700141cc406Sopenharmony_ci	  usleep (delay);
4701141cc406Sopenharmony_ci	  Outb (DATA, 0x87);
4702141cc406Sopenharmony_ci	  usleep (delay);
4703141cc406Sopenharmony_ci	}
4704141cc406Sopenharmony_ci      status = Inb (STATUS);
4705141cc406Sopenharmony_ci      /* status = 126 when scanner not connected .... */
4706141cc406Sopenharmony_ci      if ((status & 0xB8) != 0x18)
4707141cc406Sopenharmony_ci	{
4708141cc406Sopenharmony_ci	  DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__,
4709141cc406Sopenharmony_ci	       __LINE__);
4710141cc406Sopenharmony_ci	  ret = 0;
4711141cc406Sopenharmony_ci	}
4712141cc406Sopenharmony_ci    }
4713141cc406Sopenharmony_ci
4714141cc406Sopenharmony_ci  /* if OK send 0x78 */
4715141cc406Sopenharmony_ci  if (ret)
4716141cc406Sopenharmony_ci    {
4717141cc406Sopenharmony_ci      Outb (DATA, 0x78);
4718141cc406Sopenharmony_ci      usleep (delay);
4719141cc406Sopenharmony_ci      Outb (DATA, 0x78);
4720141cc406Sopenharmony_ci      usleep (delay);
4721141cc406Sopenharmony_ci      if (count == 5)
4722141cc406Sopenharmony_ci	{
4723141cc406Sopenharmony_ci	  Outb (DATA, 0x78);
4724141cc406Sopenharmony_ci	  usleep (delay);
4725141cc406Sopenharmony_ci	  Outb (DATA, 0x78);
4726141cc406Sopenharmony_ci	  usleep (delay);
4727141cc406Sopenharmony_ci	  Outb (DATA, 0x78);
4728141cc406Sopenharmony_ci	  usleep (delay);
4729141cc406Sopenharmony_ci	}
4730141cc406Sopenharmony_ci      status = Inb (STATUS);
4731141cc406Sopenharmony_ci      if ((status & 0x30) != 0x30)
4732141cc406Sopenharmony_ci	{
4733141cc406Sopenharmony_ci	  DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__,
4734141cc406Sopenharmony_ci	       __LINE__);
4735141cc406Sopenharmony_ci	  ret = 0;
4736141cc406Sopenharmony_ci	}
4737141cc406Sopenharmony_ci    }
4738141cc406Sopenharmony_ci
4739141cc406Sopenharmony_ci  /* ring OK, send termination */
4740141cc406Sopenharmony_ci  if (ret)
4741141cc406Sopenharmony_ci    {
4742141cc406Sopenharmony_ci      Outb (DATA, 0x08);
4743141cc406Sopenharmony_ci      usleep (delay);
4744141cc406Sopenharmony_ci      Outb (DATA, 0x08);
4745141cc406Sopenharmony_ci      usleep (delay);
4746141cc406Sopenharmony_ci      if (count == 5)
4747141cc406Sopenharmony_ci	{
4748141cc406Sopenharmony_ci	  Outb (DATA, 0x08);
4749141cc406Sopenharmony_ci	  usleep (delay);
4750141cc406Sopenharmony_ci	  Outb (DATA, 0x08);
4751141cc406Sopenharmony_ci	  usleep (delay);
4752141cc406Sopenharmony_ci	  Outb (DATA, 0x08);
4753141cc406Sopenharmony_ci	  usleep (delay);
4754141cc406Sopenharmony_ci	}
4755141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
4756141cc406Sopenharmony_ci      usleep (delay);
4757141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
4758141cc406Sopenharmony_ci      usleep (delay);
4759141cc406Sopenharmony_ci      if (count == 5)
4760141cc406Sopenharmony_ci	{
4761141cc406Sopenharmony_ci	  Outb (DATA, 0xFF);
4762141cc406Sopenharmony_ci	  usleep (delay);
4763141cc406Sopenharmony_ci	  Outb (DATA, 0xFF);
4764141cc406Sopenharmony_ci	  usleep (delay);
4765141cc406Sopenharmony_ci	  Outb (DATA, 0xFF);
4766141cc406Sopenharmony_ci	  usleep (delay);
4767141cc406Sopenharmony_ci	}
4768141cc406Sopenharmony_ci    }
4769141cc406Sopenharmony_ci
4770141cc406Sopenharmony_ci  /* restore state */
4771141cc406Sopenharmony_ci  Outb (CONTROL, control);
4772141cc406Sopenharmony_ci  Outb (DATA, data);
4773141cc406Sopenharmony_ci  return ret;
4774141cc406Sopenharmony_ci}
4775141cc406Sopenharmony_ci
4776141cc406Sopenharmony_ci/*****************************************************************************/
4777141cc406Sopenharmony_ci/* test some version       : returns 1 on success, 0 otherwise               */
4778141cc406Sopenharmony_ci/*****************************************************************************/
4779141cc406Sopenharmony_ci
4780141cc406Sopenharmony_ci
4781141cc406Sopenharmony_cistatic int
4782141cc406Sopenharmony_citestVersion (int no)
4783141cc406Sopenharmony_ci{
4784141cc406Sopenharmony_ci  int data;
4785141cc406Sopenharmony_ci  int status;
4786141cc406Sopenharmony_ci  int control;
4787141cc406Sopenharmony_ci  int count;
4788141cc406Sopenharmony_ci  int tmp;
4789141cc406Sopenharmony_ci
4790141cc406Sopenharmony_ci  data = Inb (DATA);
4791141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0x3F;
4792141cc406Sopenharmony_ci  Outb (CONTROL, (control & 0x1F) | 0x04);
4793141cc406Sopenharmony_ci
4794141cc406Sopenharmony_ci  /* send magic sequence */
4795141cc406Sopenharmony_ci  Outb (DATA, 0x22);
4796141cc406Sopenharmony_ci  Outb (DATA, 0x22);
4797141cc406Sopenharmony_ci  Outb (DATA, 0x22);
4798141cc406Sopenharmony_ci  Outb (DATA, 0x22);
4799141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4800141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4801141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4802141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4803141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4804141cc406Sopenharmony_ci  Outb (DATA, 0xAA);
4805141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4806141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4807141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4808141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4809141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4810141cc406Sopenharmony_ci  Outb (DATA, 0x55);
4811141cc406Sopenharmony_ci  Outb (DATA, 0x00);
4812141cc406Sopenharmony_ci  Outb (DATA, 0x00);
4813141cc406Sopenharmony_ci  Outb (DATA, 0x00);
4814141cc406Sopenharmony_ci  Outb (DATA, 0x00);
4815141cc406Sopenharmony_ci  Outb (DATA, 0x00);
4816141cc406Sopenharmony_ci  Outb (DATA, 0x00);
4817141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4818141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4819141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4820141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4821141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4822141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
4823141cc406Sopenharmony_ci  Outb (DATA, 0x87);
4824141cc406Sopenharmony_ci  Outb (DATA, 0x87);
4825141cc406Sopenharmony_ci  Outb (DATA, 0x87);
4826141cc406Sopenharmony_ci  Outb (DATA, 0x87);
4827141cc406Sopenharmony_ci  Outb (DATA, 0x87);
4828141cc406Sopenharmony_ci  Outb (DATA, 0x87);
4829141cc406Sopenharmony_ci  Outb (DATA, 0x78);
4830141cc406Sopenharmony_ci  Outb (DATA, 0x78);
4831141cc406Sopenharmony_ci  Outb (DATA, 0x78);
4832141cc406Sopenharmony_ci  Outb (DATA, 0x78);
4833141cc406Sopenharmony_ci  Outb (DATA, 0x78);
4834141cc406Sopenharmony_ci  Outb (DATA, 0x78);
4835141cc406Sopenharmony_ci  tmp = no | 0x88;
4836141cc406Sopenharmony_ci  Outb (DATA, tmp);
4837141cc406Sopenharmony_ci  Outb (DATA, tmp);
4838141cc406Sopenharmony_ci  Outb (DATA, tmp);
4839141cc406Sopenharmony_ci  Outb (DATA, tmp);
4840141cc406Sopenharmony_ci  Outb (DATA, tmp);
4841141cc406Sopenharmony_ci  Outb (DATA, tmp);
4842141cc406Sopenharmony_ci
4843141cc406Sopenharmony_ci  /* test status */
4844141cc406Sopenharmony_ci  status = Inb (STATUS);
4845141cc406Sopenharmony_ci  status = Inb (STATUS);
4846141cc406Sopenharmony_ci  if ((status & 0xB8) != 0)
4847141cc406Sopenharmony_ci    {
4848141cc406Sopenharmony_ci      /* 1600P fails here */
4849141cc406Sopenharmony_ci      DBG (64, "status %d doesn't match! %s:%d\n", status, __FILE__,
4850141cc406Sopenharmony_ci	   __LINE__);
4851141cc406Sopenharmony_ci      Outb (CONTROL, control);
4852141cc406Sopenharmony_ci      Outb (DATA, data);
4853141cc406Sopenharmony_ci      return 0;
4854141cc406Sopenharmony_ci    }
4855141cc406Sopenharmony_ci
4856141cc406Sopenharmony_ci  count = 0xF0;
4857141cc406Sopenharmony_ci  do
4858141cc406Sopenharmony_ci    {
4859141cc406Sopenharmony_ci      tmp = no | 0x80;
4860141cc406Sopenharmony_ci      Outb (DATA, tmp);
4861141cc406Sopenharmony_ci      Outb (DATA, tmp);
4862141cc406Sopenharmony_ci      Outb (DATA, tmp);
4863141cc406Sopenharmony_ci      Outb (DATA, tmp);
4864141cc406Sopenharmony_ci      Outb (DATA, tmp);
4865141cc406Sopenharmony_ci      Outb (DATA, tmp);
4866141cc406Sopenharmony_ci      tmp = no | 0x88;
4867141cc406Sopenharmony_ci      Outb (DATA, tmp);
4868141cc406Sopenharmony_ci      Outb (DATA, tmp);
4869141cc406Sopenharmony_ci      Outb (DATA, tmp);
4870141cc406Sopenharmony_ci      Outb (DATA, tmp);
4871141cc406Sopenharmony_ci      Outb (DATA, tmp);
4872141cc406Sopenharmony_ci      Outb (DATA, tmp);
4873141cc406Sopenharmony_ci
4874141cc406Sopenharmony_ci      /* command received ? */
4875141cc406Sopenharmony_ci      status = Inb (STATUS);
4876141cc406Sopenharmony_ci      status = ((status << 1) & 0x70) | (status & 0x80);
4877141cc406Sopenharmony_ci      if (status != count)
4878141cc406Sopenharmony_ci	{
4879141cc406Sopenharmony_ci	  /* since failure is expected, we don't alaways print */
4880141cc406Sopenharmony_ci	  /* this message ...                                   */
4881141cc406Sopenharmony_ci	  DBG (2, "status %d doesn't match count 0x%X! %s:%d\n", status,
4882141cc406Sopenharmony_ci	       count, __FILE__, __LINE__);
4883141cc406Sopenharmony_ci	  Outb (CONTROL, control);
4884141cc406Sopenharmony_ci	  Outb (DATA, data);
4885141cc406Sopenharmony_ci	  return 0;
4886141cc406Sopenharmony_ci	}
4887141cc406Sopenharmony_ci
4888141cc406Sopenharmony_ci      /* next */
4889141cc406Sopenharmony_ci      count -= 0x10;
4890141cc406Sopenharmony_ci    }
4891141cc406Sopenharmony_ci  while (count > 0);
4892141cc406Sopenharmony_ci
4893141cc406Sopenharmony_ci  /* restore port , successful exit */
4894141cc406Sopenharmony_ci  Outb (CONTROL, control);
4895141cc406Sopenharmony_ci  Outb (DATA, data);
4896141cc406Sopenharmony_ci  return 1;
4897141cc406Sopenharmony_ci}
4898141cc406Sopenharmony_ci
4899141cc406Sopenharmony_ci
4900141cc406Sopenharmony_ci/* sends len bytes to scanner        */
4901141cc406Sopenharmony_ci/* needs data channel to be set up   */
4902141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
4903141cc406Sopenharmony_cistatic int
4904141cc406Sopenharmony_cisendLength (int *cmd, int len)
4905141cc406Sopenharmony_ci{
4906141cc406Sopenharmony_ci  int i;
4907141cc406Sopenharmony_ci  int reg, wait;
4908141cc406Sopenharmony_ci  int try = 0;
4909141cc406Sopenharmony_ci
4910141cc406Sopenharmony_ci  /* send header */
4911141cc406Sopenharmony_ciretry:
4912141cc406Sopenharmony_ci  wait = registerRead (0x19) & 0xF8;
4913141cc406Sopenharmony_ci
4914141cc406Sopenharmony_ci  registerWrite (0x1C, 0x55);
4915141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
4916141cc406Sopenharmony_ci
4917141cc406Sopenharmony_ci  registerWrite (0x1C, 0xAA);
4918141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
4919141cc406Sopenharmony_ci
4920141cc406Sopenharmony_ci  /* sync when needed */
4921141cc406Sopenharmony_ci  if ((wait & 0x08) == 0x00)
4922141cc406Sopenharmony_ci    {
4923141cc406Sopenharmony_ci      reg = registerRead (0x1C);
4924141cc406Sopenharmony_ci      while (((reg & 0x10) != 0x10) && (reg != 0x6B) && (reg != 0xAB)
4925141cc406Sopenharmony_ci	     && (reg != 0x23))
4926141cc406Sopenharmony_ci	{
4927141cc406Sopenharmony_ci	  DBG (0,
4928141cc406Sopenharmony_ci	       "sendLength failed, expected reg & 0x10=0x10 , found 0x%02X (%s:%d)\n",
4929141cc406Sopenharmony_ci	       reg, __FILE__, __LINE__);
4930141cc406Sopenharmony_ci	  if (try > 10)
4931141cc406Sopenharmony_ci	    {
4932141cc406Sopenharmony_ci	      DBG (0, "Aborting...\n");
4933141cc406Sopenharmony_ci	      return 0;
4934141cc406Sopenharmony_ci	    }
4935141cc406Sopenharmony_ci	  else
4936141cc406Sopenharmony_ci	    {
4937141cc406Sopenharmony_ci	      DBG (0, "Retrying ...\n");
4938141cc406Sopenharmony_ci	    }
4939141cc406Sopenharmony_ci	  /* resend */
4940141cc406Sopenharmony_ci	  epilogue ();
4941141cc406Sopenharmony_ci	  prologue (0x10);
4942141cc406Sopenharmony_ci	  try++;
4943141cc406Sopenharmony_ci	  goto retry;
4944141cc406Sopenharmony_ci	}
4945141cc406Sopenharmony_ci      for (i = 0; i < 10; i++)
4946141cc406Sopenharmony_ci	{
4947141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
4948141cc406Sopenharmony_ci	  if (reg != 0xC8)
4949141cc406Sopenharmony_ci	    {
4950141cc406Sopenharmony_ci	      DBG (0, "Unexpected reg19=0x%2X  (%s:%d)\n", reg, __FILE__,
4951141cc406Sopenharmony_ci		   __LINE__);
4952141cc406Sopenharmony_ci	      /* 0xF0 certainly means error */
4953141cc406Sopenharmony_ci	      if ((reg == 0xC0) || (reg == 0xD0) || (reg == 0x80))
4954141cc406Sopenharmony_ci		{
4955141cc406Sopenharmony_ci		  /* resend */
4956141cc406Sopenharmony_ci		  try++;
4957141cc406Sopenharmony_ci		  if (try > 20)
4958141cc406Sopenharmony_ci		    {
4959141cc406Sopenharmony_ci		      DBG (0, "sendLength retry failed (%s:%d)\n", __FILE__,
4960141cc406Sopenharmony_ci			   __LINE__);
4961141cc406Sopenharmony_ci		      return 0;
4962141cc406Sopenharmony_ci		    }
4963141cc406Sopenharmony_ci
4964141cc406Sopenharmony_ci		  epilogue ();
4965141cc406Sopenharmony_ci		  sendCommand (0x00);
4966141cc406Sopenharmony_ci		  sendCommand (0xE0);
4967141cc406Sopenharmony_ci		  Outb (DATA, 0x00);
4968141cc406Sopenharmony_ci		  Outb (CONTROL, 0x01);
4969141cc406Sopenharmony_ci		  Outb (CONTROL, 0x04);
4970141cc406Sopenharmony_ci		  sendCommand (0x30);
4971141cc406Sopenharmony_ci
4972141cc406Sopenharmony_ci		  prologue (0x10);
4973141cc406Sopenharmony_ci		  goto retry;
4974141cc406Sopenharmony_ci		}
4975141cc406Sopenharmony_ci	    }
4976141cc406Sopenharmony_ci	}
4977141cc406Sopenharmony_ci      do
4978141cc406Sopenharmony_ci	{
4979141cc406Sopenharmony_ci	  if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0xC8))
4980141cc406Sopenharmony_ci	    {
4981141cc406Sopenharmony_ci	      /* status has changed while waiting */
4982141cc406Sopenharmony_ci	      /* but it's too early               */
4983141cc406Sopenharmony_ci	      DBG (0, "Unexpected reg19=0x%2X  (%s:%d)\n", reg, __FILE__,
4984141cc406Sopenharmony_ci		   __LINE__);
4985141cc406Sopenharmony_ci	    }
4986141cc406Sopenharmony_ci	  /* 0xF0 certainly means error */
4987141cc406Sopenharmony_ci	  if ((reg == 0xC0) || (reg == 0xD0) || (reg == 0x80))
4988141cc406Sopenharmony_ci	    {
4989141cc406Sopenharmony_ci	      /* resend */
4990141cc406Sopenharmony_ci	      try++;
4991141cc406Sopenharmony_ci	      epilogue ();
4992141cc406Sopenharmony_ci
4993141cc406Sopenharmony_ci	      sendCommand (0x00);
4994141cc406Sopenharmony_ci	      sendCommand (0xE0);
4995141cc406Sopenharmony_ci	      Outb (DATA, 0x00);
4996141cc406Sopenharmony_ci	      Outb (CONTROL, 0x01);
4997141cc406Sopenharmony_ci	      Outb (CONTROL, 0x04);
4998141cc406Sopenharmony_ci	      sendCommand (0x30);
4999141cc406Sopenharmony_ci
5000141cc406Sopenharmony_ci	      prologue (0x10);
5001141cc406Sopenharmony_ci	      goto retry;
5002141cc406Sopenharmony_ci	    }
5003141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
5004141cc406Sopenharmony_ci	}
5005141cc406Sopenharmony_ci      while (reg != 0xC8);
5006141cc406Sopenharmony_ci    }
5007141cc406Sopenharmony_ci
5008141cc406Sopenharmony_ci  /* send bytes */
5009141cc406Sopenharmony_ci  i = 0;
5010141cc406Sopenharmony_ci  while ((reg == 0xC8) && (i < len))
5011141cc406Sopenharmony_ci    {
5012141cc406Sopenharmony_ci      /* write byte */
5013141cc406Sopenharmony_ci      registerWrite (0x1C, cmd[i]);
5014141cc406Sopenharmony_ci      reg = registerRead (0x19) & 0xF8;
5015141cc406Sopenharmony_ci
5016141cc406Sopenharmony_ci      /* 1B handling: escape it to confirm value  */
5017141cc406Sopenharmony_ci      if (cmd[i] == 0x1B)
5018141cc406Sopenharmony_ci	{
5019141cc406Sopenharmony_ci	  registerWrite (0x1C, cmd[i]);
5020141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
5021141cc406Sopenharmony_ci	}
5022141cc406Sopenharmony_ci      i++;
5023141cc406Sopenharmony_ci    }
5024141cc406Sopenharmony_ci  DBG (16, "sendLength, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5025141cc406Sopenharmony_ci  if ((reg != 0xC0) && (reg != 0xD0))
5026141cc406Sopenharmony_ci    {
5027141cc406Sopenharmony_ci      DBG (0,
5028141cc406Sopenharmony_ci	   "sendLength failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
5029141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
5030141cc406Sopenharmony_ci      DBG (0, "Blindly going on .....\n");
5031141cc406Sopenharmony_ci    }
5032141cc406Sopenharmony_ci
5033141cc406Sopenharmony_ci  /* check if 'finished status' received too early */
5034141cc406Sopenharmony_ci  if (((reg == 0xC0) || (reg == 0xD0)) && (i != len))
5035141cc406Sopenharmony_ci    {
5036141cc406Sopenharmony_ci      DBG (0, "sendLength failed: sent only %d bytes out of %d (%s:%d)\n", i,
5037141cc406Sopenharmony_ci	   len, __FILE__, __LINE__);
5038141cc406Sopenharmony_ci      return 0;
5039141cc406Sopenharmony_ci    }
5040141cc406Sopenharmony_ci
5041141cc406Sopenharmony_ci
5042141cc406Sopenharmony_ci  reg = registerRead (0x1C);
5043141cc406Sopenharmony_ci  DBG (16, "sendLength, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5044141cc406Sopenharmony_ci
5045141cc406Sopenharmony_ci  /* model 0x07 has always the last bit set to 1 */
5046141cc406Sopenharmony_ci  scannerStatus = reg & 0xFC;
5047141cc406Sopenharmony_ci  reg = reg & 0x10;
5048141cc406Sopenharmony_ci  if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8))
5049141cc406Sopenharmony_ci    {
5050141cc406Sopenharmony_ci      DBG (0, "sendLength failed: acknowledge not received (%s:%d)\n",
5051141cc406Sopenharmony_ci	   __FILE__, __LINE__);
5052141cc406Sopenharmony_ci      return 0;
5053141cc406Sopenharmony_ci    }
5054141cc406Sopenharmony_ci  if (try)
5055141cc406Sopenharmony_ci    {
5056141cc406Sopenharmony_ci      DBG (0, "sendLength retry success (retry %d time%s) ... (%s:%d)\n", try,
5057141cc406Sopenharmony_ci	   (try > 1) ? "s" : "", __FILE__, __LINE__);
5058141cc406Sopenharmony_ci    }
5059141cc406Sopenharmony_ci  return 1;
5060141cc406Sopenharmony_ci}
5061141cc406Sopenharmony_ci
5062141cc406Sopenharmony_ci
5063141cc406Sopenharmony_ci/* sends data bytes to scanner       */
5064141cc406Sopenharmony_ci/* needs data channel to be set up   */
5065141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
5066141cc406Sopenharmony_cistatic int
5067141cc406Sopenharmony_cisendData610p (int *cmd, int len)
5068141cc406Sopenharmony_ci{
5069141cc406Sopenharmony_ci  int i, status, j;
5070141cc406Sopenharmony_ci
5071141cc406Sopenharmony_ci  i = 0;
5072141cc406Sopenharmony_ci  status = 0xC8;
5073141cc406Sopenharmony_ci  /* while ((i < len) && ((status & 0x08) == 0x08)) XXX STEF XXX */
5074141cc406Sopenharmony_ci  while (i < len)
5075141cc406Sopenharmony_ci    {
5076141cc406Sopenharmony_ci      /* escape special values */
5077141cc406Sopenharmony_ci      if (cmd[i] == 0x1B)
5078141cc406Sopenharmony_ci	status = putByte610p (0x1B);
5079141cc406Sopenharmony_ci      if (i > 0)
5080141cc406Sopenharmony_ci	{
5081141cc406Sopenharmony_ci	  if ((cmd[i] == 0xAA) && (cmd[i - 1] == 0x55))
5082141cc406Sopenharmony_ci	    status = putByte610p (0x1B);
5083141cc406Sopenharmony_ci	}
5084141cc406Sopenharmony_ci      /* regular values */
5085141cc406Sopenharmony_ci      status = putByte610p (cmd[i]);
5086141cc406Sopenharmony_ci      i++;
5087141cc406Sopenharmony_ci    }
5088141cc406Sopenharmony_ci  j = 0;
5089141cc406Sopenharmony_ci  while ((status & 0x08) && (j < 256))
5090141cc406Sopenharmony_ci    {
5091141cc406Sopenharmony_ci      status = getStatus610p ();
5092141cc406Sopenharmony_ci      j++;
5093141cc406Sopenharmony_ci    }
5094141cc406Sopenharmony_ci  if ((status != 0xC0) && (status != 0xD0))
5095141cc406Sopenharmony_ci    {
5096141cc406Sopenharmony_ci      DBG (0,
5097141cc406Sopenharmony_ci	   "sendData610p() failed, status=0x%02X, expected 0xC0 or 0xD0 (%s:%d)\n",
5098141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
5099141cc406Sopenharmony_ci      return 0;
5100141cc406Sopenharmony_ci    }
5101141cc406Sopenharmony_ci
5102141cc406Sopenharmony_ci  /* check if 'finished status' received too early */
5103141cc406Sopenharmony_ci  if (i < len)
5104141cc406Sopenharmony_ci    {
5105141cc406Sopenharmony_ci      DBG (0, "sendData610p failed: sent only %d bytes out of %d (%s:%d)\n",
5106141cc406Sopenharmony_ci	   i, len, __FILE__, __LINE__);
5107141cc406Sopenharmony_ci      return 0;
5108141cc406Sopenharmony_ci    }
5109141cc406Sopenharmony_ci  return 1;
5110141cc406Sopenharmony_ci}
5111141cc406Sopenharmony_ci
5112141cc406Sopenharmony_ci
5113141cc406Sopenharmony_ci/* sends data bytes to scanner       */
5114141cc406Sopenharmony_ci/* needs data channel to be set up   */
5115141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
5116141cc406Sopenharmony_cistatic int
5117141cc406Sopenharmony_cisendData (int *cmd, int len)
5118141cc406Sopenharmony_ci{
5119141cc406Sopenharmony_ci  int i;
5120141cc406Sopenharmony_ci  int reg;
5121141cc406Sopenharmony_ci
5122141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
5123141cc406Sopenharmony_ci    return sendData610p (cmd, len);
5124141cc406Sopenharmony_ci
5125141cc406Sopenharmony_ci  /* send header */
5126141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
5127141cc406Sopenharmony_ci
5128141cc406Sopenharmony_ci  /* send bytes */
5129141cc406Sopenharmony_ci  i = 0;
5130141cc406Sopenharmony_ci  while ((reg == 0xC8) && (i < len))
5131141cc406Sopenharmony_ci    {
5132141cc406Sopenharmony_ci      /* write byte */
5133141cc406Sopenharmony_ci      registerWrite (0x1C, cmd[i]);
5134141cc406Sopenharmony_ci      reg = registerRead (0x19) & 0xF8;
5135141cc406Sopenharmony_ci
5136141cc406Sopenharmony_ci      /* 1B handling: escape it to confirm value  */
5137141cc406Sopenharmony_ci      if (cmd[i] == 0x1B)
5138141cc406Sopenharmony_ci	{
5139141cc406Sopenharmony_ci	  registerWrite (0x1C, 0x1B);
5140141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
5141141cc406Sopenharmony_ci	}
5142141cc406Sopenharmony_ci
5143141cc406Sopenharmony_ci      /* escape 55 AA pattern by adding 1B */
5144141cc406Sopenharmony_ci      if ((i < len - 1) && (cmd[i] == 0x55) && (cmd[i + 1] == 0xAA))
5145141cc406Sopenharmony_ci	{
5146141cc406Sopenharmony_ci	  registerWrite (0x1C, 0x1B);
5147141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
5148141cc406Sopenharmony_ci	}
5149141cc406Sopenharmony_ci
5150141cc406Sopenharmony_ci      /* next value */
5151141cc406Sopenharmony_ci      i++;
5152141cc406Sopenharmony_ci    }
5153141cc406Sopenharmony_ci  DBG (16, "sendData, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5154141cc406Sopenharmony_ci  if ((reg != 0xC0) && (reg != 0xD0))
5155141cc406Sopenharmony_ci    {
5156141cc406Sopenharmony_ci      DBG (0, "sendData failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
5157141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
5158141cc406Sopenharmony_ci      DBG (0, "Blindly going on .....\n");
5159141cc406Sopenharmony_ci    }
5160141cc406Sopenharmony_ci
5161141cc406Sopenharmony_ci  /* check if 'finished status' received too early */
5162141cc406Sopenharmony_ci  if (((reg == 0xC0) || (reg == 0xD0)) && (i < len))
5163141cc406Sopenharmony_ci    {
5164141cc406Sopenharmony_ci      DBG (0, "sendData failed: sent only %d bytes out of %d (%s:%d)\n", i,
5165141cc406Sopenharmony_ci	   len, __FILE__, __LINE__);
5166141cc406Sopenharmony_ci      return 0;
5167141cc406Sopenharmony_ci    }
5168141cc406Sopenharmony_ci
5169141cc406Sopenharmony_ci
5170141cc406Sopenharmony_ci  reg = registerRead (0x1C);
5171141cc406Sopenharmony_ci  DBG (16, "sendData, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5172141cc406Sopenharmony_ci
5173141cc406Sopenharmony_ci  /* model 0x07 has always the last bit set to 1 */
5174141cc406Sopenharmony_ci  scannerStatus = reg & 0xFC;
5175141cc406Sopenharmony_ci  reg = reg & 0x10;
5176141cc406Sopenharmony_ci  if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8)
5177141cc406Sopenharmony_ci      && (scannerStatus != 0x20))
5178141cc406Sopenharmony_ci    {
5179141cc406Sopenharmony_ci      DBG (0, "sendData failed: acknowledge not received (%s:%d)\n", __FILE__,
5180141cc406Sopenharmony_ci	   __LINE__);
5181141cc406Sopenharmony_ci      return 0;
5182141cc406Sopenharmony_ci    }
5183141cc406Sopenharmony_ci  return 1;
5184141cc406Sopenharmony_ci}
5185141cc406Sopenharmony_ci
5186141cc406Sopenharmony_ci
5187141cc406Sopenharmony_ci/* receive data bytes from scanner   */
5188141cc406Sopenharmony_ci/* needs data channel to be set up   */
5189141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
5190141cc406Sopenharmony_ci/* uses pausedBufferRead             */
5191141cc406Sopenharmony_cistatic int
5192141cc406Sopenharmony_cipausedReadData (int size, unsigned char *dest)
5193141cc406Sopenharmony_ci{
5194141cc406Sopenharmony_ci  int reg;
5195141cc406Sopenharmony_ci  int tmp;
5196141cc406Sopenharmony_ci  int read;
5197141cc406Sopenharmony_ci
5198141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0D);
5199141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x00);
5200141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
5201141cc406Sopenharmony_ci  if ((reg != 0xC0) && (reg != 0xD0))
5202141cc406Sopenharmony_ci    {
5203141cc406Sopenharmony_ci      DBG (0, "Unexpected reg19: 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
5204141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
5205141cc406Sopenharmony_ci      return 0;
5206141cc406Sopenharmony_ci    }
5207141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
5208141cc406Sopenharmony_ci    {
5209141cc406Sopenharmony_ci      REGISTERWRITE (0x1A, 0x44);
5210141cc406Sopenharmony_ci    }
5211141cc406Sopenharmony_ci  REGISTERREAD (0x0C, 0x04);
5212141cc406Sopenharmony_ci  REGISTERWRITE (0x0C, 0x44);	/* sets data direction ? */
5213141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
5214141cc406Sopenharmony_ci    {
5215141cc406Sopenharmony_ci      compatMode ();
5216141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);	/* reset ? */
5217141cc406Sopenharmony_ci      ECPSetBuffer (size);
5218141cc406Sopenharmony_ci      read = ECPbufferRead (size, dest);
5219141cc406Sopenharmony_ci      DBG (16, "ECPbufferRead(%d,dest) passed (%s:%d)\n", size, __FILE__,
5220141cc406Sopenharmony_ci	   __LINE__);
5221141cc406Sopenharmony_ci      REGISTERWRITE (0x1A, 0x84);
5222141cc406Sopenharmony_ci    }
5223141cc406Sopenharmony_ci  else
5224141cc406Sopenharmony_ci    {
5225141cc406Sopenharmony_ci      read = pausedBufferRead (size, dest);
5226141cc406Sopenharmony_ci    }
5227141cc406Sopenharmony_ci  if (read < size)
5228141cc406Sopenharmony_ci    {
5229141cc406Sopenharmony_ci      DBG (16,
5230141cc406Sopenharmony_ci	   "pausedBufferRead(%d,dest) failed, only got %d bytes (%s:%d)\n",
5231141cc406Sopenharmony_ci	   size, read, __FILE__, __LINE__);
5232141cc406Sopenharmony_ci      return 0;
5233141cc406Sopenharmony_ci    }
5234141cc406Sopenharmony_ci  DBG (16, "pausedBufferRead(%d,dest) passed (%s:%d)\n", size, __FILE__,
5235141cc406Sopenharmony_ci       __LINE__);
5236141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0D);
5237141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x00);
5238141cc406Sopenharmony_ci  return 1;
5239141cc406Sopenharmony_ci}
5240141cc406Sopenharmony_ci
5241141cc406Sopenharmony_ci
5242141cc406Sopenharmony_ci
5243141cc406Sopenharmony_ci/* receive data bytes from scanner   */
5244141cc406Sopenharmony_ci/* needs data channel to be set up   */
5245141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
5246141cc406Sopenharmony_cistatic int
5247141cc406Sopenharmony_cireceiveData610p (int *cmd, int len)
5248141cc406Sopenharmony_ci{
5249141cc406Sopenharmony_ci  int i;
5250141cc406Sopenharmony_ci  int status;
5251141cc406Sopenharmony_ci
5252141cc406Sopenharmony_ci  i = 0;
5253141cc406Sopenharmony_ci  status = 0xD0;
5254141cc406Sopenharmony_ci  byteMode ();
5255141cc406Sopenharmony_ci  while (i < len)
5256141cc406Sopenharmony_ci    {
5257141cc406Sopenharmony_ci      status = Inb (STATUS) & 0xF8;
5258141cc406Sopenharmony_ci      Outb (CONTROL, 0x26);	/* data reverse+ 'reg' */
5259141cc406Sopenharmony_ci      cmd[i] = Inb (DATA);
5260141cc406Sopenharmony_ci      Outb (CONTROL, 0x24);	/* data reverse+ 'reg' */
5261141cc406Sopenharmony_ci      i++;
5262141cc406Sopenharmony_ci    }
5263141cc406Sopenharmony_ci  if (status != 0xC0)
5264141cc406Sopenharmony_ci    {
5265141cc406Sopenharmony_ci      DBG (0, "receiveData610p failed  got 0x%02X instead of 0xC0 (%s:%d)\n",
5266141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
5267141cc406Sopenharmony_ci      DBG (0, "Blindly going on .....\n");
5268141cc406Sopenharmony_ci    }
5269141cc406Sopenharmony_ci
5270141cc406Sopenharmony_ci  /* check if 'finished status' received to early */
5271141cc406Sopenharmony_ci  if ((status == 0xC0) && (i != len))
5272141cc406Sopenharmony_ci    {
5273141cc406Sopenharmony_ci      DBG (0,
5274141cc406Sopenharmony_ci	   "receiveData610p failed: received only %d bytes out of %d (%s:%d)\n",
5275141cc406Sopenharmony_ci	   i, len, __FILE__, __LINE__);
5276141cc406Sopenharmony_ci      return 0;
5277141cc406Sopenharmony_ci    }
5278141cc406Sopenharmony_ci  return 1;
5279141cc406Sopenharmony_ci}
5280141cc406Sopenharmony_ci
5281141cc406Sopenharmony_ci/* receive data bytes from scanner   */
5282141cc406Sopenharmony_ci/* needs data channel to be set up   */
5283141cc406Sopenharmony_ci/* returns 1 on success, 0 otherwise */
5284141cc406Sopenharmony_cistatic int
5285141cc406Sopenharmony_cireceiveData (int *cmd, int len)
5286141cc406Sopenharmony_ci{
5287141cc406Sopenharmony_ci  int i;
5288141cc406Sopenharmony_ci  int reg;
5289141cc406Sopenharmony_ci
5290141cc406Sopenharmony_ci  /* send header */
5291141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
5292141cc406Sopenharmony_ci
5293141cc406Sopenharmony_ci  /* send bytes */
5294141cc406Sopenharmony_ci  i = 0;
5295141cc406Sopenharmony_ci  while (((reg == 0xD0) || (reg == 0xC0)) && (i < len))
5296141cc406Sopenharmony_ci    {
5297141cc406Sopenharmony_ci      /* write byte */
5298141cc406Sopenharmony_ci      cmd[i] = registerRead (0x1C);
5299141cc406Sopenharmony_ci      reg = registerRead (0x19) & 0xF8;
5300141cc406Sopenharmony_ci      i++;
5301141cc406Sopenharmony_ci    }
5302141cc406Sopenharmony_ci  DBG (16, "receiveData, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5303141cc406Sopenharmony_ci  if ((reg != 0xC0) && (reg != 0xD0))
5304141cc406Sopenharmony_ci    {
5305141cc406Sopenharmony_ci      DBG (0, "sendData failed  got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n",
5306141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
5307141cc406Sopenharmony_ci      DBG (0, "Blindly going on .....\n");
5308141cc406Sopenharmony_ci    }
5309141cc406Sopenharmony_ci
5310141cc406Sopenharmony_ci  /* check if 'finished status' received to early */
5311141cc406Sopenharmony_ci  if (((reg == 0xC0) || (reg == 0xD0)) && (i != len))
5312141cc406Sopenharmony_ci    {
5313141cc406Sopenharmony_ci      DBG (0,
5314141cc406Sopenharmony_ci	   "receiveData failed: received only %d bytes out of %d (%s:%d)\n",
5315141cc406Sopenharmony_ci	   i, len, __FILE__, __LINE__);
5316141cc406Sopenharmony_ci      return 0;
5317141cc406Sopenharmony_ci    }
5318141cc406Sopenharmony_ci
5319141cc406Sopenharmony_ci
5320141cc406Sopenharmony_ci  reg = registerRead (0x1C);
5321141cc406Sopenharmony_ci  DBG (16, "receiveData, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
5322141cc406Sopenharmony_ci
5323141cc406Sopenharmony_ci  /* model 0x07 has always the last bit set to 1 */
5324141cc406Sopenharmony_ci  scannerStatus = reg & 0xF8;
5325141cc406Sopenharmony_ci  reg = reg & 0x10;
5326141cc406Sopenharmony_ci  if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8))
5327141cc406Sopenharmony_ci    {
5328141cc406Sopenharmony_ci      DBG (0, "receiveData failed: acknowledge not received (%s:%d)\n",
5329141cc406Sopenharmony_ci	   __FILE__, __LINE__);
5330141cc406Sopenharmony_ci      return 0;
5331141cc406Sopenharmony_ci    }
5332141cc406Sopenharmony_ci  return 1;
5333141cc406Sopenharmony_ci}
5334141cc406Sopenharmony_ci
5335141cc406Sopenharmony_ci
5336141cc406Sopenharmony_ci/* 1=success, 0 failed */
5337141cc406Sopenharmony_cistatic int
5338141cc406Sopenharmony_cifonc001 (void)
5339141cc406Sopenharmony_ci{
5340141cc406Sopenharmony_ci  int i;
5341141cc406Sopenharmony_ci  int res;
5342141cc406Sopenharmony_ci  int reg;
5343141cc406Sopenharmony_ci
5344141cc406Sopenharmony_ci  res = 1;
5345141cc406Sopenharmony_ci  while (res == 1)
5346141cc406Sopenharmony_ci    {
5347141cc406Sopenharmony_ci      registerWrite (0x1A, 0x0C);
5348141cc406Sopenharmony_ci      registerWrite (0x18, 0x40);
5349141cc406Sopenharmony_ci
5350141cc406Sopenharmony_ci      /* send 0x06 */
5351141cc406Sopenharmony_ci      registerWrite (0x1A, 0x06);
5352141cc406Sopenharmony_ci      for (i = 0; i < 10; i++)
5353141cc406Sopenharmony_ci	{
5354141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
5355141cc406Sopenharmony_ci	  if ((reg & 0x78) == 0x38)
5356141cc406Sopenharmony_ci	    {
5357141cc406Sopenharmony_ci	      res = 0;
5358141cc406Sopenharmony_ci	      break;
5359141cc406Sopenharmony_ci	    }
5360141cc406Sopenharmony_ci	}
5361141cc406Sopenharmony_ci      if (res == 1)
5362141cc406Sopenharmony_ci	{
5363141cc406Sopenharmony_ci	  registerWrite (0x1A, 0x00);
5364141cc406Sopenharmony_ci	  registerWrite (0x1A, 0x0C);
5365141cc406Sopenharmony_ci	}
5366141cc406Sopenharmony_ci    }
5367141cc406Sopenharmony_ci
5368141cc406Sopenharmony_ci  /* send 0x07 */
5369141cc406Sopenharmony_ci  registerWrite (0x1A, 0x07);
5370141cc406Sopenharmony_ci  res = 1;
5371141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
5372141cc406Sopenharmony_ci    {
5373141cc406Sopenharmony_ci      reg = registerRead (0x19) & 0xF8;
5374141cc406Sopenharmony_ci      if ((reg & 0x78) == 0x38)
5375141cc406Sopenharmony_ci	{
5376141cc406Sopenharmony_ci	  res = 0;
5377141cc406Sopenharmony_ci	  break;
5378141cc406Sopenharmony_ci	}
5379141cc406Sopenharmony_ci    }
5380141cc406Sopenharmony_ci  if (res != 0)
5381141cc406Sopenharmony_ci    return 0;
5382141cc406Sopenharmony_ci
5383141cc406Sopenharmony_ci  /* send 0x04 */
5384141cc406Sopenharmony_ci  registerWrite (0x1A, 0x04);
5385141cc406Sopenharmony_ci  res = 1;
5386141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
5387141cc406Sopenharmony_ci    {
5388141cc406Sopenharmony_ci      reg = registerRead (0x19) & 0xF8;
5389141cc406Sopenharmony_ci      if ((reg & 0xF8) == 0xF8)
5390141cc406Sopenharmony_ci	{
5391141cc406Sopenharmony_ci	  res = 0;
5392141cc406Sopenharmony_ci	  break;
5393141cc406Sopenharmony_ci	}
5394141cc406Sopenharmony_ci    }
5395141cc406Sopenharmony_ci  if (res != 0)
5396141cc406Sopenharmony_ci    return 0;
5397141cc406Sopenharmony_ci
5398141cc406Sopenharmony_ci  /* send 0x05 */
5399141cc406Sopenharmony_ci  registerWrite (0x1A, 0x05);
5400141cc406Sopenharmony_ci  res = 1;
5401141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
5402141cc406Sopenharmony_ci    {
5403141cc406Sopenharmony_ci      reg = registerRead (0x1A);
5404141cc406Sopenharmony_ci      if (reg == 0x05)
5405141cc406Sopenharmony_ci	{
5406141cc406Sopenharmony_ci	  res = 0;
5407141cc406Sopenharmony_ci	  break;
5408141cc406Sopenharmony_ci	}
5409141cc406Sopenharmony_ci    }
5410141cc406Sopenharmony_ci  if (res != 0)
5411141cc406Sopenharmony_ci    return 0;
5412141cc406Sopenharmony_ci
5413141cc406Sopenharmony_ci  /* end */
5414141cc406Sopenharmony_ci  registerWrite (0x1A, 0x84);
5415141cc406Sopenharmony_ci  return 1;
5416141cc406Sopenharmony_ci}
5417141cc406Sopenharmony_ci
5418141cc406Sopenharmony_ci
5419141cc406Sopenharmony_ci
5420141cc406Sopenharmony_ci
5421141cc406Sopenharmony_ci
5422141cc406Sopenharmony_ci
5423141cc406Sopenharmony_ci
5424141cc406Sopenharmony_ci/* 1 OK, 0 failed */
5425141cc406Sopenharmony_cistatic int
5426141cc406Sopenharmony_cifoncSendWord (int *cmd)
5427141cc406Sopenharmony_ci{
5428141cc406Sopenharmony_ci  prologue (0x10);
5429141cc406Sopenharmony_ci  if (sendWord (cmd) == 0)
5430141cc406Sopenharmony_ci    {
5431141cc406Sopenharmony_ci      DBG (0, "sendWord(cmd) failed (%s:%d)\n", __FILE__, __LINE__);
5432141cc406Sopenharmony_ci      return 0;
5433141cc406Sopenharmony_ci    }
5434141cc406Sopenharmony_ci  epilogue ();
5435141cc406Sopenharmony_ci
5436141cc406Sopenharmony_ci  return 1;
5437141cc406Sopenharmony_ci}
5438141cc406Sopenharmony_ci
5439141cc406Sopenharmony_ci
5440141cc406Sopenharmony_cistatic int
5441141cc406Sopenharmony_cicmdSetDataBuffer (int *data)
5442141cc406Sopenharmony_ci{
5443141cc406Sopenharmony_ci  int cmd1[] = { 0x00, 0x00, 0x22, 0x88, -1 };	/* 34 bytes write on channel 8 */
5444141cc406Sopenharmony_ci  int cmd2[] =
5445141cc406Sopenharmony_ci    { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80,
5446141cc406Sopenharmony_ci    0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
5447141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -1
5448141cc406Sopenharmony_ci  };
5449141cc406Sopenharmony_ci  int cmd3[] = { 0x00, 0x08, 0x00, 0x84, -1 };	/* 2048 bytes size write on channel 4 (data) */
5450141cc406Sopenharmony_ci  int cmd4[] = { 0x00, 0x08, 0x00, 0xC4, -1 };	/* 2048 bytes size read on channel 4 (data) */
5451141cc406Sopenharmony_ci  int i;
5452141cc406Sopenharmony_ci  unsigned char dest[2048];
5453141cc406Sopenharmony_ci
5454141cc406Sopenharmony_ci  /* cmdSet(8,34,cmd2), but without prologue/epilogue */
5455141cc406Sopenharmony_ci  /* set block length to 34 bytes on 'channel 8' */
5456141cc406Sopenharmony_ci  sendWord (cmd1);
5457141cc406Sopenharmony_ci  DBG (16, "sendWord(cmd1) passed (%s:%d) \n", __FILE__, __LINE__);
5458141cc406Sopenharmony_ci
5459141cc406Sopenharmony_ci  /* sendData */
5460141cc406Sopenharmony_ci  sendData (cmd2, 0x22);
5461141cc406Sopenharmony_ci  DBG (16, "sendData(cmd2) passed (%s:%d) \n", __FILE__, __LINE__);
5462141cc406Sopenharmony_ci
5463141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
5464141cc406Sopenharmony_ci    {
5465141cc406Sopenharmony_ci      bloc8Decode (cmd2);
5466141cc406Sopenharmony_ci    }
5467141cc406Sopenharmony_ci
5468141cc406Sopenharmony_ci  /* set block length to 2048, write on 'channel 4' */
5469141cc406Sopenharmony_ci  sendWord (cmd3);
5470141cc406Sopenharmony_ci  DBG (16, "sendWord(cmd3) passed (%s:%d) \n", __FILE__, __LINE__);
5471141cc406Sopenharmony_ci
5472141cc406Sopenharmony_ci  if (sendData (data, 2048) == 0)
5473141cc406Sopenharmony_ci    {
5474141cc406Sopenharmony_ci      DBG (0, "sendData(data,%d) failed (%s:%d)\n", 2048, __FILE__, __LINE__);
5475141cc406Sopenharmony_ci      return 0;
5476141cc406Sopenharmony_ci    }
5477141cc406Sopenharmony_ci  TRACE (16, "sendData(data,2048) passed ...");
5478141cc406Sopenharmony_ci
5479141cc406Sopenharmony_ci  /* read back all data sent to 'channel 4' */
5480141cc406Sopenharmony_ci  sendWord (cmd4);
5481141cc406Sopenharmony_ci  DBG (16, "sendWord(cmd4) passed (%s:%d) \n", __FILE__, __LINE__);
5482141cc406Sopenharmony_ci
5483141cc406Sopenharmony_ci  if (pausedReadData (2048, dest) == 0)
5484141cc406Sopenharmony_ci    {
5485141cc406Sopenharmony_ci      DBG (16, "pausedReadData(2048,dest) failed (%s:%d)\n", __FILE__,
5486141cc406Sopenharmony_ci	   __LINE__);
5487141cc406Sopenharmony_ci      return 0;
5488141cc406Sopenharmony_ci    }
5489141cc406Sopenharmony_ci  DBG (16, "pausedReadData(2048,dest) passed (%s:%d)\n", __FILE__, __LINE__);
5490141cc406Sopenharmony_ci
5491141cc406Sopenharmony_ci  /* dest should hold the same data than donnees */
5492141cc406Sopenharmony_ci  for (i = 0; i < 2047; i++)
5493141cc406Sopenharmony_ci    {
5494141cc406Sopenharmony_ci      if (data[i] != (int) (dest[i]))
5495141cc406Sopenharmony_ci	{
5496141cc406Sopenharmony_ci	  DBG
5497141cc406Sopenharmony_ci	    (0,
5498141cc406Sopenharmony_ci	     "Warning data read back differs: expected %02X found dest[%d]=%02X ! (%s:%d)\n",
5499141cc406Sopenharmony_ci	     data[i], i, dest[i], __FILE__, __LINE__);
5500141cc406Sopenharmony_ci	}
5501141cc406Sopenharmony_ci    }
5502141cc406Sopenharmony_ci  return 1;
5503141cc406Sopenharmony_ci}
5504141cc406Sopenharmony_ci
5505141cc406Sopenharmony_ci
5506141cc406Sopenharmony_ci/* 1: OK
5507141cc406Sopenharmony_ci   0: end session failed */
5508141cc406Sopenharmony_ci
5509141cc406Sopenharmony_ciint
5510141cc406Sopenharmony_cisanei_umax_pp_endSession (void)
5511141cc406Sopenharmony_ci{
5512141cc406Sopenharmony_ci  int zero[5] = { 0, 0, 0, 0, -1 };
5513141cc406Sopenharmony_ci
5514141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () != 610)
5515141cc406Sopenharmony_ci    {
5516141cc406Sopenharmony_ci      prologue (0x00);
5517141cc406Sopenharmony_ci      sendWord (zero);
5518141cc406Sopenharmony_ci      epilogue ();
5519141cc406Sopenharmony_ci      sanei_umax_pp_cmdSync (0xC2);
5520141cc406Sopenharmony_ci      sanei_umax_pp_cmdSync (0x00);	/* cancels any pending operation */
5521141cc406Sopenharmony_ci      sanei_umax_pp_cmdSync (0x00);	/* cancels any pending operation */
5522141cc406Sopenharmony_ci    }
5523141cc406Sopenharmony_ci  else
5524141cc406Sopenharmony_ci    {
5525141cc406Sopenharmony_ci      CMDSYNC (0x00);
5526141cc406Sopenharmony_ci      CMDSYNC (0xC2);
5527141cc406Sopenharmony_ci      CMDSYNC (0x00);
5528141cc406Sopenharmony_ci      CMDSYNC (0x00);
5529141cc406Sopenharmony_ci    }
5530141cc406Sopenharmony_ci  compatMode ();
5531141cc406Sopenharmony_ci
5532141cc406Sopenharmony_ci  /* restore port state */
5533141cc406Sopenharmony_ci  Outb (DATA, gData);
5534141cc406Sopenharmony_ci  Outb (CONTROL, gControl);
5535141cc406Sopenharmony_ci
5536141cc406Sopenharmony_ci  /* OUF */
5537141cc406Sopenharmony_ci  DBG (1, "End session done ...\n");
5538141cc406Sopenharmony_ci  return 1;
5539141cc406Sopenharmony_ci}
5540141cc406Sopenharmony_ci
5541141cc406Sopenharmony_ci
5542141cc406Sopenharmony_ci/* initialize scanner with default values
5543141cc406Sopenharmony_ci * and do head re-homing if needed */
5544141cc406Sopenharmony_ciint
5545141cc406Sopenharmony_ciinitScanner610p (int recover)
5546141cc406Sopenharmony_ci{
5547141cc406Sopenharmony_ci  int first, rc, x;
5548141cc406Sopenharmony_ci  int cmd55AA[9] = { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, -1 };
5549141cc406Sopenharmony_ci  int cmd02[17] = { 0x02, 0x80, 0x00, 0x40, 0x30, 0x00, 0xC0, 0x2F,
5550141cc406Sopenharmony_ci    0x2F, 0x07, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x00, -1
5551141cc406Sopenharmony_ci  };
5552141cc406Sopenharmony_ci  int op01[17] =
5553141cc406Sopenharmony_ci    { 0x01, 0x00, 0x32, 0x70, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00,
5554141cc406Sopenharmony_ci    0x00, 0x80, 0xA4, 0x00, -1
5555141cc406Sopenharmony_ci  };
5556141cc406Sopenharmony_ci  int op11[17] =
5557141cc406Sopenharmony_ci    { 0x01, 0x80, 0x0C, 0x70, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x01, 0x00, 0x00,
5558141cc406Sopenharmony_ci    0x00, 0x80, 0xA4, 0x00, -1
5559141cc406Sopenharmony_ci  };
5560141cc406Sopenharmony_ci  int op21[17] =
5561141cc406Sopenharmony_ci    { 0x01, 0x00, 0x01, 0x40, 0x30, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00,
5562141cc406Sopenharmony_ci    0x00, 0x80, 0xF4, 0x00, -1
5563141cc406Sopenharmony_ci  };
5564141cc406Sopenharmony_ci  int op31[17] =
5565141cc406Sopenharmony_ci    { 0x01, 0x00, 0x39, 0x73, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00,
5566141cc406Sopenharmony_ci    0x00, 0x80, 0xB4, 0x00, -1
5567141cc406Sopenharmony_ci  };
5568141cc406Sopenharmony_ci
5569141cc406Sopenharmony_ci  int op02[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
5570141cc406Sopenharmony_ci    0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00,
5571141cc406Sopenharmony_ci    0x76, 0x00, 0x75, 0xEF, 0x06, 0x00, 0x00, 0xF6,
5572141cc406Sopenharmony_ci    0x4D, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
5573141cc406Sopenharmony_ci    0xDF, 0x1B, -1
5574141cc406Sopenharmony_ci  };
5575141cc406Sopenharmony_ci  int op22[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
5576141cc406Sopenharmony_ci    0x00, 0x03, 0xC1, 0x80, 0x00, 0x20, 0x02, 0x00,
5577141cc406Sopenharmony_ci    0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00,
5578141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
5579141cc406Sopenharmony_ci    0xDF, 0x1B, -1
5580141cc406Sopenharmony_ci  };
5581141cc406Sopenharmony_ci
5582141cc406Sopenharmony_ci  int op03[9] = { 0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0xFF, 0xFF, -1 };
5583141cc406Sopenharmony_ci  struct timeval tv;
5584141cc406Sopenharmony_ci
5585141cc406Sopenharmony_ci  byteMode ();			/* just to get sure */
5586141cc406Sopenharmony_ci  first = 0;
5587141cc406Sopenharmony_ci  rc = inquire ();
5588141cc406Sopenharmony_ci
5589141cc406Sopenharmony_ci  /* get time to handle settle time delay */
5590141cc406Sopenharmony_ci  gettimeofday (&tv, NULL);
5591141cc406Sopenharmony_ci  gTime = tv.tv_sec;
5592141cc406Sopenharmony_ci  /* default delay */
5593141cc406Sopenharmony_ci  gDelay = 5;
5594141cc406Sopenharmony_ci
5595141cc406Sopenharmony_ci  if (rc == 0)
5596141cc406Sopenharmony_ci    {
5597141cc406Sopenharmony_ci      DBG (0, "inquire() failed ! (%s:%d) \n", __FILE__, __LINE__);
5598141cc406Sopenharmony_ci      return 0;
5599141cc406Sopenharmony_ci    }
5600141cc406Sopenharmony_ci  if (rc == 2)
5601141cc406Sopenharmony_ci    {
5602141cc406Sopenharmony_ci      /* same value used by windows driver */
5603141cc406Sopenharmony_ci      gDelay = 45;
5604141cc406Sopenharmony_ci      DBG (1, "inquire() signals re-homing needed ... (%s:%d) \n",
5605141cc406Sopenharmony_ci	   __FILE__, __LINE__);
5606141cc406Sopenharmony_ci      first = 1;
5607141cc406Sopenharmony_ci    }
5608141cc406Sopenharmony_ci  DBG (1, "inquire() passed ... (%s:%d) \n", __FILE__, __LINE__);
5609141cc406Sopenharmony_ci
5610141cc406Sopenharmony_ci  rc = loadDefaultTables ();
5611141cc406Sopenharmony_ci  if (rc == 0)
5612141cc406Sopenharmony_ci    {
5613141cc406Sopenharmony_ci      DBG (0, "loadDefaultTables() failed ! (%s:%d) \n", __FILE__, __LINE__);
5614141cc406Sopenharmony_ci      return 0;
5615141cc406Sopenharmony_ci    }
5616141cc406Sopenharmony_ci  DBG (1, "loadDefaultTables() passed ... (%s:%d) \n", __FILE__, __LINE__);
5617141cc406Sopenharmony_ci  if (recover)
5618141cc406Sopenharmony_ci    first = 1;
5619141cc406Sopenharmony_ci
5620141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, cmd02);
5621141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, cmd55AA);
5622141cc406Sopenharmony_ci
5623141cc406Sopenharmony_ci  if (!first)
5624141cc406Sopenharmony_ci    {
5625141cc406Sopenharmony_ci      CMDSYNC (0x00);
5626141cc406Sopenharmony_ci      CMDSYNC (0xC2);
5627141cc406Sopenharmony_ci      CMDSYNC (0x00);
5628141cc406Sopenharmony_ci      DBG (1, "initScanner610p done ...\n");
5629141cc406Sopenharmony_ci      return 1;
5630141cc406Sopenharmony_ci    }
5631141cc406Sopenharmony_ci
5632141cc406Sopenharmony_ci  /* here we do re-homing
5633141cc406Sopenharmony_ci   * since it is first probe or recover */
5634141cc406Sopenharmony_ci  /* move forward */
5635141cc406Sopenharmony_ci  CMDSYNC (0xC2);
5636141cc406Sopenharmony_ci  if (!recover)
5637141cc406Sopenharmony_ci    {
5638141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, op01);
5639141cc406Sopenharmony_ci      CMDSETGET (8, 0x22, op02);
5640141cc406Sopenharmony_ci      CMDSYNC (0xC2);
5641141cc406Sopenharmony_ci      CMDSYNC (0x00);
5642141cc406Sopenharmony_ci      CMDSETGET (4, 0x08, op03);
5643141cc406Sopenharmony_ci      CMDSYNC (0x40);
5644141cc406Sopenharmony_ci      CMDSYNC (0xC2);
5645141cc406Sopenharmony_ci      sleep (2);
5646141cc406Sopenharmony_ci    }
5647141cc406Sopenharmony_ci
5648141cc406Sopenharmony_ci  /* move backward */
5649141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, op11);
5650141cc406Sopenharmony_ci  CMDSETGET (8, 0x22, op02);
5651141cc406Sopenharmony_ci  CMDSYNC (0xC2);
5652141cc406Sopenharmony_ci  CMDSYNC (0x00);
5653141cc406Sopenharmony_ci  CMDSYNC (0x00);
5654141cc406Sopenharmony_ci  CMDSETGET (4, 0x08, op03);
5655141cc406Sopenharmony_ci  CMDSYNC (0x40);
5656141cc406Sopenharmony_ci  CMDSYNC (0xC2);
5657141cc406Sopenharmony_ci  sleep (2);
5658141cc406Sopenharmony_ci
5659141cc406Sopenharmony_ci  /* means 'CONTINUE MOVE' */
5660141cc406Sopenharmony_ci  CMDSYNC (0x00);
5661141cc406Sopenharmony_ci  while ((scannerStatus & MOTOR_BIT) == 0)
5662141cc406Sopenharmony_ci    {
5663141cc406Sopenharmony_ci      CMDSYNC (0xC2);
5664141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, op21);
5665141cc406Sopenharmony_ci      CMDSETGET (8, 0x22, op22);
5666141cc406Sopenharmony_ci      CMDSYNC (0x40);
5667141cc406Sopenharmony_ci      usleep (20000);
5668141cc406Sopenharmony_ci    }
5669141cc406Sopenharmony_ci  CMDSYNC (0xC2);
5670141cc406Sopenharmony_ci  CMDSYNC (0x00);
5671141cc406Sopenharmony_ci
5672141cc406Sopenharmony_ci  /* send head away */
5673141cc406Sopenharmony_ci  if (!recover)
5674141cc406Sopenharmony_ci    {
5675141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, op31);
5676141cc406Sopenharmony_ci      CMDSETGET (8, 0x22, op02);
5677141cc406Sopenharmony_ci      if (DBG_LEVEL > 8)
5678141cc406Sopenharmony_ci	{
5679141cc406Sopenharmony_ci	  bloc2Decode (op31);
5680141cc406Sopenharmony_ci	  bloc8Decode (op02);
5681141cc406Sopenharmony_ci	}
5682141cc406Sopenharmony_ci      CMDSYNC (0xC2);
5683141cc406Sopenharmony_ci      CMDSYNC (0x00);
5684141cc406Sopenharmony_ci      CMDSETGET (4, 0x08, op03);
5685141cc406Sopenharmony_ci      CMDSYNC (0x40);
5686141cc406Sopenharmony_ci      CMDSYNC (0xC2);
5687141cc406Sopenharmony_ci      sleep (9);
5688141cc406Sopenharmony_ci    }
5689141cc406Sopenharmony_ci
5690141cc406Sopenharmony_ci  CMDSYNC (0x00);
5691141cc406Sopenharmony_ci
5692141cc406Sopenharmony_ci  /* this code has been added, without corresponding logs/
5693141cc406Sopenharmony_ci   * it seem I just can't found 'real' parking command ...
5694141cc406Sopenharmony_ci   */
5695141cc406Sopenharmony_ci  /* send park command */
5696141cc406Sopenharmony_ci  if (sanei_umax_pp_park () == 0)
5697141cc406Sopenharmony_ci    {
5698141cc406Sopenharmony_ci      TRACE (0, "sanei_umax_pp_park failed! ");
5699141cc406Sopenharmony_ci      return 0;
5700141cc406Sopenharmony_ci    }
5701141cc406Sopenharmony_ci  /* and wait it to succeed */
5702141cc406Sopenharmony_ci  if (sanei_umax_pp_parkWait () == 0)
5703141cc406Sopenharmony_ci    {
5704141cc406Sopenharmony_ci      TRACE (0, "sanei_umax_pp_parkWait failed! ");
5705141cc406Sopenharmony_ci      return 0;
5706141cc406Sopenharmony_ci    }
5707141cc406Sopenharmony_ci
5708141cc406Sopenharmony_ci  /* override gamma table with 610P defaults */
5709141cc406Sopenharmony_ci  for (x = 0; x < 256; x++)
5710141cc406Sopenharmony_ci    {
5711141cc406Sopenharmony_ci      ggRed[x] = x;
5712141cc406Sopenharmony_ci      ggGreen[x] = x;
5713141cc406Sopenharmony_ci      ggBlue[x] = x;
5714141cc406Sopenharmony_ci    }
5715141cc406Sopenharmony_ci
5716141cc406Sopenharmony_ci  DBG (1, "initScanner610p done ...\n");
5717141cc406Sopenharmony_ci  return 1;
5718141cc406Sopenharmony_ci}
5719141cc406Sopenharmony_ci
5720141cc406Sopenharmony_ci/* 1: OK
5721141cc406Sopenharmony_ci   2: homing happened
5722141cc406Sopenharmony_ci   3: scanner busy
5723141cc406Sopenharmony_ci   0: init failed
5724141cc406Sopenharmony_ci
5725141cc406Sopenharmony_ci   init transport layer
5726141cc406Sopenharmony_ci   init scanner
5727141cc406Sopenharmony_ci*/
5728141cc406Sopenharmony_ci
5729141cc406Sopenharmony_ciint
5730141cc406Sopenharmony_cisanei_umax_pp_initScanner (int recover)
5731141cc406Sopenharmony_ci{
5732141cc406Sopenharmony_ci  int i;
5733141cc406Sopenharmony_ci  int status;
5734141cc406Sopenharmony_ci  int readcmd[64];
5735141cc406Sopenharmony_ci  /* in umax1220u, this buffer is opc[16] */
5736141cc406Sopenharmony_ci  int sentcmd[17] =
5737141cc406Sopenharmony_ci    { 0x02, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00, 0x2F, 0x2F, 0x07, 0x00,
5738141cc406Sopenharmony_ci    0x00, 0x00, 0x80, 0xF0, 0x00, -1
5739141cc406Sopenharmony_ci  };
5740141cc406Sopenharmony_ci  int cmdA7[9] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, -1 };
5741141cc406Sopenharmony_ci
5742141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
5743141cc406Sopenharmony_ci    return initScanner610p (recover);
5744141cc406Sopenharmony_ci
5745141cc406Sopenharmony_ci  if (getModel () == 0x07)
5746141cc406Sopenharmony_ci    sentcmd[15] = 0x00;
5747141cc406Sopenharmony_ci  else
5748141cc406Sopenharmony_ci    sentcmd[15] = 0x18;
5749141cc406Sopenharmony_ci
5750141cc406Sopenharmony_ci  /* fails here if there is an unfinished previous scan */
5751141cc406Sopenharmony_ci  CMDSETGET (0x02, 16, sentcmd);
5752141cc406Sopenharmony_ci
5753141cc406Sopenharmony_ci  /* needs some init */
5754141cc406Sopenharmony_ci  if (sentcmd[15] == 0x18)
5755141cc406Sopenharmony_ci    {
5756141cc406Sopenharmony_ci      sentcmd[15] = 0x00;	/* was 0x18 */
5757141cc406Sopenharmony_ci      CMDSETGET (0x02, 16, sentcmd);
5758141cc406Sopenharmony_ci
5759141cc406Sopenharmony_ci      /* in umax1220u, this buffer does not exist */
5760141cc406Sopenharmony_ci      CMDSETGET (0x01, 8, cmdA7);
5761141cc406Sopenharmony_ci    }
5762141cc406Sopenharmony_ci
5763141cc406Sopenharmony_ci
5764141cc406Sopenharmony_ci  /* ~ opb3: inquire status */
5765141cc406Sopenharmony_ci  CMDGET (0x08, 36, readcmd);
5766141cc406Sopenharmony_ci  if (DBG_LEVEL >= 32)
5767141cc406Sopenharmony_ci    {
5768141cc406Sopenharmony_ci      bloc8Decode (readcmd);
5769141cc406Sopenharmony_ci    }
5770141cc406Sopenharmony_ci  DBG (16, "cmdGet(0x08,36,readcmd) passed (%s:%d)\n", __FILE__, __LINE__);
5771141cc406Sopenharmony_ci
5772141cc406Sopenharmony_ci  /* is the scanner busy parking ? */
5773141cc406Sopenharmony_ci  status = sanei_umax_pp_scannerStatus ();
5774141cc406Sopenharmony_ci  DBG (8, "INQUIRE SCANNER STATUS IS 0x%02X  (%s:%d)\n", status, __FILE__,
5775141cc406Sopenharmony_ci       __LINE__);
5776141cc406Sopenharmony_ci  if ((!recover) && (status & MOTOR_BIT) == 0x00)
5777141cc406Sopenharmony_ci    {
5778141cc406Sopenharmony_ci      DBG (1, "Warning: scanner motor on, giving up ...  (%s:%d)\n", __FILE__,
5779141cc406Sopenharmony_ci	   __LINE__);
5780141cc406Sopenharmony_ci      return 3;
5781141cc406Sopenharmony_ci    }
5782141cc406Sopenharmony_ci
5783141cc406Sopenharmony_ci  /* head homing needed ? */
5784141cc406Sopenharmony_ci  if ((readcmd[34] != 0x1A) || (recover == 1))
5785141cc406Sopenharmony_ci    {				/* homing needed, readcmd[34] should be 0x48 */
5786141cc406Sopenharmony_ci      int op01[17] =
5787141cc406Sopenharmony_ci	{ 0x01, 0x00, 0x32, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x17, 0x05, 0x00,
5788141cc406Sopenharmony_ci	0x00, 0x00, 0x80, 0xE4, 0x00, -1
5789141cc406Sopenharmony_ci      };
5790141cc406Sopenharmony_ci      int op05[17] =
5791141cc406Sopenharmony_ci	{ 0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x13, 0x05, 0x00,
5792141cc406Sopenharmony_ci	0x00, 0x00, 0x80, 0xF0, 0x00, -1
5793141cc406Sopenharmony_ci      };
5794141cc406Sopenharmony_ci      int op02[37] =
5795141cc406Sopenharmony_ci	{ 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40,
5796141cc406Sopenharmony_ci	0x01, 0x00, 0x20, 0x02, 0x00, 0x16, 0x00, 0x70, 0x9F, 0x06, 0x00,
5797141cc406Sopenharmony_ci	0x00, 0xF6, 0x4D, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF,
5798141cc406Sopenharmony_ci	0x0B, 0x1A, 0x00, -1
5799141cc406Sopenharmony_ci      };
5800141cc406Sopenharmony_ci      int op04[37] =
5801141cc406Sopenharmony_ci	{ 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1,
5802141cc406Sopenharmony_ci	0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03,
5803141cc406Sopenharmony_ci	0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF,
5804141cc406Sopenharmony_ci	0x0B, 0x1A, 0x00, -1
5805141cc406Sopenharmony_ci      };
5806141cc406Sopenharmony_ci      int op03[9] = { 0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0xFF, 0xFF, -1 };
5807141cc406Sopenharmony_ci
5808141cc406Sopenharmony_ci      CMDSYNC (0xC2);
5809141cc406Sopenharmony_ci      CMDSETGET (0x02, 16, op01);
5810141cc406Sopenharmony_ci      CMDSETGET (0x08, 36, op02);
5811141cc406Sopenharmony_ci
5812141cc406Sopenharmony_ci      if (!recover)
5813141cc406Sopenharmony_ci	{
5814141cc406Sopenharmony_ci	  CMDSYNC (0xC2);
5815141cc406Sopenharmony_ci	  CMDSYNC (0x00);
5816141cc406Sopenharmony_ci	  CMDSETGET (0x04, 8, op03);
5817141cc406Sopenharmony_ci	  CMDSYNC (0x40);
5818141cc406Sopenharmony_ci	  do
5819141cc406Sopenharmony_ci	    {
5820141cc406Sopenharmony_ci	      sleep (1);
5821141cc406Sopenharmony_ci	      CMDSYNC (0xC2);
5822141cc406Sopenharmony_ci	    }
5823141cc406Sopenharmony_ci	  while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90);
5824141cc406Sopenharmony_ci
5825141cc406Sopenharmony_ci	  op01[2] = 0x1E;
5826141cc406Sopenharmony_ci	  op01[9] = 0x01;
5827141cc406Sopenharmony_ci	  CMDSETGET (0x02, 16, op01);
5828141cc406Sopenharmony_ci	  CMDSETGET (0x08, 36, op02);
5829141cc406Sopenharmony_ci	  CMDSYNC (0x00);
5830141cc406Sopenharmony_ci	  CMDSYNC (0x00);
5831141cc406Sopenharmony_ci	  CMDSETGET (0x04, 8, op03);
5832141cc406Sopenharmony_ci
5833141cc406Sopenharmony_ci	  CMDSYNC (0x40);
5834141cc406Sopenharmony_ci	  do
5835141cc406Sopenharmony_ci	    {
5836141cc406Sopenharmony_ci	      sleep (1);
5837141cc406Sopenharmony_ci	      CMDSYNC (0xC2);
5838141cc406Sopenharmony_ci	    }
5839141cc406Sopenharmony_ci	  while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90);
5840141cc406Sopenharmony_ci	  CMDSYNC (0x00);
5841141cc406Sopenharmony_ci	}
5842141cc406Sopenharmony_ci
5843141cc406Sopenharmony_ci      for (i = 0; i < 4; i++)
5844141cc406Sopenharmony_ci	{
5845141cc406Sopenharmony_ci
5846141cc406Sopenharmony_ci	  do
5847141cc406Sopenharmony_ci	    {
5848141cc406Sopenharmony_ci	      usleep (500000);
5849141cc406Sopenharmony_ci	      CMDSYNC (0xC2);
5850141cc406Sopenharmony_ci	      status = sanei_umax_pp_scannerStatus ();
5851141cc406Sopenharmony_ci	      status = status & 0x10;
5852141cc406Sopenharmony_ci	    }
5853141cc406Sopenharmony_ci	  while (status != 0x10);	/* was 0x90 */
5854141cc406Sopenharmony_ci	  CMDSETGET (0x02, 16, op05);
5855141cc406Sopenharmony_ci	  CMDSETGET (0x08, 36, op04);
5856141cc406Sopenharmony_ci	  CMDSYNC (0x40);
5857141cc406Sopenharmony_ci	  status = sanei_umax_pp_scannerStatus ();
5858141cc406Sopenharmony_ci	  DBG (16, "loop %d passed, status=0x%02X (%s:%d)\n", i, status,
5859141cc406Sopenharmony_ci	       __FILE__, __LINE__);
5860141cc406Sopenharmony_ci	}
5861141cc406Sopenharmony_ci
5862141cc406Sopenharmony_ci
5863141cc406Sopenharmony_ci
5864141cc406Sopenharmony_ci      /* get head back home ... */
5865141cc406Sopenharmony_ci      do
5866141cc406Sopenharmony_ci	{
5867141cc406Sopenharmony_ci	  i++;
5868141cc406Sopenharmony_ci	  do
5869141cc406Sopenharmony_ci	    {
5870141cc406Sopenharmony_ci	      usleep (500000);
5871141cc406Sopenharmony_ci	      CMDSYNC (0xC2);
5872141cc406Sopenharmony_ci	      status = sanei_umax_pp_scannerStatus ();
5873141cc406Sopenharmony_ci	      status = status & 0x10;
5874141cc406Sopenharmony_ci	    }
5875141cc406Sopenharmony_ci	  while (status != 0x10);	/* was 0x90 */
5876141cc406Sopenharmony_ci	  CMDSETGET (0x02, 16, op05);
5877141cc406Sopenharmony_ci	  CMDSETGET (0x08, 36, op04);
5878141cc406Sopenharmony_ci	  CMDSYNC (0x40);
5879141cc406Sopenharmony_ci	  status = sanei_umax_pp_scannerStatus ();
5880141cc406Sopenharmony_ci	  DBG (16, "loop %d passed, status=0x%02X (%s:%d)\n", i, status,
5881141cc406Sopenharmony_ci	       __FILE__, __LINE__);
5882141cc406Sopenharmony_ci	}
5883141cc406Sopenharmony_ci      while ((status & MOTOR_BIT) == 0x00);	/* 0xD0 when head is back home */
5884141cc406Sopenharmony_ci
5885141cc406Sopenharmony_ci      do
5886141cc406Sopenharmony_ci	{
5887141cc406Sopenharmony_ci	  usleep (500000);
5888141cc406Sopenharmony_ci	  CMDSYNC (0xC2);
5889141cc406Sopenharmony_ci	}
5890141cc406Sopenharmony_ci      while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90);
5891141cc406Sopenharmony_ci
5892141cc406Sopenharmony_ci
5893141cc406Sopenharmony_ci      /* don't do automatic home sequence on recovery */
5894141cc406Sopenharmony_ci      if (!recover)
5895141cc406Sopenharmony_ci	{
5896141cc406Sopenharmony_ci	  CMDSYNC (0x00);
5897141cc406Sopenharmony_ci	  op01[2] = 0x1A;
5898141cc406Sopenharmony_ci	  op01[3] = 0x74;	/* was 0x70 */
5899141cc406Sopenharmony_ci	  op01[9] = 0x05;	/* initial value */
5900141cc406Sopenharmony_ci	  op01[14] = 0xF4;	/* was 0xE4 */
5901141cc406Sopenharmony_ci	  CMDSETGET (0x02, 16, op01);
5902141cc406Sopenharmony_ci	  CMDSETGET (0x08, 36, op02);
5903141cc406Sopenharmony_ci	  CMDSYNC (0xC2);
5904141cc406Sopenharmony_ci	  CMDSYNC (0x00);
5905141cc406Sopenharmony_ci	  CMDSETGET (0x04, 8, op03);
5906141cc406Sopenharmony_ci	  CMDSYNC (0x40);
5907141cc406Sopenharmony_ci
5908141cc406Sopenharmony_ci	  /* wait for automatic homing sequence */
5909141cc406Sopenharmony_ci	  /* to complete, thus avoiding         */
5910141cc406Sopenharmony_ci	  /* scanning too early                 */
5911141cc406Sopenharmony_ci	  do
5912141cc406Sopenharmony_ci	    {
5913141cc406Sopenharmony_ci	      /* the sleep is here to prevent */
5914141cc406Sopenharmony_ci	      /* excessive CPU usage, can be  */
5915141cc406Sopenharmony_ci	      /* removed, if we don't care    */
5916141cc406Sopenharmony_ci	      sleep (3);
5917141cc406Sopenharmony_ci	      CMDSYNC (0xC2);
5918141cc406Sopenharmony_ci	      DBG (16, "PARKING polling status is 0x%02X   (%s:%d)\n",
5919141cc406Sopenharmony_ci		   sanei_umax_pp_scannerStatus (), __FILE__, __LINE__);
5920141cc406Sopenharmony_ci	    }
5921141cc406Sopenharmony_ci	  while (sanei_umax_pp_scannerStatus () == 0x90);
5922141cc406Sopenharmony_ci	}
5923141cc406Sopenharmony_ci
5924141cc406Sopenharmony_ci      /* signal homing */
5925141cc406Sopenharmony_ci      return 2;
5926141cc406Sopenharmony_ci    }
5927141cc406Sopenharmony_ci
5928141cc406Sopenharmony_ci
5929141cc406Sopenharmony_ci  /* end ... */
5930141cc406Sopenharmony_ci  DBG (1, "Scanner init done ...\n");
5931141cc406Sopenharmony_ci  return 1;
5932141cc406Sopenharmony_ci}
5933141cc406Sopenharmony_ci
5934141cc406Sopenharmony_ci
5935141cc406Sopenharmony_ci/*
5936141cc406Sopenharmony_ci        1: OK
5937141cc406Sopenharmony_ci           2: failed, try again
5938141cc406Sopenharmony_ci           0: init failed
5939141cc406Sopenharmony_ci
5940141cc406Sopenharmony_ci        initialize the transport layer
5941141cc406Sopenharmony_ci
5942141cc406Sopenharmony_ci   */
5943141cc406Sopenharmony_ci
5944141cc406Sopenharmony_cistatic int
5945141cc406Sopenharmony_ciinitTransport610p (void)
5946141cc406Sopenharmony_ci{
5947141cc406Sopenharmony_ci  int tmp, i;
5948141cc406Sopenharmony_ci  int zero[5] = { 0, 0, 0, 0, -1 };
5949141cc406Sopenharmony_ci
5950141cc406Sopenharmony_ci  /* test EPP availability */
5951141cc406Sopenharmony_ci  connect610p ();
5952141cc406Sopenharmony_ci  if (sync610p () == 0)
5953141cc406Sopenharmony_ci    {
5954141cc406Sopenharmony_ci      DBG (0,
5955141cc406Sopenharmony_ci	   "sync610p failed! Scanner not present or powered off ...  (%s:%d)\n",
5956141cc406Sopenharmony_ci	   __FILE__, __LINE__);
5957141cc406Sopenharmony_ci      return 0;
5958141cc406Sopenharmony_ci    }
5959141cc406Sopenharmony_ci  if (EPPsendWord610p (zero) == 0)
5960141cc406Sopenharmony_ci    {
5961141cc406Sopenharmony_ci      DBG (1, "No EPP mode detected\n");
5962141cc406Sopenharmony_ci      gMode = UMAX_PP_PARPORT_BYTE;
5963141cc406Sopenharmony_ci    }
5964141cc406Sopenharmony_ci  else
5965141cc406Sopenharmony_ci    {
5966141cc406Sopenharmony_ci      DBG (1, "EPP mode detected\n");
5967141cc406Sopenharmony_ci      gMode = UMAX_PP_PARPORT_EPP;
5968141cc406Sopenharmony_ci    }
5969141cc406Sopenharmony_ci  disconnect610p ();
5970141cc406Sopenharmony_ci
5971141cc406Sopenharmony_ci  /* set up to bidirectionnal */
5972141cc406Sopenharmony_ci  /* in fact we could add support for EPP */
5973141cc406Sopenharmony_ci  /* but let's make 610 work first */
5974141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_BYTE)
5975141cc406Sopenharmony_ci    {
5976141cc406Sopenharmony_ci      byteMode ();
5977141cc406Sopenharmony_ci
5978141cc406Sopenharmony_ci      /* reset after failure */
5979141cc406Sopenharmony_ci      /* set to data reverse */
5980141cc406Sopenharmony_ci      Outb (CONTROL, 0x2C);
5981141cc406Sopenharmony_ci      Inb (CONTROL);
5982141cc406Sopenharmony_ci      for (i = 0; i < 10; i++)
5983141cc406Sopenharmony_ci	Outb (DATA, 0xAA);
5984141cc406Sopenharmony_ci      tmp = Inb (DATA);
5985141cc406Sopenharmony_ci      tmp = Inb (DATA);
5986141cc406Sopenharmony_ci      if (tmp != 0xFF)
5987141cc406Sopenharmony_ci	{
5988141cc406Sopenharmony_ci	  DBG (1, "Found 0x%X expected 0xFF  (%s:%d)\n", tmp, __FILE__,
5989141cc406Sopenharmony_ci	       __LINE__);
5990141cc406Sopenharmony_ci	}
5991141cc406Sopenharmony_ci      for (i = 0; i < 4; i++)
5992141cc406Sopenharmony_ci	{
5993141cc406Sopenharmony_ci	  Outb (DATA, 0x00);
5994141cc406Sopenharmony_ci	  tmp = Inb (DATA);
5995141cc406Sopenharmony_ci	  if (tmp != 0xFF)
5996141cc406Sopenharmony_ci	    {
5997141cc406Sopenharmony_ci	      DBG (1, "Found 0x%X expected 0xFF  (%s:%d)\n", tmp, __FILE__,
5998141cc406Sopenharmony_ci		   __LINE__);
5999141cc406Sopenharmony_ci	      return 0;
6000141cc406Sopenharmony_ci	    }
6001141cc406Sopenharmony_ci	  Outb (DATA, 0xFF);
6002141cc406Sopenharmony_ci	  tmp = Inb (DATA);
6003141cc406Sopenharmony_ci	  if (tmp != 0xFF)
6004141cc406Sopenharmony_ci	    {
6005141cc406Sopenharmony_ci	      DBG (1, "Found 0x%X expected 0xFF  (%s:%d)\n", tmp, __FILE__,
6006141cc406Sopenharmony_ci		   __LINE__);
6007141cc406Sopenharmony_ci	      return 0;
6008141cc406Sopenharmony_ci	    }
6009141cc406Sopenharmony_ci	}
6010141cc406Sopenharmony_ci      TRACE (16, "RESET done... ");
6011141cc406Sopenharmony_ci      byteMode ();
6012141cc406Sopenharmony_ci
6013141cc406Sopenharmony_ci      if (SPPsendWord610p (zero) == 0)
6014141cc406Sopenharmony_ci	{
6015141cc406Sopenharmony_ci	  DBG (0, "SPPsendWord610p(zero) failed! (%s:%d)\n", __FILE__,
6016141cc406Sopenharmony_ci	       __LINE__);
6017141cc406Sopenharmony_ci	  return 0;
6018141cc406Sopenharmony_ci	}
6019141cc406Sopenharmony_ci      TRACE (16, "SPPsendWord610p(zero) passed... ");
6020141cc406Sopenharmony_ci    }
6021141cc406Sopenharmony_ci
6022141cc406Sopenharmony_ci  /* OK ! */
6023141cc406Sopenharmony_ci  TRACE (1, "initTransport610p done... ");
6024141cc406Sopenharmony_ci  return 1;
6025141cc406Sopenharmony_ci}
6026141cc406Sopenharmony_ci
6027141cc406Sopenharmony_ci/*
6028141cc406Sopenharmony_ci        1: OK
6029141cc406Sopenharmony_ci           2: failed, try again
6030141cc406Sopenharmony_ci           0: init failed
6031141cc406Sopenharmony_ci
6032141cc406Sopenharmony_ci        initialize the transport layer
6033141cc406Sopenharmony_ci
6034141cc406Sopenharmony_ci   */
6035141cc406Sopenharmony_ci
6036141cc406Sopenharmony_cistatic int
6037141cc406Sopenharmony_ciinitTransport1220P (int recover)	/* ECP OK !! */
6038141cc406Sopenharmony_ci{
6039141cc406Sopenharmony_ci  int i, j;
6040141cc406Sopenharmony_ci  int reg, tmp;
6041141cc406Sopenharmony_ci  unsigned char *dest = NULL;
6042141cc406Sopenharmony_ci  int zero[5] = { 0, 0, 0, 0, -1 };
6043141cc406Sopenharmony_ci  int model, nb;
6044141cc406Sopenharmony_ci
6045141cc406Sopenharmony_ci  connect ();
6046141cc406Sopenharmony_ci  DBG (16, "connect() passed... (%s:%d)\n", __FILE__, __LINE__);
6047141cc406Sopenharmony_ci  gEPAT = 0xC7;
6048141cc406Sopenharmony_ci  reg = registerRead (0x0B);
6049141cc406Sopenharmony_ci  if (reg != gEPAT)
6050141cc406Sopenharmony_ci    {
6051141cc406Sopenharmony_ci      DBG (16, "Error! expected reg0B=0x%02X, found 0x%02X! (%s:%d) \n",
6052141cc406Sopenharmony_ci	   gEPAT, reg, __FILE__, __LINE__);
6053141cc406Sopenharmony_ci      DBG (16, "Scanner needs probing ... \n");
6054141cc406Sopenharmony_ci      if (sanei_umax_pp_probeScanner (recover) != 1)
6055141cc406Sopenharmony_ci	{
6056141cc406Sopenharmony_ci	  return 0;
6057141cc406Sopenharmony_ci	}
6058141cc406Sopenharmony_ci      else
6059141cc406Sopenharmony_ci	{
6060141cc406Sopenharmony_ci	  return 2;		/* signals retry initTransport() */
6061141cc406Sopenharmony_ci	}
6062141cc406Sopenharmony_ci    }
6063141cc406Sopenharmony_ci
6064141cc406Sopenharmony_ci  reg = registerRead (0x0D);
6065141cc406Sopenharmony_ci  reg = (reg & 0xE8) | 0x43;
6066141cc406Sopenharmony_ci  registerWrite (0x0D, reg);
6067141cc406Sopenharmony_ci  REGISTERWRITE (0x0C, 0x04);
6068141cc406Sopenharmony_ci  reg = registerRead (0x0A);
6069141cc406Sopenharmony_ci  if (reg != 0x00)
6070141cc406Sopenharmony_ci    {
6071141cc406Sopenharmony_ci      if (reg != 0x1C)
6072141cc406Sopenharmony_ci	{
6073141cc406Sopenharmony_ci	  DBG (0, "Warning! expected reg0A=0x00, found 0x%02X! (%s:%d) \n",
6074141cc406Sopenharmony_ci	       reg, __FILE__, __LINE__);
6075141cc406Sopenharmony_ci	}
6076141cc406Sopenharmony_ci      else
6077141cc406Sopenharmony_ci	{
6078141cc406Sopenharmony_ci	  DBG (16, "Scanner in idle state .... (%s:%d)\n", __FILE__,
6079141cc406Sopenharmony_ci	       __LINE__);
6080141cc406Sopenharmony_ci	}
6081141cc406Sopenharmony_ci    }
6082141cc406Sopenharmony_ci
6083141cc406Sopenharmony_ci  /* model detection: redone since we might not be probing each time ... */
6084141cc406Sopenharmony_ci  /* write addr in 0x0E, read value at 0x0F                              */
6085141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x01);
6086141cc406Sopenharmony_ci  model = registerRead (0x0F);
6087141cc406Sopenharmony_ci  setModel (model);
6088141cc406Sopenharmony_ci
6089141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x1C);
6090141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
6091141cc406Sopenharmony_ci    {
6092141cc406Sopenharmony_ci      REGISTERWRITE (0x08, 0x10);
6093141cc406Sopenharmony_ci    }
6094141cc406Sopenharmony_ci  else
6095141cc406Sopenharmony_ci    {
6096141cc406Sopenharmony_ci      REGISTERWRITE (0x08, 0x21);
6097141cc406Sopenharmony_ci    }
6098141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0F);
6099141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x0C);
6100141cc406Sopenharmony_ci
6101141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x1C);
6102141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x10);
6103141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x1C);
6104141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
6105141cc406Sopenharmony_ci    {
6106141cc406Sopenharmony_ci      REGISTERWRITE (0x0F, 0x00);
6107141cc406Sopenharmony_ci    }
6108141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x11);
6109141cc406Sopenharmony_ci
6110141cc406Sopenharmony_ci  dest = (unsigned char *) (malloc (65536));
6111141cc406Sopenharmony_ci  if (dest == NULL)
6112141cc406Sopenharmony_ci    {
6113141cc406Sopenharmony_ci      DBG (0, "Failed to allocate 64 Ko !\n");
6114141cc406Sopenharmony_ci      return 0;
6115141cc406Sopenharmony_ci    }
6116141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
6117141cc406Sopenharmony_ci    {
6118141cc406Sopenharmony_ci      dest[i * 2] = i;
6119141cc406Sopenharmony_ci      dest[i * 2 + 1] = 0xFF - i;
6120141cc406Sopenharmony_ci      dest[512 + i * 2] = i;
6121141cc406Sopenharmony_ci      dest[512 + i * 2 + 1] = 0xFF - i;
6122141cc406Sopenharmony_ci    }
6123141cc406Sopenharmony_ci  nb = 150;
6124141cc406Sopenharmony_ci  for (i = 0; i < nb; i++)
6125141cc406Sopenharmony_ci    {
6126141cc406Sopenharmony_ci      bufferWrite (0x400, dest);
6127141cc406Sopenharmony_ci      DBG (16,
6128141cc406Sopenharmony_ci	   "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
6129141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6130141cc406Sopenharmony_ci    }
6131141cc406Sopenharmony_ci
6132141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);
6133141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x11);
6134141cc406Sopenharmony_ci
6135141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
6136141cc406Sopenharmony_ci    {
6137141cc406Sopenharmony_ci      ECPSetBuffer (0x400);
6138141cc406Sopenharmony_ci    }
6139141cc406Sopenharmony_ci  for (i = 0; i < nb; i++)
6140141cc406Sopenharmony_ci    {
6141141cc406Sopenharmony_ci      /* XXX Compat/Byte ??? XXX */
6142141cc406Sopenharmony_ci      bufferRead (0x400, dest);
6143141cc406Sopenharmony_ci      for (j = 0; j < 256; j++)
6144141cc406Sopenharmony_ci	{
6145141cc406Sopenharmony_ci	  if (dest[j * 2] != j)
6146141cc406Sopenharmony_ci	    {
6147141cc406Sopenharmony_ci	      DBG (0,
6148141cc406Sopenharmony_ci		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6149141cc406Sopenharmony_ci		   j * 2, j, dest[j * 2]);
6150141cc406Sopenharmony_ci	      return 0;
6151141cc406Sopenharmony_ci	    }
6152141cc406Sopenharmony_ci	  if (dest[j * 2 + 1] != 0xFF - j)
6153141cc406Sopenharmony_ci	    {
6154141cc406Sopenharmony_ci	      DBG
6155141cc406Sopenharmony_ci		(0,
6156141cc406Sopenharmony_ci		 "Altered buffer value at %03X, expected %02X, found %02X\n",
6157141cc406Sopenharmony_ci		 j * 2 + 1, 0xFF - j, dest[j * 2 + 1]);
6158141cc406Sopenharmony_ci	      return 0;
6159141cc406Sopenharmony_ci	    }
6160141cc406Sopenharmony_ci	  if (dest[512 + j * 2] != j)
6161141cc406Sopenharmony_ci	    {
6162141cc406Sopenharmony_ci	      DBG (0,
6163141cc406Sopenharmony_ci		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6164141cc406Sopenharmony_ci		   512 + j * 2, j, dest[512 + j * 2]);
6165141cc406Sopenharmony_ci	      return 0;
6166141cc406Sopenharmony_ci	    }
6167141cc406Sopenharmony_ci	  if (dest[512 + j * 2 + 1] != 0xFF - j)
6168141cc406Sopenharmony_ci	    {
6169141cc406Sopenharmony_ci	      DBG
6170141cc406Sopenharmony_ci		(0,
6171141cc406Sopenharmony_ci		 "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n",
6172141cc406Sopenharmony_ci		 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]);
6173141cc406Sopenharmony_ci	      return 0;
6174141cc406Sopenharmony_ci	    }
6175141cc406Sopenharmony_ci	}
6176141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n",
6177141cc406Sopenharmony_ci	   i, __FILE__, __LINE__);
6178141cc406Sopenharmony_ci    }
6179141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);
6180141cc406Sopenharmony_ci  /* ECP: "HEAVY" reconnect here */
6181141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
6182141cc406Sopenharmony_ci    {
6183141cc406Sopenharmony_ci      epilogue ();
6184141cc406Sopenharmony_ci      /* 3 line: set to initial parport state ? */
6185141cc406Sopenharmony_ci      byteMode ();		/*Outb (ECR, 0x20); */
6186141cc406Sopenharmony_ci      Outb (DATA, 0x04);
6187141cc406Sopenharmony_ci      Outb (CONTROL, 0x0C);
6188141cc406Sopenharmony_ci
6189141cc406Sopenharmony_ci      /* the following is a variant of connect(); */
6190141cc406Sopenharmony_ci      Inb (ECR);
6191141cc406Sopenharmony_ci      Inb (ECR);
6192141cc406Sopenharmony_ci      byteMode ();		/*Outb (ECR, 0x20); */
6193141cc406Sopenharmony_ci      byteMode ();		/*Outb (ECR, 0x20); */
6194141cc406Sopenharmony_ci      Inb (CONTROL);
6195141cc406Sopenharmony_ci      Outb (CONTROL, 0x0C);
6196141cc406Sopenharmony_ci      Inb (DATA);
6197141cc406Sopenharmony_ci      sendCommand (0xE0);
6198141cc406Sopenharmony_ci      Outb (DATA, 0XFF);
6199141cc406Sopenharmony_ci      Outb (DATA, 0XFF);
6200141cc406Sopenharmony_ci      ClearRegister (0);
6201141cc406Sopenharmony_ci      WRITESLOW (0x0E, 0x0A);
6202141cc406Sopenharmony_ci      SLOWNIBBLEREGISTERREAD (0x0F, 0x08);
6203141cc406Sopenharmony_ci      /* resend value OR'ed 0x08 ? */
6204141cc406Sopenharmony_ci      WRITESLOW (0x0F, 0x08);
6205141cc406Sopenharmony_ci      WRITESLOW (0x08, 0x10);
6206141cc406Sopenharmony_ci      disconnect ();
6207141cc406Sopenharmony_ci      prologue (0x10);
6208141cc406Sopenharmony_ci    }
6209141cc406Sopenharmony_ci
6210141cc406Sopenharmony_ci  if (fonc001 () != 1)
6211141cc406Sopenharmony_ci    {
6212141cc406Sopenharmony_ci      DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__);
6213141cc406Sopenharmony_ci      return 0;
6214141cc406Sopenharmony_ci    }
6215141cc406Sopenharmony_ci  DBG (16, "fonc001() passed ...  (%s:%d) \n", __FILE__, __LINE__);
6216141cc406Sopenharmony_ci
6217141cc406Sopenharmony_ci  /* sync */
6218141cc406Sopenharmony_ci  if (sendWord (zero) == 0)
6219141cc406Sopenharmony_ci    {
6220141cc406Sopenharmony_ci      DBG (0, "sendWord(zero) failed (%s:%d)\n", __FILE__, __LINE__);
6221141cc406Sopenharmony_ci      return 0;
6222141cc406Sopenharmony_ci    }
6223141cc406Sopenharmony_ci  DBG (16, "sendWord(zero) passed (%s:%d)\n", __FILE__, __LINE__);
6224141cc406Sopenharmony_ci  epilogue ();
6225141cc406Sopenharmony_ci
6226141cc406Sopenharmony_ci  /* OK ! */
6227141cc406Sopenharmony_ci  free (dest);
6228141cc406Sopenharmony_ci  DBG (1, "initTransport1220P done ...\n");
6229141cc406Sopenharmony_ci  return 1;
6230141cc406Sopenharmony_ci}
6231141cc406Sopenharmony_ci
6232141cc406Sopenharmony_ci/*
6233141cc406Sopenharmony_ci        1: OK
6234141cc406Sopenharmony_ci           2: failed, try again
6235141cc406Sopenharmony_ci           0: init failed
6236141cc406Sopenharmony_ci
6237141cc406Sopenharmony_ci        initialize the transport layer
6238141cc406Sopenharmony_ci
6239141cc406Sopenharmony_ci   */
6240141cc406Sopenharmony_ci
6241141cc406Sopenharmony_ciint
6242141cc406Sopenharmony_cisanei_umax_pp_initTransport (int recover)
6243141cc406Sopenharmony_ci{
6244141cc406Sopenharmony_ci  TRACE (16, "sanei_umax_pp_initTransport");
6245141cc406Sopenharmony_ci  switch (sanei_umax_pp_getastra ())
6246141cc406Sopenharmony_ci    {
6247141cc406Sopenharmony_ci    case 610:
6248141cc406Sopenharmony_ci      return initTransport610p ();
6249141cc406Sopenharmony_ci    case 1220:
6250141cc406Sopenharmony_ci    case 1600:
6251141cc406Sopenharmony_ci    case 2000:
6252141cc406Sopenharmony_ci    default:
6253141cc406Sopenharmony_ci      return initTransport1220P (recover);
6254141cc406Sopenharmony_ci    }
6255141cc406Sopenharmony_ci}
6256141cc406Sopenharmony_ci
6257141cc406Sopenharmony_ci
6258141cc406Sopenharmony_ci/* 1: OK
6259141cc406Sopenharmony_ci   0: probe failed */
6260141cc406Sopenharmony_ci
6261141cc406Sopenharmony_cistatic int
6262141cc406Sopenharmony_ciprobe610p (int recover)
6263141cc406Sopenharmony_ci{
6264141cc406Sopenharmony_ci  if (initTransport610p () == 0)
6265141cc406Sopenharmony_ci    {
6266141cc406Sopenharmony_ci      DBG (0, "initTransport610p() failed (%s:%d)\n", __FILE__, __LINE__);
6267141cc406Sopenharmony_ci      return 0;
6268141cc406Sopenharmony_ci    }
6269141cc406Sopenharmony_ci
6270141cc406Sopenharmony_ci  /* make sure we won't try 1220/200P later
6271141cc406Sopenharmony_ci   * since we got here, we have a 610, and in any case
6272141cc406Sopenharmony_ci   * NOT a 1220P/2000P, since no EPAT present */
6273141cc406Sopenharmony_ci  sanei_umax_pp_setastra (610);
6274141cc406Sopenharmony_ci
6275141cc406Sopenharmony_ci  if (initScanner610p (recover) == 0)
6276141cc406Sopenharmony_ci    {
6277141cc406Sopenharmony_ci      DBG (0, "initScanner610p() failed (%s:%d)\n", __FILE__, __LINE__);
6278141cc406Sopenharmony_ci      return 0;
6279141cc406Sopenharmony_ci    }
6280141cc406Sopenharmony_ci  /* successful end ... */
6281141cc406Sopenharmony_ci  DBG (1, "UMAX Astra 610p detected\n");
6282141cc406Sopenharmony_ci  DBG (1, "probe610p done ...\n");
6283141cc406Sopenharmony_ci  return 1;
6284141cc406Sopenharmony_ci}
6285141cc406Sopenharmony_ci
6286141cc406Sopenharmony_ci
6287141cc406Sopenharmony_ci  /*
6288141cc406Sopenharmony_ci   * try PS2 mode
6289141cc406Sopenharmony_ci   * returns 1 on success, 0 on failure
6290141cc406Sopenharmony_ci   */
6291141cc406Sopenharmony_ciint
6292141cc406Sopenharmony_ciprobePS2 (unsigned char *dest)
6293141cc406Sopenharmony_ci{
6294141cc406Sopenharmony_ci  int i, tmp;
6295141cc406Sopenharmony_ci
6296141cc406Sopenharmony_ci  /* write/read full buffer */
6297141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
6298141cc406Sopenharmony_ci    {
6299141cc406Sopenharmony_ci      WRITESLOW (0x0A, i);
6300141cc406Sopenharmony_ci      SLOWNIBBLEREGISTERREAD (0x0A, i);
6301141cc406Sopenharmony_ci      WRITESLOW (0x0A, 0xFF - i);
6302141cc406Sopenharmony_ci      SLOWNIBBLEREGISTERREAD (0x0A, 0xFF - i);
6303141cc406Sopenharmony_ci    }
6304141cc406Sopenharmony_ci
6305141cc406Sopenharmony_ci  /* end test for nibble byte/byte mode */
6306141cc406Sopenharmony_ci
6307141cc406Sopenharmony_ci  /* now we try nibble buffered mode */
6308141cc406Sopenharmony_ci  WRITESLOW (0x13, 0x01);
6309141cc406Sopenharmony_ci  WRITESLOW (0x13, 0x00);	/*reset something */
6310141cc406Sopenharmony_ci  WRITESLOW (0x0A, 0x11);
6311141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)	/* 10 ~ 11 ? */
6312141cc406Sopenharmony_ci    {
6313141cc406Sopenharmony_ci      PS2bufferRead (0x400, dest);
6314141cc406Sopenharmony_ci      DBG (16, "Loop %d: PS2bufferRead passed ... (%s:%d)\n", i, __FILE__,
6315141cc406Sopenharmony_ci	   __LINE__);
6316141cc406Sopenharmony_ci    }
6317141cc406Sopenharmony_ci
6318141cc406Sopenharmony_ci  /* write buffer */
6319141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6320141cc406Sopenharmony_ci    {
6321141cc406Sopenharmony_ci      PS2bufferWrite (0x400, dest);
6322141cc406Sopenharmony_ci      DBG (16, "Loop %d: PS2bufferWrite passed ... (%s:%d)\n", i, __FILE__,
6323141cc406Sopenharmony_ci	   __LINE__);
6324141cc406Sopenharmony_ci    }
6325141cc406Sopenharmony_ci
6326141cc406Sopenharmony_ci  SLOWNIBBLEREGISTERREAD (0x0C, 0x04);
6327141cc406Sopenharmony_ci  WRITESLOW (0x13, 0x01);
6328141cc406Sopenharmony_ci  WRITESLOW (0x13, 0x00);
6329141cc406Sopenharmony_ci  WRITESLOW (0x0A, 0x18);
6330141cc406Sopenharmony_ci
6331141cc406Sopenharmony_ci  return 1;
6332141cc406Sopenharmony_ci}
6333141cc406Sopenharmony_ci
6334141cc406Sopenharmony_ci  /*
6335141cc406Sopenharmony_ci   * try EPP 8 then 32 bits
6336141cc406Sopenharmony_ci   * returns 1 on success, 0 on failure
6337141cc406Sopenharmony_ci   */
6338141cc406Sopenharmony_ciint
6339141cc406Sopenharmony_ciprobeEPP (unsigned char *dest)
6340141cc406Sopenharmony_ci{
6341141cc406Sopenharmony_ci  int tmp, i, j;
6342141cc406Sopenharmony_ci  int reg;
6343141cc406Sopenharmony_ci
6344141cc406Sopenharmony_ci  /* test EPP MODE */
6345141cc406Sopenharmony_ci  setEPPMode (8);
6346141cc406Sopenharmony_ci  gMode = UMAX_PP_PARPORT_EPP;
6347141cc406Sopenharmony_ci  ClearRegister (0);
6348141cc406Sopenharmony_ci  DBG (16, "ClearRegister(0) passed... (%s:%d)\n", __FILE__, __LINE__);
6349141cc406Sopenharmony_ci  WRITESLOW (0x08, 0x22);
6350141cc406Sopenharmony_ci  init001 ();
6351141cc406Sopenharmony_ci  DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
6352141cc406Sopenharmony_ci  gEPAT = 0xC7;
6353141cc406Sopenharmony_ci  init002 (0);
6354141cc406Sopenharmony_ci  DBG (16, "init002(0) passed... (%s:%d)\n", __FILE__, __LINE__);
6355141cc406Sopenharmony_ci
6356141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0);
6357141cc406Sopenharmony_ci
6358141cc406Sopenharmony_ci  /* catch any failure to read back data in EPP mode */
6359141cc406Sopenharmony_ci  reg = registerRead (0x0A);
6360141cc406Sopenharmony_ci  if (reg != 0)
6361141cc406Sopenharmony_ci    {
6362141cc406Sopenharmony_ci      DBG (0, "registerRead, found 0x%X expected 0x00 (%s:%d)\n", reg,
6363141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6364141cc406Sopenharmony_ci      if (reg == 0xFF)
6365141cc406Sopenharmony_ci	{
6366141cc406Sopenharmony_ci	  DBG (0,
6367141cc406Sopenharmony_ci	       "*** It appears that EPP data transfer doesn't work    ***\n");
6368141cc406Sopenharmony_ci	  DBG (0,
6369141cc406Sopenharmony_ci	       "*** Please read SETTING EPP section in sane-umax_pp.5 ***\n");
6370141cc406Sopenharmony_ci	}
6371141cc406Sopenharmony_ci      return 0;
6372141cc406Sopenharmony_ci    }
6373141cc406Sopenharmony_ci  else
6374141cc406Sopenharmony_ci    {
6375141cc406Sopenharmony_ci      DBG (16, "registerRead(0x0A)=0x00 passed... (%s:%d)\n", __FILE__,
6376141cc406Sopenharmony_ci	   __LINE__);
6377141cc406Sopenharmony_ci    }
6378141cc406Sopenharmony_ci  registerWrite (0x0A, 0xFF);
6379141cc406Sopenharmony_ci  DBG (16, "registerWrite(0x%X,0x%X) passed...   (%s:%d)\n", 0x0A, 0xFF,
6380141cc406Sopenharmony_ci       __FILE__, __LINE__);
6381141cc406Sopenharmony_ci  REGISTERREAD (0x0A, 0xFF);
6382141cc406Sopenharmony_ci  for (i = 1; i < 256; i++)
6383141cc406Sopenharmony_ci    {
6384141cc406Sopenharmony_ci      REGISTERWRITE (0x0A, i);
6385141cc406Sopenharmony_ci      REGISTERREAD (0x0A, i);
6386141cc406Sopenharmony_ci      REGISTERWRITE (0x0A, 0xFF - i);
6387141cc406Sopenharmony_ci      REGISTERREAD (0x0A, 0xFF - i);
6388141cc406Sopenharmony_ci    }
6389141cc406Sopenharmony_ci
6390141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x01);
6391141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x00);
6392141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x11);
6393141cc406Sopenharmony_ci
6394141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6395141cc406Sopenharmony_ci    {
6396141cc406Sopenharmony_ci      bufferRead (0x400, dest);
6397141cc406Sopenharmony_ci      for (j = 0; j < 512; j++)
6398141cc406Sopenharmony_ci	{
6399141cc406Sopenharmony_ci	  if (dest[2 * j] != (j % 256))
6400141cc406Sopenharmony_ci	    {
6401141cc406Sopenharmony_ci	      DBG (0, "Loop %d, char %d bufferRead failed! (%s:%d)\n", i,
6402141cc406Sopenharmony_ci		   j * 2, __FILE__, __LINE__);
6403141cc406Sopenharmony_ci	      return 0;
6404141cc406Sopenharmony_ci	    }
6405141cc406Sopenharmony_ci	  if (dest[2 * j + 1] != (0xFF - (j % 256)))
6406141cc406Sopenharmony_ci	    {
6407141cc406Sopenharmony_ci	      DBG (0, "Loop %d, char %d bufferRead failed! (%s:%d)\n", i,
6408141cc406Sopenharmony_ci		   j * 2 + 1, __FILE__, __LINE__);
6409141cc406Sopenharmony_ci	      return 0;
6410141cc406Sopenharmony_ci	    }
6411141cc406Sopenharmony_ci	}
6412141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n", i,
6413141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6414141cc406Sopenharmony_ci    }
6415141cc406Sopenharmony_ci
6416141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6417141cc406Sopenharmony_ci    {
6418141cc406Sopenharmony_ci      bufferWrite (0x400, dest);
6419141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
6420141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6421141cc406Sopenharmony_ci    }
6422141cc406Sopenharmony_ci
6423141cc406Sopenharmony_ci
6424141cc406Sopenharmony_ci  REGISTERREAD (0x0C, 4);
6425141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x01);
6426141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x00);
6427141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);
6428141cc406Sopenharmony_ci
6429141cc406Sopenharmony_ci  Outb (DATA, 0x0);
6430141cc406Sopenharmony_ci  ClearRegister (0);
6431141cc406Sopenharmony_ci  init001 ();
6432141cc406Sopenharmony_ci
6433141cc406Sopenharmony_ci  if (checkEPAT () != 0)
6434141cc406Sopenharmony_ci    return 0;
6435141cc406Sopenharmony_ci  DBG (16, "checkEPAT() passed... (%s:%d)\n", __FILE__, __LINE__);
6436141cc406Sopenharmony_ci
6437141cc406Sopenharmony_ci  tmp = Inb (CONTROL) & 0x1F;
6438141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
6439141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
6440141cc406Sopenharmony_ci
6441141cc406Sopenharmony_ci  WRITESLOW (0x08, 0x21);
6442141cc406Sopenharmony_ci  init001 ();
6443141cc406Sopenharmony_ci  DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
6444141cc406Sopenharmony_ci  WRITESLOW (0x08, 0x21);
6445141cc406Sopenharmony_ci  init001 ();
6446141cc406Sopenharmony_ci  DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
6447141cc406Sopenharmony_ci  SPPResetLPT ();
6448141cc406Sopenharmony_ci
6449141cc406Sopenharmony_ci
6450141cc406Sopenharmony_ci  if (init005 (0x80))
6451141cc406Sopenharmony_ci    {
6452141cc406Sopenharmony_ci      DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__);
6453141cc406Sopenharmony_ci    }
6454141cc406Sopenharmony_ci  DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__);
6455141cc406Sopenharmony_ci  if (init005 (0xEC))
6456141cc406Sopenharmony_ci    {
6457141cc406Sopenharmony_ci      DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__);
6458141cc406Sopenharmony_ci    }
6459141cc406Sopenharmony_ci  DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__);
6460141cc406Sopenharmony_ci
6461141cc406Sopenharmony_ci
6462141cc406Sopenharmony_ci  /* write/read buffer loop */
6463141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
6464141cc406Sopenharmony_ci    {
6465141cc406Sopenharmony_ci      REGISTERWRITE (0x0A, i);
6466141cc406Sopenharmony_ci      REGISTERREAD (0x0A, i);
6467141cc406Sopenharmony_ci      REGISTERWRITE (0x0A, 0xFF - i);
6468141cc406Sopenharmony_ci      REGISTERREAD (0x0A, 0xFF - i);
6469141cc406Sopenharmony_ci    }
6470141cc406Sopenharmony_ci  DBG (16, "EPP write/read buffer loop passed... (%s:%d)\n", __FILE__,
6471141cc406Sopenharmony_ci       __LINE__);
6472141cc406Sopenharmony_ci
6473141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x01);
6474141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x00);
6475141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x11);
6476141cc406Sopenharmony_ci
6477141cc406Sopenharmony_ci  /* test EPP32 mode */
6478141cc406Sopenharmony_ci  /* we set 32 bits I/O mode first, then step back to */
6479141cc406Sopenharmony_ci  /* 8bits if tests fail                              */
6480141cc406Sopenharmony_ci  setEPPMode (32);
6481141cc406Sopenharmony_ci  for (i = 0; (i < 10) && (getEPPMode () == 32); i++)
6482141cc406Sopenharmony_ci    {
6483141cc406Sopenharmony_ci      bufferRead (0x400, dest);
6484141cc406Sopenharmony_ci      /* if 32 bit I/O work, we should have a buffer */
6485141cc406Sopenharmony_ci      /* filled by 00 FF 01 FE 02 FD 03 FC .....     */
6486141cc406Sopenharmony_ci      for (j = 0; j < 0x200; j++)
6487141cc406Sopenharmony_ci	{
6488141cc406Sopenharmony_ci	  if ((dest[j * 2] != j % 256)
6489141cc406Sopenharmony_ci	      || (dest[j * 2 + 1] != 0xFF - (j % 256)))
6490141cc406Sopenharmony_ci	    {
6491141cc406Sopenharmony_ci	      DBG (1, "Setting EPP I/O to 8 bits ... (%s:%d)\n", __FILE__,
6492141cc406Sopenharmony_ci		   __LINE__);
6493141cc406Sopenharmony_ci	      setEPPMode (8);
6494141cc406Sopenharmony_ci	      /* leave out current loop since an error was detected */
6495141cc406Sopenharmony_ci	      break;
6496141cc406Sopenharmony_ci	    }
6497141cc406Sopenharmony_ci	}
6498141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferRead(0x400) passed... (%s:%d)\n", i,
6499141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6500141cc406Sopenharmony_ci    }
6501141cc406Sopenharmony_ci  DBG (1, "%d bits EPP data transfer\n", getEPPMode ());
6502141cc406Sopenharmony_ci
6503141cc406Sopenharmony_ci
6504141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6505141cc406Sopenharmony_ci    {
6506141cc406Sopenharmony_ci      bufferWrite (0x400, dest);
6507141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
6508141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6509141cc406Sopenharmony_ci    }
6510141cc406Sopenharmony_ci
6511141cc406Sopenharmony_ci
6512141cc406Sopenharmony_ci
6513141cc406Sopenharmony_ci  REGISTERREAD (0x0C, 0x04);
6514141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x01);
6515141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x00);
6516141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);
6517141cc406Sopenharmony_ci
6518141cc406Sopenharmony_ci  WRITESLOW (0x08, 0x21);
6519141cc406Sopenharmony_ci  init001 ();
6520141cc406Sopenharmony_ci  DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
6521141cc406Sopenharmony_ci  SPPResetLPT ();
6522141cc406Sopenharmony_ci
6523141cc406Sopenharmony_ci  if (init005 (0x80))
6524141cc406Sopenharmony_ci    {
6525141cc406Sopenharmony_ci      DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__);
6526141cc406Sopenharmony_ci    }
6527141cc406Sopenharmony_ci  DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__);
6528141cc406Sopenharmony_ci  if (init005 (0xEC))
6529141cc406Sopenharmony_ci    {
6530141cc406Sopenharmony_ci      DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__);
6531141cc406Sopenharmony_ci    }
6532141cc406Sopenharmony_ci  DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__);
6533141cc406Sopenharmony_ci
6534141cc406Sopenharmony_ci
6535141cc406Sopenharmony_ci  /* write/read buffer loop */
6536141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
6537141cc406Sopenharmony_ci    {
6538141cc406Sopenharmony_ci      REGISTERWRITE (0x0A, i);
6539141cc406Sopenharmony_ci      REGISTERREAD (0x0A, i);
6540141cc406Sopenharmony_ci      REGISTERWRITE (0x0A, 0xFF - i);
6541141cc406Sopenharmony_ci      REGISTERREAD (0x0A, 0xFF - i);
6542141cc406Sopenharmony_ci    }
6543141cc406Sopenharmony_ci  DBG (16, "EPP write/read buffer loop passed... (%s:%d)\n", __FILE__,
6544141cc406Sopenharmony_ci       __LINE__);
6545141cc406Sopenharmony_ci
6546141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x01);
6547141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x00);
6548141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x11);
6549141cc406Sopenharmony_ci
6550141cc406Sopenharmony_ci
6551141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6552141cc406Sopenharmony_ci    {
6553141cc406Sopenharmony_ci      bufferRead (0x400, dest);
6554141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferRead(0x400) passed... (%s:%d)\n", i,
6555141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6556141cc406Sopenharmony_ci    }
6557141cc406Sopenharmony_ci
6558141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6559141cc406Sopenharmony_ci    {
6560141cc406Sopenharmony_ci      bufferWrite (0x400, dest);
6561141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
6562141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6563141cc406Sopenharmony_ci    }
6564141cc406Sopenharmony_ci  REGISTERREAD (0x0C, 0x04);
6565141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x01);
6566141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x00);
6567141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);
6568141cc406Sopenharmony_ci  gMode = UMAX_PP_PARPORT_EPP;
6569141cc406Sopenharmony_ci  return 1;
6570141cc406Sopenharmony_ci}
6571141cc406Sopenharmony_ci
6572141cc406Sopenharmony_ci  /*
6573141cc406Sopenharmony_ci   * try ECP mode
6574141cc406Sopenharmony_ci   * returns 1 on success, 0 on failure
6575141cc406Sopenharmony_ci   */
6576141cc406Sopenharmony_ciint
6577141cc406Sopenharmony_ciprobeECP (unsigned char *dest)
6578141cc406Sopenharmony_ci{
6579141cc406Sopenharmony_ci  int i, j, tmp;
6580141cc406Sopenharmony_ci  unsigned char breg;
6581141cc406Sopenharmony_ci
6582141cc406Sopenharmony_ci  /* if ECP not available, fail */
6583141cc406Sopenharmony_ci  if (gECP != 1)
6584141cc406Sopenharmony_ci    {
6585141cc406Sopenharmony_ci      DBG (1, "Hardware can't do ECP, giving up (%s:%d) ...\n", __FILE__,
6586141cc406Sopenharmony_ci	   __LINE__);
6587141cc406Sopenharmony_ci      return 0;
6588141cc406Sopenharmony_ci    }
6589141cc406Sopenharmony_ci  gMode = UMAX_PP_PARPORT_ECP;
6590141cc406Sopenharmony_ci
6591141cc406Sopenharmony_ci/* clean from EPP failure */
6592141cc406Sopenharmony_ci  breg = Inb (CONTROL);
6593141cc406Sopenharmony_ci  Outb (CONTROL, breg & 0x04);
6594141cc406Sopenharmony_ci
6595141cc406Sopenharmony_ci/* reset sequence */
6596141cc406Sopenharmony_ci  byteMode ();			/*Outb (ECR, 0x20);            byte mode */
6597141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6598141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
6599141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
6600141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
6601141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
6602141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
6603141cc406Sopenharmony_ci    {
6604141cc406Sopenharmony_ci      breg = (Inb (STATUS)) & 0xF8;
6605141cc406Sopenharmony_ci      if (breg != 0x48)
6606141cc406Sopenharmony_ci	{
6607141cc406Sopenharmony_ci	  DBG (0,
6608141cc406Sopenharmony_ci	       "probeECP() failed at sync step %d, status=0x%02X, expected 0x48 (%s:%d)\n",
6609141cc406Sopenharmony_ci	       i, breg, __FILE__, __LINE__);
6610141cc406Sopenharmony_ci	  return 0;
6611141cc406Sopenharmony_ci	}
6612141cc406Sopenharmony_ci    }
6613141cc406Sopenharmony_ci  Outb (CONTROL, 0x0E);
6614141cc406Sopenharmony_ci  Outb (CONTROL, 0x0E);
6615141cc406Sopenharmony_ci  Outb (CONTROL, 0x0E);
6616141cc406Sopenharmony_ci  breg = (Inb (STATUS)) & 0xF8;
6617141cc406Sopenharmony_ci  if (breg != 0x48)
6618141cc406Sopenharmony_ci    {
6619141cc406Sopenharmony_ci      DBG (0, "probeECP() failed, status=0x%02X, expected 0x48 (%s:%d)\n",
6620141cc406Sopenharmony_ci	   breg, __FILE__, __LINE__);
6621141cc406Sopenharmony_ci      return 0;
6622141cc406Sopenharmony_ci    }
6623141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6624141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6625141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6626141cc406Sopenharmony_ci  breg = Inb (STATUS) & 0xF8;
6627141cc406Sopenharmony_ci  breg = (Inb (STATUS)) & 0xF8;
6628141cc406Sopenharmony_ci  if (breg != 0xC8)
6629141cc406Sopenharmony_ci    {
6630141cc406Sopenharmony_ci      DBG (0, "probeECP() failed, status=0x%02X, expected 0xC8 (%s:%d)\n",
6631141cc406Sopenharmony_ci	   breg, __FILE__, __LINE__);
6632141cc406Sopenharmony_ci      return 0;
6633141cc406Sopenharmony_ci    }
6634141cc406Sopenharmony_ci/* end of reset sequence */
6635141cc406Sopenharmony_ci
6636141cc406Sopenharmony_ci  Outb (DATA, 0x00);
6637141cc406Sopenharmony_ci  ClearRegister (0);
6638141cc406Sopenharmony_ci
6639141cc406Sopenharmony_ci/* utile ? semble tester le registre de configuration
6640141cc406Sopenharmony_ci * inb ECR,35
6641141cc406Sopenharmony_ci * inb 77B,FF
6642141cc406Sopenharmony_ci * inb ECR,35
6643141cc406Sopenharmony_ci */
6644141cc406Sopenharmony_ci/* routine A */
6645141cc406Sopenharmony_ci  breg = Inb (CONTROL);		/* 0x04 évidemment! */
6646141cc406Sopenharmony_ci  breg = Inb (ECR);
6647141cc406Sopenharmony_ci  breg = Inb (ECR);
6648141cc406Sopenharmony_ci  breg = Inb (ECR);
6649141cc406Sopenharmony_ci  breg = Inb (ECR);
6650141cc406Sopenharmony_ci  breg = Inb (CONTROL);
6651141cc406Sopenharmony_ci  byteMode ();			/*Outb (ECR, 0x20);            byte mode */
6652141cc406Sopenharmony_ci  /*byteMode ();                        Outb (ECR, 0x20); */
6653141cc406Sopenharmony_ci  breg = Inb (CONTROL);
6654141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6655141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6656141cc406Sopenharmony_ci  breg = Inb (ECR);		/* 35 expected */
6657141cc406Sopenharmony_ci  breg = Inb (ECR);		/* 35 expected */
6658141cc406Sopenharmony_ci  breg = Inb (ECR);		/* 35 expected */
6659141cc406Sopenharmony_ci  breg = Inb (ECR);		/* 35 expected */
6660141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6661141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6662141cc406Sopenharmony_ci  byteMode ();
6663141cc406Sopenharmony_ci  byteMode ();
6664141cc406Sopenharmony_ci
6665141cc406Sopenharmony_ci  ClearRegister (0);
6666141cc406Sopenharmony_ci
6667141cc406Sopenharmony_ci/* routine C */
6668141cc406Sopenharmony_ci  PS2registerWrite (0x08, 0x01);
6669141cc406Sopenharmony_ci
6670141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
6671141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6672141cc406Sopenharmony_ci
6673141cc406Sopenharmony_ci  ClearRegister (0);
6674141cc406Sopenharmony_ci
6675141cc406Sopenharmony_ci  breg = PS2Something (0x10);
6676141cc406Sopenharmony_ci  if (breg != 0x0B)
6677141cc406Sopenharmony_ci    {
6678141cc406Sopenharmony_ci      DBG (0, "probeECP() failed, reg10=0x%02X, expected 0x0B (%s:%d)\n",
6679141cc406Sopenharmony_ci	   breg, __FILE__, __LINE__);
6680141cc406Sopenharmony_ci      /* return 0; */
6681141cc406Sopenharmony_ci    }
6682141cc406Sopenharmony_ci
6683141cc406Sopenharmony_ci
6684141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
6685141cc406Sopenharmony_ci    {
6686141cc406Sopenharmony_ci      ECPregisterWrite (0x0A, i);
6687141cc406Sopenharmony_ci      breg = ECPregisterRead (0x0A);
6688141cc406Sopenharmony_ci      if (breg != i)
6689141cc406Sopenharmony_ci	{
6690141cc406Sopenharmony_ci	  DBG (0, "probeECP(), loop %d failed (%s:%d)\n", i, __FILE__,
6691141cc406Sopenharmony_ci	       __LINE__);
6692141cc406Sopenharmony_ci	  return 0;
6693141cc406Sopenharmony_ci	}
6694141cc406Sopenharmony_ci      ECPregisterWrite (0x0A, 0xFF - i);
6695141cc406Sopenharmony_ci      breg = ECPregisterRead (0x0A);
6696141cc406Sopenharmony_ci      if (breg != 0xFF - i)
6697141cc406Sopenharmony_ci	{
6698141cc406Sopenharmony_ci	  DBG (0, "probeECP(), loop %d failed (%s:%d)\n", i, __FILE__,
6699141cc406Sopenharmony_ci	       __LINE__);
6700141cc406Sopenharmony_ci	  return 0;
6701141cc406Sopenharmony_ci	}
6702141cc406Sopenharmony_ci    }
6703141cc406Sopenharmony_ci  DBG (16, "probeECP(), loop passed (%s:%d)\n", __FILE__, __LINE__);
6704141cc406Sopenharmony_ci
6705141cc406Sopenharmony_ci  ECPregisterWrite (0x13, 0x01);
6706141cc406Sopenharmony_ci  ECPregisterWrite (0x13, 0x00);
6707141cc406Sopenharmony_ci  ECPregisterWrite (0x0A, 0x11);
6708141cc406Sopenharmony_ci
6709141cc406Sopenharmony_ci  /* there is one buffer transfer size set up */
6710141cc406Sopenharmony_ci  /* subsequent reads are done in a row       */
6711141cc406Sopenharmony_ci  ECPSetBuffer (0x400);
6712141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6713141cc406Sopenharmony_ci    {
6714141cc406Sopenharmony_ci      /* if (i > 0) */
6715141cc406Sopenharmony_ci      compatMode ();
6716141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);	/* reset ? */
6717141cc406Sopenharmony_ci
6718141cc406Sopenharmony_ci      ECPbufferRead (1024, dest);
6719141cc406Sopenharmony_ci      /* check content of the returned buffer */
6720141cc406Sopenharmony_ci      for (j = 0; j < 256; j++)
6721141cc406Sopenharmony_ci	{
6722141cc406Sopenharmony_ci	  if (dest[j * 2] != j)
6723141cc406Sopenharmony_ci	    {
6724141cc406Sopenharmony_ci	      DBG (0,
6725141cc406Sopenharmony_ci		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6726141cc406Sopenharmony_ci		   j * 2, j, dest[j * 2]);
6727141cc406Sopenharmony_ci	      return 0;
6728141cc406Sopenharmony_ci	    }
6729141cc406Sopenharmony_ci	  if (dest[j * 2 + 1] != 0xFF - j)
6730141cc406Sopenharmony_ci	    {
6731141cc406Sopenharmony_ci	      DBG
6732141cc406Sopenharmony_ci		(0,
6733141cc406Sopenharmony_ci		 "Altered buffer value at %03X, expected %02X, found %02X\n",
6734141cc406Sopenharmony_ci		 j * 2 + 1, 0xFF - j, dest[j * 2 + 1]);
6735141cc406Sopenharmony_ci	      return 0;
6736141cc406Sopenharmony_ci	    }
6737141cc406Sopenharmony_ci	  if (dest[512 + j * 2] != j)
6738141cc406Sopenharmony_ci	    {
6739141cc406Sopenharmony_ci	      DBG (0,
6740141cc406Sopenharmony_ci		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6741141cc406Sopenharmony_ci		   512 + j * 2, j, dest[512 + j * 2]);
6742141cc406Sopenharmony_ci	      return 0;
6743141cc406Sopenharmony_ci	    }
6744141cc406Sopenharmony_ci	  if (dest[512 + j * 2 + 1] != 0xFF - j)
6745141cc406Sopenharmony_ci	    {
6746141cc406Sopenharmony_ci	      DBG
6747141cc406Sopenharmony_ci		(0,
6748141cc406Sopenharmony_ci		 "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n",
6749141cc406Sopenharmony_ci		 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]);
6750141cc406Sopenharmony_ci	      return 0;
6751141cc406Sopenharmony_ci	    }
6752141cc406Sopenharmony_ci	}
6753141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
6754141cc406Sopenharmony_ci      byteMode ();
6755141cc406Sopenharmony_ci    }
6756141cc406Sopenharmony_ci
6757141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6758141cc406Sopenharmony_ci    ECPbufferWrite (1024, dest);
6759141cc406Sopenharmony_ci
6760141cc406Sopenharmony_ci  breg = ECPregisterRead (0x0C);
6761141cc406Sopenharmony_ci  if (breg != 0x04)
6762141cc406Sopenharmony_ci    {
6763141cc406Sopenharmony_ci      DBG (0, "Warning! expected reg0C=0x04, found 0x%02X! (%s:%d) \n", breg,
6764141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6765141cc406Sopenharmony_ci    }
6766141cc406Sopenharmony_ci
6767141cc406Sopenharmony_ci  ECPregisterWrite (0x13, 0x01);
6768141cc406Sopenharmony_ci  ECPregisterWrite (0x13, 0x00);
6769141cc406Sopenharmony_ci  ECPregisterWrite (0x0A, 0x18);
6770141cc406Sopenharmony_ci
6771141cc406Sopenharmony_ci  /* reset printer ? */
6772141cc406Sopenharmony_ci  Outb (DATA, 0x00);
6773141cc406Sopenharmony_ci  Outb (CONTROL, 0x00);
6774141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);
6775141cc406Sopenharmony_ci
6776141cc406Sopenharmony_ci  for (i = 0; i < 3; i++)
6777141cc406Sopenharmony_ci    {				/* will go in a function */
6778141cc406Sopenharmony_ci      ClearRegister (0);
6779141cc406Sopenharmony_ci      if (waitAck () != 1)
6780141cc406Sopenharmony_ci	{
6781141cc406Sopenharmony_ci	  DBG (0, "probeECP failed because of waitAck() (%s:%d) \n", __FILE__,
6782141cc406Sopenharmony_ci	       __LINE__);
6783141cc406Sopenharmony_ci	  /* return 0; may fail without harm ... ??? */
6784141cc406Sopenharmony_ci	}
6785141cc406Sopenharmony_ci      /* are these 2 out really needed ? */
6786141cc406Sopenharmony_ci      PS2registerWrite (0x08, 0x01);
6787141cc406Sopenharmony_ci      Outb (CONTROL, 0x0C);	/* select + reset */
6788141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);	/* reset */
6789141cc406Sopenharmony_ci    }
6790141cc406Sopenharmony_ci
6791141cc406Sopenharmony_ci  /* prologue of the 'rotate test' */
6792141cc406Sopenharmony_ci  ClearRegister (0);
6793141cc406Sopenharmony_ci  breg = PS2Something (0x10);
6794141cc406Sopenharmony_ci  if (breg != 0x0B)
6795141cc406Sopenharmony_ci    {
6796141cc406Sopenharmony_ci      DBG (0,
6797141cc406Sopenharmony_ci	   "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", breg,
6798141cc406Sopenharmony_ci	   __FILE__, __LINE__);
6799141cc406Sopenharmony_ci    }
6800141cc406Sopenharmony_ci  Outb (CONTROL, 0x04);		/* reset */
6801141cc406Sopenharmony_ci
6802141cc406Sopenharmony_ci  if (init005 (0x80))
6803141cc406Sopenharmony_ci    {
6804141cc406Sopenharmony_ci      DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__);
6805141cc406Sopenharmony_ci    }
6806141cc406Sopenharmony_ci  DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__);
6807141cc406Sopenharmony_ci  if (init005 (0xEC))
6808141cc406Sopenharmony_ci    {
6809141cc406Sopenharmony_ci      DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__);
6810141cc406Sopenharmony_ci    }
6811141cc406Sopenharmony_ci  DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__);
6812141cc406Sopenharmony_ci
6813141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
6814141cc406Sopenharmony_ci    {
6815141cc406Sopenharmony_ci      REGISTERWRITE (0x0A, i);
6816141cc406Sopenharmony_ci      REGISTERREAD (0x0A, i);
6817141cc406Sopenharmony_ci      REGISTERWRITE (0x0A, 0xFF - i);
6818141cc406Sopenharmony_ci      REGISTERREAD (0x0A, 0xFF - i);
6819141cc406Sopenharmony_ci    }
6820141cc406Sopenharmony_ci  DBG (16, "ECPprobe(), write/read buffer loop passed (%s:%d)\n", __FILE__,
6821141cc406Sopenharmony_ci       __LINE__);
6822141cc406Sopenharmony_ci
6823141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x01);
6824141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x00);
6825141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x11);
6826141cc406Sopenharmony_ci
6827141cc406Sopenharmony_ci  /* should be a function */
6828141cc406Sopenharmony_ci  /* in probeEPP(), we begin 32 bit mode test here */
6829141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6830141cc406Sopenharmony_ci    {
6831141cc406Sopenharmony_ci      compatMode ();
6832141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);	/* reset ? */
6833141cc406Sopenharmony_ci
6834141cc406Sopenharmony_ci      ECPbufferRead (0x400, dest);
6835141cc406Sopenharmony_ci      /* check content of the returned buffer */
6836141cc406Sopenharmony_ci      for (j = 0; j < 256; j++)
6837141cc406Sopenharmony_ci	{
6838141cc406Sopenharmony_ci	  if (dest[j * 2] != j)
6839141cc406Sopenharmony_ci	    {
6840141cc406Sopenharmony_ci	      DBG (0,
6841141cc406Sopenharmony_ci		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6842141cc406Sopenharmony_ci		   j * 2, j, dest[j * 2]);
6843141cc406Sopenharmony_ci	      return 0;
6844141cc406Sopenharmony_ci	    }
6845141cc406Sopenharmony_ci	  if (dest[j * 2 + 1] != 0xFF - j)
6846141cc406Sopenharmony_ci	    {
6847141cc406Sopenharmony_ci	      DBG
6848141cc406Sopenharmony_ci		(0,
6849141cc406Sopenharmony_ci		 "Altered buffer value at %03X, expected %02X, found %02X\n",
6850141cc406Sopenharmony_ci		 j * 2 + 1, 0xFF - j, dest[j * 2 + 1]);
6851141cc406Sopenharmony_ci	      return 0;
6852141cc406Sopenharmony_ci	    }
6853141cc406Sopenharmony_ci	  if (dest[512 + j * 2] != j)
6854141cc406Sopenharmony_ci	    {
6855141cc406Sopenharmony_ci	      DBG (0,
6856141cc406Sopenharmony_ci		   "Altered buffer value at %03X, expected %02X, found %02X\n",
6857141cc406Sopenharmony_ci		   512 + j * 2, j, dest[512 + j * 2]);
6858141cc406Sopenharmony_ci	      return 0;
6859141cc406Sopenharmony_ci	    }
6860141cc406Sopenharmony_ci	  if (dest[512 + j * 2 + 1] != 0xFF - j)
6861141cc406Sopenharmony_ci	    {
6862141cc406Sopenharmony_ci	      DBG
6863141cc406Sopenharmony_ci		(0,
6864141cc406Sopenharmony_ci		 "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n",
6865141cc406Sopenharmony_ci		 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]);
6866141cc406Sopenharmony_ci	      return 0;
6867141cc406Sopenharmony_ci	    }
6868141cc406Sopenharmony_ci	}
6869141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
6870141cc406Sopenharmony_ci      byteMode ();
6871141cc406Sopenharmony_ci    }
6872141cc406Sopenharmony_ci
6873141cc406Sopenharmony_ci  for (i = 0; i < 10; i++)
6874141cc406Sopenharmony_ci    ECPbufferWrite (1024, dest);
6875141cc406Sopenharmony_ci
6876141cc406Sopenharmony_ci  REGISTERREAD (0x0C, 0x04);
6877141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x01);
6878141cc406Sopenharmony_ci  REGISTERWRITE (0x13, 0x00);
6879141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);
6880141cc406Sopenharmony_ci  waitAck ();
6881141cc406Sopenharmony_ci
6882141cc406Sopenharmony_ci  return 1;
6883141cc406Sopenharmony_ci}
6884141cc406Sopenharmony_ci
6885141cc406Sopenharmony_ci
6886141cc406Sopenharmony_ci
6887141cc406Sopenharmony_ci/* 1: OK
6888141cc406Sopenharmony_ci   0: probe failed */
6889141cc406Sopenharmony_ci
6890141cc406Sopenharmony_ciint
6891141cc406Sopenharmony_cisanei_umax_pp_probeScanner (int recover)
6892141cc406Sopenharmony_ci{
6893141cc406Sopenharmony_ci  int tmp, i, j;
6894141cc406Sopenharmony_ci  int reg, nb;
6895141cc406Sopenharmony_ci  unsigned char *dest = NULL;
6896141cc406Sopenharmony_ci  int initbuf[2049];
6897141cc406Sopenharmony_ci  int voidbuf[2049];
6898141cc406Sopenharmony_ci  int val;
6899141cc406Sopenharmony_ci  int zero[5] = { 0, 0, 0, 0, -1 };
6900141cc406Sopenharmony_ci  int model;
6901141cc406Sopenharmony_ci
6902141cc406Sopenharmony_ci  /* saves port state */
6903141cc406Sopenharmony_ci  gData = Inb (DATA);
6904141cc406Sopenharmony_ci  gControl = Inb (CONTROL);
6905141cc406Sopenharmony_ci
6906141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
6907141cc406Sopenharmony_ci    return probe610p (recover);
6908141cc406Sopenharmony_ci
6909141cc406Sopenharmony_ci  /* save and set CONTROL */
6910141cc406Sopenharmony_ci  tmp = (Inb (CONTROL)) & 0x1F;
6911141cc406Sopenharmony_ci  tmp = (Inb (CONTROL)) & 0x1F;
6912141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
6913141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
6914141cc406Sopenharmony_ci
6915141cc406Sopenharmony_ci  tmp = Inb (DATA);
6916141cc406Sopenharmony_ci  tmp = Inb (CONTROL) & 0x3F;
6917141cc406Sopenharmony_ci  Outb (CONTROL, tmp);
6918141cc406Sopenharmony_ci
6919141cc406Sopenharmony_ci  tmp = Inb (CONTROL) & 0x3F;
6920141cc406Sopenharmony_ci  tmp = Inb (DATA);
6921141cc406Sopenharmony_ci  tmp = Inb (CONTROL) & 0x3F;
6922141cc406Sopenharmony_ci  tmp = Inb (DATA);
6923141cc406Sopenharmony_ci
6924141cc406Sopenharmony_ci  /*  any scanner ? */
6925141cc406Sopenharmony_ci  /* fast detect */
6926141cc406Sopenharmony_ci  tmp = ringScanner (2, 0);
6927141cc406Sopenharmony_ci  if (!tmp)
6928141cc406Sopenharmony_ci    {
6929141cc406Sopenharmony_ci      DBG (1, "No scanner detected by 'ringScanner(2,0)'...\n");
6930141cc406Sopenharmony_ci      tmp = ringScanner (5, 0);
6931141cc406Sopenharmony_ci      if (!tmp)
6932141cc406Sopenharmony_ci	{
6933141cc406Sopenharmony_ci	  DBG (1, "No scanner detected by 'ringScanner(5,0)'...\n");
6934141cc406Sopenharmony_ci	  tmp = ringScanner (5, 10000);
6935141cc406Sopenharmony_ci	  if (!tmp)
6936141cc406Sopenharmony_ci	    {
6937141cc406Sopenharmony_ci	      DBG (1, "No scanner detected by 'ringScanner(5,10000)'...\n");
6938141cc406Sopenharmony_ci	      tmp = ringScanner (5, 10000);
6939141cc406Sopenharmony_ci	      if (!tmp)
6940141cc406Sopenharmony_ci		{
6941141cc406Sopenharmony_ci		  DBG (1,
6942141cc406Sopenharmony_ci		       "No scanner detected by 'ringScanner(5,10000)'...\n");
6943141cc406Sopenharmony_ci		}
6944141cc406Sopenharmony_ci	    }
6945141cc406Sopenharmony_ci	}
6946141cc406Sopenharmony_ci    }
6947141cc406Sopenharmony_ci  if (!tmp)
6948141cc406Sopenharmony_ci    {
6949141cc406Sopenharmony_ci      DBG (1, "No 1220P/2000P scanner detected by 'ringScanner()'...\n");
6950141cc406Sopenharmony_ci    }
6951141cc406Sopenharmony_ci  DBG (16, "ringScanner passed...\n");
6952141cc406Sopenharmony_ci
6953141cc406Sopenharmony_ci  gControl = Inb (CONTROL) & 0x3F;
6954141cc406Sopenharmony_ci  g67D = 1;
6955141cc406Sopenharmony_ci  if (sendCommand (0x30) == 0)
6956141cc406Sopenharmony_ci    {
6957141cc406Sopenharmony_ci      DBG (0, "sendCommand(0x30) (%s:%d) failed ...\n", __FILE__, __LINE__);
6958141cc406Sopenharmony_ci      return 0;
6959141cc406Sopenharmony_ci    }
6960141cc406Sopenharmony_ci  DBG (16, "sendCommand(0x30) passed ... (%s:%d)\n", __FILE__, __LINE__);
6961141cc406Sopenharmony_ci  g67E = 4;			/* bytes to read */
6962141cc406Sopenharmony_ci  if (sendCommand (0x00) == 0)
6963141cc406Sopenharmony_ci    {
6964141cc406Sopenharmony_ci      DBG (0, "sendCommand(0x00) (%s:%d) failed ...\n", __FILE__, __LINE__);
6965141cc406Sopenharmony_ci      return 0;
6966141cc406Sopenharmony_ci    }
6967141cc406Sopenharmony_ci  DBG (16, "sendCommand(0x00) passed... (%s:%d)\n", __FILE__, __LINE__);
6968141cc406Sopenharmony_ci  g67E = 0;			/* bytes to read */
6969141cc406Sopenharmony_ci  if (testVersion (0) == 0)
6970141cc406Sopenharmony_ci    {
6971141cc406Sopenharmony_ci      DBG (16, "testVersion(0) (%s:%d) failed ...\n", __FILE__, __LINE__);
6972141cc406Sopenharmony_ci    }
6973141cc406Sopenharmony_ci  DBG (16, "testVersion(0) passed...\n");
6974141cc406Sopenharmony_ci  /* must fail for 1220P and 2000P */
6975141cc406Sopenharmony_ci  if (testVersion (1) == 0)	/* software doesn't do it for model 0x07 */
6976141cc406Sopenharmony_ci    {				/* but it works ..                       */
6977141cc406Sopenharmony_ci      DBG (16, "testVersion(1) failed (expected) ... (%s:%d)\n", __FILE__,
6978141cc406Sopenharmony_ci	   __LINE__);
6979141cc406Sopenharmony_ci    }
6980141cc406Sopenharmony_ci  else
6981141cc406Sopenharmony_ci    {
6982141cc406Sopenharmony_ci      DBG (16, "Unexpected success on testVersion(1) ... (%s:%d)\n", __FILE__,
6983141cc406Sopenharmony_ci	   __LINE__);
6984141cc406Sopenharmony_ci    }
6985141cc406Sopenharmony_ci  if (testVersion (0) == 0)
6986141cc406Sopenharmony_ci    {
6987141cc406Sopenharmony_ci      DBG (16, "testVersion(0) (%s:%d) failed ...\n", __FILE__, __LINE__);
6988141cc406Sopenharmony_ci    }
6989141cc406Sopenharmony_ci  DBG (16, "testVersion(0) passed...\n");
6990141cc406Sopenharmony_ci  /* must fail */
6991141cc406Sopenharmony_ci  if (testVersion (1) == 0)
6992141cc406Sopenharmony_ci    {
6993141cc406Sopenharmony_ci      DBG (16, "testVersion(1) failed (expected) ... (%s:%d)\n", __FILE__,
6994141cc406Sopenharmony_ci	   __LINE__);
6995141cc406Sopenharmony_ci    }
6996141cc406Sopenharmony_ci  else
6997141cc406Sopenharmony_ci    {
6998141cc406Sopenharmony_ci      DBG (16, "Unexpected success on testVersion(1) ... (%s:%d)\n", __FILE__,
6999141cc406Sopenharmony_ci	   __LINE__);
7000141cc406Sopenharmony_ci    }
7001141cc406Sopenharmony_ci
7002141cc406Sopenharmony_ci  Outb (DATA, 0x04);
7003141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
7004141cc406Sopenharmony_ci  Outb (DATA, 0x04);
7005141cc406Sopenharmony_ci  Outb (CONTROL, 0x0C);
7006141cc406Sopenharmony_ci
7007141cc406Sopenharmony_ci  gControl = Inb (CONTROL) & 0x3F;
7008141cc406Sopenharmony_ci  Outb (CONTROL, gControl & 0xEF);
7009141cc406Sopenharmony_ci
7010141cc406Sopenharmony_ci
7011141cc406Sopenharmony_ci
7012141cc406Sopenharmony_ci  if (sendCommand (0x40) == 0)
7013141cc406Sopenharmony_ci    {
7014141cc406Sopenharmony_ci      DBG (0, "sendCommand(0x40) (%s:%d) failed ...\n", __FILE__, __LINE__);
7015141cc406Sopenharmony_ci      return 0;
7016141cc406Sopenharmony_ci    }
7017141cc406Sopenharmony_ci  DBG (16, "sendCommand(0x40) passed...\n");
7018141cc406Sopenharmony_ci  if (sendCommand (0xE0) == 0)
7019141cc406Sopenharmony_ci    {
7020141cc406Sopenharmony_ci      DBG (0, "sendCommand(0xE0) (%s:%d) failed ...\n", __FILE__, __LINE__);
7021141cc406Sopenharmony_ci      return 0;
7022141cc406Sopenharmony_ci    }
7023141cc406Sopenharmony_ci  DBG (16, "sendCommand(0xE0) passed...\n");
7024141cc406Sopenharmony_ci
7025141cc406Sopenharmony_ci  ClearRegister (0);
7026141cc406Sopenharmony_ci  DBG (16, "ClearRegister(0) passed...\n");
7027141cc406Sopenharmony_ci
7028141cc406Sopenharmony_ci  SPPResetLPT ();
7029141cc406Sopenharmony_ci  DBG (16, "SPPResetLPT() passed...\n");
7030141cc406Sopenharmony_ci
7031141cc406Sopenharmony_ci  Outb (CONTROL, 4);
7032141cc406Sopenharmony_ci  Outb (CONTROL, 4);
7033141cc406Sopenharmony_ci
7034141cc406Sopenharmony_ci
7035141cc406Sopenharmony_ci  /* test PS2 mode */
7036141cc406Sopenharmony_ci
7037141cc406Sopenharmony_ci  tmp = PS2registerRead (0x0B);
7038141cc406Sopenharmony_ci  if (tmp == 0xC7)
7039141cc406Sopenharmony_ci    {
7040141cc406Sopenharmony_ci      /* epat C7 detected */
7041141cc406Sopenharmony_ci      DBG (16, "PS2registerRead(0x0B)=0x%X passed...\n", tmp);
7042141cc406Sopenharmony_ci
7043141cc406Sopenharmony_ci      PS2registerWrite (8, 0);
7044141cc406Sopenharmony_ci      DBG (16, "PS2registerWrite(8,0) passed...   (%s:%d)\n", __FILE__,
7045141cc406Sopenharmony_ci	   __LINE__);
7046141cc406Sopenharmony_ci
7047141cc406Sopenharmony_ci      tmp = PS2registerRead (0x0A);
7048141cc406Sopenharmony_ci      if (tmp != 0x00)
7049141cc406Sopenharmony_ci	{
7050141cc406Sopenharmony_ci	  if (tmp == 0x1C)
7051141cc406Sopenharmony_ci	    {
7052141cc406Sopenharmony_ci	      DBG (16, "Previous probe detected ... (%s:%d)\n", __FILE__,
7053141cc406Sopenharmony_ci		   __LINE__);
7054141cc406Sopenharmony_ci	    }
7055141cc406Sopenharmony_ci	  else
7056141cc406Sopenharmony_ci	    {
7057141cc406Sopenharmony_ci	      DBG (0, "Found 0x%X expected 0x00  (%s:%d)\n", tmp, __FILE__,
7058141cc406Sopenharmony_ci		   __LINE__);
7059141cc406Sopenharmony_ci	    }
7060141cc406Sopenharmony_ci	}
7061141cc406Sopenharmony_ci      DBG (16, "PS2registerRead(0x0A)=0x%X passed ...(%s:%d)\n", tmp,
7062141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7063141cc406Sopenharmony_ci
7064141cc406Sopenharmony_ci    }
7065141cc406Sopenharmony_ci  else
7066141cc406Sopenharmony_ci    {
7067141cc406Sopenharmony_ci      DBG (4, "Found 0x%X expected 0xC7 (%s:%d)\n", tmp, __FILE__, __LINE__);
7068141cc406Sopenharmony_ci      if ((tmp == 0xFF) && (sanei_umax_pp_getparport () < 1))
7069141cc406Sopenharmony_ci	{
7070141cc406Sopenharmony_ci	  DBG (0,
7071141cc406Sopenharmony_ci	       "It is likely that the hardware address (0x%X) you specified is wrong\n",
7072141cc406Sopenharmony_ci	       gPort);
7073141cc406Sopenharmony_ci	  return 0;
7074141cc406Sopenharmony_ci	}
7075141cc406Sopenharmony_ci      /* probe for a 610p, since we can't detect an EPAT */
7076141cc406Sopenharmony_ci      DBG (1, "Trying 610p (%s:%d)\n", __FILE__, __LINE__);
7077141cc406Sopenharmony_ci      return probe610p (recover);
7078141cc406Sopenharmony_ci    }
7079141cc406Sopenharmony_ci
7080141cc406Sopenharmony_ci  /* clear register 3 */
7081141cc406Sopenharmony_ci  ClearRegister (3);
7082141cc406Sopenharmony_ci  DBG (16, "ClearRegister(3) passed...\n");
7083141cc406Sopenharmony_ci
7084141cc406Sopenharmony_ci  /* wait ? */
7085141cc406Sopenharmony_ci  i = 65535;
7086141cc406Sopenharmony_ci  while (i > 0)
7087141cc406Sopenharmony_ci    {
7088141cc406Sopenharmony_ci      tmp = Inb (DATA);
7089141cc406Sopenharmony_ci      tmp = Inb (DATA);
7090141cc406Sopenharmony_ci      i--;
7091141cc406Sopenharmony_ci    }
7092141cc406Sopenharmony_ci  DBG (16, "FFFF in loop passed...\n");
7093141cc406Sopenharmony_ci
7094141cc406Sopenharmony_ci  ClearRegister (0);
7095141cc406Sopenharmony_ci  DBG (16, "ClearRegister(0) passed... (%s:%d)\n", __FILE__, __LINE__);
7096141cc406Sopenharmony_ci  fflush (stdout);
7097141cc406Sopenharmony_ci
7098141cc406Sopenharmony_ci  /* 1220/2000P branch */
7099141cc406Sopenharmony_ci  WRITESLOW (0x0E, 1);
7100141cc406Sopenharmony_ci
7101141cc406Sopenharmony_ci  /* register 0x0F used only once: model number ? Or ASIC revision ? */
7102141cc406Sopenharmony_ci  /* comm mode ?                                                     */
7103141cc406Sopenharmony_ci  model = PS2registerRead (0x0F);
7104141cc406Sopenharmony_ci  DBG (1, "UMAX Astra 1220/1600/2000 P ASIC detected (mode=%d)\n", model);
7105141cc406Sopenharmony_ci  setModel (model);
7106141cc406Sopenharmony_ci  DBG (16, "PS2registerRead(0x0F) passed... (%s:%d)\n", __FILE__, __LINE__);
7107141cc406Sopenharmony_ci
7108141cc406Sopenharmony_ci  /* scanner powered off */
7109141cc406Sopenharmony_ci  if (model == 0x1B)
7110141cc406Sopenharmony_ci    {
7111141cc406Sopenharmony_ci      DBG (0, "Register 0x0F=0x1B, scanner powered off ! (%s:%d)\n", __FILE__,
7112141cc406Sopenharmony_ci	   __LINE__);
7113141cc406Sopenharmony_ci      return 0;
7114141cc406Sopenharmony_ci    }
7115141cc406Sopenharmony_ci
7116141cc406Sopenharmony_ci
7117141cc406Sopenharmony_ci  if ((model != 0x1F) && (model != 0x07))
7118141cc406Sopenharmony_ci    {
7119141cc406Sopenharmony_ci      DBG
7120141cc406Sopenharmony_ci	(0,
7121141cc406Sopenharmony_ci	 "Unexpected value for for register 0x0F, expected 0x07 or 0x1F, got 0x%02X ! (%s:%d)\n",
7122141cc406Sopenharmony_ci	 model, __FILE__, __LINE__);
7123141cc406Sopenharmony_ci      DBG (0, "There is a new scanner revision in town, or a bug ....\n");
7124141cc406Sopenharmony_ci    }
7125141cc406Sopenharmony_ci
7126141cc406Sopenharmony_ci  WRITESLOW (0x08, 0x02);
7127141cc406Sopenharmony_ci  WRITESLOW (0x0E, 0x0F);
7128141cc406Sopenharmony_ci  WRITESLOW (0x0F, 0x0C);
7129141cc406Sopenharmony_ci  WRITESLOW (0x0C, 0x04);
7130141cc406Sopenharmony_ci  tmp = PS2registerRead (0x0D);
7131141cc406Sopenharmony_ci  if ((tmp != 0x00) && (tmp != 0x40))
7132141cc406Sopenharmony_ci    {
7133141cc406Sopenharmony_ci      DBG
7134141cc406Sopenharmony_ci	(0,
7135141cc406Sopenharmony_ci	 "Unexpected value for for register 0x0D, expected 0x00 or 0x40, got 0x%02X ! (%s:%d)\n",
7136141cc406Sopenharmony_ci	 tmp, __FILE__, __LINE__);
7137141cc406Sopenharmony_ci    }
7138141cc406Sopenharmony_ci  WRITESLOW (0x0D, 0x1B);
7139141cc406Sopenharmony_ci  switch (model)
7140141cc406Sopenharmony_ci    {
7141141cc406Sopenharmony_ci    case 0x1F:
7142141cc406Sopenharmony_ci      WRITESLOW (0x12, 0x14);
7143141cc406Sopenharmony_ci      SLOWNIBBLEREGISTERREAD (0x12, 0x10);
7144141cc406Sopenharmony_ci      break;
7145141cc406Sopenharmony_ci    case 0x07:
7146141cc406Sopenharmony_ci      WRITESLOW (0x12, 0x00);
7147141cc406Sopenharmony_ci      SLOWNIBBLEREGISTERREAD (0x12, 0x00);
7148141cc406Sopenharmony_ci      /* we may get 0x20, in this case some color aberration may occur */
7149141cc406Sopenharmony_ci      /* must depend on the parport */
7150141cc406Sopenharmony_ci      /* model 0x07 + 0x00=>0x20=2000P */
7151141cc406Sopenharmony_ci      break;
7152141cc406Sopenharmony_ci    default:
7153141cc406Sopenharmony_ci      WRITESLOW (0x12, 0x00);
7154141cc406Sopenharmony_ci      SLOWNIBBLEREGISTERREAD (0x12, 0x20);
7155141cc406Sopenharmony_ci      break;
7156141cc406Sopenharmony_ci    }
7157141cc406Sopenharmony_ci  SLOWNIBBLEREGISTERREAD (0x0D, 0x18);
7158141cc406Sopenharmony_ci  SLOWNIBBLEREGISTERREAD (0x0C, 0x04);
7159141cc406Sopenharmony_ci  SLOWNIBBLEREGISTERREAD (0x0A, 0x00);
7160141cc406Sopenharmony_ci  WRITESLOW (0x0E, 0x0A);
7161141cc406Sopenharmony_ci  WRITESLOW (0x0F, 0x00);
7162141cc406Sopenharmony_ci  WRITESLOW (0x0E, 0x0D);
7163141cc406Sopenharmony_ci  WRITESLOW (0x0F, 0x00);
7164141cc406Sopenharmony_ci  dest = (unsigned char *) malloc (65536);
7165141cc406Sopenharmony_ci  if (dest == NULL)
7166141cc406Sopenharmony_ci    {
7167141cc406Sopenharmony_ci      DBG (0, "Failed to allocate 64K (%s:%d)\n", __FILE__, __LINE__);
7168141cc406Sopenharmony_ci      return 0;
7169141cc406Sopenharmony_ci    }
7170141cc406Sopenharmony_ci
7171141cc406Sopenharmony_ci  gMode = UMAX_PP_PARPORT_PS2;
7172141cc406Sopenharmony_ci  if (probePS2 (dest))
7173141cc406Sopenharmony_ci    {				/* PS2 mode works */
7174141cc406Sopenharmony_ci      DBG (16, "probePS2 passed ... (%s:%d)\n", __FILE__, __LINE__);
7175141cc406Sopenharmony_ci      gprobed = UMAX_PP_PARPORT_PS2;
7176141cc406Sopenharmony_ci    }
7177141cc406Sopenharmony_ci
7178141cc406Sopenharmony_ci  Outb (CONTROL, 4);
7179141cc406Sopenharmony_ci  SLOWNIBBLEREGISTERREAD (0x0A, 0x18);
7180141cc406Sopenharmony_ci  WRITESLOW (0x08, 0x40);
7181141cc406Sopenharmony_ci  WRITESLOW (0x08, 0x60);
7182141cc406Sopenharmony_ci  WRITESLOW (0x08, 0x22);
7183141cc406Sopenharmony_ci
7184141cc406Sopenharmony_ci  gMode = UMAX_PP_PARPORT_EPP;
7185141cc406Sopenharmony_ci  if (probeEPP (dest))
7186141cc406Sopenharmony_ci    {				/* EPP mode works */
7187141cc406Sopenharmony_ci      gprobed = UMAX_PP_PARPORT_EPP;
7188141cc406Sopenharmony_ci      gMode = UMAX_PP_PARPORT_EPP;
7189141cc406Sopenharmony_ci      DBG (16, "probeEPP passed ... (%s:%d)\n", __FILE__, __LINE__);
7190141cc406Sopenharmony_ci    }
7191141cc406Sopenharmony_ci  else
7192141cc406Sopenharmony_ci    {				/* EPP fails, try ECP */
7193141cc406Sopenharmony_ci      DBG (16, "probeEPP failed ... (%s:%d)\n", __FILE__, __LINE__);
7194141cc406Sopenharmony_ci      gMode = UMAX_PP_PARPORT_ECP;
7195141cc406Sopenharmony_ci      if (probeECP (dest))
7196141cc406Sopenharmony_ci	{			/* ECP mode works */
7197141cc406Sopenharmony_ci	  DBG (16, "probeECP passed ... (%s:%d)\n", __FILE__, __LINE__);
7198141cc406Sopenharmony_ci	  gprobed = UMAX_PP_PARPORT_ECP;
7199141cc406Sopenharmony_ci	}
7200141cc406Sopenharmony_ci      else
7201141cc406Sopenharmony_ci	{			/* ECP and EPP fail, give up */
7202141cc406Sopenharmony_ci	  /* PS2 could be used */
7203141cc406Sopenharmony_ci	  DBG (16, "probeECP failed ... (%s:%d)\n", __FILE__, __LINE__);
7204141cc406Sopenharmony_ci	  DBG (1, "No EPP or ECP mode working, giving up ... (%s:%d)\n",
7205141cc406Sopenharmony_ci	       __FILE__, __LINE__);
7206141cc406Sopenharmony_ci	  free (dest);
7207141cc406Sopenharmony_ci	  return 0;
7208141cc406Sopenharmony_ci	}
7209141cc406Sopenharmony_ci    }
7210141cc406Sopenharmony_ci
7211141cc406Sopenharmony_ci  /* some operations here may have to go into probeEPP/probeECP */
7212141cc406Sopenharmony_ci  g6FE = 1;
7213141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
7214141cc406Sopenharmony_ci    {
7215141cc406Sopenharmony_ci      WRITESLOW (0x08, 0x01);
7216141cc406Sopenharmony_ci      Outb (CONTROL, 0x0C);
7217141cc406Sopenharmony_ci      Outb (CONTROL, 0x04);
7218141cc406Sopenharmony_ci      ClearRegister (0);
7219141cc406Sopenharmony_ci      tmp = PS2Something (0x10);
7220141cc406Sopenharmony_ci      if (tmp != 0x0B)
7221141cc406Sopenharmony_ci	{
7222141cc406Sopenharmony_ci	  DBG (0,
7223141cc406Sopenharmony_ci	       "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", tmp,
7224141cc406Sopenharmony_ci	       __FILE__, __LINE__);
7225141cc406Sopenharmony_ci	}
7226141cc406Sopenharmony_ci    }
7227141cc406Sopenharmony_ci  else
7228141cc406Sopenharmony_ci    {
7229141cc406Sopenharmony_ci      WRITESLOW (0x08, 0x21);
7230141cc406Sopenharmony_ci      init001 ();
7231141cc406Sopenharmony_ci      DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__);
7232141cc406Sopenharmony_ci    }
7233141cc406Sopenharmony_ci
7234141cc406Sopenharmony_ci
7235141cc406Sopenharmony_ci  reg = registerRead (0x0D);
7236141cc406Sopenharmony_ci  reg = (reg & 0xE8) | 0x43;
7237141cc406Sopenharmony_ci  registerWrite (0x0D, reg);
7238141cc406Sopenharmony_ci
7239141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);
7240141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0F);
7241141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x0C);
7242141cc406Sopenharmony_ci
7243141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x1C);
7244141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x10);
7245141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x1C);
7246141cc406Sopenharmony_ci
7247141cc406Sopenharmony_ci
7248141cc406Sopenharmony_ci  reg = registerRead (0x0D);	/* 0x48 expected */
7249141cc406Sopenharmony_ci  reg = registerRead (0x0D);
7250141cc406Sopenharmony_ci  reg = registerRead (0x0D);
7251141cc406Sopenharmony_ci  reg = (reg & 0xB7) | 0x03;
7252141cc406Sopenharmony_ci  registerWrite (0x0D, reg);
7253141cc406Sopenharmony_ci  DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
7254141cc406Sopenharmony_ci
7255141cc406Sopenharmony_ci  reg = registerRead (0x12);	/* 0x10 for model 0x0F, 0x20 for model 0x07 */
7256141cc406Sopenharmony_ci  /* 0x00 when in ECP mode ... */
7257141cc406Sopenharmony_ci  reg = reg & 0xEF;
7258141cc406Sopenharmony_ci  registerWrite (0x12, reg);
7259141cc406Sopenharmony_ci  DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
7260141cc406Sopenharmony_ci
7261141cc406Sopenharmony_ci  reg = registerRead (0x0A);
7262141cc406Sopenharmony_ci  if (reg != 0x1C)
7263141cc406Sopenharmony_ci    {
7264141cc406Sopenharmony_ci      DBG (0, "Warning! expected reg0A=0x1C, found 0x%02X! (%s:%d) \n", reg,
7265141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7266141cc406Sopenharmony_ci    }
7267141cc406Sopenharmony_ci  DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
7268141cc406Sopenharmony_ci
7269141cc406Sopenharmony_ci  /*Inb(CONTROL);       ECP 0x04 expected */
7270141cc406Sopenharmony_ci  disconnect ();
7271141cc406Sopenharmony_ci  DBG (16, "disconnect() passed... (%s:%d)\n", __FILE__, __LINE__);
7272141cc406Sopenharmony_ci  connect ();
7273141cc406Sopenharmony_ci  DBG (16, "connect() passed... (%s:%d)\n", __FILE__, __LINE__);
7274141cc406Sopenharmony_ci
7275141cc406Sopenharmony_ci
7276141cc406Sopenharmony_ci  /* some sort of countdown, some warming-up ? */
7277141cc406Sopenharmony_ci  /* maybe some data sent to the stepper motor */
7278141cc406Sopenharmony_ci  /* if (model == 0x07) */
7279141cc406Sopenharmony_ci  {
7280141cc406Sopenharmony_ci    /* REGISTERWRITE (0x0A, 0x00);
7281141cc406Sopenharmony_ci       reg = registerRead (0x0D);
7282141cc406Sopenharmony_ci       reg = (reg & 0xE8);
7283141cc406Sopenharmony_ci       registerWrite (0x0D, reg);
7284141cc406Sopenharmony_ci       DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__); */
7285141cc406Sopenharmony_ci    epilogue ();
7286141cc406Sopenharmony_ci    prologue (0x10);
7287141cc406Sopenharmony_ci
7288141cc406Sopenharmony_ci    reg = registerRead (0x13);
7289141cc406Sopenharmony_ci    if (reg != 0x00)
7290141cc406Sopenharmony_ci      {
7291141cc406Sopenharmony_ci	DBG (0, "Warning! expected reg13=0x00, found 0x%02X! (%s:%d) \n",
7292141cc406Sopenharmony_ci	     reg, __FILE__, __LINE__);
7293141cc406Sopenharmony_ci      }
7294141cc406Sopenharmony_ci    REGISTERWRITE (0x13, 0x81);
7295141cc406Sopenharmony_ci    usleep (10000);
7296141cc406Sopenharmony_ci    REGISTERWRITE (0x13, 0x80);
7297141cc406Sopenharmony_ci    /* could it be step-motor values ? */
7298141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x04);	/* FF->R04 */
7299141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0xFF);
7300141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x05);	/* 03->R05 */
7301141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x03);
7302141cc406Sopenharmony_ci    REGISTERWRITE (0x10, 0x66);
7303141cc406Sopenharmony_ci    usleep (10000);
7304141cc406Sopenharmony_ci
7305141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x04);	/* FF->R04 */
7306141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0xFF);
7307141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x05);	/* 01 ->R05 */
7308141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x01);
7309141cc406Sopenharmony_ci    REGISTERWRITE (0x10, 0x55);
7310141cc406Sopenharmony_ci    usleep (10000);
7311141cc406Sopenharmony_ci
7312141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x04);	/* FF -> R04 */
7313141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0xFF);
7314141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x05);	/* 00 -> R05 */
7315141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x00);
7316141cc406Sopenharmony_ci    REGISTERWRITE (0x10, 0x44);
7317141cc406Sopenharmony_ci    usleep (10000);
7318141cc406Sopenharmony_ci
7319141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x04);	/* 7F -> R04 */
7320141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x7F);
7321141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x05);	/* 00 -> R05 */
7322141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x00);
7323141cc406Sopenharmony_ci    REGISTERWRITE (0x10, 0x33);
7324141cc406Sopenharmony_ci    usleep (10000);
7325141cc406Sopenharmony_ci
7326141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x04);	/* 3F -> R04 */
7327141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x3F);
7328141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x05);
7329141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x00);	/* 00 -> R05 */
7330141cc406Sopenharmony_ci    REGISTERWRITE (0x10, 0x22);
7331141cc406Sopenharmony_ci    usleep (10000);
7332141cc406Sopenharmony_ci
7333141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x04);
7334141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x00);
7335141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x05);
7336141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x00);
7337141cc406Sopenharmony_ci    REGISTERWRITE (0x10, 0x11);
7338141cc406Sopenharmony_ci    usleep (10000);
7339141cc406Sopenharmony_ci
7340141cc406Sopenharmony_ci    REGISTERWRITE (0x13, 0x81);
7341141cc406Sopenharmony_ci    usleep (10000);
7342141cc406Sopenharmony_ci    REGISTERWRITE (0x13, 0x80);
7343141cc406Sopenharmony_ci
7344141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x04);
7345141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x00);
7346141cc406Sopenharmony_ci    REGISTERWRITE (0x0E, 0x05);
7347141cc406Sopenharmony_ci    REGISTERWRITE (0x0F, 0x00);
7348141cc406Sopenharmony_ci    usleep (10000);
7349141cc406Sopenharmony_ci
7350141cc406Sopenharmony_ci    reg = registerRead (0x10);
7351141cc406Sopenharmony_ci    DBG (1, "Count-down value is 0x%02X  (%s:%d)\n", reg, __FILE__, __LINE__);
7352141cc406Sopenharmony_ci    /* 2 reports of CF, was FF first (typo ?) */
7353141cc406Sopenharmony_ci    /* CF seems a valid value                 */
7354141cc406Sopenharmony_ci    /* in case of CF, we may have timeout ... */
7355141cc406Sopenharmony_ci    /*if (reg != 0x00)
7356141cc406Sopenharmony_ci       {
7357141cc406Sopenharmony_ci       DBG (0, "Warning! expected reg10=0x00, found 0x%02X! (%s:%d) \n",
7358141cc406Sopenharmony_ci       reg, __FILE__, __LINE__);
7359141cc406Sopenharmony_ci       } */
7360141cc406Sopenharmony_ci    REGISTERWRITE (0x13, 0x00);
7361141cc406Sopenharmony_ci  }
7362141cc406Sopenharmony_ci/* end of countdown */
7363141cc406Sopenharmony_ci  DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
7364141cc406Sopenharmony_ci  /* *NOT* epilogue(); (when EPP) */
7365141cc406Sopenharmony_ci  /*REGISTERWRITE (0x0A, 0x00);
7366141cc406Sopenharmony_ci     REGISTERREAD (0x0D, 0x40);
7367141cc406Sopenharmony_ci     REGISTERWRITE (0x0D, 0x00); */
7368141cc406Sopenharmony_ci  epilogue ();
7369141cc406Sopenharmony_ci  prologue (0x10);
7370141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0D);
7371141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x00);
7372141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x1C);
7373141cc406Sopenharmony_ci
7374141cc406Sopenharmony_ci  /* real start of high level protocol ? */
7375141cc406Sopenharmony_ci  if (fonc001 () != 1)
7376141cc406Sopenharmony_ci    {
7377141cc406Sopenharmony_ci      DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__);
7378141cc406Sopenharmony_ci      return 0;
7379141cc406Sopenharmony_ci    }
7380141cc406Sopenharmony_ci  DBG (16, "fonc001() passed (%s:%d) \n", __FILE__, __LINE__);
7381141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xC8;
7382141cc406Sopenharmony_ci  /* if reg=E8 or D8 , we have a 'messed' scanner */
7383141cc406Sopenharmony_ci
7384141cc406Sopenharmony_ci  /* 4 transform buffers + 'void' are sent: 1 B&W, and 3 RGB ? */
7385141cc406Sopenharmony_ci  memset (initbuf, 0x00, 2048 * sizeof (int));
7386141cc406Sopenharmony_ci  memset (voidbuf, 0x00, 2048 * sizeof (int));
7387141cc406Sopenharmony_ci
7388141cc406Sopenharmony_ci  initbuf[512] = 0xFF;
7389141cc406Sopenharmony_ci  initbuf[513] = 0xAA;
7390141cc406Sopenharmony_ci  initbuf[514] = 0x55;
7391141cc406Sopenharmony_ci
7392141cc406Sopenharmony_ci  for (j = 0; j < 4; j++)
7393141cc406Sopenharmony_ci    {
7394141cc406Sopenharmony_ci      for (i = 0; i < 256; i++)
7395141cc406Sopenharmony_ci	{
7396141cc406Sopenharmony_ci	  voidbuf[512 * j + 2 * i] = i;
7397141cc406Sopenharmony_ci	  voidbuf[512 * j + 2 * i] = 0xFF - i;
7398141cc406Sopenharmony_ci	}
7399141cc406Sopenharmony_ci    }
7400141cc406Sopenharmony_ci
7401141cc406Sopenharmony_ci  /* one pass (B&W ?) */
7402141cc406Sopenharmony_ci  if (cmdSetDataBuffer (initbuf) != 1)
7403141cc406Sopenharmony_ci    {
7404141cc406Sopenharmony_ci      DBG (0, "cmdSetDataBuffer(initbuf) failed ! (%s:%d) \n", __FILE__,
7405141cc406Sopenharmony_ci	   __LINE__);
7406141cc406Sopenharmony_ci      return 0;
7407141cc406Sopenharmony_ci    }
7408141cc406Sopenharmony_ci  DBG (16, "cmdSetDataBuffer(initbuf) passed... (%s:%d)\n", __FILE__,
7409141cc406Sopenharmony_ci       __LINE__);
7410141cc406Sopenharmony_ci  if (cmdSetDataBuffer (voidbuf) != 1)
7411141cc406Sopenharmony_ci    {
7412141cc406Sopenharmony_ci      DBG (0, "cmdSetDataBuffer(voidbuf) failed ! (%s:%d) \n", __FILE__,
7413141cc406Sopenharmony_ci	   __LINE__);
7414141cc406Sopenharmony_ci      return 0;
7415141cc406Sopenharmony_ci    }
7416141cc406Sopenharmony_ci  DBG (16, "cmdSetDataBuffer(voidbuf) passed... (%s:%d)\n", __FILE__,
7417141cc406Sopenharmony_ci       __LINE__);
7418141cc406Sopenharmony_ci
7419141cc406Sopenharmony_ci  /* everything above the FF 55 AA tag is 'void' */
7420141cc406Sopenharmony_ci  /* it seems that the buffer is reused and only the beginning is initialized */
7421141cc406Sopenharmony_ci  for (i = 515; i < 2048; i++)
7422141cc406Sopenharmony_ci    initbuf[i] = voidbuf[i];
7423141cc406Sopenharmony_ci
7424141cc406Sopenharmony_ci  /* three pass (RGB ?) */
7425141cc406Sopenharmony_ci  for (i = 0; i < 3; i++)
7426141cc406Sopenharmony_ci    {
7427141cc406Sopenharmony_ci      if (cmdSetDataBuffer (initbuf) != 1)
7428141cc406Sopenharmony_ci	{
7429141cc406Sopenharmony_ci	  DBG (0, "cmdSetDataBuffer(initbuf) failed ! (%s:%d) \n", __FILE__,
7430141cc406Sopenharmony_ci	       __LINE__);
7431141cc406Sopenharmony_ci	  return 0;
7432141cc406Sopenharmony_ci	}
7433141cc406Sopenharmony_ci      DBG (16, "Loop %d: cmdSetDataBuffer(initbuf) passed... (%s:%d)\n", i,
7434141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7435141cc406Sopenharmony_ci      if (cmdSetDataBuffer (voidbuf) != 1)
7436141cc406Sopenharmony_ci	{
7437141cc406Sopenharmony_ci	  DBG (0, "Loop %d: cmdSetDataBuffer(voidbuf) failed ! (%s:%d) \n", i,
7438141cc406Sopenharmony_ci	       __FILE__, __LINE__);
7439141cc406Sopenharmony_ci	  return 0;
7440141cc406Sopenharmony_ci	}
7441141cc406Sopenharmony_ci    }
7442141cc406Sopenharmony_ci
7443141cc406Sopenharmony_ci
7444141cc406Sopenharmony_ci  /* memory size testing ? */
7445141cc406Sopenharmony_ci  /* load 150 Ko in scanner */
7446141cc406Sopenharmony_ci  REGISTERWRITE (0x1A, 0x00);
7447141cc406Sopenharmony_ci  REGISTERWRITE (0x1A, 0x0C);
7448141cc406Sopenharmony_ci  REGISTERWRITE (0x1A, 0x00);
7449141cc406Sopenharmony_ci  REGISTERWRITE (0x1A, 0x0C);
7450141cc406Sopenharmony_ci
7451141cc406Sopenharmony_ci
7452141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x11);	/* start */
7453141cc406Sopenharmony_ci  nb = 150;
7454141cc406Sopenharmony_ci  for (i = 0; i < nb; i++)	/* 300 for ECP ??? */
7455141cc406Sopenharmony_ci    {
7456141cc406Sopenharmony_ci      bufferWrite (0x400, dest);
7457141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i,
7458141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7459141cc406Sopenharmony_ci    }
7460141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);	/* end */
7461141cc406Sopenharmony_ci
7462141cc406Sopenharmony_ci  /* read them back */
7463141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x11);	/*start transfer */
7464141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
7465141cc406Sopenharmony_ci    {
7466141cc406Sopenharmony_ci      ECPSetBuffer (0x400);
7467141cc406Sopenharmony_ci    }
7468141cc406Sopenharmony_ci
7469141cc406Sopenharmony_ci  for (i = 0; i < nb; i++)	/* 300 for ECP ??? */
7470141cc406Sopenharmony_ci    {
7471141cc406Sopenharmony_ci      bufferRead (0x400, dest);
7472141cc406Sopenharmony_ci      DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n", i,
7473141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7474141cc406Sopenharmony_ci    }
7475141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x18);	/*end transfer */
7476141cc406Sopenharmony_ci
7477141cc406Sopenharmony_ci  /* fully disconnect, then reconnect */
7478141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
7479141cc406Sopenharmony_ci    {
7480141cc406Sopenharmony_ci      epilogue ();
7481141cc406Sopenharmony_ci      sendCommand (0xE0);
7482141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
7483141cc406Sopenharmony_ci      Outb (DATA, 0xFF);
7484141cc406Sopenharmony_ci      ClearRegister (0);
7485141cc406Sopenharmony_ci      WRITESLOW (0x0E, 0x0A);
7486141cc406Sopenharmony_ci      SLOWNIBBLEREGISTERREAD (0x0F, 0x00);
7487141cc406Sopenharmony_ci      WRITESLOW (0x0F, 0x08);
7488141cc406Sopenharmony_ci      WRITESLOW (0x08, 0x10);	/* 0x10 ?? */
7489141cc406Sopenharmony_ci      prologue (0x10);
7490141cc406Sopenharmony_ci    }
7491141cc406Sopenharmony_ci
7492141cc406Sopenharmony_ci
7493141cc406Sopenharmony_ci  /* almost cmdSync(0x00) which halts any pending operation */
7494141cc406Sopenharmony_ci  if (fonc001 () != 1)
7495141cc406Sopenharmony_ci    {
7496141cc406Sopenharmony_ci      DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__);
7497141cc406Sopenharmony_ci      return 0;
7498141cc406Sopenharmony_ci    }
7499141cc406Sopenharmony_ci  DBG (16, "Fct001() passed (%s:%d) \n", __FILE__, __LINE__);
7500141cc406Sopenharmony_ci  if (sendWord (zero) == 0)
7501141cc406Sopenharmony_ci    {
7502141cc406Sopenharmony_ci      DBG (0, "sendWord(zero) failed (%s:%d)\n", __FILE__, __LINE__);
7503141cc406Sopenharmony_ci      return 0;
7504141cc406Sopenharmony_ci    }
7505141cc406Sopenharmony_ci  epilogue ();
7506141cc406Sopenharmony_ci  DBG (16, "sendWord(zero) passed (%s:%d)\n", __FILE__, __LINE__);
7507141cc406Sopenharmony_ci
7508141cc406Sopenharmony_ci
7509141cc406Sopenharmony_ci  /* end transport init */
7510141cc406Sopenharmony_ci  /* now high level (connected) protocol begins */
7511141cc406Sopenharmony_ci  val = sanei_umax_pp_initScanner (recover);
7512141cc406Sopenharmony_ci  if (val == 0)
7513141cc406Sopenharmony_ci    {
7514141cc406Sopenharmony_ci      DBG (0, "initScanner() failed (%s:%d)\n", __FILE__, __LINE__);
7515141cc406Sopenharmony_ci      return 0;
7516141cc406Sopenharmony_ci    }
7517141cc406Sopenharmony_ci
7518141cc406Sopenharmony_ci
7519141cc406Sopenharmony_ci  /* if no homing .... */
7520141cc406Sopenharmony_ci  if (val == 1)
7521141cc406Sopenharmony_ci    {
7522141cc406Sopenharmony_ci      CMDSYNC (0);
7523141cc406Sopenharmony_ci      CMDSYNC (0xC2);
7524141cc406Sopenharmony_ci      CMDSYNC (0);
7525141cc406Sopenharmony_ci    }
7526141cc406Sopenharmony_ci
7527141cc406Sopenharmony_ci  /* set port to its initial state */
7528141cc406Sopenharmony_ci  Outb (DATA, gData);
7529141cc406Sopenharmony_ci  Outb (CONTROL, gControl);
7530141cc406Sopenharmony_ci
7531141cc406Sopenharmony_ci  free (dest);
7532141cc406Sopenharmony_ci  DBG (1, "probe done ...\n");
7533141cc406Sopenharmony_ci  return 1;
7534141cc406Sopenharmony_ci}
7535141cc406Sopenharmony_ci
7536141cc406Sopenharmony_ci
7537141cc406Sopenharmony_cistatic int
7538141cc406Sopenharmony_cidisconnect_epat (void)
7539141cc406Sopenharmony_ci{
7540141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x00);
7541141cc406Sopenharmony_ci  registerRead (0x0D);
7542141cc406Sopenharmony_ci  REGISTERWRITE (0x0D, 0x00);
7543141cc406Sopenharmony_ci  disconnect ();
7544141cc406Sopenharmony_ci  return 1;
7545141cc406Sopenharmony_ci}
7546141cc406Sopenharmony_ci
7547141cc406Sopenharmony_ci
7548141cc406Sopenharmony_cistatic int
7549141cc406Sopenharmony_ciconnect_epat (int r08)
7550141cc406Sopenharmony_ci{
7551141cc406Sopenharmony_ci  int reg;
7552141cc406Sopenharmony_ci
7553141cc406Sopenharmony_ci  if (connect () != 1)
7554141cc406Sopenharmony_ci    {
7555141cc406Sopenharmony_ci      DBG (0, "connect_epat: connect() failed! (%s:%d)\n", __FILE__,
7556141cc406Sopenharmony_ci	   __LINE__);
7557141cc406Sopenharmony_ci      return 0;
7558141cc406Sopenharmony_ci    }
7559141cc406Sopenharmony_ci
7560141cc406Sopenharmony_ci  reg = registerRead (0x0B);
7561141cc406Sopenharmony_ci  if (reg != gEPAT)
7562141cc406Sopenharmony_ci    {
7563141cc406Sopenharmony_ci      /* ASIC version            is not */
7564141cc406Sopenharmony_ci      /* the one expected (epat c7)     */
7565141cc406Sopenharmony_ci      DBG (0, "Error! expected reg0B=0x%02X, found 0x%02X! (%s:%d) \n", gEPAT,
7566141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
7567141cc406Sopenharmony_ci      /* we try to clean all */
7568141cc406Sopenharmony_ci      disconnect ();
7569141cc406Sopenharmony_ci      return 0;
7570141cc406Sopenharmony_ci    }
7571141cc406Sopenharmony_ci  reg = registerRead (0x0D);
7572141cc406Sopenharmony_ci  reg = (reg | 0x43) & 0xEB;
7573141cc406Sopenharmony_ci  REGISTERWRITE (0x0D, reg);
7574141cc406Sopenharmony_ci  REGISTERWRITE (0x0C, 0x04);
7575141cc406Sopenharmony_ci  reg = registerRead (0x0A);
7576141cc406Sopenharmony_ci  if (reg != 0x00)
7577141cc406Sopenharmony_ci    {
7578141cc406Sopenharmony_ci      /* a previous unfinished command */
7579141cc406Sopenharmony_ci      /* has left an uncleared value   */
7580141cc406Sopenharmony_ci      DBG (0, "Warning! expected reg0A=0x00, found 0x%02X! (%s:%d) \n", reg,
7581141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7582141cc406Sopenharmony_ci    }
7583141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x1C);
7584141cc406Sopenharmony_ci  if (r08 != 0)
7585141cc406Sopenharmony_ci    {
7586141cc406Sopenharmony_ci      if (gMode == UMAX_PP_PARPORT_ECP)
7587141cc406Sopenharmony_ci	{
7588141cc406Sopenharmony_ci	  REGISTERWRITE (0x08, r08);	/* 0x01 or 0x10 ??? */
7589141cc406Sopenharmony_ci	}
7590141cc406Sopenharmony_ci      else
7591141cc406Sopenharmony_ci	{
7592141cc406Sopenharmony_ci	  REGISTERWRITE (0x08, 0x21);
7593141cc406Sopenharmony_ci	}
7594141cc406Sopenharmony_ci    }
7595141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0F);
7596141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x0C);
7597141cc406Sopenharmony_ci  REGISTERWRITE (0x0A, 0x1C);
7598141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x10);
7599141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x1C);
7600141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
7601141cc406Sopenharmony_ci    {
7602141cc406Sopenharmony_ci      REGISTERWRITE (0x0F, 0x00);
7603141cc406Sopenharmony_ci    }
7604141cc406Sopenharmony_ci  return 1;
7605141cc406Sopenharmony_ci}
7606141cc406Sopenharmony_ci
7607141cc406Sopenharmony_ci
7608141cc406Sopenharmony_cistatic int
7609141cc406Sopenharmony_ciprologue (int r08)
7610141cc406Sopenharmony_ci{
7611141cc406Sopenharmony_ci  switch (sanei_umax_pp_getastra ())
7612141cc406Sopenharmony_ci    {
7613141cc406Sopenharmony_ci    case 610:
7614141cc406Sopenharmony_ci      connect610p ();
7615141cc406Sopenharmony_ci      return sync610p ();
7616141cc406Sopenharmony_ci    case 1220:
7617141cc406Sopenharmony_ci    case 1600:
7618141cc406Sopenharmony_ci    case 2000:
7619141cc406Sopenharmony_ci    default:
7620141cc406Sopenharmony_ci      return connect_epat (r08);
7621141cc406Sopenharmony_ci    }
7622141cc406Sopenharmony_ci}
7623141cc406Sopenharmony_ci
7624141cc406Sopenharmony_ci
7625141cc406Sopenharmony_ci
7626141cc406Sopenharmony_cistatic int
7627141cc406Sopenharmony_ciepilogue (void)
7628141cc406Sopenharmony_ci{
7629141cc406Sopenharmony_ci  switch (sanei_umax_pp_getastra ())
7630141cc406Sopenharmony_ci    {
7631141cc406Sopenharmony_ci    case 610:
7632141cc406Sopenharmony_ci      return disconnect610p ();
7633141cc406Sopenharmony_ci    case 1220:
7634141cc406Sopenharmony_ci    case 1600:
7635141cc406Sopenharmony_ci    case 2000:
7636141cc406Sopenharmony_ci    default:
7637141cc406Sopenharmony_ci      return disconnect_epat ();
7638141cc406Sopenharmony_ci    }
7639141cc406Sopenharmony_ci}
7640141cc406Sopenharmony_ci
7641141cc406Sopenharmony_ci
7642141cc406Sopenharmony_cistatic int
7643141cc406Sopenharmony_ciEPPcmdGet610p (int cmd, int len, int *val)
7644141cc406Sopenharmony_ci{
7645141cc406Sopenharmony_ci  int word[4];
7646141cc406Sopenharmony_ci  int i, status, control;
7647141cc406Sopenharmony_ci
7648141cc406Sopenharmony_ci  word[0] = len / 65536;
7649141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
7650141cc406Sopenharmony_ci  word[2] = len % 256;
7651141cc406Sopenharmony_ci  word[3] = (cmd & 0x3F) | 0x80 | 0x40;	/* 0x40 means 'read' */
7652141cc406Sopenharmony_ci
7653141cc406Sopenharmony_ci  connect610p ();
7654141cc406Sopenharmony_ci  sync610p ();
7655141cc406Sopenharmony_ci
7656141cc406Sopenharmony_ci  /* sends magic seal 55 AA */
7657141cc406Sopenharmony_ci  status = EPPputByte610p (0x55);
7658141cc406Sopenharmony_ci  if (status != 0xC8)
7659141cc406Sopenharmony_ci    {
7660141cc406Sopenharmony_ci      DBG (1, "EPPcmdGet610p: Found 0x%X expected 0xC8  (%s:%d)\n", status,
7661141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7662141cc406Sopenharmony_ci      return 0;
7663141cc406Sopenharmony_ci    }
7664141cc406Sopenharmony_ci  status = EPPputByte610p (0xAA);
7665141cc406Sopenharmony_ci  if (status != 0xC8)
7666141cc406Sopenharmony_ci    {
7667141cc406Sopenharmony_ci      DBG (1, "EPPcmdGet610p: Found 0x%02X expected 0xC8  (%s:%d)\n", status,
7668141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7669141cc406Sopenharmony_ci      return 0;
7670141cc406Sopenharmony_ci    }
7671141cc406Sopenharmony_ci
7672141cc406Sopenharmony_ci  /* tests status */
7673141cc406Sopenharmony_ci  /* scannerStatus=0x58 */
7674141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
7675141cc406Sopenharmony_ci  if (status != 0xC8)
7676141cc406Sopenharmony_ci    {
7677141cc406Sopenharmony_ci      DBG (1,
7678141cc406Sopenharmony_ci	   "EPPcmdGet610p: Found 0x%X expected 0xC8, status=0x%02X  (%s:%d)\n",
7679141cc406Sopenharmony_ci	   status, scannerStatus, __FILE__, __LINE__);
7680141cc406Sopenharmony_ci      return 0;
7681141cc406Sopenharmony_ci    }
7682141cc406Sopenharmony_ci
7683141cc406Sopenharmony_ci
7684141cc406Sopenharmony_ci  /* sends length of data */
7685141cc406Sopenharmony_ci  for (i = 0; (i < 4) && (status == 0xC8); i++)
7686141cc406Sopenharmony_ci    {
7687141cc406Sopenharmony_ci      status = EPPputByte610p (word[i]);
7688141cc406Sopenharmony_ci    }
7689141cc406Sopenharmony_ci  if (status != 0xC8)
7690141cc406Sopenharmony_ci    {
7691141cc406Sopenharmony_ci      DBG (1, "EPPcmdGet610p: loop %d, found 0x%02X expected 0xC8  (%s:%d)\n",
7692141cc406Sopenharmony_ci	   i, status, __FILE__, __LINE__);
7693141cc406Sopenharmony_ci      return 0;
7694141cc406Sopenharmony_ci    }
7695141cc406Sopenharmony_ci
7696141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
7697141cc406Sopenharmony_ci
7698141cc406Sopenharmony_ci  /* tests status */
7699141cc406Sopenharmony_ci  /* scannerStatus=0x58 */
7700141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
7701141cc406Sopenharmony_ci  if (status != 0xD0)
7702141cc406Sopenharmony_ci    {
7703141cc406Sopenharmony_ci      DBG (1,
7704141cc406Sopenharmony_ci	   "EPPcmdGet610p: Found 0x%X expected 0xD0, status=0x%02X  (%s:%d)\n",
7705141cc406Sopenharmony_ci	   status, scannerStatus, __FILE__, __LINE__);
7706141cc406Sopenharmony_ci      return 0;
7707141cc406Sopenharmony_ci    }
7708141cc406Sopenharmony_ci
7709141cc406Sopenharmony_ci  /* data reverse */
7710141cc406Sopenharmony_ci  control = Inb (CONTROL) & 0xF4;
7711141cc406Sopenharmony_ci  control = control | 0xA0;
7712141cc406Sopenharmony_ci
7713141cc406Sopenharmony_ci  /* receive data */
7714141cc406Sopenharmony_ci  i = 0;
7715141cc406Sopenharmony_ci  while (i < len)
7716141cc406Sopenharmony_ci    {
7717141cc406Sopenharmony_ci      status = Inb (STATUS) & 0xF8;
7718141cc406Sopenharmony_ci      if (status & 0x08)
7719141cc406Sopenharmony_ci	{
7720141cc406Sopenharmony_ci	  DBG (1,
7721141cc406Sopenharmony_ci	       "EPPcmdGet610p: loop %d, found 0x%X expected 0xD0 or 0xC0  (%s:%d)\n",
7722141cc406Sopenharmony_ci	       i, status, __FILE__, __LINE__);
7723141cc406Sopenharmony_ci	  return 0;
7724141cc406Sopenharmony_ci	}
7725141cc406Sopenharmony_ci      val[i] = Inb (EPPDATA);
7726141cc406Sopenharmony_ci      i++;
7727141cc406Sopenharmony_ci    }
7728141cc406Sopenharmony_ci
7729141cc406Sopenharmony_ci  if (DBG_LEVEL >= 8)
7730141cc406Sopenharmony_ci    {
7731141cc406Sopenharmony_ci      char *str = NULL;
7732141cc406Sopenharmony_ci
7733141cc406Sopenharmony_ci      str = malloc (3 * len + 1);
7734141cc406Sopenharmony_ci      if (str != NULL)
7735141cc406Sopenharmony_ci	{
7736141cc406Sopenharmony_ci	  for (i = 0; i < len; i++)
7737141cc406Sopenharmony_ci	    {
7738141cc406Sopenharmony_ci	      sprintf (str + 3 * i, "%02X ", val[i]);
7739141cc406Sopenharmony_ci	    }
7740141cc406Sopenharmony_ci	  str[3 * i] = 0x00;
7741141cc406Sopenharmony_ci	  DBG (8, "String received for %02X: %s\n", cmd, str);
7742141cc406Sopenharmony_ci	  free (str);
7743141cc406Sopenharmony_ci	}
7744141cc406Sopenharmony_ci      else
7745141cc406Sopenharmony_ci	{
7746141cc406Sopenharmony_ci	  TRACE (8, "not enough memory for debugging ...");
7747141cc406Sopenharmony_ci	}
7748141cc406Sopenharmony_ci    }
7749141cc406Sopenharmony_ci
7750141cc406Sopenharmony_ci  /* scannerStatus=0x58 */
7751141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
7752141cc406Sopenharmony_ci  scannerStatus = status;
7753141cc406Sopenharmony_ci  if (status != 0xC0)
7754141cc406Sopenharmony_ci    {
7755141cc406Sopenharmony_ci      DBG (0, "EPPcmdGet610p: Found 0x%02X expected 0xC0  (%s:%d)\n", status,
7756141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7757141cc406Sopenharmony_ci      return 0;
7758141cc406Sopenharmony_ci    }
7759141cc406Sopenharmony_ci  disconnect610p ();
7760141cc406Sopenharmony_ci  return 1;
7761141cc406Sopenharmony_ci}
7762141cc406Sopenharmony_ci
7763141cc406Sopenharmony_ci
7764141cc406Sopenharmony_ci
7765141cc406Sopenharmony_cistatic int
7766141cc406Sopenharmony_cicmdGet610p (int cmd, int len, int *val)
7767141cc406Sopenharmony_ci{
7768141cc406Sopenharmony_ci  int word[5];
7769141cc406Sopenharmony_ci  int i, j, status;
7770141cc406Sopenharmony_ci
7771141cc406Sopenharmony_ci  if ((cmd == 8) && (len > 0x23))
7772141cc406Sopenharmony_ci    len = 0x23;
7773141cc406Sopenharmony_ci
7774141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_EPP)
7775141cc406Sopenharmony_ci    return EPPcmdGet610p (cmd, len, val);
7776141cc406Sopenharmony_ci
7777141cc406Sopenharmony_ci  /* compute word */
7778141cc406Sopenharmony_ci  word[0] = len / 65536;
7779141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
7780141cc406Sopenharmony_ci  word[2] = len % 256;
7781141cc406Sopenharmony_ci  word[3] = (cmd & 0x3F) | 0x80 | 0x40;	/* 0x40 means 'read' */
7782141cc406Sopenharmony_ci  word[4] = -1;
7783141cc406Sopenharmony_ci
7784141cc406Sopenharmony_ci  connect610p ();
7785141cc406Sopenharmony_ci  sync610p ();
7786141cc406Sopenharmony_ci  if (sendLength610p (word) == 0)
7787141cc406Sopenharmony_ci    {
7788141cc406Sopenharmony_ci      DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__);
7789141cc406Sopenharmony_ci      return 0;
7790141cc406Sopenharmony_ci    }
7791141cc406Sopenharmony_ci  status = getStatus610p ();
7792141cc406Sopenharmony_ci  scannerStatus = status;
7793141cc406Sopenharmony_ci  if ((status != 0xC0) && (status != 0xD0))
7794141cc406Sopenharmony_ci    {
7795141cc406Sopenharmony_ci      DBG (0, "Found 0x%02X expected 0xC0 or 0xD0 (%s:%d)\n", status,
7796141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7797141cc406Sopenharmony_ci      return 0;
7798141cc406Sopenharmony_ci    }
7799141cc406Sopenharmony_ci  if (receiveData610p (val, len) == 0)
7800141cc406Sopenharmony_ci    {
7801141cc406Sopenharmony_ci      DBG (0, "sendData610p(val,%d) failed  (%s:%d)\n", len, __FILE__,
7802141cc406Sopenharmony_ci	   __LINE__);
7803141cc406Sopenharmony_ci      return 0;
7804141cc406Sopenharmony_ci    }
7805141cc406Sopenharmony_ci  status = getStatus610p ();
7806141cc406Sopenharmony_ci  scannerStatus = status;
7807141cc406Sopenharmony_ci  j = 0;
7808141cc406Sopenharmony_ci  while ((j < 256) && (status & 0x08))
7809141cc406Sopenharmony_ci    {
7810141cc406Sopenharmony_ci      status = getStatus610p ();
7811141cc406Sopenharmony_ci      j++;
7812141cc406Sopenharmony_ci    }
7813141cc406Sopenharmony_ci  if (status != 0xC0)
7814141cc406Sopenharmony_ci    {
7815141cc406Sopenharmony_ci      DBG (0, "Found 0x%02X expected 0xC0  (%s:%d)\n", status, __FILE__,
7816141cc406Sopenharmony_ci	   __LINE__);
7817141cc406Sopenharmony_ci      return 0;
7818141cc406Sopenharmony_ci    }
7819141cc406Sopenharmony_ci  disconnect610p ();
7820141cc406Sopenharmony_ci
7821141cc406Sopenharmony_ci  if (DBG_LEVEL >= 8)
7822141cc406Sopenharmony_ci    {
7823141cc406Sopenharmony_ci      char *str = NULL;
7824141cc406Sopenharmony_ci
7825141cc406Sopenharmony_ci      str = malloc (3 * len + 1);
7826141cc406Sopenharmony_ci      if (str != NULL)
7827141cc406Sopenharmony_ci	{
7828141cc406Sopenharmony_ci	  for (i = 0; i < len; i++)
7829141cc406Sopenharmony_ci	    {
7830141cc406Sopenharmony_ci	      sprintf (str + 3 * i, "%02X ", val[i]);
7831141cc406Sopenharmony_ci	    }
7832141cc406Sopenharmony_ci	  str[3 * i] = 0x00;
7833141cc406Sopenharmony_ci	  DBG (8, "String received for %02X: %s\n", cmd, str);
7834141cc406Sopenharmony_ci	  free (str);
7835141cc406Sopenharmony_ci	}
7836141cc406Sopenharmony_ci      else
7837141cc406Sopenharmony_ci	{
7838141cc406Sopenharmony_ci	  TRACE (8, "not enough memory for debugging ...");
7839141cc406Sopenharmony_ci	}
7840141cc406Sopenharmony_ci    }
7841141cc406Sopenharmony_ci  return 1;
7842141cc406Sopenharmony_ci}
7843141cc406Sopenharmony_ci
7844141cc406Sopenharmony_ci
7845141cc406Sopenharmony_cistatic int
7846141cc406Sopenharmony_ciEPPcmdSet610p (int cmd, int len, int *val)
7847141cc406Sopenharmony_ci{
7848141cc406Sopenharmony_ci  int word[5];
7849141cc406Sopenharmony_ci  int i, status;
7850141cc406Sopenharmony_ci
7851141cc406Sopenharmony_ci  if ((cmd == 8) && (len > 0x23))
7852141cc406Sopenharmony_ci    {
7853141cc406Sopenharmony_ci      /* blank useless extra bytes */
7854141cc406Sopenharmony_ci      for (i = 0x22; i < len; i++)
7855141cc406Sopenharmony_ci	val[i] = 0x00;
7856141cc406Sopenharmony_ci    }
7857141cc406Sopenharmony_ci
7858141cc406Sopenharmony_ci  word[0] = len / 65536;
7859141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
7860141cc406Sopenharmony_ci  word[2] = len % 256;
7861141cc406Sopenharmony_ci  word[3] = (cmd & 0x3F) | 0x80;
7862141cc406Sopenharmony_ci
7863141cc406Sopenharmony_ci  connect610p ();
7864141cc406Sopenharmony_ci  sync610p ();
7865141cc406Sopenharmony_ci
7866141cc406Sopenharmony_ci  /* sends magic seal 55 AA */
7867141cc406Sopenharmony_ci  status = EPPputByte610p (0x55);
7868141cc406Sopenharmony_ci  if ((status != 0xC8) && (status!=0xC0))
7869141cc406Sopenharmony_ci    {
7870141cc406Sopenharmony_ci      DBG (0, "EPPcmdSet610p: Found 0x%X expected 0xC0 or 0xC8  (%s:%d)\n", status,
7871141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7872141cc406Sopenharmony_ci      return 0;
7873141cc406Sopenharmony_ci    }
7874141cc406Sopenharmony_ci  status = EPPputByte610p (0xAA);
7875141cc406Sopenharmony_ci  if ((status != 0xC8) && (status!=0xC0))
7876141cc406Sopenharmony_ci    {
7877141cc406Sopenharmony_ci      DBG (0, "EPPcmdSet610p: Found 0x%X expected 0xC0 or 0xC8  (%s:%d)\n", status,
7878141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7879141cc406Sopenharmony_ci      return 0;
7880141cc406Sopenharmony_ci    }
7881141cc406Sopenharmony_ci
7882141cc406Sopenharmony_ci  /* tests status */
7883141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
7884141cc406Sopenharmony_ci  if ((status != 0xC8) && (status!=0xC0))
7885141cc406Sopenharmony_ci    {
7886141cc406Sopenharmony_ci      DBG (0, "EPPcmdSet610p: Found 0x%02X expected 0xC0 or 0xC8  (%s:%d)\n", status,
7887141cc406Sopenharmony_ci	   __FILE__, __LINE__);
7888141cc406Sopenharmony_ci      return 0;
7889141cc406Sopenharmony_ci    }
7890141cc406Sopenharmony_ci
7891141cc406Sopenharmony_ci  /* sends length of data */
7892141cc406Sopenharmony_ci  for (i = 0; i < 4; i++)
7893141cc406Sopenharmony_ci    {
7894141cc406Sopenharmony_ci      status = EPPputByte610p (word[i]);
7895141cc406Sopenharmony_ci    }
7896141cc406Sopenharmony_ci  if ((status != 0xC8) && (status!=0xC0))
7897141cc406Sopenharmony_ci    {
7898141cc406Sopenharmony_ci      DBG (0, "EPPcmdSet610p: loop %d, found 0x%02X expected 0xC0 or 0xC8  (%s:%d)\n",
7899141cc406Sopenharmony_ci	   i, status, __FILE__, __LINE__);
7900141cc406Sopenharmony_ci      return 0;
7901141cc406Sopenharmony_ci    }
7902141cc406Sopenharmony_ci
7903141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
7904141cc406Sopenharmony_ci
7905141cc406Sopenharmony_ci  /* tests status */
7906141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
7907141cc406Sopenharmony_ci  if (status != 0xC0)
7908141cc406Sopenharmony_ci    {
7909141cc406Sopenharmony_ci      DBG (0, "Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__,
7910141cc406Sopenharmony_ci	   __LINE__);
7911141cc406Sopenharmony_ci      return 0;
7912141cc406Sopenharmony_ci    }
7913141cc406Sopenharmony_ci
7914141cc406Sopenharmony_ci  /* sends data */
7915141cc406Sopenharmony_ci  status = 0xC8;
7916141cc406Sopenharmony_ci  for (i = 0; (i < len) && (status == 0xC8); i++)
7917141cc406Sopenharmony_ci    {
7918141cc406Sopenharmony_ci      /* escape special values with ESC (0x1B) */
7919141cc406Sopenharmony_ci      if (val[i] == 0x1B)
7920141cc406Sopenharmony_ci	status = EPPputByte610p (0x1B);
7921141cc406Sopenharmony_ci      if (i > 0)
7922141cc406Sopenharmony_ci	{
7923141cc406Sopenharmony_ci	  if ((val[i] == 0xAA) && (val[i - 1] == 0x55))
7924141cc406Sopenharmony_ci	    status = EPPputByte610p (0x1B);
7925141cc406Sopenharmony_ci	}
7926141cc406Sopenharmony_ci      /* now send data */
7927141cc406Sopenharmony_ci      status = EPPputByte610p (val[i]);
7928141cc406Sopenharmony_ci    }
7929141cc406Sopenharmony_ci
7930141cc406Sopenharmony_ci  if (status != 0xC8)
7931141cc406Sopenharmony_ci    {
7932141cc406Sopenharmony_ci      DBG (0, "EPPcmdSet610p: loop %d, found 0x%02X expected 0xC8 (%s:%d)\n",
7933141cc406Sopenharmony_ci	   i, status, __FILE__, __LINE__);
7934141cc406Sopenharmony_ci      return 0;
7935141cc406Sopenharmony_ci    }
7936141cc406Sopenharmony_ci
7937141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
7938141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
7939141cc406Sopenharmony_ci  if (status != 0xC0)
7940141cc406Sopenharmony_ci    {
7941141cc406Sopenharmony_ci      DBG (0, "Found 0x%X expected 0xC0  (%s:%d)\n", status, __FILE__,
7942141cc406Sopenharmony_ci	   __LINE__);
7943141cc406Sopenharmony_ci      return 0;
7944141cc406Sopenharmony_ci    }
7945141cc406Sopenharmony_ci
7946141cc406Sopenharmony_ci  disconnect610p ();
7947141cc406Sopenharmony_ci  return 1;
7948141cc406Sopenharmony_ci}
7949141cc406Sopenharmony_ci
7950141cc406Sopenharmony_ci
7951141cc406Sopenharmony_cistatic int
7952141cc406Sopenharmony_cicmdSet610p (int cmd, int len, int *val)
7953141cc406Sopenharmony_ci{
7954141cc406Sopenharmony_ci  int word[5];
7955141cc406Sopenharmony_ci  int i, j, status;
7956141cc406Sopenharmony_ci
7957141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_EPP)
7958141cc406Sopenharmony_ci    return EPPcmdSet610p (cmd, len, val);
7959141cc406Sopenharmony_ci
7960141cc406Sopenharmony_ci  if ((cmd == 8) && (len > 0x23))
7961141cc406Sopenharmony_ci    {
7962141cc406Sopenharmony_ci      /* blank useless extra bytes */
7963141cc406Sopenharmony_ci      for (i = 0x22; i < len; i++)
7964141cc406Sopenharmony_ci	val[i] = 0x00;
7965141cc406Sopenharmony_ci    }
7966141cc406Sopenharmony_ci
7967141cc406Sopenharmony_ci  /* compute word */
7968141cc406Sopenharmony_ci  word[0] = len / 65536;
7969141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
7970141cc406Sopenharmony_ci  word[2] = len % 256;
7971141cc406Sopenharmony_ci  word[3] = (cmd & 0x3F) | 0x80;
7972141cc406Sopenharmony_ci  word[4] = -1;
7973141cc406Sopenharmony_ci
7974141cc406Sopenharmony_ci  connect610p ();
7975141cc406Sopenharmony_ci  sync610p ();
7976141cc406Sopenharmony_ci  if (sendLength610p (word) == 0)
7977141cc406Sopenharmony_ci    {
7978141cc406Sopenharmony_ci      DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__);
7979141cc406Sopenharmony_ci      return 0;
7980141cc406Sopenharmony_ci    }
7981141cc406Sopenharmony_ci  status = getStatus610p ();
7982141cc406Sopenharmony_ci  scannerStatus = status;
7983141cc406Sopenharmony_ci  if ((status != 0xC0) && (status != 0xD0))
7984141cc406Sopenharmony_ci    {
7985141cc406Sopenharmony_ci      DBG (1, "Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__,
7986141cc406Sopenharmony_ci	   __LINE__);
7987141cc406Sopenharmony_ci      return 0;
7988141cc406Sopenharmony_ci    }
7989141cc406Sopenharmony_ci  if (sendData610p (val, len) == 0)
7990141cc406Sopenharmony_ci    {
7991141cc406Sopenharmony_ci      DBG (1, "sendData610p(val,%d) failed  (%s:%d)\n", len, __FILE__,
7992141cc406Sopenharmony_ci	   __LINE__);
7993141cc406Sopenharmony_ci      return 0;
7994141cc406Sopenharmony_ci    }
7995141cc406Sopenharmony_ci  status = getStatus610p ();
7996141cc406Sopenharmony_ci  scannerStatus = status;
7997141cc406Sopenharmony_ci  j = 0;
7998141cc406Sopenharmony_ci  while ((j < 256) && (status & 0x08))
7999141cc406Sopenharmony_ci    {
8000141cc406Sopenharmony_ci      status = getStatus610p ();
8001141cc406Sopenharmony_ci      j++;
8002141cc406Sopenharmony_ci    }
8003141cc406Sopenharmony_ci  if (status != 0xC0)
8004141cc406Sopenharmony_ci    {
8005141cc406Sopenharmony_ci      DBG (1, "Found 0x%X expected 0xC0  (%s:%d)\n", status, __FILE__,
8006141cc406Sopenharmony_ci	   __LINE__);
8007141cc406Sopenharmony_ci      /* return 0; */
8008141cc406Sopenharmony_ci    }
8009141cc406Sopenharmony_ci  disconnect610p ();
8010141cc406Sopenharmony_ci  return 1;
8011141cc406Sopenharmony_ci}
8012141cc406Sopenharmony_ci
8013141cc406Sopenharmony_cistatic int
8014141cc406Sopenharmony_cicmdSet (int cmd, int len, int *val)
8015141cc406Sopenharmony_ci{
8016141cc406Sopenharmony_ci  int word[5];
8017141cc406Sopenharmony_ci  int i;
8018141cc406Sopenharmony_ci
8019141cc406Sopenharmony_ci  if (DBG_LEVEL >= 8)
8020141cc406Sopenharmony_ci    {
8021141cc406Sopenharmony_ci      char *str = NULL;
8022141cc406Sopenharmony_ci
8023141cc406Sopenharmony_ci      str = malloc (3 * len + 1);
8024141cc406Sopenharmony_ci      if (str != NULL)
8025141cc406Sopenharmony_ci	{
8026141cc406Sopenharmony_ci	  for (i = 0; i < len; i++)
8027141cc406Sopenharmony_ci	    {
8028141cc406Sopenharmony_ci	      sprintf (str + 3 * i, "%02X ", val[i]);
8029141cc406Sopenharmony_ci	    }
8030141cc406Sopenharmony_ci	  str[3 * i] = 0x00;
8031141cc406Sopenharmony_ci	  DBG (8, "String sent     for %02X: %s\n", cmd, str);
8032141cc406Sopenharmony_ci	  free (str);
8033141cc406Sopenharmony_ci	}
8034141cc406Sopenharmony_ci      else
8035141cc406Sopenharmony_ci	{
8036141cc406Sopenharmony_ci	  TRACE (8, "not enough memory for debugging ...");
8037141cc406Sopenharmony_ci	}
8038141cc406Sopenharmony_ci    }
8039141cc406Sopenharmony_ci
8040141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
8041141cc406Sopenharmony_ci    return cmdSet610p (cmd, len, val);
8042141cc406Sopenharmony_ci
8043141cc406Sopenharmony_ci  /* cmd 08 as 2 length depending upon model */
8044141cc406Sopenharmony_ci  if ((cmd == 8) && (getModel () == 0x07))
8045141cc406Sopenharmony_ci    {
8046141cc406Sopenharmony_ci      len = 35;
8047141cc406Sopenharmony_ci    }
8048141cc406Sopenharmony_ci
8049141cc406Sopenharmony_ci  /* compute word */
8050141cc406Sopenharmony_ci  word[0] = len / 65536;
8051141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
8052141cc406Sopenharmony_ci  word[2] = len % 256;
8053141cc406Sopenharmony_ci  word[3] = (cmd & 0x3F) | 0x80;
8054141cc406Sopenharmony_ci
8055141cc406Sopenharmony_ci  if (!prologue (0x10))
8056141cc406Sopenharmony_ci    {
8057141cc406Sopenharmony_ci      DBG (0, "cmdSet: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8058141cc406Sopenharmony_ci      return 0;
8059141cc406Sopenharmony_ci    }
8060141cc406Sopenharmony_ci
8061141cc406Sopenharmony_ci  /* send data */
8062141cc406Sopenharmony_ci  if (sendLength (word, 4) == 0)
8063141cc406Sopenharmony_ci    {
8064141cc406Sopenharmony_ci      DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8065141cc406Sopenharmony_ci      return 0;
8066141cc406Sopenharmony_ci    }
8067141cc406Sopenharmony_ci  TRACE (16, "sendLength(word,4) passed ...");
8068141cc406Sopenharmony_ci
8069141cc406Sopenharmony_ci  /* head end */
8070141cc406Sopenharmony_ci  epilogue ();
8071141cc406Sopenharmony_ci
8072141cc406Sopenharmony_ci  if (len > 0)
8073141cc406Sopenharmony_ci    {
8074141cc406Sopenharmony_ci      /* send body */
8075141cc406Sopenharmony_ci      if (!prologue (0x10))
8076141cc406Sopenharmony_ci	{
8077141cc406Sopenharmony_ci	  DBG (0, "cmdSet: prologue failed !   (%s:%d)\n", __FILE__,
8078141cc406Sopenharmony_ci	       __LINE__);
8079141cc406Sopenharmony_ci	}
8080141cc406Sopenharmony_ci
8081141cc406Sopenharmony_ci      /* send data */
8082141cc406Sopenharmony_ci      if (sendData (val, len) == 0)
8083141cc406Sopenharmony_ci	{
8084141cc406Sopenharmony_ci	  DBG (0, "sendData(word,%d) failed (%s:%d)\n", len, __FILE__,
8085141cc406Sopenharmony_ci	       __LINE__);
8086141cc406Sopenharmony_ci	  epilogue ();
8087141cc406Sopenharmony_ci	  return 0;
8088141cc406Sopenharmony_ci	}
8089141cc406Sopenharmony_ci      TRACE (16, "sendData(val,len) passed ...");
8090141cc406Sopenharmony_ci      /* body end */
8091141cc406Sopenharmony_ci      epilogue ();
8092141cc406Sopenharmony_ci    }
8093141cc406Sopenharmony_ci  return 1;
8094141cc406Sopenharmony_ci}
8095141cc406Sopenharmony_ci
8096141cc406Sopenharmony_cistatic int
8097141cc406Sopenharmony_cicmdGet (int cmd, int len, int *val)
8098141cc406Sopenharmony_ci{
8099141cc406Sopenharmony_ci  int word[5];
8100141cc406Sopenharmony_ci  int i;
8101141cc406Sopenharmony_ci
8102141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
8103141cc406Sopenharmony_ci    return cmdGet610p (cmd, len, val);
8104141cc406Sopenharmony_ci
8105141cc406Sopenharmony_ci  /* cmd 08 as 2 length depending upon model */
8106141cc406Sopenharmony_ci  if ((cmd == 8) && (getModel () == 0x07))
8107141cc406Sopenharmony_ci    {
8108141cc406Sopenharmony_ci      len = 35;
8109141cc406Sopenharmony_ci    }
8110141cc406Sopenharmony_ci
8111141cc406Sopenharmony_ci  /* compute word */
8112141cc406Sopenharmony_ci  word[0] = len / 65536;
8113141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
8114141cc406Sopenharmony_ci  word[2] = len % 256;
8115141cc406Sopenharmony_ci  word[3] = (cmd & 0x3F) | 0x80 | 0x40;	/* 0x40 means 'read' */
8116141cc406Sopenharmony_ci  word[4] = -1;
8117141cc406Sopenharmony_ci
8118141cc406Sopenharmony_ci  /* send header */
8119141cc406Sopenharmony_ci  if (!prologue (0x10))
8120141cc406Sopenharmony_ci    {
8121141cc406Sopenharmony_ci      DBG (0, "cmdGet: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8122141cc406Sopenharmony_ci      return 0;
8123141cc406Sopenharmony_ci    }
8124141cc406Sopenharmony_ci
8125141cc406Sopenharmony_ci  /* send data */
8126141cc406Sopenharmony_ci  if (sendLength (word, 4) == 0)
8127141cc406Sopenharmony_ci    {
8128141cc406Sopenharmony_ci      DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8129141cc406Sopenharmony_ci      return 0;
8130141cc406Sopenharmony_ci    }
8131141cc406Sopenharmony_ci  TRACE (16, "sendLength(word,4) passed ...");
8132141cc406Sopenharmony_ci
8133141cc406Sopenharmony_ci  /* head end */
8134141cc406Sopenharmony_ci  epilogue ();
8135141cc406Sopenharmony_ci
8136141cc406Sopenharmony_ci
8137141cc406Sopenharmony_ci  /* send header */
8138141cc406Sopenharmony_ci  if (!prologue (0x10))
8139141cc406Sopenharmony_ci    {
8140141cc406Sopenharmony_ci      DBG (0, "cmdGet: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8141141cc406Sopenharmony_ci      return 0;
8142141cc406Sopenharmony_ci    }
8143141cc406Sopenharmony_ci
8144141cc406Sopenharmony_ci  /* get actual data */
8145141cc406Sopenharmony_ci  if (receiveData (val, len) == 0)
8146141cc406Sopenharmony_ci    {
8147141cc406Sopenharmony_ci      DBG (0, "receiveData(val,len) failed (%s:%d)\n", __FILE__, __LINE__);
8148141cc406Sopenharmony_ci      epilogue ();
8149141cc406Sopenharmony_ci      return 0;
8150141cc406Sopenharmony_ci    }
8151141cc406Sopenharmony_ci  if (DBG_LEVEL >= 8)
8152141cc406Sopenharmony_ci    {
8153141cc406Sopenharmony_ci      char *str = NULL;
8154141cc406Sopenharmony_ci
8155141cc406Sopenharmony_ci      str = malloc (3 * len + 1);
8156141cc406Sopenharmony_ci      if (str != NULL)
8157141cc406Sopenharmony_ci	{
8158141cc406Sopenharmony_ci	  for (i = 0; i < len; i++)
8159141cc406Sopenharmony_ci	    {
8160141cc406Sopenharmony_ci	      sprintf (str + 3 * i, "%02X ", val[i]);
8161141cc406Sopenharmony_ci	    }
8162141cc406Sopenharmony_ci	  str[3 * i] = 0x00;
8163141cc406Sopenharmony_ci	  DBG (8, "String received for %02X: %s\n", cmd, str);
8164141cc406Sopenharmony_ci	  free (str);
8165141cc406Sopenharmony_ci	}
8166141cc406Sopenharmony_ci      else
8167141cc406Sopenharmony_ci	{
8168141cc406Sopenharmony_ci	  TRACE (8, "not enough memory for debugging ...");
8169141cc406Sopenharmony_ci	}
8170141cc406Sopenharmony_ci    }
8171141cc406Sopenharmony_ci  epilogue ();
8172141cc406Sopenharmony_ci  return 1;
8173141cc406Sopenharmony_ci}
8174141cc406Sopenharmony_ci
8175141cc406Sopenharmony_ci
8176141cc406Sopenharmony_ci
8177141cc406Sopenharmony_cistatic int
8178141cc406Sopenharmony_cicmdSetGet (int cmd, int len, int *val)
8179141cc406Sopenharmony_ci{
8180141cc406Sopenharmony_ci  int *tampon;
8181141cc406Sopenharmony_ci  int i;
8182141cc406Sopenharmony_ci
8183141cc406Sopenharmony_ci  /* model revision 0x07 uses 35 bytes buffers */
8184141cc406Sopenharmony_ci  /* cmd 08 as 2 length depending upon model */
8185141cc406Sopenharmony_ci  if ((cmd == 8) && (getModel () == 0x07))
8186141cc406Sopenharmony_ci    {
8187141cc406Sopenharmony_ci      len = 0x23;
8188141cc406Sopenharmony_ci    }
8189141cc406Sopenharmony_ci
8190141cc406Sopenharmony_ci  /* first we send */
8191141cc406Sopenharmony_ci  if (cmdSet (cmd, len, val) == 0)
8192141cc406Sopenharmony_ci    {
8193141cc406Sopenharmony_ci      DBG (0, "cmdSetGet failed !  (%s:%d)\n", __FILE__, __LINE__);
8194141cc406Sopenharmony_ci      return 0;
8195141cc406Sopenharmony_ci    }
8196141cc406Sopenharmony_ci
8197141cc406Sopenharmony_ci  tampon = (int *) malloc (len * sizeof (int));
8198141cc406Sopenharmony_ci  memset (tampon, 0x00, len * sizeof (int));
8199141cc406Sopenharmony_ci  if (tampon == NULL)
8200141cc406Sopenharmony_ci    {
8201141cc406Sopenharmony_ci      DBG (0, "Failed to allocate room for %d int ! (%s:%d)\n", len, __FILE__,
8202141cc406Sopenharmony_ci	   __LINE__);
8203141cc406Sopenharmony_ci      epilogue ();
8204141cc406Sopenharmony_ci      return 0;
8205141cc406Sopenharmony_ci    }
8206141cc406Sopenharmony_ci
8207141cc406Sopenharmony_ci  /* then we receive */
8208141cc406Sopenharmony_ci  if (cmdGet (cmd, len, tampon) == 0)
8209141cc406Sopenharmony_ci    {
8210141cc406Sopenharmony_ci      DBG (0, "cmdSetGet failed !  (%s:%d)\n", __FILE__, __LINE__);
8211141cc406Sopenharmony_ci      free (tampon);
8212141cc406Sopenharmony_ci      epilogue ();
8213141cc406Sopenharmony_ci      return 0;
8214141cc406Sopenharmony_ci    }
8215141cc406Sopenharmony_ci
8216141cc406Sopenharmony_ci  /* check and copy */
8217141cc406Sopenharmony_ci  for (i = 0; (i < len) && (val[i] >= 0); i++)
8218141cc406Sopenharmony_ci    {
8219141cc406Sopenharmony_ci      if (tampon[i] != val[i])
8220141cc406Sopenharmony_ci	{
8221141cc406Sopenharmony_ci	  DBG
8222141cc406Sopenharmony_ci	    (0,
8223141cc406Sopenharmony_ci	     "Warning data read back differs: expected %02X found tampon[%d]=%02X ! (%s:%d)\n",
8224141cc406Sopenharmony_ci	     val[i], i, tampon[i], __FILE__, __LINE__);
8225141cc406Sopenharmony_ci	}
8226141cc406Sopenharmony_ci      val[i] = tampon[i];
8227141cc406Sopenharmony_ci    }
8228141cc406Sopenharmony_ci
8229141cc406Sopenharmony_ci
8230141cc406Sopenharmony_ci  /* OK */
8231141cc406Sopenharmony_ci  free (tampon);
8232141cc406Sopenharmony_ci  return 1;
8233141cc406Sopenharmony_ci}
8234141cc406Sopenharmony_ci
8235141cc406Sopenharmony_ci
8236141cc406Sopenharmony_ci/* 1 OK, 0 failed */
8237141cc406Sopenharmony_cistatic int
8238141cc406Sopenharmony_ciEPPcmdGetBuffer610p (int cmd, int len, unsigned char *buffer)
8239141cc406Sopenharmony_ci{
8240141cc406Sopenharmony_ci  int status, i, tmp, control;
8241141cc406Sopenharmony_ci  int word[5];
8242141cc406Sopenharmony_ci  int count, needed, max;
8243141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
8244141cc406Sopenharmony_ci  int fd, mode, rc, wait;
8245141cc406Sopenharmony_ci#endif
8246141cc406Sopenharmony_ci  int loop, remain;
8247141cc406Sopenharmony_ci
8248141cc406Sopenharmony_ci  /* first we set length and channel */
8249141cc406Sopenharmony_ci  /* compute word */
8250141cc406Sopenharmony_ci  word[0] = len / 65536;
8251141cc406Sopenharmony_ci  word[1] = (len / 256) % 256;
8252141cc406Sopenharmony_ci  word[2] = len % 256;
8253141cc406Sopenharmony_ci  word[3] = (cmd & 0x0F) | 0xC0;
8254141cc406Sopenharmony_ci  word[4] = -1;
8255141cc406Sopenharmony_ci
8256141cc406Sopenharmony_ci  connect610p ();		/* start of EPPsendLength610p */
8257141cc406Sopenharmony_ci  sync610p ();
8258141cc406Sopenharmony_ci
8259141cc406Sopenharmony_ci  /* sends magic seal 55 AA */
8260141cc406Sopenharmony_ci  status = EPPputByte610p (0x55);
8261141cc406Sopenharmony_ci  if ((status != 0xD0) && (status != 0xC8))
8262141cc406Sopenharmony_ci    {
8263141cc406Sopenharmony_ci      DBG (0, "EPPcmdGetBuffer610p: Found 0x%X expected 0xC8 or 0xD0 (%s:%d)\n",
8264141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
8265141cc406Sopenharmony_ci      return 0;
8266141cc406Sopenharmony_ci    }
8267141cc406Sopenharmony_ci  status = EPPputByte610p (0xAA);
8268141cc406Sopenharmony_ci  if ((status != 0xD0) && (status != 0xC8))
8269141cc406Sopenharmony_ci    {
8270141cc406Sopenharmony_ci      DBG (0, "EPPcmdGetBuffer610p: Found 0x%02X expected 0xC8 or 0xD0 (%s:%d)\n",
8271141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
8272141cc406Sopenharmony_ci      return 0;
8273141cc406Sopenharmony_ci    }
8274141cc406Sopenharmony_ci
8275141cc406Sopenharmony_ci  /* tests status */
8276141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
8277141cc406Sopenharmony_ci  if ((status != 0xD0) && (status != 0xC8))
8278141cc406Sopenharmony_ci    {
8279141cc406Sopenharmony_ci      DBG (0, "EPPcmdGetBuffer610p: Found 0x%X expected 0xC8 or 0xD0 (%s:%d)\n",
8280141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
8281141cc406Sopenharmony_ci      return 0;
8282141cc406Sopenharmony_ci    }
8283141cc406Sopenharmony_ci
8284141cc406Sopenharmony_ci  /* sends length of data */
8285141cc406Sopenharmony_ci  for (i = 0; i < 4; i++)
8286141cc406Sopenharmony_ci    {
8287141cc406Sopenharmony_ci      status = EPPputByte610p (word[i]);
8288141cc406Sopenharmony_ci    }
8289141cc406Sopenharmony_ci  if ((status != 0xC0) && (status != 0xC8))
8290141cc406Sopenharmony_ci    {
8291141cc406Sopenharmony_ci      DBG (0,
8292141cc406Sopenharmony_ci	   "EPPcmdGetBuffer610p: loop %d, found 0x%02X expected 0xC0 or 0xC8  (%s:%d)\n",
8293141cc406Sopenharmony_ci	   i, status, __FILE__, __LINE__);
8294141cc406Sopenharmony_ci      return 0;
8295141cc406Sopenharmony_ci    }
8296141cc406Sopenharmony_ci
8297141cc406Sopenharmony_ci  Outb (DATA, 0xFF);
8298141cc406Sopenharmony_ci
8299141cc406Sopenharmony_ci  /* test status */
8300141cc406Sopenharmony_ci  status = EPPgetStatus610p ();
8301141cc406Sopenharmony_ci  if ((status != 0xC0) && (status != 0xD0))
8302141cc406Sopenharmony_ci    {
8303141cc406Sopenharmony_ci      DBG (0,
8304141cc406Sopenharmony_ci	   "EPPcmdGetBuffer610p: Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n",
8305141cc406Sopenharmony_ci	   status, __FILE__, __LINE__);
8306141cc406Sopenharmony_ci      /*return 0; */
8307141cc406Sopenharmony_ci    }
8308141cc406Sopenharmony_ci  disconnect610p ();		/* end of EPPsendLength610p */
8309141cc406Sopenharmony_ci
8310141cc406Sopenharmony_ci  /* max data read in one go */
8311141cc406Sopenharmony_ci  if (sanei_umax_pp_getfull () == 1)
8312141cc406Sopenharmony_ci    max = 2550 / 3;
8313141cc406Sopenharmony_ci  else
8314141cc406Sopenharmony_ci    max = 32768;
8315141cc406Sopenharmony_ci
8316141cc406Sopenharmony_ci  /* loop until enough data is read */
8317141cc406Sopenharmony_ci  count = 0;
8318141cc406Sopenharmony_ci  while (count < len)
8319141cc406Sopenharmony_ci    {
8320141cc406Sopenharmony_ci      if (len - count > max)
8321141cc406Sopenharmony_ci	needed = max;
8322141cc406Sopenharmony_ci      else
8323141cc406Sopenharmony_ci	needed = len - count;
8324141cc406Sopenharmony_ci      if (needed % 4)
8325141cc406Sopenharmony_ci	remain = needed % 4;
8326141cc406Sopenharmony_ci      else
8327141cc406Sopenharmony_ci	remain = 4;
8328141cc406Sopenharmony_ci      loop = (needed - remain) / 2;
8329141cc406Sopenharmony_ci      DBG (32, "EPPcmdGetBuffer610p: %d loops to do \n", loop);
8330141cc406Sopenharmony_ci
8331141cc406Sopenharmony_ci      status = 0x20;
8332141cc406Sopenharmony_ci
8333141cc406Sopenharmony_ci      /* wait for data ready */
8334141cc406Sopenharmony_ci      while ((status & 0x80) != 0x80)
8335141cc406Sopenharmony_ci	{
8336141cc406Sopenharmony_ci	  /* this is SPPgetStatus */
8337141cc406Sopenharmony_ci	  connect610p ();
8338141cc406Sopenharmony_ci	  Outb (CONTROL, 0x07);
8339141cc406Sopenharmony_ci	  Outb (DATA, 0xFF);
8340141cc406Sopenharmony_ci	  tmp = Inb (DATA);
8341141cc406Sopenharmony_ci	  if (tmp != 0xFF)
8342141cc406Sopenharmony_ci	    {
8343141cc406Sopenharmony_ci	      DBG (0,
8344141cc406Sopenharmony_ci		   "EPPcmdGetBuffer610p found 0x%02X expected 0xFF  (%s:%d)\n",
8345141cc406Sopenharmony_ci		   tmp, __FILE__, __LINE__);
8346141cc406Sopenharmony_ci	      return 0;
8347141cc406Sopenharmony_ci	    }
8348141cc406Sopenharmony_ci	  status = Inb (STATUS) & 0xF8;
8349141cc406Sopenharmony_ci	  if ((status & 0x80) != 0x80)
8350141cc406Sopenharmony_ci	    {
8351141cc406Sopenharmony_ci	      disconnect610p ();
8352141cc406Sopenharmony_ci	      usleep(1000);
8353141cc406Sopenharmony_ci	    }
8354141cc406Sopenharmony_ci	  else
8355141cc406Sopenharmony_ci	    {
8356141cc406Sopenharmony_ci	      Outb (CONTROL, 0x04);
8357141cc406Sopenharmony_ci	      sync610p ();
8358141cc406Sopenharmony_ci	      Outb (DATA, 0xFF);
8359141cc406Sopenharmony_ci	      control = (Inb (CONTROL) & 0x44) | 0xE4;
8360141cc406Sopenharmony_ci	      Outb (CONTROL, control);
8361141cc406Sopenharmony_ci	    }
8362141cc406Sopenharmony_ci	}
8363141cc406Sopenharmony_ci
8364141cc406Sopenharmony_ci      /* EPP block read */
8365141cc406Sopenharmony_ci      /* there is one form for full CCD width reads, and another for other
8366141cc406Sopenharmony_ci         reads */
8367141cc406Sopenharmony_ci#ifdef HAVE_LINUX_PPDEV_H
8368141cc406Sopenharmony_ci      wait = 0;
8369141cc406Sopenharmony_ci      /* check we have ppdev working */
8370141cc406Sopenharmony_ci      fd = sanei_umax_pp_getparport ();
8371141cc406Sopenharmony_ci      if (fd > 0)
8372141cc406Sopenharmony_ci	{
8373141cc406Sopenharmony_ci	  mode = 1;		/* data_reverse */
8374141cc406Sopenharmony_ci	  rc = ioctl (fd, PPDATADIR, &mode);
8375141cc406Sopenharmony_ci	  if (rc)
8376141cc406Sopenharmony_ci	    DBG (0,
8377141cc406Sopenharmony_ci		 "EPPcmdGetBuffer610p: ppdev ioctl returned <%s>  (%s:%d)\n",
8378141cc406Sopenharmony_ci		 strerror (errno), __FILE__, __LINE__);
8379141cc406Sopenharmony_ci
8380141cc406Sopenharmony_ci#ifdef PPSETFLAGS
8381141cc406Sopenharmony_ci	  mode = PP_FASTREAD;
8382141cc406Sopenharmony_ci	  rc = ioctl (fd, PPSETFLAGS, &mode);
8383141cc406Sopenharmony_ci	  if (rc)
8384141cc406Sopenharmony_ci	    DBG (0,
8385141cc406Sopenharmony_ci		 "EPPcmdGetBuffer610p: ppdev ioctl returned <%s>  (%s:%d)\n",
8386141cc406Sopenharmony_ci		 strerror (errno), __FILE__, __LINE__);
8387141cc406Sopenharmony_ci#endif
8388141cc406Sopenharmony_ci	  mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
8389141cc406Sopenharmony_ci	  rc = ioctl (fd, PPSETMODE, &mode);
8390141cc406Sopenharmony_ci	  if (rc)
8391141cc406Sopenharmony_ci	    {
8392141cc406Sopenharmony_ci	      DBG (0,
8393141cc406Sopenharmony_ci		   "EPPcmdGetBuffer610p: ppdev ioctl returned <%s>  (%s:%d)\n",
8394141cc406Sopenharmony_ci		   strerror (errno), __FILE__, __LINE__);
8395141cc406Sopenharmony_ci	      return 0;
8396141cc406Sopenharmony_ci	    }
8397141cc406Sopenharmony_ci	  if (sanei_umax_pp_getfull () == 1)
8398141cc406Sopenharmony_ci	    {
8399141cc406Sopenharmony_ci	      do
8400141cc406Sopenharmony_ci		{
8401141cc406Sopenharmony_ci		  rc = read (fd, buffer + count, needed);
8402141cc406Sopenharmony_ci		}
8403141cc406Sopenharmony_ci	      while (rc == EAGAIN);
8404141cc406Sopenharmony_ci	      if (rc < 0)
8405141cc406Sopenharmony_ci		{
8406141cc406Sopenharmony_ci		  DBG (0,
8407141cc406Sopenharmony_ci		       "EPPcmdGetBuffer610p: ppdev read failed <%s> (%s:%d)\n",
8408141cc406Sopenharmony_ci		       strerror (errno), __FILE__, __LINE__);
8409141cc406Sopenharmony_ci		  return 0;
8410141cc406Sopenharmony_ci		}
8411141cc406Sopenharmony_ci#ifdef IOLOG
8412141cc406Sopenharmony_ci	      DBG (0, "insb *%d\n", rc);
8413141cc406Sopenharmony_ci#endif
8414141cc406Sopenharmony_ci	      needed = rc;
8415141cc406Sopenharmony_ci	    }
8416141cc406Sopenharmony_ci	  else
8417141cc406Sopenharmony_ci	    {
8418141cc406Sopenharmony_ci		  for (loop = 0; (loop < needed) && (wait==0); loop++)
8419141cc406Sopenharmony_ci		    {
8420141cc406Sopenharmony_ci		      status = Inb (STATUS) & 0xF8;
8421141cc406Sopenharmony_ci		      if ((status != 0xD0) && (status != 0xC0)
8422141cc406Sopenharmony_ci			  && (status != 0xC8))
8423141cc406Sopenharmony_ci			{
8424141cc406Sopenharmony_ci			  DBG (0,
8425141cc406Sopenharmony_ci			       "EPPcmdGetBuffer610p found 0x%02X expected 0xD0 or 0xC0 (%s:%d)\n",
8426141cc406Sopenharmony_ci			       status, __FILE__, __LINE__);
8427141cc406Sopenharmony_ci			  return 0;
8428141cc406Sopenharmony_ci			}
8429141cc406Sopenharmony_ci		      if (status == 0xC8)
8430141cc406Sopenharmony_ci		        {
8431141cc406Sopenharmony_ci		          wait = 1;
8432141cc406Sopenharmony_ci		          needed=loop;
8433141cc406Sopenharmony_ci			}
8434141cc406Sopenharmony_ci		      else
8435141cc406Sopenharmony_ci		        {
8436141cc406Sopenharmony_ci		          tmp = Inb (EPPDATA);
8437141cc406Sopenharmony_ci		          buffer[count + loop] = tmp;
8438141cc406Sopenharmony_ci			}
8439141cc406Sopenharmony_ci		    }
8440141cc406Sopenharmony_ci	    }
8441141cc406Sopenharmony_ci	}
8442141cc406Sopenharmony_ci      else
8443141cc406Sopenharmony_ci#endif /* HAVE_LINUX_PPDEV_H */
8444141cc406Sopenharmony_ci	{
8445141cc406Sopenharmony_ci	  Insb (EPPDATA, buffer + count, needed);
8446141cc406Sopenharmony_ci	}
8447141cc406Sopenharmony_ci      count += needed;
8448141cc406Sopenharmony_ci      disconnect610p ();
8449141cc406Sopenharmony_ci    }
8450141cc406Sopenharmony_ci  usleep (10000);
8451141cc406Sopenharmony_ci  /* ??? CMDSYNC (0x00); */
8452141cc406Sopenharmony_ci  /* everything went fine */
8453141cc406Sopenharmony_ci  return 1;
8454141cc406Sopenharmony_ci}
8455141cc406Sopenharmony_ci
8456141cc406Sopenharmony_ci/* 1 OK, 0 failed */
8457141cc406Sopenharmony_cistatic int
8458141cc406Sopenharmony_cicmdGetBuffer610p (int cmd, int len, unsigned char *buffer)
8459141cc406Sopenharmony_ci{
8460141cc406Sopenharmony_ci  int status, i, tmp;
8461141cc406Sopenharmony_ci  int word[5];
8462141cc406Sopenharmony_ci  int read, needed, max;
8463141cc406Sopenharmony_ci
8464141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_EPP)
8465141cc406Sopenharmony_ci    return EPPcmdGetBuffer610p (cmd, len, buffer);
8466141cc406Sopenharmony_ci
8467141cc406Sopenharmony_ci  /* first we set length and channel */
8468141cc406Sopenharmony_ci  /* compute word */
8469141cc406Sopenharmony_ci  word[0] = len / 65536;
8470141cc406Sopenharmony_ci  word[1] = (len / 256) % 256;
8471141cc406Sopenharmony_ci  word[2] = len % 256;
8472141cc406Sopenharmony_ci  word[3] = (cmd & 0x0F) | 0xC0;
8473141cc406Sopenharmony_ci  word[4] = -1;
8474141cc406Sopenharmony_ci
8475141cc406Sopenharmony_ci  connect610p ();
8476141cc406Sopenharmony_ci  sync610p ();
8477141cc406Sopenharmony_ci  if (sendLength610p (word) == 0)
8478141cc406Sopenharmony_ci    {
8479141cc406Sopenharmony_ci      DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__);
8480141cc406Sopenharmony_ci      return 0;
8481141cc406Sopenharmony_ci    }
8482141cc406Sopenharmony_ci  status = getStatus610p ();
8483141cc406Sopenharmony_ci  scannerStatus = status;
8484141cc406Sopenharmony_ci  if ((status != 0xC0) && (status != 0xD0))
8485141cc406Sopenharmony_ci    {
8486141cc406Sopenharmony_ci      DBG (1, "Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__,
8487141cc406Sopenharmony_ci	   __LINE__);
8488141cc406Sopenharmony_ci      return 0;
8489141cc406Sopenharmony_ci    }
8490141cc406Sopenharmony_ci  disconnect610p ();
8491141cc406Sopenharmony_ci
8492141cc406Sopenharmony_ci  if (sanei_umax_pp_getfull () == 1)
8493141cc406Sopenharmony_ci    max = 2550 / 3;
8494141cc406Sopenharmony_ci  else
8495141cc406Sopenharmony_ci    max = 32768;
8496141cc406Sopenharmony_ci  read = 0;
8497141cc406Sopenharmony_ci  while (read < len)
8498141cc406Sopenharmony_ci    {
8499141cc406Sopenharmony_ci      if (len - read > max)
8500141cc406Sopenharmony_ci	needed = max;
8501141cc406Sopenharmony_ci      else
8502141cc406Sopenharmony_ci	needed = len - read;
8503141cc406Sopenharmony_ci
8504141cc406Sopenharmony_ci      if (sanei_umax_pp_getfull () == 0)
8505141cc406Sopenharmony_ci	status = getStatus610p ();
8506141cc406Sopenharmony_ci      else
8507141cc406Sopenharmony_ci	status = 0x20;
8508141cc406Sopenharmony_ci
8509141cc406Sopenharmony_ci      /* wait for data ready */
8510141cc406Sopenharmony_ci      while ((status & 0x80) == 0x00)
8511141cc406Sopenharmony_ci	{
8512141cc406Sopenharmony_ci	  connect610p ();
8513141cc406Sopenharmony_ci	  Outb (CONTROL, 0x07);
8514141cc406Sopenharmony_ci	  Outb (DATA, 0xFF);
8515141cc406Sopenharmony_ci	  tmp = Inb (DATA);
8516141cc406Sopenharmony_ci	  if (tmp != 0xFF)
8517141cc406Sopenharmony_ci	    {
8518141cc406Sopenharmony_ci	      DBG (0,
8519141cc406Sopenharmony_ci		   "cmdGetBuffer610p found 0x%02X expected 0xFF  (%s:%d)\n",
8520141cc406Sopenharmony_ci		   tmp, __FILE__, __LINE__);
8521141cc406Sopenharmony_ci	      return 0;
8522141cc406Sopenharmony_ci	    }
8523141cc406Sopenharmony_ci	  status = Inb (STATUS) & 0xF8;
8524141cc406Sopenharmony_ci	  if ((status & 0x80) == 0x00)
8525141cc406Sopenharmony_ci	    disconnect610p ();
8526141cc406Sopenharmony_ci	  else
8527141cc406Sopenharmony_ci	    {
8528141cc406Sopenharmony_ci	      Outb (CONTROL, 0x04);
8529141cc406Sopenharmony_ci	      sync610p ();
8530141cc406Sopenharmony_ci	      byteMode ();
8531141cc406Sopenharmony_ci	    }
8532141cc406Sopenharmony_ci	}
8533141cc406Sopenharmony_ci
8534141cc406Sopenharmony_ci      i = 0;
8535141cc406Sopenharmony_ci      while (i < needed)
8536141cc406Sopenharmony_ci	{
8537141cc406Sopenharmony_ci	  if (sanei_umax_pp_getfull () == 0)
8538141cc406Sopenharmony_ci	    {
8539141cc406Sopenharmony_ci	      status = Inb (STATUS) & 0xF8;
8540141cc406Sopenharmony_ci	      if (status == 0xC8)
8541141cc406Sopenharmony_ci		{
8542141cc406Sopenharmony_ci		  for (tmp = 0; tmp < 18; tmp++)
8543141cc406Sopenharmony_ci		    status = Inb (STATUS) & 0xF8;
8544141cc406Sopenharmony_ci		  break;
8545141cc406Sopenharmony_ci		}
8546141cc406Sopenharmony_ci	    }
8547141cc406Sopenharmony_ci	  Outb (CONTROL, 0x26);	/* data reverse+ 'reg' */
8548141cc406Sopenharmony_ci	  buffer[read + i] = Inb (DATA);
8549141cc406Sopenharmony_ci	  Outb (CONTROL, 0x24);	/* data reverse+ 'reg' */
8550141cc406Sopenharmony_ci	  i++;
8551141cc406Sopenharmony_ci	}
8552141cc406Sopenharmony_ci      byteMode ();
8553141cc406Sopenharmony_ci      disconnect610p ();
8554141cc406Sopenharmony_ci      read += i;
8555141cc406Sopenharmony_ci    }
8556141cc406Sopenharmony_ci
8557141cc406Sopenharmony_ci  return 1;
8558141cc406Sopenharmony_ci}
8559141cc406Sopenharmony_ci
8560141cc406Sopenharmony_ci
8561141cc406Sopenharmony_ci/* 1 OK, 0 failed */
8562141cc406Sopenharmony_cistatic int
8563141cc406Sopenharmony_cicmdGetBuffer (int cmd, int len, unsigned char *buffer)
8564141cc406Sopenharmony_ci{
8565141cc406Sopenharmony_ci  int reg, tmp;
8566141cc406Sopenharmony_ci  int word[5], read;
8567141cc406Sopenharmony_ci  int needed;
8568141cc406Sopenharmony_ci
8569141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
8570141cc406Sopenharmony_ci    return cmdGetBuffer610p (cmd, len, buffer);
8571141cc406Sopenharmony_ci
8572141cc406Sopenharmony_ci  /* compute word */
8573141cc406Sopenharmony_ci  word[0] = len / 65536;
8574141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
8575141cc406Sopenharmony_ci  word[2] = len % 256;
8576141cc406Sopenharmony_ci  word[3] = (cmd & 0x0F) | 0xC0;
8577141cc406Sopenharmony_ci  word[4] = -1;
8578141cc406Sopenharmony_ci
8579141cc406Sopenharmony_ci  /* send word: len+addr(?) */
8580141cc406Sopenharmony_ci  if (foncSendWord (word) == 0)
8581141cc406Sopenharmony_ci    {
8582141cc406Sopenharmony_ci      DBG (0, "foncSendWord(word) failed (%s:%d)\n", __FILE__, __LINE__);
8583141cc406Sopenharmony_ci      return 0;
8584141cc406Sopenharmony_ci    }
8585141cc406Sopenharmony_ci  DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__);
8586141cc406Sopenharmony_ci
8587141cc406Sopenharmony_ci  prologue (0x10);
8588141cc406Sopenharmony_ci
8589141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0D);
8590141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x00);
8591141cc406Sopenharmony_ci
8592141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
8593141cc406Sopenharmony_ci
8594141cc406Sopenharmony_ci  /* wait if busy */
8595141cc406Sopenharmony_ci  while ((reg & 0x08) == 0x08)
8596141cc406Sopenharmony_ci    reg = registerRead (0x19) & 0xF8;
8597141cc406Sopenharmony_ci  if ((reg != 0xC0) && (reg != 0xD0))
8598141cc406Sopenharmony_ci    {
8599141cc406Sopenharmony_ci      DBG (0, "cmdGetBuffer failed (%s:%d)\n", __FILE__, __LINE__);
8600141cc406Sopenharmony_ci      return 0;
8601141cc406Sopenharmony_ci    }
8602141cc406Sopenharmony_ci
8603141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_ECP)
8604141cc406Sopenharmony_ci    {
8605141cc406Sopenharmony_ci      REGISTERWRITE (0x1A, 0x44);
8606141cc406Sopenharmony_ci    }
8607141cc406Sopenharmony_ci
8608141cc406Sopenharmony_ci  read = 0;
8609141cc406Sopenharmony_ci  reg = registerRead (0x0C);
8610141cc406Sopenharmony_ci  if (reg != 0x04)
8611141cc406Sopenharmony_ci    {
8612141cc406Sopenharmony_ci      DBG (0, "cmdGetBuffer failed: unexpected status 0x%02X  ...(%s:%d)\n",
8613141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
8614141cc406Sopenharmony_ci      return 0;
8615141cc406Sopenharmony_ci    }
8616141cc406Sopenharmony_ci  REGISTERWRITE (0x0C, reg | 0x40);
8617141cc406Sopenharmony_ci
8618141cc406Sopenharmony_ci  /* actual data */
8619141cc406Sopenharmony_ci  read = 0;
8620141cc406Sopenharmony_ci  while (read < len)
8621141cc406Sopenharmony_ci    {
8622141cc406Sopenharmony_ci      needed = len - read;
8623141cc406Sopenharmony_ci      if (needed > 32768)
8624141cc406Sopenharmony_ci	needed = 32768;
8625141cc406Sopenharmony_ci      if (gMode == UMAX_PP_PARPORT_ECP)
8626141cc406Sopenharmony_ci	{
8627141cc406Sopenharmony_ci	  compatMode ();
8628141cc406Sopenharmony_ci	  Outb (CONTROL, 0x04);	/* reset ? */
8629141cc406Sopenharmony_ci	  ECPSetBuffer (needed);
8630141cc406Sopenharmony_ci	  tmp = ECPbufferRead (needed, buffer + read);
8631141cc406Sopenharmony_ci	  DBG (16, "ECPbufferRead(%d,buffer+read) passed (%s:%d)\n", needed,
8632141cc406Sopenharmony_ci	       __FILE__, __LINE__);
8633141cc406Sopenharmony_ci	  REGISTERWRITE (0x1A, 0x84);
8634141cc406Sopenharmony_ci	}
8635141cc406Sopenharmony_ci      else
8636141cc406Sopenharmony_ci	{
8637141cc406Sopenharmony_ci	  tmp = pausedBufferRead (needed, buffer + read);
8638141cc406Sopenharmony_ci	}
8639141cc406Sopenharmony_ci      if (tmp < needed)
8640141cc406Sopenharmony_ci	{
8641141cc406Sopenharmony_ci	  DBG (64, "cmdGetBuffer only got %d bytes out of %d ...(%s:%d)\n",
8642141cc406Sopenharmony_ci	       tmp, needed, __FILE__, __LINE__);
8643141cc406Sopenharmony_ci	}
8644141cc406Sopenharmony_ci      else
8645141cc406Sopenharmony_ci	{
8646141cc406Sopenharmony_ci	  DBG (64,
8647141cc406Sopenharmony_ci	       "cmdGetBuffer got all %d bytes out of %d , read=%d...(%s:%d)\n",
8648141cc406Sopenharmony_ci	       tmp, 32768, read, __FILE__, __LINE__);
8649141cc406Sopenharmony_ci	}
8650141cc406Sopenharmony_ci      read += tmp;
8651141cc406Sopenharmony_ci      DBG (16, "Read %d bytes out of %d (last block is %d bytes) (%s:%d)\n",
8652141cc406Sopenharmony_ci	   read, len, tmp, __FILE__, __LINE__);
8653141cc406Sopenharmony_ci      if (read < len)
8654141cc406Sopenharmony_ci	{
8655141cc406Sopenharmony_ci	  /* wait for scanner to be ready */
8656141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
8657141cc406Sopenharmony_ci	  DBG (64, "Status after block read is 0x%02X (%s:%d)\n", reg,
8658141cc406Sopenharmony_ci	       __FILE__, __LINE__);
8659141cc406Sopenharmony_ci	  if ((reg & 0x08) == 0x08)
8660141cc406Sopenharmony_ci	    {
8661141cc406Sopenharmony_ci	      int pass = 0;
8662141cc406Sopenharmony_ci
8663141cc406Sopenharmony_ci	      do
8664141cc406Sopenharmony_ci		{
8665141cc406Sopenharmony_ci		  reg = registerRead (0x19) & 0xF8;
8666141cc406Sopenharmony_ci		  usleep (100);
8667141cc406Sopenharmony_ci		  pass++;
8668141cc406Sopenharmony_ci		}
8669141cc406Sopenharmony_ci	      while ((pass < 32768) && ((reg & 0x08) == 0x08));
8670141cc406Sopenharmony_ci	      DBG (64, "Status after waiting is 0x%02X (pass=%d) (%s:%d)\n",
8671141cc406Sopenharmony_ci		   reg, pass, __FILE__, __LINE__);
8672141cc406Sopenharmony_ci	      if ((reg != 0xC0) && (reg != 0xD0))
8673141cc406Sopenharmony_ci		{
8674141cc406Sopenharmony_ci		  DBG (0,
8675141cc406Sopenharmony_ci		       "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n",
8676141cc406Sopenharmony_ci		       reg, __FILE__, __LINE__);
8677141cc406Sopenharmony_ci		  DBG (0, "Going on...\n");
8678141cc406Sopenharmony_ci		}
8679141cc406Sopenharmony_ci	    }
8680141cc406Sopenharmony_ci
8681141cc406Sopenharmony_ci	  /* signal we want next data chunk */
8682141cc406Sopenharmony_ci	  if (gMode == UMAX_PP_PARPORT_ECP)
8683141cc406Sopenharmony_ci	    {
8684141cc406Sopenharmony_ci	      REGISTERWRITE (0x1A, 0x44);
8685141cc406Sopenharmony_ci	    }
8686141cc406Sopenharmony_ci	  reg = registerRead (0x0C);
8687141cc406Sopenharmony_ci	  registerWrite (0x0C, reg | 0x40);
8688141cc406Sopenharmony_ci	}
8689141cc406Sopenharmony_ci    }
8690141cc406Sopenharmony_ci
8691141cc406Sopenharmony_ci  /* OK ! */
8692141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0D);
8693141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x00);
8694141cc406Sopenharmony_ci
8695141cc406Sopenharmony_ci  /* epilogue */
8696141cc406Sopenharmony_ci  epilogue ();
8697141cc406Sopenharmony_ci  return 1;
8698141cc406Sopenharmony_ci}
8699141cc406Sopenharmony_ci
8700141cc406Sopenharmony_ci/* 1 OK, 0 failed */
8701141cc406Sopenharmony_cistatic int
8702141cc406Sopenharmony_cicmdGetBuffer32 (int cmd, int len, unsigned char *buffer)
8703141cc406Sopenharmony_ci{
8704141cc406Sopenharmony_ci  int reg, tmp;
8705141cc406Sopenharmony_ci  int word[5], read;
8706141cc406Sopenharmony_ci
8707141cc406Sopenharmony_ci  /* compute word */
8708141cc406Sopenharmony_ci  word[0] = len / 65536;
8709141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
8710141cc406Sopenharmony_ci  word[2] = len % 256;
8711141cc406Sopenharmony_ci  word[3] = (cmd & 0x3F) | 0x80 | 0x40;
8712141cc406Sopenharmony_ci
8713141cc406Sopenharmony_ci  if (!prologue (0x10))
8714141cc406Sopenharmony_ci    {
8715141cc406Sopenharmony_ci      DBG (0, "cmdSet: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8716141cc406Sopenharmony_ci      return 0;
8717141cc406Sopenharmony_ci    }
8718141cc406Sopenharmony_ci
8719141cc406Sopenharmony_ci  /* send data */
8720141cc406Sopenharmony_ci  if (sendLength (word, 4) == 0)
8721141cc406Sopenharmony_ci    {
8722141cc406Sopenharmony_ci      DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8723141cc406Sopenharmony_ci      return 0;
8724141cc406Sopenharmony_ci    }
8725141cc406Sopenharmony_ci  TRACE (16, "sendLength(word,4) passed ...");
8726141cc406Sopenharmony_ci
8727141cc406Sopenharmony_ci  /* head end */
8728141cc406Sopenharmony_ci  epilogue ();
8729141cc406Sopenharmony_ci
8730141cc406Sopenharmony_ci  prologue (0x10);
8731141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0D);
8732141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x00);
8733141cc406Sopenharmony_ci
8734141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
8735141cc406Sopenharmony_ci
8736141cc406Sopenharmony_ci  /* wait if busy */
8737141cc406Sopenharmony_ci  while ((reg & 0x08) == 0x08)
8738141cc406Sopenharmony_ci    reg = registerRead (0x19) & 0xF8;
8739141cc406Sopenharmony_ci  if ((reg != 0xC0) && (reg != 0xD0))
8740141cc406Sopenharmony_ci    {
8741141cc406Sopenharmony_ci      DBG (0, "cmdGetBuffer32 failed: unexpected status 0x%02X  ...(%s:%d)\n",
8742141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
8743141cc406Sopenharmony_ci      return 0;
8744141cc406Sopenharmony_ci    }
8745141cc406Sopenharmony_ci  reg = registerRead (0x0C);
8746141cc406Sopenharmony_ci  if (reg != 0x04)
8747141cc406Sopenharmony_ci    {
8748141cc406Sopenharmony_ci      DBG (0, "cmdGetBuffer32 failed: unexpected status 0x%02X  ...(%s:%d)\n",
8749141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
8750141cc406Sopenharmony_ci      return 0;
8751141cc406Sopenharmony_ci    }
8752141cc406Sopenharmony_ci  REGISTERWRITE (0x0C, reg | 0x40);
8753141cc406Sopenharmony_ci
8754141cc406Sopenharmony_ci  read = 0;
8755141cc406Sopenharmony_ci  while (read < len)
8756141cc406Sopenharmony_ci    {
8757141cc406Sopenharmony_ci      if (read + 1700 < len)
8758141cc406Sopenharmony_ci	{
8759141cc406Sopenharmony_ci	  tmp = 1700;
8760141cc406Sopenharmony_ci	  bufferRead (tmp, buffer + read);
8761141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
8762141cc406Sopenharmony_ci	  if ((read + tmp < len) && (reg & 0x08) == 0x08)
8763141cc406Sopenharmony_ci	    {
8764141cc406Sopenharmony_ci	      do
8765141cc406Sopenharmony_ci		{
8766141cc406Sopenharmony_ci		  reg = registerRead (0x19) & 0xF8;
8767141cc406Sopenharmony_ci		}
8768141cc406Sopenharmony_ci	      while ((reg & 0x08) == 0x08);
8769141cc406Sopenharmony_ci	      if ((reg != 0xC0) && (reg != 0xD0))
8770141cc406Sopenharmony_ci		{
8771141cc406Sopenharmony_ci		  DBG (0,
8772141cc406Sopenharmony_ci		       "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n",
8773141cc406Sopenharmony_ci		       reg, __FILE__, __LINE__);
8774141cc406Sopenharmony_ci		  DBG (0, "Going on...\n");
8775141cc406Sopenharmony_ci		}
8776141cc406Sopenharmony_ci	    }
8777141cc406Sopenharmony_ci	  reg = registerRead (0x0C);
8778141cc406Sopenharmony_ci	  registerWrite (0x0C, reg | 0x40);
8779141cc406Sopenharmony_ci	  read += tmp;
8780141cc406Sopenharmony_ci	}
8781141cc406Sopenharmony_ci      else
8782141cc406Sopenharmony_ci	{
8783141cc406Sopenharmony_ci	  tmp = len - read;
8784141cc406Sopenharmony_ci	  bufferRead (tmp, buffer + read);
8785141cc406Sopenharmony_ci	  read += tmp;
8786141cc406Sopenharmony_ci	  if ((read < len))
8787141cc406Sopenharmony_ci	    {
8788141cc406Sopenharmony_ci	      reg = registerRead (0x19) & 0xF8;
8789141cc406Sopenharmony_ci	      while ((reg & 0x08) == 0x08)
8790141cc406Sopenharmony_ci		{
8791141cc406Sopenharmony_ci		  reg = registerRead (0x19) & 0xF8;
8792141cc406Sopenharmony_ci		}
8793141cc406Sopenharmony_ci	    }
8794141cc406Sopenharmony_ci	}
8795141cc406Sopenharmony_ci    }
8796141cc406Sopenharmony_ci
8797141cc406Sopenharmony_ci  /* OK ! */
8798141cc406Sopenharmony_ci  epilogue ();
8799141cc406Sopenharmony_ci  return 1;
8800141cc406Sopenharmony_ci}
8801141cc406Sopenharmony_ci
8802141cc406Sopenharmony_ciint
8803141cc406Sopenharmony_cisanei_umax_pp_cmdSync (int cmd)
8804141cc406Sopenharmony_ci{
8805141cc406Sopenharmony_ci  int word[5];
8806141cc406Sopenharmony_ci
8807141cc406Sopenharmony_ci
8808141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
8809141cc406Sopenharmony_ci    return cmdSync610p (cmd);
8810141cc406Sopenharmony_ci
8811141cc406Sopenharmony_ci  /* compute word */
8812141cc406Sopenharmony_ci  word[0] = 0x00;
8813141cc406Sopenharmony_ci  word[1] = 0x00;
8814141cc406Sopenharmony_ci  word[2] = 0x00;
8815141cc406Sopenharmony_ci  word[3] = cmd;
8816141cc406Sopenharmony_ci
8817141cc406Sopenharmony_ci  if (!prologue (0x10))
8818141cc406Sopenharmony_ci    {
8819141cc406Sopenharmony_ci      DBG (0, "cmdSync: prologue failed !   (%s:%d)\n", __FILE__, __LINE__);
8820141cc406Sopenharmony_ci    }
8821141cc406Sopenharmony_ci
8822141cc406Sopenharmony_ci  /* send data */
8823141cc406Sopenharmony_ci  if (sendLength (word, 4) == 0)
8824141cc406Sopenharmony_ci    {
8825141cc406Sopenharmony_ci      DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8826141cc406Sopenharmony_ci      return 0;
8827141cc406Sopenharmony_ci    }
8828141cc406Sopenharmony_ci  TRACE (16, "sendLength(word,4) passed ...");
8829141cc406Sopenharmony_ci
8830141cc406Sopenharmony_ci  /* end OK */
8831141cc406Sopenharmony_ci  epilogue ();
8832141cc406Sopenharmony_ci
8833141cc406Sopenharmony_ci  return 1;
8834141cc406Sopenharmony_ci}
8835141cc406Sopenharmony_ci
8836141cc406Sopenharmony_ci
8837141cc406Sopenharmony_ci/* numbers of bytes read, else 0 (failed)                             */
8838141cc406Sopenharmony_ci/* read data by chunk EXACTLY the width of the scan area in the given */
8839141cc406Sopenharmony_ci/* resolution . If a valid file descriptor is given, we write data    */
8840141cc406Sopenharmony_ci/* in it according to the color mode, before polling the scanner      */
8841141cc406Sopenharmony_ci/* len should not be bigger than 2 Megs                                      */
8842141cc406Sopenharmony_ci
8843141cc406Sopenharmony_ciint
8844141cc406Sopenharmony_cicmdGetBlockBuffer (int cmd, int len, int window, unsigned char *buffer)
8845141cc406Sopenharmony_ci{
8846141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
8847141cc406Sopenharmony_ci  struct timeval td, tf;
8848141cc406Sopenharmony_ci  float elapsed;
8849141cc406Sopenharmony_ci#endif
8850141cc406Sopenharmony_ci  int reg;
8851141cc406Sopenharmony_ci  int word[5], read;
8852141cc406Sopenharmony_ci
8853141cc406Sopenharmony_ci  /* compute word */
8854141cc406Sopenharmony_ci  word[0] = len / 65536;
8855141cc406Sopenharmony_ci  word[1] = len / 256 % 256;
8856141cc406Sopenharmony_ci  word[2] = len % 256;
8857141cc406Sopenharmony_ci  word[3] = (cmd & 0x3F) | 0x80 | 0x40;
8858141cc406Sopenharmony_ci
8859141cc406Sopenharmony_ci  if (!prologue (0x10))
8860141cc406Sopenharmony_ci    {
8861141cc406Sopenharmony_ci      DBG (0, "cmdGetBlockBuffer: prologue failed !   (%s:%d)\n", __FILE__,
8862141cc406Sopenharmony_ci	   __LINE__);
8863141cc406Sopenharmony_ci    }
8864141cc406Sopenharmony_ci
8865141cc406Sopenharmony_ci  /* send data */
8866141cc406Sopenharmony_ci  if (sendLength (word, 4) == 0)
8867141cc406Sopenharmony_ci    {
8868141cc406Sopenharmony_ci      DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__);
8869141cc406Sopenharmony_ci      return 0;
8870141cc406Sopenharmony_ci    }
8871141cc406Sopenharmony_ci  TRACE (16, "sendLength(word,4) passed ...");
8872141cc406Sopenharmony_ci  /* head end */
8873141cc406Sopenharmony_ci  epilogue ();
8874141cc406Sopenharmony_ci
8875141cc406Sopenharmony_ci
8876141cc406Sopenharmony_ci
8877141cc406Sopenharmony_ci  if (!prologue (0x10))
8878141cc406Sopenharmony_ci    {
8879141cc406Sopenharmony_ci      DBG (0, "cmdGetBlockBuffer: prologue failed !   (%s:%d)\n", __FILE__,
8880141cc406Sopenharmony_ci	   __LINE__);
8881141cc406Sopenharmony_ci    }
8882141cc406Sopenharmony_ci
8883141cc406Sopenharmony_ci
8884141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0D);
8885141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x00);
8886141cc406Sopenharmony_ci
8887141cc406Sopenharmony_ci  /* init counter */
8888141cc406Sopenharmony_ci  read = 0;
8889141cc406Sopenharmony_ci
8890141cc406Sopenharmony_ci  /* read scanner state */
8891141cc406Sopenharmony_ci  reg = registerRead (0x19) & 0xF8;
8892141cc406Sopenharmony_ci
8893141cc406Sopenharmony_ci
8894141cc406Sopenharmony_ci  /* read loop */
8895141cc406Sopenharmony_ci  while (read < len)
8896141cc406Sopenharmony_ci    {
8897141cc406Sopenharmony_ci      /* wait for the data to be ready */
8898141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
8899141cc406Sopenharmony_ci      gettimeofday (&td, NULL);
8900141cc406Sopenharmony_ci#endif
8901141cc406Sopenharmony_ci      while ((reg & 0x08) == 0x08)
8902141cc406Sopenharmony_ci	{
8903141cc406Sopenharmony_ci	  reg = registerRead (0x19) & 0xF8;
8904141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
8905141cc406Sopenharmony_ci	  gettimeofday (&tf, NULL);
8906141cc406Sopenharmony_ci	  elapsed =
8907141cc406Sopenharmony_ci	    ((tf.tv_sec * 1000000 + tf.tv_usec) -
8908141cc406Sopenharmony_ci	     (td.tv_sec * 1000000 + td.tv_usec)) / 1000000;
8909141cc406Sopenharmony_ci	  if (elapsed > 3)
8910141cc406Sopenharmony_ci	    {
8911141cc406Sopenharmony_ci	      DBG
8912141cc406Sopenharmony_ci		(0,
8913141cc406Sopenharmony_ci		 "Time-out (%.2f s) waiting for scanner ... giving up on status 0x%02X !   (%s:%d)\n",
8914141cc406Sopenharmony_ci		 elapsed, reg, __FILE__, __LINE__);
8915141cc406Sopenharmony_ci	      epilogue ();
8916141cc406Sopenharmony_ci	      return read;
8917141cc406Sopenharmony_ci	    }
8918141cc406Sopenharmony_ci#endif
8919141cc406Sopenharmony_ci	}
8920141cc406Sopenharmony_ci      if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0x00))
8921141cc406Sopenharmony_ci	{
8922141cc406Sopenharmony_ci	  DBG (0,
8923141cc406Sopenharmony_ci	       "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n",
8924141cc406Sopenharmony_ci	       reg, __FILE__, __LINE__);
8925141cc406Sopenharmony_ci	  DBG (0, "Going on...\n");
8926141cc406Sopenharmony_ci	}
8927141cc406Sopenharmony_ci
8928141cc406Sopenharmony_ci      /* signals next chunk */
8929141cc406Sopenharmony_ci      reg = registerRead (0x0C);
8930141cc406Sopenharmony_ci      if (reg != 0x04)
8931141cc406Sopenharmony_ci	{
8932141cc406Sopenharmony_ci	  DBG (0,
8933141cc406Sopenharmony_ci	       "cmdGetBlockBuffer failed: unexpected value reg0C=0x%02X  ...(%s:%d)\n",
8934141cc406Sopenharmony_ci	       reg, __FILE__, __LINE__);
8935141cc406Sopenharmony_ci	  return 0;
8936141cc406Sopenharmony_ci	}
8937141cc406Sopenharmony_ci      REGISTERWRITE (0x0C, reg | 0x40);
8938141cc406Sopenharmony_ci
8939141cc406Sopenharmony_ci
8940141cc406Sopenharmony_ci      /* there is always a full block ready when scanner is ready */
8941141cc406Sopenharmony_ci      /* 32 bits I/O read , window must match the width of scan   */
8942141cc406Sopenharmony_ci      bufferRead (window, buffer + read);
8943141cc406Sopenharmony_ci
8944141cc406Sopenharmony_ci      /* add bytes read */
8945141cc406Sopenharmony_ci      read += window;
8946141cc406Sopenharmony_ci
8947141cc406Sopenharmony_ci
8948141cc406Sopenharmony_ci      DBG (16, "Read %d bytes out of %d (last block is %d bytes) (%s:%d)\n",
8949141cc406Sopenharmony_ci	   read, len, window, __FILE__, __LINE__);
8950141cc406Sopenharmony_ci
8951141cc406Sopenharmony_ci      /* test status after read */
8952141cc406Sopenharmony_ci      reg = registerRead (0x19) & 0xF8;
8953141cc406Sopenharmony_ci    }
8954141cc406Sopenharmony_ci
8955141cc406Sopenharmony_ci
8956141cc406Sopenharmony_ci  /* wait for the data to be ready */
8957141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
8958141cc406Sopenharmony_ci  gettimeofday (&td, NULL);
8959141cc406Sopenharmony_ci#endif
8960141cc406Sopenharmony_ci  while ((reg & 0x08) == 0x08)
8961141cc406Sopenharmony_ci    {
8962141cc406Sopenharmony_ci      reg = registerRead (0x19) & 0xF8;
8963141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
8964141cc406Sopenharmony_ci      gettimeofday (&tf, NULL);
8965141cc406Sopenharmony_ci      elapsed =
8966141cc406Sopenharmony_ci	((tf.tv_sec * 1000000 + tf.tv_usec) -
8967141cc406Sopenharmony_ci	 (td.tv_sec * 1000000 + td.tv_usec)) / 1000000;
8968141cc406Sopenharmony_ci      if (elapsed > 3)
8969141cc406Sopenharmony_ci	{
8970141cc406Sopenharmony_ci	  DBG
8971141cc406Sopenharmony_ci	    (0,
8972141cc406Sopenharmony_ci	     "Time-out (%.2f s) waiting for scanner ... giving up on status 0x%02X !   (%s:%d)\n",
8973141cc406Sopenharmony_ci	     elapsed, reg, __FILE__, __LINE__);
8974141cc406Sopenharmony_ci	  epilogue ();
8975141cc406Sopenharmony_ci	  return read;
8976141cc406Sopenharmony_ci	}
8977141cc406Sopenharmony_ci#endif
8978141cc406Sopenharmony_ci    }
8979141cc406Sopenharmony_ci  if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0x00))
8980141cc406Sopenharmony_ci    {
8981141cc406Sopenharmony_ci      DBG (0, "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n",
8982141cc406Sopenharmony_ci	   reg, __FILE__, __LINE__);
8983141cc406Sopenharmony_ci      DBG (0, "Going on...\n");
8984141cc406Sopenharmony_ci    }
8985141cc406Sopenharmony_ci
8986141cc406Sopenharmony_ci  REGISTERWRITE (0x0E, 0x0D);
8987141cc406Sopenharmony_ci  REGISTERWRITE (0x0F, 0x00);
8988141cc406Sopenharmony_ci
8989141cc406Sopenharmony_ci
8990141cc406Sopenharmony_ci  /* OK ! */
8991141cc406Sopenharmony_ci  epilogue ();
8992141cc406Sopenharmony_ci  return read;
8993141cc406Sopenharmony_ci}
8994141cc406Sopenharmony_ci
8995141cc406Sopenharmony_ci/*
8996141cc406Sopenharmony_ci * encodes DC offsets: must be in [0..0x0F] range
8997141cc406Sopenharmony_ci */
8998141cc406Sopenharmony_cistatic void
8999141cc406Sopenharmony_ciencodeDC (int dcRed, int dcGreen, int dcBlue, int *motor)
9000141cc406Sopenharmony_ci{
9001141cc406Sopenharmony_ci  motor[11] = (motor[11] & 0x0F) | dcRed << 4;
9002141cc406Sopenharmony_ci  motor[12] = (motor[12] & 0xC3) | dcGreen << 2;
9003141cc406Sopenharmony_ci  motor[13] = (motor[13] & 0xF0) | dcBlue;
9004141cc406Sopenharmony_ci}
9005141cc406Sopenharmony_ci
9006141cc406Sopenharmony_cistatic void
9007141cc406Sopenharmony_cidecodeDC (int *motor)
9008141cc406Sopenharmony_ci{
9009141cc406Sopenharmony_ci  DBG (0, "DC (R,G,B)=(%d,%d,%d)\n",
9010141cc406Sopenharmony_ci       (motor[11] & 0xF0) >> 4, (motor[12] & 0x3C) >> 2, motor[13] & 0x0F);
9011141cc406Sopenharmony_ci}
9012141cc406Sopenharmony_ci
9013141cc406Sopenharmony_ci
9014141cc406Sopenharmony_ci/*
9015141cc406Sopenharmony_ci * encodes VGA : must be in [0..0x0F] range
9016141cc406Sopenharmony_ci */
9017141cc406Sopenharmony_cistatic void
9018141cc406Sopenharmony_ciencodeVGA (int vgaRed, int vgaGreen, int vgaBlue, int *motor)
9019141cc406Sopenharmony_ci{
9020141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () > 610)
9021141cc406Sopenharmony_ci    {
9022141cc406Sopenharmony_ci      motor[10] = (vgaRed << 4) | vgaGreen;
9023141cc406Sopenharmony_ci      motor[11] = (motor[11] & 0xF0) | vgaBlue;
9024141cc406Sopenharmony_ci    }
9025141cc406Sopenharmony_ci  else
9026141cc406Sopenharmony_ci    {
9027141cc406Sopenharmony_ci      motor[10] = (vgaGreen << 4) | vgaBlue;
9028141cc406Sopenharmony_ci      motor[11] = (motor[11] & 0xF0) | vgaRed;
9029141cc406Sopenharmony_ci      /* ancien
9030141cc406Sopenharmony_ci         F00: vert
9031141cc406Sopenharmony_ci         0F0: bleu
9032141cc406Sopenharmony_ci         00F: rouge
9033141cc406Sopenharmony_ci         motor[10] = (vgaRed << 4) | vgaGreen;
9034141cc406Sopenharmony_ci         motor[11] = (motor[11] & 0xF0) | vgaBlue; */
9035141cc406Sopenharmony_ci    }
9036141cc406Sopenharmony_ci}
9037141cc406Sopenharmony_ci
9038141cc406Sopenharmony_cistatic void
9039141cc406Sopenharmony_cidecodeVGA (int *motor)
9040141cc406Sopenharmony_ci{
9041141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () > 610)
9042141cc406Sopenharmony_ci    {
9043141cc406Sopenharmony_ci      DBG (0, "VGA (R,G,B)=(%d,%d,%d)\n",
9044141cc406Sopenharmony_ci	   (motor[10] & 0xF0) >> 4, (motor[10] & 0x0F), (motor[11] & 0x0F));
9045141cc406Sopenharmony_ci    }
9046141cc406Sopenharmony_ci  else
9047141cc406Sopenharmony_ci    {
9048141cc406Sopenharmony_ci      DBG (0, "VGA (R,G,B)=(%d,%d,%d)\n",
9049141cc406Sopenharmony_ci	   (motor[11] & 0x0F), (motor[10] & 0xF0) >> 4, (motor[10] & 0x0F));
9050141cc406Sopenharmony_ci    }
9051141cc406Sopenharmony_ci}
9052141cc406Sopenharmony_ci
9053141cc406Sopenharmony_ci/*
9054141cc406Sopenharmony_ci * this function encodes total head movement which includes
9055141cc406Sopenharmony_ci * y movement and scan area height
9056141cc406Sopenharmony_ci * height is scan area height
9057141cc406Sopenharmony_ci * ypos   is head movement before scan
9058141cc406Sopenharmony_ci * total move will be ypos+height */
9059141cc406Sopenharmony_cistatic void
9060141cc406Sopenharmony_ciencodeHY (int height, int ypos, int *motor)
9061141cc406Sopenharmony_ci{
9062141cc406Sopenharmony_ci  motor[0] = height % 256;
9063141cc406Sopenharmony_ci  motor[1] = (height / 256) & 0x3F;
9064141cc406Sopenharmony_ci  motor[1] = motor[1] | (ypos & 0x03) << 6;
9065141cc406Sopenharmony_ci  motor[2] = (ypos >> 2) % 256;
9066141cc406Sopenharmony_ci  motor[3] = (motor[3] & 0xF0) | ((ypos >> 10) & 0x0F);
9067141cc406Sopenharmony_ci}
9068141cc406Sopenharmony_ci
9069141cc406Sopenharmony_ci/*
9070141cc406Sopenharmony_ci * this function encodes x start and x end on the CCD
9071141cc406Sopenharmony_ci * w is width of scanning area
9072141cc406Sopenharmony_ci * x is start of scanning area
9073141cc406Sopenharmony_ci * dpi is x resolution
9074141cc406Sopenharmony_ci * color is non zero if scanning in color
9075141cc406Sopenharmony_ci * bytes is on aoverride for bpl, since it sin't clear today when
9076141cc406Sopenharmony_ci * the formula has to be applied
9077141cc406Sopenharmony_ci */
9078141cc406Sopenharmony_cistatic void
9079141cc406Sopenharmony_ciencodeWX (int width, int xstart, int dpi, int color, int *ccd, int bytes)
9080141cc406Sopenharmony_ci{
9081141cc406Sopenharmony_ci  int xend;
9082141cc406Sopenharmony_ci  int bpl;
9083141cc406Sopenharmony_ci  int x;
9084141cc406Sopenharmony_ci
9085141cc406Sopenharmony_ci  xend = xstart + width;
9086141cc406Sopenharmony_ci  x = xstart - 1;
9087141cc406Sopenharmony_ci
9088141cc406Sopenharmony_ci  /* x start encoding */
9089141cc406Sopenharmony_ci  ccd[17] = x % 256;
9090141cc406Sopenharmony_ci  ccd[18] = (ccd[18] & 0xF0) | ((x / 256) & 0x0F);
9091141cc406Sopenharmony_ci  /* models >=1220P have a 600 dpi CCD: x is bigger */
9092141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () > 610)
9093141cc406Sopenharmony_ci    {
9094141cc406Sopenharmony_ci      if (x > 0x1000)
9095141cc406Sopenharmony_ci	ccd[33] |= 0x40;
9096141cc406Sopenharmony_ci      else
9097141cc406Sopenharmony_ci	ccd[33] &= 0xBF;
9098141cc406Sopenharmony_ci    }
9099141cc406Sopenharmony_ci
9100141cc406Sopenharmony_ci  /* x end encoding */
9101141cc406Sopenharmony_ci  ccd[18] = (ccd[18] & 0x0F) | ((xend % 16) << 4);
9102141cc406Sopenharmony_ci  ccd[19] = (xend / 16) % 256;
9103141cc406Sopenharmony_ci  /* models >=1220P have a 600 dpi CCD: x is bigger */
9104141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () > 610)
9105141cc406Sopenharmony_ci    {
9106141cc406Sopenharmony_ci      if (xend > 0x1000)
9107141cc406Sopenharmony_ci	ccd[33] |= 0x80;
9108141cc406Sopenharmony_ci      else
9109141cc406Sopenharmony_ci	ccd[33] &= 0x7F;
9110141cc406Sopenharmony_ci    }
9111141cc406Sopenharmony_ci
9112141cc406Sopenharmony_ci  /* now bytes per line */
9113141cc406Sopenharmony_ci  /* bpl = (op[24] - 0x41) * 256 + 8192 * (op[34] & 0x01) + op[23]; */
9114141cc406Sopenharmony_ci  bpl = (color == 0 ? 1 : 3) * width * dpi;
9115141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () > 610)
9116141cc406Sopenharmony_ci    {
9117141cc406Sopenharmony_ci      bpl /= 600;
9118141cc406Sopenharmony_ci      if (bpl >= 8192)
9119141cc406Sopenharmony_ci	ccd[34] |= 0x01;
9120141cc406Sopenharmony_ci      else
9121141cc406Sopenharmony_ci	ccd[34] &= 0xFE;
9122141cc406Sopenharmony_ci    }
9123141cc406Sopenharmony_ci  else
9124141cc406Sopenharmony_ci    {
9125141cc406Sopenharmony_ci      bpl /= 300;
9126141cc406Sopenharmony_ci    }
9127141cc406Sopenharmony_ci  if (bytes > 0)
9128141cc406Sopenharmony_ci    bpl = bytes;
9129141cc406Sopenharmony_ci  ccd[23] = bpl % 256;
9130141cc406Sopenharmony_ci  ccd[24] = 0x41 + ((bpl / 256) & 0x1F);
9131141cc406Sopenharmony_ci}
9132141cc406Sopenharmony_ci
9133141cc406Sopenharmony_ci  /* cropping coefficient: last 2 bytes gives the coefficient applied */
9134141cc406Sopenharmony_ci  /* to data scanned to get the actual image resolution               */
9135141cc406Sopenharmony_cistatic void
9136141cc406Sopenharmony_ciencodeCoefficient (int color, int dpi, int *calibration)
9137141cc406Sopenharmony_ci{
9138141cc406Sopenharmony_ci  int w, idx = 0;
9139141cc406Sopenharmony_ci  int *coeff;
9140141cc406Sopenharmony_ci
9141141cc406Sopenharmony_ci  /* 75, 150, 300, 600 and 1200 dpi */
9142141cc406Sopenharmony_ci  int color610p[4][2] =
9143141cc406Sopenharmony_ci    { {0x88, 0x88}, {0xAA, 0xAA}, {0xFF, 0xFF}, {0xFF, 0xFF} };
9144141cc406Sopenharmony_ci  int gray610p[4][2] =
9145141cc406Sopenharmony_ci    { {0x88, 0x01}, {0xAA, 0x11}, {0xFF, 0xAA}, {0xFF, 0xFF} };
9146141cc406Sopenharmony_ci
9147141cc406Sopenharmony_ci  /* FF means coeff=1
9148141cc406Sopenharmony_ci   * AA       coeff=1/2
9149141cc406Sopenharmony_ci   * 88       coeff=1/4
9150141cc406Sopenharmony_ci   * 80       coeff=1/8
9151141cc406Sopenharmony_ci   * first coeff for CCD (x)
9152141cc406Sopenharmony_ci   * second coeff for motor steps (y)
9153141cc406Sopenharmony_ci   */
9154141cc406Sopenharmony_ci  int color1220p[5][2] =
9155141cc406Sopenharmony_ci    { {0x80, 0xAA}, {0x88, 0xFF}, {0xAA, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} };
9156141cc406Sopenharmony_ci  int gray1220p[5][2] =
9157141cc406Sopenharmony_ci    { {0x80, 0x88}, {0x88, 0xAA}, {0xAA, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} };
9158141cc406Sopenharmony_ci
9159141cc406Sopenharmony_ci  switch (dpi)
9160141cc406Sopenharmony_ci    {
9161141cc406Sopenharmony_ci    case 1200:
9162141cc406Sopenharmony_ci      idx = 4;
9163141cc406Sopenharmony_ci      break;
9164141cc406Sopenharmony_ci    case 600:
9165141cc406Sopenharmony_ci      idx = 3;
9166141cc406Sopenharmony_ci      break;
9167141cc406Sopenharmony_ci    case 300:
9168141cc406Sopenharmony_ci      idx = 2;
9169141cc406Sopenharmony_ci      break;
9170141cc406Sopenharmony_ci    case 150:
9171141cc406Sopenharmony_ci      idx = 1;
9172141cc406Sopenharmony_ci      break;
9173141cc406Sopenharmony_ci    case 75:
9174141cc406Sopenharmony_ci      idx = 0;
9175141cc406Sopenharmony_ci      break;
9176141cc406Sopenharmony_ci    }
9177141cc406Sopenharmony_ci
9178141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () < 1210)
9179141cc406Sopenharmony_ci    {
9180141cc406Sopenharmony_ci      w = 2550;
9181141cc406Sopenharmony_ci      if (color >= RGB_MODE)
9182141cc406Sopenharmony_ci	coeff = color610p[idx];
9183141cc406Sopenharmony_ci      else
9184141cc406Sopenharmony_ci	coeff = gray610p[idx];
9185141cc406Sopenharmony_ci    }
9186141cc406Sopenharmony_ci  else
9187141cc406Sopenharmony_ci    {
9188141cc406Sopenharmony_ci      w = 5100;
9189141cc406Sopenharmony_ci      if (color >= RGB_MODE)
9190141cc406Sopenharmony_ci	coeff = color1220p[idx];
9191141cc406Sopenharmony_ci      else
9192141cc406Sopenharmony_ci	coeff = gray1220p[idx];
9193141cc406Sopenharmony_ci    }
9194141cc406Sopenharmony_ci
9195141cc406Sopenharmony_ci  /* x coefficient */
9196141cc406Sopenharmony_ci  calibration[3 * w + 768] = coeff[0];
9197141cc406Sopenharmony_ci
9198141cc406Sopenharmony_ci  /* y coefficient */
9199141cc406Sopenharmony_ci  calibration[3 * w + 769] = coeff[1];
9200141cc406Sopenharmony_ci}
9201141cc406Sopenharmony_ci
9202141cc406Sopenharmony_ci
9203141cc406Sopenharmony_cistatic void
9204141cc406Sopenharmony_cibloc2Decode (int *op)
9205141cc406Sopenharmony_ci{
9206141cc406Sopenharmony_ci  int i;
9207141cc406Sopenharmony_ci  int scanh;
9208141cc406Sopenharmony_ci  int skiph;
9209141cc406Sopenharmony_ci  int dpi = 0;
9210141cc406Sopenharmony_ci  int dir = 0;
9211141cc406Sopenharmony_ci  int color = 0;
9212141cc406Sopenharmony_ci  char str[64];
9213141cc406Sopenharmony_ci
9214141cc406Sopenharmony_ci  for (i = 0; i < 16; i++)
9215141cc406Sopenharmony_ci    sprintf (str + 3 * i, "%02X ", (unsigned char) op[i]);
9216141cc406Sopenharmony_ci  str[48] = 0x00;
9217141cc406Sopenharmony_ci  DBG (0, "Command block 2: %s\n", str);
9218141cc406Sopenharmony_ci
9219141cc406Sopenharmony_ci
9220141cc406Sopenharmony_ci  scanh = op[0] + (op[1] & 0x3F) * 256;
9221141cc406Sopenharmony_ci  skiph = ((op[1] & 0xC0) >> 6) + (op[2] << 2) + ((op[3] & 0x0F) << 10);
9222141cc406Sopenharmony_ci
9223141cc406Sopenharmony_ci  if (op[3] & 0x10)
9224141cc406Sopenharmony_ci    dir = 1;
9225141cc406Sopenharmony_ci  else
9226141cc406Sopenharmony_ci    dir = 0;
9227141cc406Sopenharmony_ci
9228141cc406Sopenharmony_ci  /* XXX STEF XXX seems to conflict with DC definitions */
9229141cc406Sopenharmony_ci  if (op[13] & 0x40)
9230141cc406Sopenharmony_ci    color = 1;
9231141cc406Sopenharmony_ci  else
9232141cc406Sopenharmony_ci    color = 0;
9233141cc406Sopenharmony_ci
9234141cc406Sopenharmony_ci  /* op[6]=0x60 at 600 and 1200 dpi */
9235141cc406Sopenharmony_ci  if ((op[8] == 0x17) && (op[9] != 0x05))
9236141cc406Sopenharmony_ci    dpi = 150;
9237141cc406Sopenharmony_ci  if ((op[8] == 0x17) && (op[9] == 0x05))
9238141cc406Sopenharmony_ci    dpi = 300;
9239141cc406Sopenharmony_ci  if ((op[9] == 0x05) && (op[14] & 0x08))
9240141cc406Sopenharmony_ci    dpi = 1200;
9241141cc406Sopenharmony_ci  if ((dpi == 0) && ((op[14] & 0x08) == 0))
9242141cc406Sopenharmony_ci    dpi = 600;
9243141cc406Sopenharmony_ci
9244141cc406Sopenharmony_ci
9245141cc406Sopenharmony_ci
9246141cc406Sopenharmony_ci  DBG (0, "\t->scan height   =0x%04X (%d)\n", scanh, scanh);
9247141cc406Sopenharmony_ci  DBG (0, "\t->skip height   =0x%04X (%d)\n", skiph, skiph);
9248141cc406Sopenharmony_ci  DBG (0, "\t->y dpi         =0x%04X (%d)\n", dpi, dpi);
9249141cc406Sopenharmony_ci  decodeVGA (op);
9250141cc406Sopenharmony_ci  decodeDC (op);
9251141cc406Sopenharmony_ci  if (dir)
9252141cc406Sopenharmony_ci    DBG (0, "\t->forward direction\n");
9253141cc406Sopenharmony_ci  else
9254141cc406Sopenharmony_ci    DBG (0, "\t->reverse direction\n");
9255141cc406Sopenharmony_ci  if (color)
9256141cc406Sopenharmony_ci    DBG (0, "\t->color scan       \n");
9257141cc406Sopenharmony_ci  else
9258141cc406Sopenharmony_ci    DBG (0, "\t->no color scan    \n");
9259141cc406Sopenharmony_ci
9260141cc406Sopenharmony_ci  /* byte 14 */
9261141cc406Sopenharmony_ci  if (op[14] & 0x20)
9262141cc406Sopenharmony_ci    {
9263141cc406Sopenharmony_ci      DBG (0, "\t->lamp on    \n");
9264141cc406Sopenharmony_ci    }
9265141cc406Sopenharmony_ci  else
9266141cc406Sopenharmony_ci    {
9267141cc406Sopenharmony_ci      DBG (0, "\t->lamp off    \n");
9268141cc406Sopenharmony_ci    }
9269141cc406Sopenharmony_ci  if (op[14] & 0x04)
9270141cc406Sopenharmony_ci    {
9271141cc406Sopenharmony_ci      DBG (0, "\t->normal scan (head stops at each row)    \n");
9272141cc406Sopenharmony_ci    }
9273141cc406Sopenharmony_ci  else
9274141cc406Sopenharmony_ci    {
9275141cc406Sopenharmony_ci      DBG (0, "\t->move and scan (head doesn't stop at each row)    \n");
9276141cc406Sopenharmony_ci    }
9277141cc406Sopenharmony_ci  DBG (0, "\n");
9278141cc406Sopenharmony_ci}
9279141cc406Sopenharmony_ci
9280141cc406Sopenharmony_ci
9281141cc406Sopenharmony_cistatic void
9282141cc406Sopenharmony_cibloc8Decode (int *op)
9283141cc406Sopenharmony_ci{
9284141cc406Sopenharmony_ci  int i, bpl;
9285141cc406Sopenharmony_ci  int xskip;
9286141cc406Sopenharmony_ci  int xend, len;
9287141cc406Sopenharmony_ci  char str[128];
9288141cc406Sopenharmony_ci
9289141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () < 1220)
9290141cc406Sopenharmony_ci    len = 34;
9291141cc406Sopenharmony_ci  else
9292141cc406Sopenharmony_ci    len = 36;
9293141cc406Sopenharmony_ci  for (i = 0; i < len; i++)
9294141cc406Sopenharmony_ci    sprintf (str + 3 * i, "%02X ", (unsigned char) op[i]);
9295141cc406Sopenharmony_ci  str[3 * i] = 0x00;
9296141cc406Sopenharmony_ci  DBG (0, "Command block 8: %s\n", str);
9297141cc406Sopenharmony_ci
9298141cc406Sopenharmony_ci  xskip = op[17] + 256 * (op[18] & 0x0F);
9299141cc406Sopenharmony_ci  if (op[33] & 0x40)
9300141cc406Sopenharmony_ci    xskip += 0x1000;
9301141cc406Sopenharmony_ci  xend = (op[18] & 0xF0) / 16 + 16 * op[19];
9302141cc406Sopenharmony_ci  if (op[33] & 0x80)
9303141cc406Sopenharmony_ci    xend += 0x1000;
9304141cc406Sopenharmony_ci  if (len > 34)
9305141cc406Sopenharmony_ci    bpl = (op[24] - 0x41) * 256 + 8192 * (op[34] & 0x01) + op[23];
9306141cc406Sopenharmony_ci  else
9307141cc406Sopenharmony_ci    bpl = (op[24] - 0x41) * 256 + op[23];
9308141cc406Sopenharmony_ci
9309141cc406Sopenharmony_ci  DBG (0, "\t->xskip     =0x%X (%d)\n", xskip, xskip);
9310141cc406Sopenharmony_ci  DBG (0, "\t->xend      =0x%X (%d)\n", xend, xend);
9311141cc406Sopenharmony_ci  DBG (0, "\t->scan width=0x%X (%d)\n", xend - xskip - 1, xend - xskip - 1);
9312141cc406Sopenharmony_ci  DBG (0, "\t->bytes/line=0x%X (%d)\n", bpl, bpl);
9313141cc406Sopenharmony_ci  DBG (0, "\t->raw       =0x%X (%d)\n", op[24] * 256 + op[23],
9314141cc406Sopenharmony_ci       op[24] * 256 + op[23]);
9315141cc406Sopenharmony_ci  DBG (0, "\n");
9316141cc406Sopenharmony_ci}
9317141cc406Sopenharmony_cistatic int
9318141cc406Sopenharmony_cicompletionWait (void)
9319141cc406Sopenharmony_ci{
9320141cc406Sopenharmony_ci  /* for 610P, wait and sync is done while
9321141cc406Sopenharmony_ci   * reading data from the scanner */
9322141cc406Sopenharmony_ci  CMDSYNC (0x40);
9323141cc406Sopenharmony_ci  usleep (100000);
9324141cc406Sopenharmony_ci  CMDSYNC (0xC2);
9325141cc406Sopenharmony_ci  if ((sanei_umax_pp_getastra () == 610)
9326141cc406Sopenharmony_ci      || ((sanei_umax_pp_scannerStatus () & 0x90) == 0x90))
9327141cc406Sopenharmony_ci    return 1;
9328141cc406Sopenharmony_ci  do
9329141cc406Sopenharmony_ci    {
9330141cc406Sopenharmony_ci      usleep (100000);
9331141cc406Sopenharmony_ci      CMDSYNC (0xC2);
9332141cc406Sopenharmony_ci    }
9333141cc406Sopenharmony_ci  while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90);
9334141cc406Sopenharmony_ci  CMDSYNC (0xC2);
9335141cc406Sopenharmony_ci  return 1;
9336141cc406Sopenharmony_ci}
9337141cc406Sopenharmony_ci
9338141cc406Sopenharmony_ciint
9339141cc406Sopenharmony_cisanei_umax_pp_setLamp (int on)
9340141cc406Sopenharmony_ci{
9341141cc406Sopenharmony_ci  int buffer[17];
9342141cc406Sopenharmony_ci  int state;
9343141cc406Sopenharmony_ci
9344141cc406Sopenharmony_ci  /* reset? */
9345141cc406Sopenharmony_ci  sanei_umax_pp_cmdSync (0x00);
9346141cc406Sopenharmony_ci  sanei_umax_pp_cmdSync (0xC2);
9347141cc406Sopenharmony_ci  sanei_umax_pp_cmdSync (0x00);
9348141cc406Sopenharmony_ci
9349141cc406Sopenharmony_ci  /* get status */
9350141cc406Sopenharmony_ci  cmdGet (0x02, 16, buffer);
9351141cc406Sopenharmony_ci  state = buffer[14] & LAMP_STATE;
9352141cc406Sopenharmony_ci  buffer[16] = -1;
9353141cc406Sopenharmony_ci  if ((state == 0) && (on == 0))
9354141cc406Sopenharmony_ci    {
9355141cc406Sopenharmony_ci      DBG (0, "Lamp already off ... (%s:%d)\n", __FILE__, __LINE__);
9356141cc406Sopenharmony_ci      return 1;
9357141cc406Sopenharmony_ci    }
9358141cc406Sopenharmony_ci  if ((state) && (on))
9359141cc406Sopenharmony_ci    {
9360141cc406Sopenharmony_ci      DBG (2, "Lamp already on ... (%s:%d)\n", __FILE__, __LINE__);
9361141cc406Sopenharmony_ci      return 1;
9362141cc406Sopenharmony_ci    }
9363141cc406Sopenharmony_ci
9364141cc406Sopenharmony_ci  /* set lamp state */
9365141cc406Sopenharmony_ci  if (on)
9366141cc406Sopenharmony_ci    buffer[14] = buffer[14] | LAMP_STATE;
9367141cc406Sopenharmony_ci  else
9368141cc406Sopenharmony_ci    buffer[14] = buffer[14] & ~LAMP_STATE;
9369141cc406Sopenharmony_ci  CMDSETGET (0x02, 16, buffer);
9370141cc406Sopenharmony_ci  TRACE (16, "setLamp passed ...");
9371141cc406Sopenharmony_ci  return 1;
9372141cc406Sopenharmony_ci}
9373141cc406Sopenharmony_ci
9374141cc406Sopenharmony_cistatic int num = 0;
9375141cc406Sopenharmony_cistatic void
9376141cc406Sopenharmony_ciDump (int len, unsigned char *data, char *name)
9377141cc406Sopenharmony_ci{
9378141cc406Sopenharmony_ci  FILE *fic;
9379141cc406Sopenharmony_ci  char titre[80];
9380141cc406Sopenharmony_ci
9381141cc406Sopenharmony_ci  if (name == NULL)
9382141cc406Sopenharmony_ci    {
9383141cc406Sopenharmony_ci      sprintf (titre, "dump%04d.bin", num);
9384141cc406Sopenharmony_ci      num++;
9385141cc406Sopenharmony_ci    }
9386141cc406Sopenharmony_ci  else
9387141cc406Sopenharmony_ci    {
9388141cc406Sopenharmony_ci      sprintf (titre, "%s", name);
9389141cc406Sopenharmony_ci    }
9390141cc406Sopenharmony_ci  fic = fopen (titre, "wb");
9391141cc406Sopenharmony_ci  if (fic == NULL)
9392141cc406Sopenharmony_ci    {
9393141cc406Sopenharmony_ci      DBG (0, "could not open %s for writing\n", titre);
9394141cc406Sopenharmony_ci      return;
9395141cc406Sopenharmony_ci    }
9396141cc406Sopenharmony_ci  fwrite (data, 1, len, fic);
9397141cc406Sopenharmony_ci  fclose (fic);
9398141cc406Sopenharmony_ci}
9399141cc406Sopenharmony_ci
9400141cc406Sopenharmony_ci
9401141cc406Sopenharmony_cistatic void
9402141cc406Sopenharmony_ciDumpNB (int width, int height, unsigned char *data, char *name)
9403141cc406Sopenharmony_ci{
9404141cc406Sopenharmony_ci  FILE *fic;
9405141cc406Sopenharmony_ci  char titre[80];
9406141cc406Sopenharmony_ci
9407141cc406Sopenharmony_ci  if (name == NULL)
9408141cc406Sopenharmony_ci    {
9409141cc406Sopenharmony_ci      sprintf (titre, "dump%04d.pnm", num);
9410141cc406Sopenharmony_ci      num++;
9411141cc406Sopenharmony_ci    }
9412141cc406Sopenharmony_ci  else
9413141cc406Sopenharmony_ci    {
9414141cc406Sopenharmony_ci      sprintf (titre, "%s", name);
9415141cc406Sopenharmony_ci    }
9416141cc406Sopenharmony_ci  fic = fopen (titre, "wb");
9417141cc406Sopenharmony_ci  if (fic == NULL)
9418141cc406Sopenharmony_ci    {
9419141cc406Sopenharmony_ci      DBG (0, "could not open %s for writing\n", titre);
9420141cc406Sopenharmony_ci      return;
9421141cc406Sopenharmony_ci    }
9422141cc406Sopenharmony_ci  fprintf (fic, "P5\n%d %d\n255\n", width, height);
9423141cc406Sopenharmony_ci  fwrite (data, width, height, fic);
9424141cc406Sopenharmony_ci  fclose (fic);
9425141cc406Sopenharmony_ci}
9426141cc406Sopenharmony_ci
9427141cc406Sopenharmony_ci
9428141cc406Sopenharmony_ci/* dump data has received from scanner (red line/green line/blue line)
9429141cc406Sopenharmony_ci   to a color pnm file */
9430141cc406Sopenharmony_cistatic void
9431141cc406Sopenharmony_ciDumpRVB (int width, int height, unsigned char *data, char *name)
9432141cc406Sopenharmony_ci{
9433141cc406Sopenharmony_ci  FILE *fic;
9434141cc406Sopenharmony_ci  char titre[80];
9435141cc406Sopenharmony_ci  int y, x;
9436141cc406Sopenharmony_ci
9437141cc406Sopenharmony_ci  if (name == NULL)
9438141cc406Sopenharmony_ci    {
9439141cc406Sopenharmony_ci      sprintf (titre, "dump%04d.pnm", num);
9440141cc406Sopenharmony_ci      num++;
9441141cc406Sopenharmony_ci    }
9442141cc406Sopenharmony_ci  else
9443141cc406Sopenharmony_ci    {
9444141cc406Sopenharmony_ci      sprintf (titre, "%s", name);
9445141cc406Sopenharmony_ci    }
9446141cc406Sopenharmony_ci  fic = fopen (titre, "wb");
9447141cc406Sopenharmony_ci  if (fic == NULL)
9448141cc406Sopenharmony_ci    {
9449141cc406Sopenharmony_ci      DBG (0, "could not open %s for writing\n", titre);
9450141cc406Sopenharmony_ci      return;
9451141cc406Sopenharmony_ci    }
9452141cc406Sopenharmony_ci  fprintf (fic, "P6\n%d %d\n255\n", width, height);
9453141cc406Sopenharmony_ci  for (y = 0; y < height; y++)
9454141cc406Sopenharmony_ci    {
9455141cc406Sopenharmony_ci      for (x = 0; x < width; x++)
9456141cc406Sopenharmony_ci	{
9457141cc406Sopenharmony_ci	  fputc (data[3 * y * width + 2 * width + x], fic);
9458141cc406Sopenharmony_ci	  fputc (data[3 * y * width + width + x], fic);
9459141cc406Sopenharmony_ci	  fputc (data[3 * y * width + x], fic);
9460141cc406Sopenharmony_ci	}
9461141cc406Sopenharmony_ci    }
9462141cc406Sopenharmony_ci  fclose (fic);
9463141cc406Sopenharmony_ci}
9464141cc406Sopenharmony_ci
9465141cc406Sopenharmony_ci/* dump a color buffer in a color PNM */
9466141cc406Sopenharmony_cistatic void
9467141cc406Sopenharmony_ciDumpRGB (int width, int height, unsigned char *data, char *name)
9468141cc406Sopenharmony_ci{
9469141cc406Sopenharmony_ci  FILE *fic;
9470141cc406Sopenharmony_ci  char titre[80];
9471141cc406Sopenharmony_ci  int y, x;
9472141cc406Sopenharmony_ci
9473141cc406Sopenharmony_ci  if (name == NULL)
9474141cc406Sopenharmony_ci    {
9475141cc406Sopenharmony_ci      sprintf (titre, "dump%04d.pnm", num);
9476141cc406Sopenharmony_ci      num++;
9477141cc406Sopenharmony_ci    }
9478141cc406Sopenharmony_ci  else
9479141cc406Sopenharmony_ci    {
9480141cc406Sopenharmony_ci      sprintf (titre, "%s", name);
9481141cc406Sopenharmony_ci    }
9482141cc406Sopenharmony_ci  fic = fopen (titre, "wb");
9483141cc406Sopenharmony_ci  fprintf (fic, "P6\n%d %d\n255\n", width, height);
9484141cc406Sopenharmony_ci  if (fic == NULL)
9485141cc406Sopenharmony_ci    {
9486141cc406Sopenharmony_ci      DBG (0, "could not open %s for writing\n", titre);
9487141cc406Sopenharmony_ci      return;
9488141cc406Sopenharmony_ci    }
9489141cc406Sopenharmony_ci  for (y = 0; y < height; y++)
9490141cc406Sopenharmony_ci    {
9491141cc406Sopenharmony_ci      for (x = 0; x < width; x++)
9492141cc406Sopenharmony_ci	{
9493141cc406Sopenharmony_ci	  fputc (data[3 * y * width + x * 3], fic);
9494141cc406Sopenharmony_ci	  fputc (data[3 * y * width + x * 3 + 1], fic);
9495141cc406Sopenharmony_ci	  fputc (data[3 * y * width + x * 3 + 2], fic);
9496141cc406Sopenharmony_ci	}
9497141cc406Sopenharmony_ci    }
9498141cc406Sopenharmony_ci  fclose (fic);
9499141cc406Sopenharmony_ci}
9500141cc406Sopenharmony_ci
9501141cc406Sopenharmony_cistatic int
9502141cc406Sopenharmony_cievalGain (int sum, int count)
9503141cc406Sopenharmony_ci{
9504141cc406Sopenharmony_ci  int gn;
9505141cc406Sopenharmony_ci  float pct;
9506141cc406Sopenharmony_ci  float avg;
9507141cc406Sopenharmony_ci  float area=50;
9508141cc406Sopenharmony_ci  float coeff=2.5;
9509141cc406Sopenharmony_ci  float cnst=0.9;
9510141cc406Sopenharmony_ci
9511141cc406Sopenharmony_ci
9512141cc406Sopenharmony_ci  /* after ~ 60 * 10 scans , it looks like 1 step is a 0.57% increase   */
9513141cc406Sopenharmony_ci  /* so we take the value and compute the percent increase to reach 250 */
9514141cc406Sopenharmony_ci  /* (target code) not 255, because we want some room for inaccuracy    */
9515141cc406Sopenharmony_ci  /* pct=100-(value*100)/250                                            */
9516141cc406Sopenharmony_ci  /* then correction is pct/0.57                                        */
9517141cc406Sopenharmony_ci  avg = (float) (sum) / (float) (count);
9518141cc406Sopenharmony_ci  pct = 100.0 - (avg * 100.0) / targetCode;
9519141cc406Sopenharmony_ci  gn = (int) (pct / 0.57);
9520141cc406Sopenharmony_ci
9521141cc406Sopenharmony_ci  /* give gain for dark areas a boost */
9522141cc406Sopenharmony_ci#ifdef UMAX_PP_DANGEROUS_EXPERIMENT
9523141cc406Sopenharmony_ci  if(getenv("AREA")!=NULL)
9524141cc406Sopenharmony_ci        cnst=atol(getenv("AREA"));
9525141cc406Sopenharmony_ci  if(getenv("COEFF")!=NULL)
9526141cc406Sopenharmony_ci        cnst=atol(getenv("COEFF"));
9527141cc406Sopenharmony_ci  if(getenv("CNST")!=NULL)
9528141cc406Sopenharmony_ci        cnst=atol(getenv("CNST"));
9529141cc406Sopenharmony_ci#endif
9530141cc406Sopenharmony_ci
9531141cc406Sopenharmony_ci  pct = gn;
9532141cc406Sopenharmony_ci  avg = exp((-pct)/area)*coeff+cnst;
9533141cc406Sopenharmony_ci  gn = gn * avg;
9534141cc406Sopenharmony_ci
9535141cc406Sopenharmony_ci  /* bound checking : there are sightings of >127 values being negative */
9536141cc406Sopenharmony_ci  if (gn < 0)
9537141cc406Sopenharmony_ci    gn = 0;
9538141cc406Sopenharmony_ci  else if (gn > 127)
9539141cc406Sopenharmony_ci    gn = 127;
9540141cc406Sopenharmony_ci  return gn;
9541141cc406Sopenharmony_ci}
9542141cc406Sopenharmony_ci
9543141cc406Sopenharmony_cistatic void
9544141cc406Sopenharmony_cicomputeCalibrationData (int color, int width, unsigned char *source,
9545141cc406Sopenharmony_ci			int *data)
9546141cc406Sopenharmony_ci{
9547141cc406Sopenharmony_ci  int p, i, l;
9548141cc406Sopenharmony_ci  int sum;
9549141cc406Sopenharmony_ci
9550141cc406Sopenharmony_ci
9551141cc406Sopenharmony_ci  memset (data, 0, (3 * 5100 + 768 + 3) * sizeof (int));
9552141cc406Sopenharmony_ci
9553141cc406Sopenharmony_ci
9554141cc406Sopenharmony_ci  /* 0 -> 5099 */
9555141cc406Sopenharmony_ci  for (i = 0; i < width; i++)
9556141cc406Sopenharmony_ci    {				/* red calibration data */
9557141cc406Sopenharmony_ci      if (color >= RGB_MODE)
9558141cc406Sopenharmony_ci	{
9559141cc406Sopenharmony_ci	  /* compute average */
9560141cc406Sopenharmony_ci	  sum = 0;
9561141cc406Sopenharmony_ci	  for (l = 0; l < 66; l++)
9562141cc406Sopenharmony_ci	    sum += source[i + l * 5100 * 3];
9563141cc406Sopenharmony_ci	  data[i] = evalGain (sum, l);
9564141cc406Sopenharmony_ci	}
9565141cc406Sopenharmony_ci      else
9566141cc406Sopenharmony_ci	data[i] = 0x00;
9567141cc406Sopenharmony_ci    }
9568141cc406Sopenharmony_ci
9569141cc406Sopenharmony_ci
9570141cc406Sopenharmony_ci  /* 5100 -> 10199: green data */
9571141cc406Sopenharmony_ci  p = 5100;
9572141cc406Sopenharmony_ci  for (i = 0; i < width; i++)
9573141cc406Sopenharmony_ci    {
9574141cc406Sopenharmony_ci      /* compute average */
9575141cc406Sopenharmony_ci      sum = 0;
9576141cc406Sopenharmony_ci      for (l = 0; l < 66; l++)
9577141cc406Sopenharmony_ci	sum += source[i + l * 5100 * 3 + 5100];
9578141cc406Sopenharmony_ci      data[p + i] = evalGain (sum, l);
9579141cc406Sopenharmony_ci    }
9580141cc406Sopenharmony_ci
9581141cc406Sopenharmony_ci
9582141cc406Sopenharmony_ci  /* 10200 -> 15299: blue */
9583141cc406Sopenharmony_ci  p = 10200;
9584141cc406Sopenharmony_ci  for (i = 0; i < width; i++)
9585141cc406Sopenharmony_ci    {
9586141cc406Sopenharmony_ci      if (color >= RGB_MODE)
9587141cc406Sopenharmony_ci	{
9588141cc406Sopenharmony_ci	  /* compute average */
9589141cc406Sopenharmony_ci	  sum = 0;
9590141cc406Sopenharmony_ci	  for (l = 0; l < 66; l++)
9591141cc406Sopenharmony_ci	    sum += source[i + l * 5100 * 3 + 5100 * 2];
9592141cc406Sopenharmony_ci	  data[p + i] = evalGain (sum, l);
9593141cc406Sopenharmony_ci	}
9594141cc406Sopenharmony_ci      else
9595141cc406Sopenharmony_ci	data[p + i] = 0x00;
9596141cc406Sopenharmony_ci    }
9597141cc406Sopenharmony_ci
9598141cc406Sopenharmony_ci
9599141cc406Sopenharmony_ci  /* gamma tables */
9600141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
9601141cc406Sopenharmony_ci    data[15300 + i] = ggRed[i];
9602141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
9603141cc406Sopenharmony_ci    data[15300 + 256 + i] = ggGreen[i];
9604141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
9605141cc406Sopenharmony_ci    data[15300 + 512 + i] = ggBlue[i];
9606141cc406Sopenharmony_ci  data[16070] = -1;
9607141cc406Sopenharmony_ci}
9608141cc406Sopenharmony_ci
9609141cc406Sopenharmony_ci
9610141cc406Sopenharmony_ci
9611141cc406Sopenharmony_ci/* move head by the distance given using precision or not */
9612141cc406Sopenharmony_ci/* 0: failed
9613141cc406Sopenharmony_ci   1: success                                          */
9614141cc406Sopenharmony_cistatic int
9615141cc406Sopenharmony_cimove (int distance, int precision, unsigned char *buffer)
9616141cc406Sopenharmony_ci{
9617141cc406Sopenharmony_ci  int header[17] = {
9618141cc406Sopenharmony_ci    0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x2F,
9619141cc406Sopenharmony_ci    0x2F, 0x01, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x00,
9620141cc406Sopenharmony_ci    -1
9621141cc406Sopenharmony_ci  };
9622141cc406Sopenharmony_ci  int body[37] = {
9623141cc406Sopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9624141cc406Sopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
9625141cc406Sopenharmony_ci    0x6E, 0xF6, 0x79, 0xBF, 0x01, 0x00, 0x00, 0x00,
9626141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68,
9627141cc406Sopenharmony_ci    0xDF, 0x13, 0x1A, 0x00,
9628141cc406Sopenharmony_ci    -1
9629141cc406Sopenharmony_ci  };
9630141cc406Sopenharmony_ci  int end[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 };
9631141cc406Sopenharmony_ci  int steps, len, cmdlen;
9632141cc406Sopenharmony_ci  unsigned char tmp[0x200];
9633141cc406Sopenharmony_ci  unsigned char *ptr;
9634141cc406Sopenharmony_ci
9635141cc406Sopenharmony_ci  if (distance == 0)
9636141cc406Sopenharmony_ci    return 0;
9637141cc406Sopenharmony_ci
9638141cc406Sopenharmony_ci  if (buffer == NULL)
9639141cc406Sopenharmony_ci    ptr = tmp;
9640141cc406Sopenharmony_ci  else
9641141cc406Sopenharmony_ci    ptr = buffer;
9642141cc406Sopenharmony_ci
9643141cc406Sopenharmony_ci  /* build commands */
9644141cc406Sopenharmony_ci  if (distance < 0)
9645141cc406Sopenharmony_ci    {
9646141cc406Sopenharmony_ci      /* header */
9647141cc406Sopenharmony_ci      steps = -distance - 1;
9648141cc406Sopenharmony_ci      header[3] = 0x20;
9649141cc406Sopenharmony_ci      header[9] = 0x01;
9650141cc406Sopenharmony_ci
9651141cc406Sopenharmony_ci      /* reverse direction body by default */
9652141cc406Sopenharmony_ci
9653141cc406Sopenharmony_ci      /* end */
9654141cc406Sopenharmony_ci      end[1] = 0xFF;
9655141cc406Sopenharmony_ci      end[2] = 0xFF;
9656141cc406Sopenharmony_ci      end[3] = -1;
9657141cc406Sopenharmony_ci      len = 3;
9658141cc406Sopenharmony_ci    }
9659141cc406Sopenharmony_ci  else
9660141cc406Sopenharmony_ci    {
9661141cc406Sopenharmony_ci      /* header */
9662141cc406Sopenharmony_ci      steps = distance - 1;
9663141cc406Sopenharmony_ci      header[3] = 0x70;
9664141cc406Sopenharmony_ci      header[9] = 0x05;
9665141cc406Sopenharmony_ci
9666141cc406Sopenharmony_ci      /* body */
9667141cc406Sopenharmony_ci      body[2] = 0x04;
9668141cc406Sopenharmony_ci      body[4] = 0x02;
9669141cc406Sopenharmony_ci      body[7] = 0x0C;
9670141cc406Sopenharmony_ci      body[9] = 0x04;
9671141cc406Sopenharmony_ci      body[10] = 0x40;
9672141cc406Sopenharmony_ci      body[11] = 0x01;
9673141cc406Sopenharmony_ci      /* end */
9674141cc406Sopenharmony_ci      len = 8;
9675141cc406Sopenharmony_ci    }
9676141cc406Sopenharmony_ci  if (steps > 0)
9677141cc406Sopenharmony_ci    {
9678141cc406Sopenharmony_ci      encodeHY (1, steps, header);
9679141cc406Sopenharmony_ci    }
9680141cc406Sopenharmony_ci
9681141cc406Sopenharmony_ci
9682141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () < 1220)
9683141cc406Sopenharmony_ci    {
9684141cc406Sopenharmony_ci      header[6] = 0xC0;
9685141cc406Sopenharmony_ci
9686141cc406Sopenharmony_ci      body[16] = 0x76;		/* encodeWX */
9687141cc406Sopenharmony_ci      body[17] = 0x00;
9688141cc406Sopenharmony_ci      body[18] = 0x15;
9689141cc406Sopenharmony_ci      body[19] = 0x70;
9690141cc406Sopenharmony_ci      body[20] = 0x01;
9691141cc406Sopenharmony_ci      body[21] = 0x00;
9692141cc406Sopenharmony_ci
9693141cc406Sopenharmony_ci      body[28] = 0x4D;
9694141cc406Sopenharmony_ci      body[29] = 0x4B;
9695141cc406Sopenharmony_ci      body[30] = 0xD0;
9696141cc406Sopenharmony_ci
9697141cc406Sopenharmony_ci      cmdlen = 0x22;
9698141cc406Sopenharmony_ci    }
9699141cc406Sopenharmony_ci  else
9700141cc406Sopenharmony_ci    cmdlen = 0x24;
9701141cc406Sopenharmony_ci
9702141cc406Sopenharmony_ci  /* precision: default header set to precision on */
9703141cc406Sopenharmony_ci  if (precision == PRECISION_OFF)
9704141cc406Sopenharmony_ci    {
9705141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () == 1600)
9706141cc406Sopenharmony_ci	header[8] = 0x15;
9707141cc406Sopenharmony_ci      else
9708141cc406Sopenharmony_ci	header[8] = 0x17;
9709141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () > 610)
9710141cc406Sopenharmony_ci	header[14] = 0xAC;
9711141cc406Sopenharmony_ci      body[20] = 0x06;
9712141cc406Sopenharmony_ci    }
9713141cc406Sopenharmony_ci  CMDSETGET (0x02, 16, header);
9714141cc406Sopenharmony_ci  CMDSETGET (0x08, cmdlen, body);
9715141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
9716141cc406Sopenharmony_ci    {
9717141cc406Sopenharmony_ci      bloc2Decode (header);
9718141cc406Sopenharmony_ci      bloc8Decode (body);
9719141cc406Sopenharmony_ci    }
9720141cc406Sopenharmony_ci  CMDSYNC (0xC2);
9721141cc406Sopenharmony_ci  if ((sanei_umax_pp_scannerStatus () & 0x80)
9722141cc406Sopenharmony_ci      || (sanei_umax_pp_getastra () < 1220))
9723141cc406Sopenharmony_ci    {
9724141cc406Sopenharmony_ci      CMDSYNC (0x00);
9725141cc406Sopenharmony_ci    }
9726141cc406Sopenharmony_ci  CMDSETGET (4, len, end);
9727141cc406Sopenharmony_ci  COMPLETIONWAIT;
9728141cc406Sopenharmony_ci  CMDGETBUF (4, 0x200, ptr);
9729141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
9730141cc406Sopenharmony_ci    {
9731141cc406Sopenharmony_ci      Dump (0x200, ptr, NULL);
9732141cc406Sopenharmony_ci    }
9733141cc406Sopenharmony_ci  DBG (16, "MOVE STATUS IS 0x%02X  (%s:%d)\n", sanei_umax_pp_scannerStatus (),
9734141cc406Sopenharmony_ci       __FILE__, __LINE__);
9735141cc406Sopenharmony_ci  CMDSYNC (0x00);
9736141cc406Sopenharmony_ci  return 1;
9737141cc406Sopenharmony_ci}
9738141cc406Sopenharmony_ci
9739141cc406Sopenharmony_ci
9740141cc406Sopenharmony_ci
9741141cc406Sopenharmony_ci/* for each column, finds the row where white/black transition occurs
9742141cc406Sopenharmony_ci        then returns the average */
9743141cc406Sopenharmony_cistatic float
9744141cc406Sopenharmony_ciedgePosition (int width, int height, unsigned char *data)
9745141cc406Sopenharmony_ci{
9746141cc406Sopenharmony_ci  int ecnt, x, y;
9747141cc406Sopenharmony_ci  float epos;
9748141cc406Sopenharmony_ci  int d, dmax, dpos, i;
9749141cc406Sopenharmony_ci  unsigned char *dbuffer = NULL;
9750141cc406Sopenharmony_ci
9751141cc406Sopenharmony_ci  if (DBG_LEVEL > 128)
9752141cc406Sopenharmony_ci    {
9753141cc406Sopenharmony_ci      dbuffer = (unsigned char *) malloc (3 * width * height);
9754141cc406Sopenharmony_ci      memset (dbuffer, 0x00, 3 * width * height);
9755141cc406Sopenharmony_ci    }
9756141cc406Sopenharmony_ci  epos = 0;
9757141cc406Sopenharmony_ci  ecnt = 0;
9758141cc406Sopenharmony_ci  for (x = 0; x < width; x++)
9759141cc406Sopenharmony_ci    {
9760141cc406Sopenharmony_ci      /* edge: white->black drop  */
9761141cc406Sopenharmony_ci      /* loop stops on black area */
9762141cc406Sopenharmony_ci      dmax = 0;
9763141cc406Sopenharmony_ci      dpos = 0;
9764141cc406Sopenharmony_ci      d = 0;
9765141cc406Sopenharmony_ci      i = 0;
9766141cc406Sopenharmony_ci      for (y = 10; (y < height) && (data[i] > 10); y++)
9767141cc406Sopenharmony_ci	{
9768141cc406Sopenharmony_ci	  i = x + y * width;
9769141cc406Sopenharmony_ci	  d = data[i - width] - data[i];
9770141cc406Sopenharmony_ci	  if (d > dmax)
9771141cc406Sopenharmony_ci	    {
9772141cc406Sopenharmony_ci	      dmax = d;
9773141cc406Sopenharmony_ci	      dpos = y;
9774141cc406Sopenharmony_ci	    }
9775141cc406Sopenharmony_ci	  if ((DBG_LEVEL > 128) && (dbuffer != NULL))
9776141cc406Sopenharmony_ci	    {
9777141cc406Sopenharmony_ci	      dbuffer[i * 3] = data[i];
9778141cc406Sopenharmony_ci	      dbuffer[i * 3 + 1] = data[i];
9779141cc406Sopenharmony_ci	      dbuffer[i * 3 + 2] = data[i];
9780141cc406Sopenharmony_ci	    }
9781141cc406Sopenharmony_ci	}
9782141cc406Sopenharmony_ci      epos += dpos;
9783141cc406Sopenharmony_ci      ecnt++;
9784141cc406Sopenharmony_ci      if ((DBG_LEVEL > 128) && (dbuffer != NULL))
9785141cc406Sopenharmony_ci	{
9786141cc406Sopenharmony_ci	  dbuffer[(x + dpos * width) * 3] = 0xFF;
9787141cc406Sopenharmony_ci	  dbuffer[(x + dpos * width) * 3 + 1] = 0x00;
9788141cc406Sopenharmony_ci	  dbuffer[(x + dpos * width) * 3 + 2] = 0x00;
9789141cc406Sopenharmony_ci	}
9790141cc406Sopenharmony_ci    }
9791141cc406Sopenharmony_ci  if (ecnt == 0)
9792141cc406Sopenharmony_ci    epos = 70;
9793141cc406Sopenharmony_ci  else
9794141cc406Sopenharmony_ci    epos = epos / ecnt;
9795141cc406Sopenharmony_ci  if ((DBG_LEVEL > 128) && (dbuffer != NULL))
9796141cc406Sopenharmony_ci    {
9797141cc406Sopenharmony_ci      i = ((int) epos) * width;
9798141cc406Sopenharmony_ci      for (x = 0; x < width; x++)
9799141cc406Sopenharmony_ci	{
9800141cc406Sopenharmony_ci	  dbuffer[(x + i) * 3] = 0x00;
9801141cc406Sopenharmony_ci	  dbuffer[(x + i) * 3 + 1] = 0xFF;
9802141cc406Sopenharmony_ci	  dbuffer[(x + i) * 3 + 2] = 0xFF;
9803141cc406Sopenharmony_ci	}
9804141cc406Sopenharmony_ci      for (y = 0; y < height; y++)
9805141cc406Sopenharmony_ci	{
9806141cc406Sopenharmony_ci	  dbuffer[(width / 2 + y * width) * 3] = 0x00;
9807141cc406Sopenharmony_ci	  dbuffer[(width / 2 + y * width) * 3 + 1] = 0xFF;
9808141cc406Sopenharmony_ci	  dbuffer[(width / 2 + y * width) * 3 + 2] = 0x00;
9809141cc406Sopenharmony_ci	}
9810141cc406Sopenharmony_ci      DumpRGB (width, height, dbuffer, NULL);
9811141cc406Sopenharmony_ci      free (dbuffer);
9812141cc406Sopenharmony_ci    }
9813141cc406Sopenharmony_ci  return epos;
9814141cc406Sopenharmony_ci}
9815141cc406Sopenharmony_ci
9816141cc406Sopenharmony_ci
9817141cc406Sopenharmony_ci
9818141cc406Sopenharmony_cistatic int
9819141cc406Sopenharmony_cimoveToOrigin (void)
9820141cc406Sopenharmony_ci{
9821141cc406Sopenharmony_ci  unsigned char buffer[54000];
9822141cc406Sopenharmony_ci  float edge;
9823141cc406Sopenharmony_ci  int val, delta = 188;
9824141cc406Sopenharmony_ci  int header[17] = {
9825141cc406Sopenharmony_ci    0xB4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F,
9826141cc406Sopenharmony_ci    0x2F, 0x05, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x00, -1
9827141cc406Sopenharmony_ci  };
9828141cc406Sopenharmony_ci
9829141cc406Sopenharmony_ci  int body[37] = {
9830141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
9831141cc406Sopenharmony_ci    0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00,
9832141cc406Sopenharmony_ci    0x6E, 0xFB, 0xC4, 0xE5, 0x06, 0x00, 0x00, 0x60,
9833141cc406Sopenharmony_ci    0x4D, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68,
9834141cc406Sopenharmony_ci    0xDF, 0x13, 0x1A, 0x00, -1
9835141cc406Sopenharmony_ci  };
9836141cc406Sopenharmony_ci
9837141cc406Sopenharmony_ci  int end[9] = {
9838141cc406Sopenharmony_ci    0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x08, 0x00,
9839141cc406Sopenharmony_ci    -1
9840141cc406Sopenharmony_ci  };
9841141cc406Sopenharmony_ci  int opsc03[9] = {
9842141cc406Sopenharmony_ci    0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0x80, 0xFF,
9843141cc406Sopenharmony_ci    -1
9844141cc406Sopenharmony_ci  };
9845141cc406Sopenharmony_ci  int w = 300, h = 180, len = 36;
9846141cc406Sopenharmony_ci
9847141cc406Sopenharmony_ci  switch (sanei_umax_pp_getastra ())
9848141cc406Sopenharmony_ci    {
9849141cc406Sopenharmony_ci    case 1600:
9850141cc406Sopenharmony_ci      header[8] = 0x2B;
9851141cc406Sopenharmony_ci
9852141cc406Sopenharmony_ci      body[29] = 0x1A;
9853141cc406Sopenharmony_ci      body[30] = 0xEE;
9854141cc406Sopenharmony_ci
9855141cc406Sopenharmony_ci      end[0] = 0x19;
9856141cc406Sopenharmony_ci      end[1] = 0xD5;
9857141cc406Sopenharmony_ci      end[4] = 0x1B;
9858141cc406Sopenharmony_ci      // fall through
9859141cc406Sopenharmony_ci    case 1220:
9860141cc406Sopenharmony_ci    case 2000:
9861141cc406Sopenharmony_ci      w = 300;
9862141cc406Sopenharmony_ci      h = 180;
9863141cc406Sopenharmony_ci      len = 36;
9864141cc406Sopenharmony_ci      delta = -188;
9865141cc406Sopenharmony_ci      CMDSYNC (0x00);
9866141cc406Sopenharmony_ci      CMDSYNC (0xC2);
9867141cc406Sopenharmony_ci      CMDSYNC (0x00);
9868141cc406Sopenharmony_ci      MOVE (196, PRECISION_OFF, NULL);
9869141cc406Sopenharmony_ci      break;
9870141cc406Sopenharmony_ci
9871141cc406Sopenharmony_ci    case 610:
9872141cc406Sopenharmony_ci
9873141cc406Sopenharmony_ci      w = 512;
9874141cc406Sopenharmony_ci      h = 90;
9875141cc406Sopenharmony_ci      len = 34;
9876141cc406Sopenharmony_ci      delta = -81;
9877141cc406Sopenharmony_ci
9878141cc406Sopenharmony_ci      opsc03[6] = 0xFF;		/* instead of 0x80 */
9879141cc406Sopenharmony_ci
9880141cc406Sopenharmony_ci      encodeHY (h, 60, header);
9881141cc406Sopenharmony_ci
9882141cc406Sopenharmony_ci      /* will add encodeDpi(dpi,cmd) */
9883141cc406Sopenharmony_ci      header[6] = 0xC0;
9884141cc406Sopenharmony_ci      header[8] = 0x17;
9885141cc406Sopenharmony_ci
9886141cc406Sopenharmony_ci      body[13] = 0x20;
9887141cc406Sopenharmony_ci      body[14] = 0x02;
9888141cc406Sopenharmony_ci
9889141cc406Sopenharmony_ci      body[16] = 0x76;
9890141cc406Sopenharmony_ci
9891141cc406Sopenharmony_ci      encodeWX (0x200, 0x501, 300, 0, body, 0x500);
9892141cc406Sopenharmony_ci
9893141cc406Sopenharmony_ci      /* fixed values for all 610p commands */
9894141cc406Sopenharmony_ci      body[28] = 0x4D;
9895141cc406Sopenharmony_ci      body[29] = 0x4B;
9896141cc406Sopenharmony_ci      body[30] = 0xD0;
9897141cc406Sopenharmony_ci
9898141cc406Sopenharmony_ci      /* LM9811 command block ? */
9899141cc406Sopenharmony_ci      end[0] = 0x88;
9900141cc406Sopenharmony_ci      end[1] = 0xE6;
9901141cc406Sopenharmony_ci      end[2] = 0xFD;
9902141cc406Sopenharmony_ci      end[3] = 0x8E;
9903141cc406Sopenharmony_ci      end[4] = 0x30;
9904141cc406Sopenharmony_ci
9905141cc406Sopenharmony_ci      break;
9906141cc406Sopenharmony_ci    }
9907141cc406Sopenharmony_ci
9908141cc406Sopenharmony_ci
9909141cc406Sopenharmony_ci  /* scan an area where is a white and a black regions, which  */
9910141cc406Sopenharmony_ci  /* can be detected and gives this offset to the origin of the */
9911141cc406Sopenharmony_ci  /* scanning windows                                          */
9912141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, header);
9913141cc406Sopenharmony_ci  CMDSETGET (8, len, body);
9914141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, end);
9915141cc406Sopenharmony_ci
9916141cc406Sopenharmony_ci  CMDSYNC (0xC2);
9917141cc406Sopenharmony_ci  CMDSYNC (0x00);
9918141cc406Sopenharmony_ci  /* signals black & white ? */
9919141cc406Sopenharmony_ci  CMDSETGET (4, 8, opsc03);
9920141cc406Sopenharmony_ci  COMPLETIONWAIT;
9921141cc406Sopenharmony_ci  CMDGETBUF (4, w * h, buffer);	/* get find position data */
9922141cc406Sopenharmony_ci  if (DBG_LEVEL > 128)
9923141cc406Sopenharmony_ci    {
9924141cc406Sopenharmony_ci      DumpNB (w, h, buffer, NULL);
9925141cc406Sopenharmony_ci    }
9926141cc406Sopenharmony_ci
9927141cc406Sopenharmony_ci  /* detection of 1600P is a by product of origin finding */
9928141cc406Sopenharmony_ci  edge = 0.0;
9929141cc406Sopenharmony_ci  for (val = 0; val < w * h; val++)
9930141cc406Sopenharmony_ci    if (buffer[val] > edge)
9931141cc406Sopenharmony_ci      edge = buffer[val];
9932141cc406Sopenharmony_ci  DBG (32, "MAX VALUE=%f        (%s:%d)\n", edge, __FILE__, __LINE__);
9933141cc406Sopenharmony_ci  if ((edge <= 30) && (sanei_umax_pp_getastra () != 1600))
9934141cc406Sopenharmony_ci    {
9935141cc406Sopenharmony_ci      DBG (2, "moveToOrigin() detected a 1600P");
9936141cc406Sopenharmony_ci      sanei_umax_pp_setastra (1600);
9937141cc406Sopenharmony_ci    }
9938141cc406Sopenharmony_ci  edge = edgePosition (w, h, buffer);
9939141cc406Sopenharmony_ci  /* rounded to lowest integer, since upping origin might lead */
9940141cc406Sopenharmony_ci  /* to bump in the other side if doing a full size preview    */
9941141cc406Sopenharmony_ci  val = (int) (edge);
9942141cc406Sopenharmony_ci
9943141cc406Sopenharmony_ci  delta += val;
9944141cc406Sopenharmony_ci  DBG (64, "Edge=%f, val=%d, delta=%d\n", edge, val, delta);
9945141cc406Sopenharmony_ci
9946141cc406Sopenharmony_ci  /* move back to y-coordinate origin */
9947141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () < 1220)
9948141cc406Sopenharmony_ci    {
9949141cc406Sopenharmony_ci      MOVE (delta, PRECISION_OFF, NULL);
9950141cc406Sopenharmony_ci    }
9951141cc406Sopenharmony_ci  else
9952141cc406Sopenharmony_ci    {
9953141cc406Sopenharmony_ci      MOVE (delta, PRECISION_ON, NULL);
9954141cc406Sopenharmony_ci    }
9955141cc406Sopenharmony_ci
9956141cc406Sopenharmony_ci  /* head successfully set to the origin */
9957141cc406Sopenharmony_ci  return 1;
9958141cc406Sopenharmony_ci}
9959141cc406Sopenharmony_ci
9960141cc406Sopenharmony_ci
9961141cc406Sopenharmony_ci/* park head: returns 1 on success, 0 otherwise  */
9962141cc406Sopenharmony_ciint
9963141cc406Sopenharmony_cisanei_umax_pp_park (void)
9964141cc406Sopenharmony_ci{
9965141cc406Sopenharmony_ci  int header610[17] = {
9966141cc406Sopenharmony_ci    0x01, 0x00, 0x01, 0x40, 0x30, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00,
9967141cc406Sopenharmony_ci    0x00, 0x80, 0xF4, 0x00, -1
9968141cc406Sopenharmony_ci  };
9969141cc406Sopenharmony_ci  int body610[35] = {
9970141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80,
9971141cc406Sopenharmony_ci    0x00, 0x20, 0x02, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00,
9972141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x1B, -1
9973141cc406Sopenharmony_ci  };
9974141cc406Sopenharmony_ci
9975141cc406Sopenharmony_ci  int header[17] =
9976141cc406Sopenharmony_ci    { 0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x13, 0x05, 0x00, 0x00,
9977141cc406Sopenharmony_ci    0x00, 0x80, 0xF0, 0x00, -1
9978141cc406Sopenharmony_ci  };
9979141cc406Sopenharmony_ci  int body[37] =
9980141cc406Sopenharmony_ci    { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80,
9981141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00,
9982141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x1B, 0x1A, 0x00,
9983141cc406Sopenharmony_ci    -1
9984141cc406Sopenharmony_ci  };
9985141cc406Sopenharmony_ci
9986141cc406Sopenharmony_ci  int status = 0x90;
9987141cc406Sopenharmony_ci
9988141cc406Sopenharmony_ci  CMDSYNC (0x00);
9989141cc406Sopenharmony_ci
9990141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () > 610)
9991141cc406Sopenharmony_ci    {
9992141cc406Sopenharmony_ci      CMDSETGET (0x02, 0x10, header);
9993141cc406Sopenharmony_ci      CMDSETGET (0x08, 0x24, body);
9994141cc406Sopenharmony_ci    }
9995141cc406Sopenharmony_ci  else
9996141cc406Sopenharmony_ci    {
9997141cc406Sopenharmony_ci      CMDSETGET (0x02, 0x10, header610);
9998141cc406Sopenharmony_ci      CMDSETGET (0x08, 0x22, body610);
9999141cc406Sopenharmony_ci    }
10000141cc406Sopenharmony_ci  CMDSYNC (0x40);
10001141cc406Sopenharmony_ci
10002141cc406Sopenharmony_ci
10003141cc406Sopenharmony_ci  status = sanei_umax_pp_scannerStatus ();
10004141cc406Sopenharmony_ci  DBG (16, "PARKING STATUS is 0x%02X (%s:%d)\n", status, __FILE__, __LINE__);
10005141cc406Sopenharmony_ci  DBG (1, "Park command issued ...\n");
10006141cc406Sopenharmony_ci  return 1;
10007141cc406Sopenharmony_ci}
10008141cc406Sopenharmony_ci
10009141cc406Sopenharmony_ci
10010141cc406Sopenharmony_ci/* calibrates CCD: returns 1 on success, 0 on failure */
10011141cc406Sopenharmony_cistatic int
10012141cc406Sopenharmony_cishadingCalibration1220p (int color,
10013141cc406Sopenharmony_ci			 int dcRed, int dcGreen, int dcBlue,
10014141cc406Sopenharmony_ci			 int vgaRed, int vgaGreen, int vgaBlue,
10015141cc406Sopenharmony_ci			 int *calibration)
10016141cc406Sopenharmony_ci{
10017141cc406Sopenharmony_ci  int opsc32[17] =
10018141cc406Sopenharmony_ci    { 0x4A, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x17, 0x05, 0xA5, 0x08,
10019141cc406Sopenharmony_ci    0x00, 0x00, 0xAC, 0x00, -1
10020141cc406Sopenharmony_ci  };
10021141cc406Sopenharmony_ci  int opsc41[37] =
10022141cc406Sopenharmony_ci    { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
10023141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x6E, 0x90, 0xD0, 0x47, 0x06, 0x00, 0x00, 0xC4,
10024141cc406Sopenharmony_ci    0x5C, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1B, 0x00,
10025141cc406Sopenharmony_ci    -1
10026141cc406Sopenharmony_ci  };
10027141cc406Sopenharmony_ci  int opscnb[37] =
10028141cc406Sopenharmony_ci    { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
10029141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x6E, 0x90, 0xD0, 0x47, 0x06, 0x00, 0x00, 0xEC,
10030141cc406Sopenharmony_ci    0x54, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1A, 0x00,
10031141cc406Sopenharmony_ci    -1
10032141cc406Sopenharmony_ci  };
10033141cc406Sopenharmony_ci  int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 };
10034141cc406Sopenharmony_ci  int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 };
10035141cc406Sopenharmony_ci  int size;
10036141cc406Sopenharmony_ci  int width = 5100;		/* full usable CCD width */
10037141cc406Sopenharmony_ci  unsigned char buffer[0x105798];
10038141cc406Sopenharmony_ci
10039141cc406Sopenharmony_ci  /* 1600P have a different CCD command block */
10040141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 1600)
10041141cc406Sopenharmony_ci    {
10042141cc406Sopenharmony_ci      opsc04[0] = 0x19;
10043141cc406Sopenharmony_ci      opsc04[1] = 0xD5;
10044141cc406Sopenharmony_ci      opsc04[4] = 0x1B;
10045141cc406Sopenharmony_ci
10046141cc406Sopenharmony_ci      opsc41[29] = 0x1A;
10047141cc406Sopenharmony_ci      opsc41[30] = 0xEE;
10048141cc406Sopenharmony_ci    }
10049141cc406Sopenharmony_ci
10050141cc406Sopenharmony_ci  /* step back by 67 ticks:                     */
10051141cc406Sopenharmony_ci  /* since we're going to scan 66 lines of data */
10052141cc406Sopenharmony_ci  /* which are going to be used as calibration  */
10053141cc406Sopenharmony_ci  /* data                                       */
10054141cc406Sopenharmony_ci  /* we are on the white area just before       */
10055141cc406Sopenharmony_ci  /* the user scan area                         */
10056141cc406Sopenharmony_ci  MOVE (-67, PRECISION_ON, NULL);
10057141cc406Sopenharmony_ci
10058141cc406Sopenharmony_ci
10059141cc406Sopenharmony_ci  CMDSYNC (0x00);
10060141cc406Sopenharmony_ci
10061141cc406Sopenharmony_ci  /* get calibration data */
10062141cc406Sopenharmony_ci  /*
10063141cc406Sopenharmony_ci     if (sanei_umax_pp_getauto ())
10064141cc406Sopenharmony_ci     {                           auto settings doesn't use offset
10065141cc406Sopenharmony_ci     offset = 0x000;
10066141cc406Sopenharmony_ci     }
10067141cc406Sopenharmony_ci     else
10068141cc406Sopenharmony_ci     {                           manual settings
10069141cc406Sopenharmony_ci     gain = 0x777;
10070141cc406Sopenharmony_ci     offset = 0x000;
10071141cc406Sopenharmony_ci     }
10072141cc406Sopenharmony_ci   */
10073141cc406Sopenharmony_ci  encodeDC (dcRed, dcGreen, dcBlue, opsc32);
10074141cc406Sopenharmony_ci  encodeVGA (vgaRed, vgaGreen, vgaBlue, opsc32);
10075141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 1600)
10076141cc406Sopenharmony_ci    {
10077141cc406Sopenharmony_ci      opsc32[13] = 0x03;
10078141cc406Sopenharmony_ci    }
10079141cc406Sopenharmony_ci
10080141cc406Sopenharmony_ci  /* 1220P/2000P shading calibration */
10081141cc406Sopenharmony_ci  if (color < RGB_MODE)
10082141cc406Sopenharmony_ci    {
10083141cc406Sopenharmony_ci      opsc32[0] -= 4;
10084141cc406Sopenharmony_ci      opsc32[13] = 0xC0;
10085141cc406Sopenharmony_ci    }
10086141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, opsc32);
10087141cc406Sopenharmony_ci  if (DBG_LEVEL >= 64)
10088141cc406Sopenharmony_ci    {
10089141cc406Sopenharmony_ci      bloc2Decode (opsc32);
10090141cc406Sopenharmony_ci    }
10091141cc406Sopenharmony_ci  if (color < RGB_MODE)
10092141cc406Sopenharmony_ci    {
10093141cc406Sopenharmony_ci      CMDSETGET (8, 0x24, opscnb);
10094141cc406Sopenharmony_ci      if (DBG_LEVEL >= 64)
10095141cc406Sopenharmony_ci	{
10096141cc406Sopenharmony_ci	  bloc8Decode (opscnb);
10097141cc406Sopenharmony_ci	}
10098141cc406Sopenharmony_ci      opsc04[6] = 0x85;
10099141cc406Sopenharmony_ci    }
10100141cc406Sopenharmony_ci  else
10101141cc406Sopenharmony_ci    {
10102141cc406Sopenharmony_ci      CMDSETGET (8, 0x24, opsc41);
10103141cc406Sopenharmony_ci      if (DBG_LEVEL >= 64)
10104141cc406Sopenharmony_ci	{
10105141cc406Sopenharmony_ci	  bloc8Decode (opsc41);
10106141cc406Sopenharmony_ci	}
10107141cc406Sopenharmony_ci      opsc04[6] = 0x0F;
10108141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () == 1600)
10109141cc406Sopenharmony_ci	opsc04[7] = 0xC0;
10110141cc406Sopenharmony_ci      else
10111141cc406Sopenharmony_ci	opsc04[7] = 0x70;
10112141cc406Sopenharmony_ci    }
10113141cc406Sopenharmony_ci
10114141cc406Sopenharmony_ci  /* BUG BW noisy here */
10115141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, opsc04);
10116141cc406Sopenharmony_ci  CMDSYNC (0xC2);
10117141cc406Sopenharmony_ci  CMDSYNC (0x00);
10118141cc406Sopenharmony_ci  CMDSETGET (4, 0x08, commit);	/* opsc03 hangs it */
10119141cc406Sopenharmony_ci  COMPLETIONWAIT;
10120141cc406Sopenharmony_ci
10121141cc406Sopenharmony_ci  opsc04[0] = 0x06;
10122141cc406Sopenharmony_ci  if (color >= RGB_MODE)
10123141cc406Sopenharmony_ci    size = 3 * width * 70;
10124141cc406Sopenharmony_ci  else
10125141cc406Sopenharmony_ci    size = width * 66;
10126141cc406Sopenharmony_ci  if (getEPPMode () == 32)
10127141cc406Sopenharmony_ci    {
10128141cc406Sopenharmony_ci      cmdGetBuffer32 (4, size, buffer);
10129141cc406Sopenharmony_ci    }
10130141cc406Sopenharmony_ci  else
10131141cc406Sopenharmony_ci    {
10132141cc406Sopenharmony_ci      CMDGETBUF (4, size, buffer);
10133141cc406Sopenharmony_ci    }
10134141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
10135141cc406Sopenharmony_ci    {
10136141cc406Sopenharmony_ci      Dump (size, buffer, NULL);
10137141cc406Sopenharmony_ci      if (color >= RGB_MODE)
10138141cc406Sopenharmony_ci	{
10139141cc406Sopenharmony_ci	  DumpRVB (width, 66, buffer, NULL);
10140141cc406Sopenharmony_ci	}
10141141cc406Sopenharmony_ci      else
10142141cc406Sopenharmony_ci	{
10143141cc406Sopenharmony_ci	  DumpNB (width, 66, buffer, NULL);
10144141cc406Sopenharmony_ci	}
10145141cc406Sopenharmony_ci    }
10146141cc406Sopenharmony_ci  computeCalibrationData (color, width, buffer, calibration);
10147141cc406Sopenharmony_ci
10148141cc406Sopenharmony_ci  DBG (1, "shadingCalibration1220p() done ...\n");
10149141cc406Sopenharmony_ci  return 1;
10150141cc406Sopenharmony_ci}
10151141cc406Sopenharmony_ci
10152141cc406Sopenharmony_ci
10153141cc406Sopenharmony_ci/* returns number of bytes read or 0 on failure */
10154141cc406Sopenharmony_ciint
10155141cc406Sopenharmony_cisanei_umax_pp_readBlock (long len, int window, int dpi, int last,
10156141cc406Sopenharmony_ci			 unsigned char *buffer)
10157141cc406Sopenharmony_ci{
10158141cc406Sopenharmony_ci  DBG (8, "readBlock(%ld,%d,%d,%d)\n", len, window, dpi, last);
10159141cc406Sopenharmony_ci  /* EPP block reading is available only when dpi >=600 */
10160141cc406Sopenharmony_ci  if ((dpi >= 600)
10161141cc406Sopenharmony_ci      && (gMode != UMAX_PP_PARPORT_ECP) && (sanei_umax_pp_getastra () > 610))
10162141cc406Sopenharmony_ci    {
10163141cc406Sopenharmony_ci      DBG (8, "cmdGetBlockBuffer(4,%ld,%d);\n", len, window);
10164141cc406Sopenharmony_ci      len = cmdGetBlockBuffer (4, len, window, buffer);
10165141cc406Sopenharmony_ci      if (len == 0)
10166141cc406Sopenharmony_ci	{
10167141cc406Sopenharmony_ci	  DBG (0, "cmdGetBlockBuffer(4,%ld,%d) failed (%s:%d)\n", len, window,
10168141cc406Sopenharmony_ci	       __FILE__, __LINE__);
10169141cc406Sopenharmony_ci	  gCancel = 1;
10170141cc406Sopenharmony_ci	}
10171141cc406Sopenharmony_ci    }
10172141cc406Sopenharmony_ci  else
10173141cc406Sopenharmony_ci    {
10174141cc406Sopenharmony_ci      if ((sanei_umax_pp_getastra () < 1210) && (len > 0xFDCE))
10175141cc406Sopenharmony_ci	{
10176141cc406Sopenharmony_ci	  len = 0xFDCE;
10177141cc406Sopenharmony_ci	  last = 0;
10178141cc406Sopenharmony_ci	}
10179141cc406Sopenharmony_ci      DBG (8, "cmdGetBuffer(4,%ld);\n", len);
10180141cc406Sopenharmony_ci      if (cmdGetBuffer (4, len, buffer) != 1)
10181141cc406Sopenharmony_ci	{
10182141cc406Sopenharmony_ci	  DBG (0, "cmdGetBuffer(4,%ld) failed (%s:%d)\n", len, __FILE__,
10183141cc406Sopenharmony_ci	       __LINE__);
10184141cc406Sopenharmony_ci	  gCancel = 1;
10185141cc406Sopenharmony_ci	}
10186141cc406Sopenharmony_ci    }
10187141cc406Sopenharmony_ci  if (!last)
10188141cc406Sopenharmony_ci    {
10189141cc406Sopenharmony_ci      /* sync with scanner */
10190141cc406Sopenharmony_ci      if (sanei_umax_pp_cmdSync (0xC2) == 0)
10191141cc406Sopenharmony_ci	{
10192141cc406Sopenharmony_ci	  DBG (0, "Warning cmdSync(0xC2) failed! (%s:%d)\n", __FILE__,
10193141cc406Sopenharmony_ci	       __LINE__);
10194141cc406Sopenharmony_ci	  DBG (0, "Trying again ...\n");
10195141cc406Sopenharmony_ci	  if (sanei_umax_pp_cmdSync (0xC2) == 0)
10196141cc406Sopenharmony_ci	    {
10197141cc406Sopenharmony_ci	      DBG (0, " failed again! (%s:%d)\n", __FILE__, __LINE__);
10198141cc406Sopenharmony_ci	      DBG (0, "Aborting ...\n");
10199141cc406Sopenharmony_ci	      gCancel = 1;
10200141cc406Sopenharmony_ci	    }
10201141cc406Sopenharmony_ci	  else
10202141cc406Sopenharmony_ci	    DBG (0, " success ...\n");
10203141cc406Sopenharmony_ci	}
10204141cc406Sopenharmony_ci    }
10205141cc406Sopenharmony_ci  return len;
10206141cc406Sopenharmony_ci}
10207141cc406Sopenharmony_ci
10208141cc406Sopenharmony_ciint
10209141cc406Sopenharmony_cisanei_umax_pp_scan (int x, int y, int width, int height, int dpi, int color,
10210141cc406Sopenharmony_ci		    int gain, int offset)
10211141cc406Sopenharmony_ci{
10212141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
10213141cc406Sopenharmony_ci  struct timeval td, tf;
10214141cc406Sopenharmony_ci  float elapsed;
10215141cc406Sopenharmony_ci#endif
10216141cc406Sopenharmony_ci  unsigned char *buffer;
10217141cc406Sopenharmony_ci  long int somme, len, read, blocksize;
10218141cc406Sopenharmony_ci  FILE *fout = NULL;
10219141cc406Sopenharmony_ci  int *dest = NULL;
10220141cc406Sopenharmony_ci  int bpl, hp;
10221141cc406Sopenharmony_ci  int th, tw, bpp;
10222141cc406Sopenharmony_ci  int nb;
10223141cc406Sopenharmony_ci  int bx, by, delta;
10224141cc406Sopenharmony_ci  int reserve, rc, remain, dataoffset;
10225141cc406Sopenharmony_ci
10226141cc406Sopenharmony_ci  if (gain != 0 || offset != 0)
10227141cc406Sopenharmony_ci    sanei_umax_pp_setauto (0);
10228141cc406Sopenharmony_ci
10229141cc406Sopenharmony_ci
10230141cc406Sopenharmony_ci  /* colors don't come in sync, so we must increase y */
10231141cc406Sopenharmony_ci  /* to have extra lines to reorder data             */
10232141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () > 610)
10233141cc406Sopenharmony_ci    {
10234141cc406Sopenharmony_ci      switch (dpi)
10235141cc406Sopenharmony_ci	{
10236141cc406Sopenharmony_ci	case 1200:
10237141cc406Sopenharmony_ci	  delta = 8;
10238141cc406Sopenharmony_ci	  break;
10239141cc406Sopenharmony_ci	case 600:
10240141cc406Sopenharmony_ci	  delta = 4;
10241141cc406Sopenharmony_ci	  break;
10242141cc406Sopenharmony_ci	case 300:
10243141cc406Sopenharmony_ci	  delta = 2;
10244141cc406Sopenharmony_ci	  break;
10245141cc406Sopenharmony_ci	case 150:
10246141cc406Sopenharmony_ci	  delta = 1;
10247141cc406Sopenharmony_ci	  break;
10248141cc406Sopenharmony_ci	default:
10249141cc406Sopenharmony_ci	  delta = 0;
10250141cc406Sopenharmony_ci	  break;
10251141cc406Sopenharmony_ci	}
10252141cc406Sopenharmony_ci    }
10253141cc406Sopenharmony_ci  else
10254141cc406Sopenharmony_ci    {
10255141cc406Sopenharmony_ci      if (color >= RGB_MODE)
10256141cc406Sopenharmony_ci	{
10257141cc406Sopenharmony_ci	  switch (dpi)
10258141cc406Sopenharmony_ci	    {
10259141cc406Sopenharmony_ci	    case 600:
10260141cc406Sopenharmony_ci	      delta = 16;
10261141cc406Sopenharmony_ci	      break;
10262141cc406Sopenharmony_ci	    case 300:
10263141cc406Sopenharmony_ci	      delta = 8;
10264141cc406Sopenharmony_ci	      break;
10265141cc406Sopenharmony_ci	    case 150:
10266141cc406Sopenharmony_ci	      delta = 4;
10267141cc406Sopenharmony_ci	      break;
10268141cc406Sopenharmony_ci	    default:
10269141cc406Sopenharmony_ci	      delta = 2;
10270141cc406Sopenharmony_ci	      break;
10271141cc406Sopenharmony_ci	    }
10272141cc406Sopenharmony_ci	}
10273141cc406Sopenharmony_ci      else
10274141cc406Sopenharmony_ci	delta = 0;
10275141cc406Sopenharmony_ci    }
10276141cc406Sopenharmony_ci
10277141cc406Sopenharmony_ci  /* in color mode, we need extra lines to reorder data */
10278141cc406Sopenharmony_ci  if (color >= RGB_MODE)
10279141cc406Sopenharmony_ci    {
10280141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () <= 610)
10281141cc406Sopenharmony_ci	dataoffset = 4 * delta;
10282141cc406Sopenharmony_ci      else
10283141cc406Sopenharmony_ci	dataoffset = 2 * delta;
10284141cc406Sopenharmony_ci    }
10285141cc406Sopenharmony_ci  else
10286141cc406Sopenharmony_ci    dataoffset = 0;
10287141cc406Sopenharmony_ci
10288141cc406Sopenharmony_ci  rc = sanei_umax_pp_startScan
10289141cc406Sopenharmony_ci    (x, y - dataoffset, width, height + dataoffset, dpi, color, gain,
10290141cc406Sopenharmony_ci     offset, &bpp, &tw, &th);
10291141cc406Sopenharmony_ci  if (rc == 1)
10292141cc406Sopenharmony_ci    {
10293141cc406Sopenharmony_ci      /* blocksize must be multiple of the number of bytes per line */
10294141cc406Sopenharmony_ci      /* max is 2096100                                             */
10295141cc406Sopenharmony_ci      /* so blocksize will hold a round number of lines, easing the */
10296141cc406Sopenharmony_ci      /* write data to file operation                               */
10297141cc406Sopenharmony_ci      bpl = bpp * tw;
10298141cc406Sopenharmony_ci      hp = 2096100 / bpl;
10299141cc406Sopenharmony_ci      blocksize = hp * bpl;
10300141cc406Sopenharmony_ci      nb = 0;
10301141cc406Sopenharmony_ci      somme = bpl * th;
10302141cc406Sopenharmony_ci      DBG (8, "Getting buffer %d*%d*%d=%ld=0x%lX    (%s:%d)  \n", bpp, tw, th,
10303141cc406Sopenharmony_ci	   somme, somme, __FILE__, __LINE__);
10304141cc406Sopenharmony_ci
10305141cc406Sopenharmony_ci      /* correct th to be usable scan height */
10306141cc406Sopenharmony_ci      th -= dataoffset;
10307141cc406Sopenharmony_ci
10308141cc406Sopenharmony_ci      /* we need a 2 * delta lines reserve to reorder data */
10309141cc406Sopenharmony_ci      if (color >= RGB_MODE)
10310141cc406Sopenharmony_ci	{
10311141cc406Sopenharmony_ci	  reserve = 2 * delta * bpl;
10312141cc406Sopenharmony_ci	  if (sanei_umax_pp_getastra () < 1210)
10313141cc406Sopenharmony_ci	    dataoffset = reserve;
10314141cc406Sopenharmony_ci	  else
10315141cc406Sopenharmony_ci	    dataoffset = 0;
10316141cc406Sopenharmony_ci	}
10317141cc406Sopenharmony_ci      else
10318141cc406Sopenharmony_ci	{
10319141cc406Sopenharmony_ci	  reserve = 0;
10320141cc406Sopenharmony_ci	  dataoffset = 0;
10321141cc406Sopenharmony_ci	}
10322141cc406Sopenharmony_ci
10323141cc406Sopenharmony_ci      /* get scanned data */
10324141cc406Sopenharmony_ci
10325141cc406Sopenharmony_ci      /* allocate memory */
10326141cc406Sopenharmony_ci      buffer = (unsigned char *) malloc (blocksize + reserve);
10327141cc406Sopenharmony_ci      if (buffer == NULL)
10328141cc406Sopenharmony_ci	{
10329141cc406Sopenharmony_ci	  DBG (0, "Failed to allocate %ld bytes, giving up....\n",
10330141cc406Sopenharmony_ci	       blocksize + reserve);
10331141cc406Sopenharmony_ci	  DBG (0, "Try to scan at lower resolution, or a smaller area.\n");
10332141cc406Sopenharmony_ci	  gCancel = 1;
10333141cc406Sopenharmony_ci	}
10334141cc406Sopenharmony_ci
10335141cc406Sopenharmony_ci      /* open output file */
10336141cc406Sopenharmony_ci      fout = fopen ("out.pnm", "wb");
10337141cc406Sopenharmony_ci      if (fout == NULL)
10338141cc406Sopenharmony_ci	{
10339141cc406Sopenharmony_ci	  DBG (0, "Failed to open 'out.pnm', giving up....\n");
10340141cc406Sopenharmony_ci	  gCancel = 1;
10341141cc406Sopenharmony_ci	}
10342141cc406Sopenharmony_ci      else
10343141cc406Sopenharmony_ci	{
10344141cc406Sopenharmony_ci	  /* write pnm header */
10345141cc406Sopenharmony_ci	  if (color >= RGB_MODE)
10346141cc406Sopenharmony_ci	    fprintf (fout, "P6\n%d %d\n255\n", tw, th - 2 * delta);
10347141cc406Sopenharmony_ci	  else
10348141cc406Sopenharmony_ci	    fprintf (fout, "P5\n%d %d\n255\n", tw, th);
10349141cc406Sopenharmony_ci	}
10350141cc406Sopenharmony_ci
10351141cc406Sopenharmony_ci      /* read some line first until we got clean data */
10352141cc406Sopenharmony_ci      read = 0;
10353141cc406Sopenharmony_ci      remain = 0;
10354141cc406Sopenharmony_ci      while (read < dataoffset)
10355141cc406Sopenharmony_ci	{
10356141cc406Sopenharmony_ci	  if (read == 0)
10357141cc406Sopenharmony_ci	    len = dataoffset;
10358141cc406Sopenharmony_ci	  else
10359141cc406Sopenharmony_ci	    len = dataoffset - read;
10360141cc406Sopenharmony_ci	  len = sanei_umax_pp_readBlock (len, tw, dpi, 0, buffer + read);
10361141cc406Sopenharmony_ci	  if (len == 0)
10362141cc406Sopenharmony_ci	    {
10363141cc406Sopenharmony_ci	      DBG (0,
10364141cc406Sopenharmony_ci		   "sanei_umax_pp_readBlock failed, cancelling scan ...\n");
10365141cc406Sopenharmony_ci	      gCancel = 1;
10366141cc406Sopenharmony_ci	    }
10367141cc406Sopenharmony_ci	  read += len;
10368141cc406Sopenharmony_ci	}
10369141cc406Sopenharmony_ci
10370141cc406Sopenharmony_ci      /* in color mode we have to fill the 'reserve' area
10371141cc406Sopenharmony_ci       * so that we can reorder data lines */
10372141cc406Sopenharmony_ci      while ((read - dataoffset < reserve) && (!gCancel))
10373141cc406Sopenharmony_ci	{
10374141cc406Sopenharmony_ci	  len = reserve - read + dataoffset;
10375141cc406Sopenharmony_ci	  len =
10376141cc406Sopenharmony_ci	    sanei_umax_pp_readBlock (len, tw, dpi, 0,
10377141cc406Sopenharmony_ci				     buffer + read - dataoffset);
10378141cc406Sopenharmony_ci	  if (len == 0)
10379141cc406Sopenharmony_ci	    {
10380141cc406Sopenharmony_ci	      DBG (0,
10381141cc406Sopenharmony_ci		   "sanei_umax_pp_readBlock failed, cancelling scan ...\n");
10382141cc406Sopenharmony_ci	      gCancel = 1;
10383141cc406Sopenharmony_ci	    }
10384141cc406Sopenharmony_ci	  read += len;
10385141cc406Sopenharmony_ci	}
10386141cc406Sopenharmony_ci
10387141cc406Sopenharmony_ci      /* data reading loop */
10388141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
10389141cc406Sopenharmony_ci      gettimeofday (&td, NULL);
10390141cc406Sopenharmony_ci#endif
10391141cc406Sopenharmony_ci      while ((read < somme) && (!gCancel))
10392141cc406Sopenharmony_ci	{
10393141cc406Sopenharmony_ci	  /* 2096100 max */
10394141cc406Sopenharmony_ci	  if (somme - read > blocksize - remain)
10395141cc406Sopenharmony_ci	    len = blocksize - remain;
10396141cc406Sopenharmony_ci	  else
10397141cc406Sopenharmony_ci	    len = somme - read;
10398141cc406Sopenharmony_ci	  len =
10399141cc406Sopenharmony_ci	    sanei_umax_pp_readBlock (len, tw, dpi, (len < blocksize),
10400141cc406Sopenharmony_ci				     buffer + reserve + remain);
10401141cc406Sopenharmony_ci	  if (len == 0)
10402141cc406Sopenharmony_ci	    {
10403141cc406Sopenharmony_ci	      DBG (0,
10404141cc406Sopenharmony_ci		   "sanei_umax_pp_readBlock failed, cancelling scan ...\n");
10405141cc406Sopenharmony_ci	      gCancel = 1;
10406141cc406Sopenharmony_ci	    }
10407141cc406Sopenharmony_ci
10408141cc406Sopenharmony_ci	  read += len;
10409141cc406Sopenharmony_ci	  nb++;
10410141cc406Sopenharmony_ci	  DBG (8, "Read %ld bytes out of %ld ...\n", read, somme);
10411141cc406Sopenharmony_ci	  DBG (8, "Read %d blocks ... \n", nb);
10412141cc406Sopenharmony_ci
10413141cc406Sopenharmony_ci	  /* write partial buffer to file */
10414141cc406Sopenharmony_ci	  if (len)
10415141cc406Sopenharmony_ci	    {
10416141cc406Sopenharmony_ci	      if (color >= RGB_MODE)
10417141cc406Sopenharmony_ci		{
10418141cc406Sopenharmony_ci		  /* using an image format that doesn't need   */
10419141cc406Sopenharmony_ci		  /* reordering would speed up write operation */
10420141cc406Sopenharmony_ci
10421141cc406Sopenharmony_ci		  /* don't forget remaining bytes from previous block */
10422141cc406Sopenharmony_ci		  hp = (len + remain) / bpl;
10423141cc406Sopenharmony_ci		  remain = (len + remain) - hp * bpl;
10424141cc406Sopenharmony_ci		  switch (sanei_umax_pp_getastra ())
10425141cc406Sopenharmony_ci		    {
10426141cc406Sopenharmony_ci		    case 610:
10427141cc406Sopenharmony_ci		      /* first comes RED
10428141cc406Sopenharmony_ci		       * then        BLUE
10429141cc406Sopenharmony_ci		       * and finally GREEN */
10430141cc406Sopenharmony_ci		      for (by = 0; by < hp; by++)
10431141cc406Sopenharmony_ci			{
10432141cc406Sopenharmony_ci			  for (bx = 0; bx < tw; bx++)
10433141cc406Sopenharmony_ci			    {
10434141cc406Sopenharmony_ci			      /* scanner data: red line, blue line then green line */
10435141cc406Sopenharmony_ci			      /* red */
10436141cc406Sopenharmony_ci			      fputc (buffer
10437141cc406Sopenharmony_ci				     [3 * (by - 2 * delta) * tw + bx +
10438141cc406Sopenharmony_ci				      reserve], fout);
10439141cc406Sopenharmony_ci			      /* green */
10440141cc406Sopenharmony_ci			      fputc (buffer
10441141cc406Sopenharmony_ci				     [3 * by * tw + 2 * tw +
10442141cc406Sopenharmony_ci				      bx + reserve], fout);
10443141cc406Sopenharmony_ci			      /* blue */
10444141cc406Sopenharmony_ci			      fputc (buffer
10445141cc406Sopenharmony_ci				     [3 * (by - delta) * tw + tw + bx +
10446141cc406Sopenharmony_ci				      reserve], fout);
10447141cc406Sopenharmony_ci			    }
10448141cc406Sopenharmony_ci			}
10449141cc406Sopenharmony_ci		      /* copy tail lines for next block */
10450141cc406Sopenharmony_ci		      /* memcpy (buffer,
10451141cc406Sopenharmony_ci		       *         (buffer + reserve) + (hp * bpl - reserve),
10452141cc406Sopenharmony_ci		       *         reserve + remain); */
10453141cc406Sopenharmony_ci		      memcpy (buffer, buffer + hp * bpl, reserve + remain);
10454141cc406Sopenharmony_ci		      break;
10455141cc406Sopenharmony_ci		    case 1600:
10456141cc406Sopenharmony_ci		      for (by = 0; by < hp; by++)
10457141cc406Sopenharmony_ci			{
10458141cc406Sopenharmony_ci			  for (bx = 0; bx < tw; bx++)
10459141cc406Sopenharmony_ci			    {
10460141cc406Sopenharmony_ci			      fputc (buffer[3 * by * tw + 2 * tw + bx], fout);
10461141cc406Sopenharmony_ci			      fputc (buffer[3 * by * tw + bx], fout);
10462141cc406Sopenharmony_ci			      fputc (buffer[3 * by * tw + tw + bx], fout);
10463141cc406Sopenharmony_ci			    }
10464141cc406Sopenharmony_ci			}
10465141cc406Sopenharmony_ci		      break;
10466141cc406Sopenharmony_ci		    default:
10467141cc406Sopenharmony_ci		      for (by = 0; by < hp; by++)
10468141cc406Sopenharmony_ci			{
10469141cc406Sopenharmony_ci			  for (bx = 0; bx < tw; bx++)
10470141cc406Sopenharmony_ci			    {
10471141cc406Sopenharmony_ci			      fputc (buffer[3 * by * tw + 2 * tw + bx], fout);
10472141cc406Sopenharmony_ci			      fputc (buffer[3 * by * tw + tw + bx], fout);
10473141cc406Sopenharmony_ci			      fputc (buffer[3 * by * tw + bx], fout);
10474141cc406Sopenharmony_ci			    }
10475141cc406Sopenharmony_ci			}
10476141cc406Sopenharmony_ci		      /* put remaining partial lines at start of buffer */
10477141cc406Sopenharmony_ci		      memcpy (buffer, buffer + hp * bpl, remain);
10478141cc406Sopenharmony_ci		      break;
10479141cc406Sopenharmony_ci		    }
10480141cc406Sopenharmony_ci		}
10481141cc406Sopenharmony_ci	      else
10482141cc406Sopenharmony_ci		fwrite (buffer, len, 1, fout);
10483141cc406Sopenharmony_ci	    }
10484141cc406Sopenharmony_ci	}
10485141cc406Sopenharmony_ci
10486141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H
10487141cc406Sopenharmony_ci      gettimeofday (&tf, NULL);
10488141cc406Sopenharmony_ci
10489141cc406Sopenharmony_ci      /* scan time are high enough to forget about usec */
10490141cc406Sopenharmony_ci      elapsed = tf.tv_sec - td.tv_sec;
10491141cc406Sopenharmony_ci      DBG (8, "%ld bytes transferred in %f seconds ( %.2f Kb/s)\n", somme,
10492141cc406Sopenharmony_ci	   elapsed, (somme / elapsed) / 1024.0);
10493141cc406Sopenharmony_ci#endif
10494141cc406Sopenharmony_ci
10495141cc406Sopenharmony_ci      /* release resources */
10496141cc406Sopenharmony_ci      if (fout != NULL)
10497141cc406Sopenharmony_ci	fclose (fout);
10498141cc406Sopenharmony_ci      free (dest);
10499141cc406Sopenharmony_ci      free (buffer);
10500141cc406Sopenharmony_ci    }				/* if start scan OK */
10501141cc406Sopenharmony_ci  else
10502141cc406Sopenharmony_ci    {
10503141cc406Sopenharmony_ci      DBG (0, "startScan failed..... \n");
10504141cc406Sopenharmony_ci    }
10505141cc406Sopenharmony_ci
10506141cc406Sopenharmony_ci  /* terminate any pending command */
10507141cc406Sopenharmony_ci  if (sanei_umax_pp_cmdSync (0x00) == 0)
10508141cc406Sopenharmony_ci    {
10509141cc406Sopenharmony_ci      DBG (0, "Warning cmdSync(0x00) failed! (%s:%d)\n", __FILE__, __LINE__);
10510141cc406Sopenharmony_ci      DBG (0, "Trying again ... ");
10511141cc406Sopenharmony_ci      if (sanei_umax_pp_cmdSync (0x00) == 0)
10512141cc406Sopenharmony_ci	{
10513141cc406Sopenharmony_ci	  DBG (0, " failed again! (%s:%d)\n", __FILE__, __LINE__);
10514141cc406Sopenharmony_ci	  DBG (0, "Blindly going on ...\n");
10515141cc406Sopenharmony_ci	}
10516141cc406Sopenharmony_ci      else
10517141cc406Sopenharmony_ci	DBG (0, " success ...\n");
10518141cc406Sopenharmony_ci
10519141cc406Sopenharmony_ci    }
10520141cc406Sopenharmony_ci
10521141cc406Sopenharmony_ci  /* parking */
10522141cc406Sopenharmony_ci  if (sanei_umax_pp_park () == 0)
10523141cc406Sopenharmony_ci    DBG (0, "Park failed !!! (%s:%d)\n", __FILE__, __LINE__);
10524141cc406Sopenharmony_ci
10525141cc406Sopenharmony_ci
10526141cc406Sopenharmony_ci  /* end ... */
10527141cc406Sopenharmony_ci  DBG (16, "Scan done ...\n");
10528141cc406Sopenharmony_ci  return 1;
10529141cc406Sopenharmony_ci}
10530141cc406Sopenharmony_ci
10531141cc406Sopenharmony_ci
10532141cc406Sopenharmony_ci
10533141cc406Sopenharmony_ci
10534141cc406Sopenharmony_ci
10535141cc406Sopenharmony_ci/*
10536141cc406Sopenharmony_ci * returns 0 on error, 1 on success: ie head parked
10537141cc406Sopenharmony_ci */
10538141cc406Sopenharmony_ciint
10539141cc406Sopenharmony_cisanei_umax_pp_parkWait (void)
10540141cc406Sopenharmony_ci{
10541141cc406Sopenharmony_ci  int status;
10542141cc406Sopenharmony_ci
10543141cc406Sopenharmony_ci  /* check if head is at home */
10544141cc406Sopenharmony_ci  DBG (16, "entering parkWait ...\n");
10545141cc406Sopenharmony_ci  do
10546141cc406Sopenharmony_ci    {
10547141cc406Sopenharmony_ci      usleep (1000);
10548141cc406Sopenharmony_ci      CMDSYNC (0x40);
10549141cc406Sopenharmony_ci      status = sanei_umax_pp_scannerStatus ();
10550141cc406Sopenharmony_ci    }
10551141cc406Sopenharmony_ci  while ((status & MOTOR_BIT) == 0x00);
10552141cc406Sopenharmony_ci  DBG (16, "parkWait done ...\n");
10553141cc406Sopenharmony_ci  return 1;
10554141cc406Sopenharmony_ci}
10555141cc406Sopenharmony_ci
10556141cc406Sopenharmony_ci
10557141cc406Sopenharmony_ci
10558141cc406Sopenharmony_ci
10559141cc406Sopenharmony_ci
10560141cc406Sopenharmony_ci
10561141cc406Sopenharmony_ci/* starts scan: return 1 on success */
10562141cc406Sopenharmony_ciint
10563141cc406Sopenharmony_cisanei_umax_pp_startScan (int x, int y, int width, int height, int dpi,
10564141cc406Sopenharmony_ci			 int color, int gain, int offset, int *rbpp,
10565141cc406Sopenharmony_ci			 int *rtw, int *rth)
10566141cc406Sopenharmony_ci{
10567141cc406Sopenharmony_ci  unsigned char *buffer;
10568141cc406Sopenharmony_ci  int rc = 0;
10569141cc406Sopenharmony_ci  int calibration[3 * 5100 + 768 + 2 + 1];
10570141cc406Sopenharmony_ci  int xdpi, ydpi, h;
10571141cc406Sopenharmony_ci  int th, tw, bpp;
10572141cc406Sopenharmony_ci  int hwdpi = 600;		/* CCD hardware dpi */
10573141cc406Sopenharmony_ci  /* DC offsets */
10574141cc406Sopenharmony_ci  int dcRed, dcGreen, dcBlue;
10575141cc406Sopenharmony_ci  int vgaRed, vgaGreen, vgaBlue;
10576141cc406Sopenharmony_ci  int len, delta;
10577141cc406Sopenharmony_ci
10578141cc406Sopenharmony_ci  int lm9811[9] = {
10579141cc406Sopenharmony_ci    0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00,
10580141cc406Sopenharmony_ci    -1
10581141cc406Sopenharmony_ci  };
10582141cc406Sopenharmony_ci
10583141cc406Sopenharmony_ci  int motor[17] = {
10584141cc406Sopenharmony_ci    0xA4, 0x80, 0x07, 0x50, 0xEC, 0x03, 0x00, 0x2F,
10585141cc406Sopenharmony_ci    0x17, 0x07, 0x84, 0x08, 0x90, 0x00, 0xAC, 0x00,
10586141cc406Sopenharmony_ci    -1
10587141cc406Sopenharmony_ci  };
10588141cc406Sopenharmony_ci
10589141cc406Sopenharmony_ci  int ccd[37] =
10590141cc406Sopenharmony_ci    { 0x00, 0x00, 0xB0, 0x4F, 0xD8, 0xE7, 0xFA, 0x10, 0xEF, 0xC4, 0x3C, 0x71,
10591141cc406Sopenharmony_ci    0x0F, 0x00, 0x04, 0x00, 0x6E, 0x61, 0xA1, 0x24, 0xC4, 0x7E, 0x00, 0xAE,
10592141cc406Sopenharmony_ci    0x41, 0xA0, 0x0A, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x33, 0x1A, 0x00,
10593141cc406Sopenharmony_ci    -1
10594141cc406Sopenharmony_ci  };
10595141cc406Sopenharmony_ci
10596141cc406Sopenharmony_ci
10597141cc406Sopenharmony_ci#ifdef UMAX_PP_DANGEROUS_EXPERIMENT
10598141cc406Sopenharmony_ci  FILE *f = NULL;
10599141cc406Sopenharmony_ci  char line[1024], *ptr;
10600141cc406Sopenharmony_ci  int *base = NULL;
10601141cc406Sopenharmony_ci  int channel;
10602141cc406Sopenharmony_ci  int max = 0;
10603141cc406Sopenharmony_ci#endif
10604141cc406Sopenharmony_ci
10605141cc406Sopenharmony_ci
10606141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 610)
10607141cc406Sopenharmony_ci    {
10608141cc406Sopenharmony_ci      hwdpi = 300;
10609141cc406Sopenharmony_ci      len = 0x22;
10610141cc406Sopenharmony_ci
10611141cc406Sopenharmony_ci      lm9811[0] = 0x88;
10612141cc406Sopenharmony_ci      lm9811[1] = 0xE6;
10613141cc406Sopenharmony_ci      lm9811[2] = 0xFD;
10614141cc406Sopenharmony_ci      lm9811[3] = 0x8E;
10615141cc406Sopenharmony_ci      lm9811[4] = 0x30;
10616141cc406Sopenharmony_ci      lm9811[5] = 0x00;
10617141cc406Sopenharmony_ci      lm9811[6] = 0x8F;
10618141cc406Sopenharmony_ci      lm9811[7] = 0x80;
10619141cc406Sopenharmony_ci
10620141cc406Sopenharmony_ci      motor[3] = 0x30;
10621141cc406Sopenharmony_ci      motor[4] = 0x0E;
10622141cc406Sopenharmony_ci      motor[5] = 0x02;
10623141cc406Sopenharmony_ci      motor[12] = 0xAA;
10624141cc406Sopenharmony_ci
10625141cc406Sopenharmony_ci      ccd[0] = 0x00;
10626141cc406Sopenharmony_ci      ccd[1] = 0x00;
10627141cc406Sopenharmony_ci      ccd[2] = 0xD8;
10628141cc406Sopenharmony_ci      ccd[3] = 0x27;
10629141cc406Sopenharmony_ci      ccd[4] = 0xEC;
10630141cc406Sopenharmony_ci      ccd[5] = 0x53;
10631141cc406Sopenharmony_ci      ccd[6] = 0x7D;
10632141cc406Sopenharmony_ci      ccd[7] = 0x8A;
10633141cc406Sopenharmony_ci      ccd[8] = 0x77;
10634141cc406Sopenharmony_ci      ccd[9] = 0xE2;
10635141cc406Sopenharmony_ci      ccd[10] = 0x9E;
10636141cc406Sopenharmony_ci      ccd[11] = 0xF8;
10637141cc406Sopenharmony_ci      ccd[12] = 0x07;
10638141cc406Sopenharmony_ci      ccd[13] = 0x20;
10639141cc406Sopenharmony_ci      ccd[14] = 0x02;
10640141cc406Sopenharmony_ci      ccd[15] = 0x00;
10641141cc406Sopenharmony_ci      ccd[16] = 0x76;
10642141cc406Sopenharmony_ci      ccd[17] = 0x5D;
10643141cc406Sopenharmony_ci      ccd[18] = 0xE0;
10644141cc406Sopenharmony_ci      ccd[19] = 0x13;
10645141cc406Sopenharmony_ci      ccd[20] = 0xE2;
10646141cc406Sopenharmony_ci      ccd[21] = 0x20;
10647141cc406Sopenharmony_ci      ccd[22] = 0x00;
10648141cc406Sopenharmony_ci      ccd[23] = 0xA8;
10649141cc406Sopenharmony_ci      ccd[24] = 0x41;
10650141cc406Sopenharmony_ci      ccd[25] = 0xA0;
10651141cc406Sopenharmony_ci      ccd[26] = 0x0A;
10652141cc406Sopenharmony_ci      ccd[27] = 0x8B;
10653141cc406Sopenharmony_ci      ccd[28] = 0x4D;
10654141cc406Sopenharmony_ci      ccd[29] = 0x4B;
10655141cc406Sopenharmony_ci      ccd[30] = 0xD0;
10656141cc406Sopenharmony_ci      ccd[31] = 0x68;
10657141cc406Sopenharmony_ci      ccd[32] = 0xDF;
10658141cc406Sopenharmony_ci      ccd[33] = 0x13;
10659141cc406Sopenharmony_ci    }
10660141cc406Sopenharmony_ci  else
10661141cc406Sopenharmony_ci    {
10662141cc406Sopenharmony_ci      len = 0x24;
10663141cc406Sopenharmony_ci      hwdpi = 600;
10664141cc406Sopenharmony_ci    }
10665141cc406Sopenharmony_ci  DBG (8, "startScan(%d,%d,%d,%d,%d,%d,%X);\n", x, y, width, height, dpi,
10666141cc406Sopenharmony_ci       color, gain);
10667141cc406Sopenharmony_ci  buffer = (unsigned char *) malloc (2096100);
10668141cc406Sopenharmony_ci  if (buffer == NULL)
10669141cc406Sopenharmony_ci    {
10670141cc406Sopenharmony_ci      DBG (0, "Failed to allocate 2096100 bytes... (%s:%d)\n", __FILE__,
10671141cc406Sopenharmony_ci	   __LINE__);
10672141cc406Sopenharmony_ci      return 0;
10673141cc406Sopenharmony_ci    }
10674141cc406Sopenharmony_ci
10675141cc406Sopenharmony_ci  /* 1600P have a different CCD command block */
10676141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 1600)
10677141cc406Sopenharmony_ci    {
10678141cc406Sopenharmony_ci      lm9811[0] = 0x19;
10679141cc406Sopenharmony_ci      lm9811[1] = 0xD5;
10680141cc406Sopenharmony_ci      lm9811[4] = 0x1B;
10681141cc406Sopenharmony_ci      lm9811[7] = 0x70;
10682141cc406Sopenharmony_ci
10683141cc406Sopenharmony_ci      ccd[29] = 0x1A;
10684141cc406Sopenharmony_ci      ccd[30] = 0xEE;
10685141cc406Sopenharmony_ci
10686141cc406Sopenharmony_ci      motor[13] = 0x03;		/* may be blur filter */
10687141cc406Sopenharmony_ci    }
10688141cc406Sopenharmony_ci
10689141cc406Sopenharmony_ci  /* matches intTransport610P */
10690141cc406Sopenharmony_ci  /* get scanner status */
10691141cc406Sopenharmony_ci  rc = inquire ();
10692141cc406Sopenharmony_ci  if (rc == 0)
10693141cc406Sopenharmony_ci    {
10694141cc406Sopenharmony_ci      DBG (0, "inquire() failed ! (%s:%d) \n", __FILE__, __LINE__);
10695141cc406Sopenharmony_ci      return 0;
10696141cc406Sopenharmony_ci    }
10697141cc406Sopenharmony_ci  DBG (16, "inquire() passed ... (%s:%d)\n", __FILE__, __LINE__);
10698141cc406Sopenharmony_ci
10699141cc406Sopenharmony_ci  rc = loadDefaultTables ();
10700141cc406Sopenharmony_ci  if (rc == 0)
10701141cc406Sopenharmony_ci    {
10702141cc406Sopenharmony_ci      DBG (0, "loadDefaultTables() failed ! (%s:%d) \n", __FILE__, __LINE__);
10703141cc406Sopenharmony_ci      return 0;
10704141cc406Sopenharmony_ci    }
10705141cc406Sopenharmony_ci  DBG (16, "loadDefaultTables() passed ... (%s:%d)\n", __FILE__, __LINE__);
10706141cc406Sopenharmony_ci
10707141cc406Sopenharmony_ci  /* find and move to zero */
10708141cc406Sopenharmony_ci  if (moveToOrigin () == 0)
10709141cc406Sopenharmony_ci    {
10710141cc406Sopenharmony_ci      DBG (0, "moveToOrigin() failed ... (%s:%d)\n", __FILE__, __LINE__);
10711141cc406Sopenharmony_ci    }
10712141cc406Sopenharmony_ci  else
10713141cc406Sopenharmony_ci    {
10714141cc406Sopenharmony_ci      DBG (16, "moveToOrigin() passed ... (%s:%d)\n", __FILE__, __LINE__);
10715141cc406Sopenharmony_ci    }
10716141cc406Sopenharmony_ci
10717141cc406Sopenharmony_ci  /* 1600P have a different CCD command block */
10718141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 1600)
10719141cc406Sopenharmony_ci    {
10720141cc406Sopenharmony_ci      lm9811[0] = 0x19;
10721141cc406Sopenharmony_ci      lm9811[1] = 0xD5;
10722141cc406Sopenharmony_ci      lm9811[4] = 0x1B;
10723141cc406Sopenharmony_ci      lm9811[7] = 0x70;
10724141cc406Sopenharmony_ci
10725141cc406Sopenharmony_ci      ccd[29] = 0x1A;
10726141cc406Sopenharmony_ci      ccd[30] = 0xEE;
10727141cc406Sopenharmony_ci
10728141cc406Sopenharmony_ci      motor[13] = 0x03;		/* may be blur filter */
10729141cc406Sopenharmony_ci    }
10730141cc406Sopenharmony_ci
10731141cc406Sopenharmony_ci  /* XXX STEF XXX : done even is manual settings, some day skip it
10732141cc406Sopenharmony_ci   * and move head the right amount */
10733141cc406Sopenharmony_ci  if (offsetCalibration (color, &dcRed, &dcGreen, &dcBlue) == 0)
10734141cc406Sopenharmony_ci    {
10735141cc406Sopenharmony_ci      DBG (0, "offsetCalibration failed !!! (%s:%d)\n", __FILE__, __LINE__);
10736141cc406Sopenharmony_ci      return 0;
10737141cc406Sopenharmony_ci    }
10738141cc406Sopenharmony_ci  DBG (16, "offsetCalibration(%d=>%d,%d,%d) passed ... (%s:%d)\n",
10739141cc406Sopenharmony_ci       color, dcRed, dcGreen, dcBlue, __FILE__, __LINE__);
10740141cc406Sopenharmony_ci
10741141cc406Sopenharmony_ci  if (coarseGainCalibration
10742141cc406Sopenharmony_ci      (color, dcRed, dcGreen, dcBlue, &vgaRed, &vgaGreen, &vgaBlue) == 0)
10743141cc406Sopenharmony_ci    {
10744141cc406Sopenharmony_ci      DBG (0, "coarseGainCalibration failed !!! (%s:%d)\n", __FILE__,
10745141cc406Sopenharmony_ci	   __LINE__);
10746141cc406Sopenharmony_ci      return 0;
10747141cc406Sopenharmony_ci    }
10748141cc406Sopenharmony_ci  DBG (16,
10749141cc406Sopenharmony_ci       "coarseGainCalibration(%d,%d,%d,%d=>%d,%d,%d) passed ... (%s:%d)\n",
10750141cc406Sopenharmony_ci       color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue,
10751141cc406Sopenharmony_ci       __FILE__, __LINE__);
10752141cc406Sopenharmony_ci
10753141cc406Sopenharmony_ci  /* manual setting overrides evaluated values */
10754141cc406Sopenharmony_ci  if (!sanei_umax_pp_getauto ())
10755141cc406Sopenharmony_ci    {
10756141cc406Sopenharmony_ci      dcRed = (offset & 0xF00) >> 8;
10757141cc406Sopenharmony_ci      dcGreen = (offset & 0x0F0) >> 4;
10758141cc406Sopenharmony_ci      dcBlue = offset & 0x00F;
10759141cc406Sopenharmony_ci      vgaRed = (gain & 0xF00) >> 8;
10760141cc406Sopenharmony_ci      vgaGreen = (gain & 0x0F0) >> 4;
10761141cc406Sopenharmony_ci      vgaBlue = gain & 0x00F;
10762141cc406Sopenharmony_ci    }
10763141cc406Sopenharmony_ci
10764141cc406Sopenharmony_ci  /* ccd calibration is always done */
10765141cc406Sopenharmony_ci  /* with final dc and vga */
10766141cc406Sopenharmony_ci  if (shadingCalibration
10767141cc406Sopenharmony_ci      (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue,
10768141cc406Sopenharmony_ci       calibration) == 0)
10769141cc406Sopenharmony_ci    {
10770141cc406Sopenharmony_ci      DBG (0, "shadingCalibration failed !!! (%s:%d)\n", __FILE__, __LINE__);
10771141cc406Sopenharmony_ci      return 0;
10772141cc406Sopenharmony_ci    }
10773141cc406Sopenharmony_ci  DBG (16,
10774141cc406Sopenharmony_ci       "shadingCalibration(%d,%d,%d,%d,%d,%d,%d) passed ... (%s:%d)\n",
10775141cc406Sopenharmony_ci       color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, __FILE__,
10776141cc406Sopenharmony_ci       __LINE__);
10777141cc406Sopenharmony_ci
10778141cc406Sopenharmony_ci  /* gamma or left shading calibration ? */
10779141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () <= 610)
10780141cc406Sopenharmony_ci    {
10781141cc406Sopenharmony_ci      if (leftShadingCalibration610p
10782141cc406Sopenharmony_ci	  (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue,
10783141cc406Sopenharmony_ci	   calibration) == 0)
10784141cc406Sopenharmony_ci	{
10785141cc406Sopenharmony_ci	  DBG (0, "leftShadingCalibration610p failed !!! (%s:%d)\n", __FILE__,
10786141cc406Sopenharmony_ci	       __LINE__);
10787141cc406Sopenharmony_ci	  return 0;
10788141cc406Sopenharmony_ci	}
10789141cc406Sopenharmony_ci      DBG (16,
10790141cc406Sopenharmony_ci	   "leftShadingCalibration610p(%d,%d,%d,%d,%d,%d,%d) passed ... (%s:%d)\n",
10791141cc406Sopenharmony_ci	   color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, __FILE__,
10792141cc406Sopenharmony_ci	   __LINE__);
10793141cc406Sopenharmony_ci    }
10794141cc406Sopenharmony_ci
10795141cc406Sopenharmony_ci  /* 1220P: x dpi is from 75 to 600 max, any modes */
10796141cc406Sopenharmony_ci  /*  610P: x dpi is from 75 to 300 max, any modes */
10797141cc406Sopenharmony_ci  if (dpi > hwdpi)
10798141cc406Sopenharmony_ci    xdpi = hwdpi;
10799141cc406Sopenharmony_ci  else
10800141cc406Sopenharmony_ci    xdpi = dpi;
10801141cc406Sopenharmony_ci
10802141cc406Sopenharmony_ci
10803141cc406Sopenharmony_ci  /* EPPRead32Buffer does not work                         */
10804141cc406Sopenharmony_ci  /* with length not multiple of four bytes, so we enlarge */
10805141cc406Sopenharmony_ci  /* width to meet this criteria ...                       */
10806141cc406Sopenharmony_ci  if ((getEPPMode () == 32) && (xdpi >= 600) && (width & 0x03)
10807141cc406Sopenharmony_ci      && (sanei_umax_pp_getastra () > 610))
10808141cc406Sopenharmony_ci    {
10809141cc406Sopenharmony_ci      width += (4 - (width & 0x03));
10810141cc406Sopenharmony_ci      /* in case we go too far on the right */
10811141cc406Sopenharmony_ci      if (x + width > 5100)
10812141cc406Sopenharmony_ci	{
10813141cc406Sopenharmony_ci	  x = 5100 - width;
10814141cc406Sopenharmony_ci	}
10815141cc406Sopenharmony_ci    }
10816141cc406Sopenharmony_ci
10817141cc406Sopenharmony_ci  /* compute target size */
10818141cc406Sopenharmony_ci  th = (height * dpi) / hwdpi;
10819141cc406Sopenharmony_ci  tw = (width * xdpi) / hwdpi;
10820141cc406Sopenharmony_ci
10821141cc406Sopenharmony_ci  /* corrects y to match exact scan area start
10822141cc406Sopenharmony_ci   * and lets room for a leading zone so that
10823141cc406Sopenharmony_ci   * we can reorder data */
10824141cc406Sopenharmony_ci  switch (sanei_umax_pp_getastra ())
10825141cc406Sopenharmony_ci    {
10826141cc406Sopenharmony_ci    case 610:
10827141cc406Sopenharmony_ci      if (color >= RGB_MODE)
10828141cc406Sopenharmony_ci	switch (dpi)
10829141cc406Sopenharmony_ci	  {
10830141cc406Sopenharmony_ci	  case 600:
10831141cc406Sopenharmony_ci	    y += 64;
10832141cc406Sopenharmony_ci	    break;
10833141cc406Sopenharmony_ci	  case 300:
10834141cc406Sopenharmony_ci	    y += 32;
10835141cc406Sopenharmony_ci	    break;
10836141cc406Sopenharmony_ci	  case 150:
10837141cc406Sopenharmony_ci	    y += 16;
10838141cc406Sopenharmony_ci	    break;
10839141cc406Sopenharmony_ci	  case 75:
10840141cc406Sopenharmony_ci	    y += 8;
10841141cc406Sopenharmony_ci	    break;
10842141cc406Sopenharmony_ci	  }
10843141cc406Sopenharmony_ci      else
10844141cc406Sopenharmony_ci	y += 80;
10845141cc406Sopenharmony_ci      // fall through
10846141cc406Sopenharmony_ci    default:
10847141cc406Sopenharmony_ci      y += 8;
10848141cc406Sopenharmony_ci      break;
10849141cc406Sopenharmony_ci    }
10850141cc406Sopenharmony_ci
10851141cc406Sopenharmony_ci  /* for 1220P/2000P move fast to scan target if possible */
10852141cc406Sopenharmony_ci  /* it is faster to move at low resolution, then scan */
10853141cc406Sopenharmony_ci  /* than scan & move at high resolution               */
10854141cc406Sopenharmony_ci  if ((sanei_umax_pp_getastra () > 610 && (dpi > 300)) && (y > 100))
10855141cc406Sopenharmony_ci    {
10856141cc406Sopenharmony_ci      /* move at 150 dpi resolution */
10857141cc406Sopenharmony_ci      move (y / 2, PRECISION_OFF, NULL);
10858141cc406Sopenharmony_ci
10859141cc406Sopenharmony_ci      /* keep the remainder for scan */
10860141cc406Sopenharmony_ci      y = y % 4;
10861141cc406Sopenharmony_ci    }
10862141cc406Sopenharmony_ci
10863141cc406Sopenharmony_ci  /* build final scan command */
10864141cc406Sopenharmony_ci
10865141cc406Sopenharmony_ci  /* round width and height */
10866141cc406Sopenharmony_ci  width = (tw * hwdpi) / xdpi;
10867141cc406Sopenharmony_ci  height = (th * hwdpi) / dpi;
10868141cc406Sopenharmony_ci
10869141cc406Sopenharmony_ci  ydpi = dpi;
10870141cc406Sopenharmony_ci  if (ydpi < 300)
10871141cc406Sopenharmony_ci    {
10872141cc406Sopenharmony_ci      if ((color >= RGB_MODE) && (sanei_umax_pp_getastra () > 610))
10873141cc406Sopenharmony_ci	{
10874141cc406Sopenharmony_ci	  if (dpi < 150)
10875141cc406Sopenharmony_ci	    ydpi = 150;
10876141cc406Sopenharmony_ci	}
10877141cc406Sopenharmony_ci      else
10878141cc406Sopenharmony_ci	ydpi = 300;
10879141cc406Sopenharmony_ci    }
10880141cc406Sopenharmony_ci  if ((color < RGB_MODE) && (sanei_umax_pp_getastra () <= 610))
10881141cc406Sopenharmony_ci    ydpi = 600;
10882141cc406Sopenharmony_ci
10883141cc406Sopenharmony_ci  /* at maximum resolution                      */
10884141cc406Sopenharmony_ci  if (color >= RGB_MODE)
10885141cc406Sopenharmony_ci    {
10886141cc406Sopenharmony_ci      h = ((height * ydpi) / hwdpi) + 8;
10887141cc406Sopenharmony_ci      bpp = 3;
10888141cc406Sopenharmony_ci    }
10889141cc406Sopenharmony_ci  else
10890141cc406Sopenharmony_ci    {
10891141cc406Sopenharmony_ci      h = ((height * ydpi) / hwdpi) + 4;
10892141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () <= 610)
10893141cc406Sopenharmony_ci	h += 16;
10894141cc406Sopenharmony_ci      bpp = 1;
10895141cc406Sopenharmony_ci    }
10896141cc406Sopenharmony_ci
10897141cc406Sopenharmony_ci  /* sets y resolution */
10898141cc406Sopenharmony_ci  switch (ydpi)
10899141cc406Sopenharmony_ci    {
10900141cc406Sopenharmony_ci    case 1200:
10901141cc406Sopenharmony_ci      motor[6] = 0x60;
10902141cc406Sopenharmony_ci      motor[8] = 0x5E;		/* *WORKING* value */
10903141cc406Sopenharmony_ci      motor[8] = 0x5F;		/* 5F gives wrong colors ? */
10904141cc406Sopenharmony_ci      motor[8] = 0x58;
10905141cc406Sopenharmony_ci      motor[9] = 0x05;
10906141cc406Sopenharmony_ci      /* XXX test value XXX motor[14] = motor[14] & 0xF0;  ~ 0x08 -> scan AND move */
10907141cc406Sopenharmony_ci      /* XXX test value XXX motor[14] = (motor[14] & 0xF0) | 0x04;         -> 600 dpi ? */
10908141cc406Sopenharmony_ci      /* XXX test value XXX motor[14] = (motor[14] & 0xF0) | 0x0C; */
10909141cc406Sopenharmony_ci      motor[14] = motor[14] & 0xF0;	/* *WORKING* 1200 dpi */
10910141cc406Sopenharmony_ci      break;
10911141cc406Sopenharmony_ci
10912141cc406Sopenharmony_ci    case 600:
10913141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () <= 610)
10914141cc406Sopenharmony_ci	{
10915141cc406Sopenharmony_ci	  motor[6] = 0xC0;
10916141cc406Sopenharmony_ci	  motor[7] = 0x2F;
10917141cc406Sopenharmony_ci	  motor[14] = motor[14] & 0xF0;
10918141cc406Sopenharmony_ci	  /* if (color >= RGB_MODE)
10919141cc406Sopenharmony_ci	     motor[14] |= 0x04; XXX STEF XXX */
10920141cc406Sopenharmony_ci	}
10921141cc406Sopenharmony_ci      else
10922141cc406Sopenharmony_ci	{
10923141cc406Sopenharmony_ci	  motor[6] = 0x60;
10924141cc406Sopenharmony_ci	  motor[14] = (motor[14] & 0xF0) | 0x04;
10925141cc406Sopenharmony_ci	}
10926141cc406Sopenharmony_ci      motor[8] = 0x2F;
10927141cc406Sopenharmony_ci      motor[9] = 0x05;
10928141cc406Sopenharmony_ci      break;
10929141cc406Sopenharmony_ci
10930141cc406Sopenharmony_ci    case 300:
10931141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () <= 610)
10932141cc406Sopenharmony_ci	{
10933141cc406Sopenharmony_ci	  motor[6] = 0xC0;
10934141cc406Sopenharmony_ci	  motor[14] = motor[14] & 0xF0;
10935141cc406Sopenharmony_ci	  if (color >= RGB_MODE)
10936141cc406Sopenharmony_ci	    motor[14] |= 0x04;
10937141cc406Sopenharmony_ci	}
10938141cc406Sopenharmony_ci      else
10939141cc406Sopenharmony_ci	{
10940141cc406Sopenharmony_ci	  motor[6] = 0x00;
10941141cc406Sopenharmony_ci	  motor[14] = (motor[14] & 0xF0) | 0x0C;
10942141cc406Sopenharmony_ci	}
10943141cc406Sopenharmony_ci      motor[8] = 0x17;
10944141cc406Sopenharmony_ci      motor[9] = 0x05;
10945141cc406Sopenharmony_ci
10946141cc406Sopenharmony_ci      /* si | 0C h=2*w, si | 04 h=w ? */
10947141cc406Sopenharmony_ci
10948141cc406Sopenharmony_ci      break;
10949141cc406Sopenharmony_ci
10950141cc406Sopenharmony_ci    case 150:
10951141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () <= 610)
10952141cc406Sopenharmony_ci	{
10953141cc406Sopenharmony_ci	  motor[6] = 0xC0;
10954141cc406Sopenharmony_ci	  motor[9] = 0x05;
10955141cc406Sopenharmony_ci	  motor[14] = motor[14] & 0xF0;
10956141cc406Sopenharmony_ci	  if (color >= RGB_MODE)
10957141cc406Sopenharmony_ci	    motor[14] |= 0x04;
10958141cc406Sopenharmony_ci	}
10959141cc406Sopenharmony_ci      else
10960141cc406Sopenharmony_ci	{
10961141cc406Sopenharmony_ci	  motor[6] = 0x00;
10962141cc406Sopenharmony_ci	  motor[9] = 0x07;
10963141cc406Sopenharmony_ci	  motor[14] = (motor[14] & 0xF0) | 0x0C;
10964141cc406Sopenharmony_ci	}
10965141cc406Sopenharmony_ci      motor[8] = 0x17;
10966141cc406Sopenharmony_ci      break;
10967141cc406Sopenharmony_ci    }
10968141cc406Sopenharmony_ci
10969141cc406Sopenharmony_ci  /* different values for 610P in B&W */
10970141cc406Sopenharmony_ci  if ((sanei_umax_pp_getastra () <= 610) && (color < RGB_MODE))
10971141cc406Sopenharmony_ci    {
10972141cc406Sopenharmony_ci      motor[7] = 0xC8;
10973141cc406Sopenharmony_ci      motor[8] = 0x2F;
10974141cc406Sopenharmony_ci      motor[9] = 0x05;
10975141cc406Sopenharmony_ci    }
10976141cc406Sopenharmony_ci
10977141cc406Sopenharmony_ci  /* y start -1 */
10978141cc406Sopenharmony_ci  y = (y * ydpi) / hwdpi;
10979141cc406Sopenharmony_ci
10980141cc406Sopenharmony_ci  if (color >= RGB_MODE)
10981141cc406Sopenharmony_ci    {
10982141cc406Sopenharmony_ci      /* 00 seems to give better results ?     */
10983141cc406Sopenharmony_ci      /* 80 some more gain, lamp power level ? */
10984141cc406Sopenharmony_ci      /* 8x does not make much difference      */
10985141cc406Sopenharmony_ci      lm9811[6] = 0x8F;
10986141cc406Sopenharmony_ci      switch (sanei_umax_pp_getastra ())
10987141cc406Sopenharmony_ci	{
10988141cc406Sopenharmony_ci	case 610:
10989141cc406Sopenharmony_ci	  lm9811[7] = 0x80;
10990141cc406Sopenharmony_ci	  motor[13] = 0x20;
10991141cc406Sopenharmony_ci	  break;
10992141cc406Sopenharmony_ci	case 1600:
10993141cc406Sopenharmony_ci	  lm9811[7] = 0x70;
10994141cc406Sopenharmony_ci	  motor[13] = 0x03;
10995141cc406Sopenharmony_ci	  break;
10996141cc406Sopenharmony_ci	default:
10997141cc406Sopenharmony_ci	  lm9811[7] = 0xF0;
10998141cc406Sopenharmony_ci	  motor[13] = 0x09;
10999141cc406Sopenharmony_ci	}
11000141cc406Sopenharmony_ci    }
11001141cc406Sopenharmony_ci  else
11002141cc406Sopenharmony_ci    {
11003141cc406Sopenharmony_ci      motor[13] = 0xC0;
11004141cc406Sopenharmony_ci      lm9811[6] = 0x80 | vgaGreen;
11005141cc406Sopenharmony_ci      switch (sanei_umax_pp_getastra ())
11006141cc406Sopenharmony_ci	{
11007141cc406Sopenharmony_ci	case 610:
11008141cc406Sopenharmony_ci	  lm9811[7] = 0xA0;
11009141cc406Sopenharmony_ci	  lm9811[6] = lm9811[6] | 0x40;
11010141cc406Sopenharmony_ci	  motor[13] = 0x6F;
11011141cc406Sopenharmony_ci	  break;
11012141cc406Sopenharmony_ci	case 1600:
11013141cc406Sopenharmony_ci	  lm9811[7] = 0x20;
11014141cc406Sopenharmony_ci	  motor[13] = 0xC3;
11015141cc406Sopenharmony_ci	  break;
11016141cc406Sopenharmony_ci	default:
11017141cc406Sopenharmony_ci	  lm9811[7] = 0xA0;
11018141cc406Sopenharmony_ci	  motor[13] = 0xC9;
11019141cc406Sopenharmony_ci	}
11020141cc406Sopenharmony_ci    }
11021141cc406Sopenharmony_ci
11022141cc406Sopenharmony_ci  encodeCoefficient (color, dpi, calibration);
11023141cc406Sopenharmony_ci  encodeWX (width, x, dpi, color, ccd, 0);
11024141cc406Sopenharmony_ci  encodeHY (h, y, motor);
11025141cc406Sopenharmony_ci  encodeDC (dcRed, dcGreen, dcBlue, motor);
11026141cc406Sopenharmony_ci  encodeVGA (vgaRed, vgaGreen, vgaBlue, motor);
11027141cc406Sopenharmony_ci
11028141cc406Sopenharmony_ci#ifdef UMAX_PP_DANGEROUS_EXPERIMENT
11029141cc406Sopenharmony_ci  /*motor[13] = 0x80;           B&W bit */
11030141cc406Sopenharmony_ci  /*motor[13] = 0x40;           green bit */
11031141cc406Sopenharmony_ci  /*motor[13] = 0x20;           red bit */
11032141cc406Sopenharmony_ci  /*motor[13] = 0x10;           blue bit */
11033141cc406Sopenharmony_ci  /* with cmd 01, may be use to do 3 pass scanning ? */
11034141cc406Sopenharmony_ci  /* bits 0 to 3 seem related to sharpness */
11035141cc406Sopenharmony_ci  f = fopen ("/tmp/dangerous.params", "rb");
11036141cc406Sopenharmony_ci  if (f != NULL)
11037141cc406Sopenharmony_ci    {
11038141cc406Sopenharmony_ci      fgets (line, 1024, f);
11039141cc406Sopenharmony_ci      while (!feof (f))
11040141cc406Sopenharmony_ci	{
11041141cc406Sopenharmony_ci	  channel = 0;
11042141cc406Sopenharmony_ci	  if (sscanf (line, "CMD%1d", &channel) != 1)
11043141cc406Sopenharmony_ci	    channel = 0;
11044141cc406Sopenharmony_ci	  switch (channel)
11045141cc406Sopenharmony_ci	    {
11046141cc406Sopenharmony_ci	    case 0:
11047141cc406Sopenharmony_ci	      break;
11048141cc406Sopenharmony_ci	    case 1:
11049141cc406Sopenharmony_ci	      base = lm9811;
11050141cc406Sopenharmony_ci	      max = 8;
11051141cc406Sopenharmony_ci	      break;
11052141cc406Sopenharmony_ci	    case 2:
11053141cc406Sopenharmony_ci	      base = motor;
11054141cc406Sopenharmony_ci	      max = 16;
11055141cc406Sopenharmony_ci	      break;
11056141cc406Sopenharmony_ci	    case 8:
11057141cc406Sopenharmony_ci	      base = ccd;
11058141cc406Sopenharmony_ci	      max = 36;
11059141cc406Sopenharmony_ci	      break;
11060141cc406Sopenharmony_ci	    default:
11061141cc406Sopenharmony_ci	      channel = 0;
11062141cc406Sopenharmony_ci	    }
11063141cc406Sopenharmony_ci	  printf ("CMD%d BEFORE: ", channel);
11064141cc406Sopenharmony_ci	  for (i = 0; i < max; i++)
11065141cc406Sopenharmony_ci	    printf ("%02X ", base[i]);
11066141cc406Sopenharmony_ci	  printf ("\n");
11067141cc406Sopenharmony_ci	  if (channel > 0)
11068141cc406Sopenharmony_ci	    {
11069141cc406Sopenharmony_ci	      ptr = line + 6;
11070141cc406Sopenharmony_ci	      for (i = 0; (i < max) && ((ptr - line) < strlen (line)); i++)
11071141cc406Sopenharmony_ci		{
11072141cc406Sopenharmony_ci		  if (ptr[0] != '-')
11073141cc406Sopenharmony_ci		    {
11074141cc406Sopenharmony_ci		      sscanf (ptr, "%X", base + i);
11075141cc406Sopenharmony_ci		    }
11076141cc406Sopenharmony_ci		  ptr += 3;
11077141cc406Sopenharmony_ci		}
11078141cc406Sopenharmony_ci	    }
11079141cc406Sopenharmony_ci	  printf ("CMD%d AFTER : ", channel);
11080141cc406Sopenharmony_ci	  for (i = 0; i < max; i++)
11081141cc406Sopenharmony_ci	    printf ("%02X ", base[i]);
11082141cc406Sopenharmony_ci	  printf ("\n");
11083141cc406Sopenharmony_ci	  fgets (line, 1024, f);
11084141cc406Sopenharmony_ci	}
11085141cc406Sopenharmony_ci      fclose (f);
11086141cc406Sopenharmony_ci    }
11087141cc406Sopenharmony_ci#endif
11088141cc406Sopenharmony_ci
11089141cc406Sopenharmony_ci  if (DBG_LEVEL >= 64)
11090141cc406Sopenharmony_ci    {
11091141cc406Sopenharmony_ci      bloc2Decode (motor);
11092141cc406Sopenharmony_ci      bloc8Decode (ccd);
11093141cc406Sopenharmony_ci    }
11094141cc406Sopenharmony_ci
11095141cc406Sopenharmony_ci  CMDSYNC (0x00);
11096141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, motor);
11097141cc406Sopenharmony_ci  CMDSETGET (8, len, ccd);
11098141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, lm9811);
11099141cc406Sopenharmony_ci  CMDSYNC (0xC2);
11100141cc406Sopenharmony_ci
11101141cc406Sopenharmony_ci  /* 3 ccd lines + 3 gamma tables + end tag */
11102141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () <= 610)
11103141cc406Sopenharmony_ci    {
11104141cc406Sopenharmony_ci      /* XXX STEF XXX : there is a 4 pixels shift to the right
11105141cc406Sopenharmony_ci       * the first shading correction value applies to the forth
11106141cc406Sopenharmony_ci       * pixel of scan (at 300 dpi), we already shift to the left
11107141cc406Sopenharmony_ci       * when doing shadingCalibration, but now we have to move coeffs
11108141cc406Sopenharmony_ci       * to match x coordinate */
11109141cc406Sopenharmony_ci      delta = x - sanei_umax_pp_getLeft ();
11110141cc406Sopenharmony_ci      if (delta)
11111141cc406Sopenharmony_ci	{
11112141cc406Sopenharmony_ci	  memcpy (calibration,
11113141cc406Sopenharmony_ci		  calibration + delta, (7650 - delta) * sizeof (int));
11114141cc406Sopenharmony_ci	}
11115141cc406Sopenharmony_ci      CMDSET (4, 0x20E4, calibration);
11116141cc406Sopenharmony_ci    }
11117141cc406Sopenharmony_ci  else
11118141cc406Sopenharmony_ci    {
11119141cc406Sopenharmony_ci      CMDSET (4, 0x3EC6, calibration);
11120141cc406Sopenharmony_ci    }
11121141cc406Sopenharmony_ci
11122141cc406Sopenharmony_ci  COMPLETIONWAIT;
11123141cc406Sopenharmony_ci
11124141cc406Sopenharmony_ci  *rbpp = bpp;
11125141cc406Sopenharmony_ci  *rtw = tw;
11126141cc406Sopenharmony_ci  *rth = th;
11127141cc406Sopenharmony_ci
11128141cc406Sopenharmony_ci  free (buffer);
11129141cc406Sopenharmony_ci  return 1;
11130141cc406Sopenharmony_ci}
11131141cc406Sopenharmony_ci
11132141cc406Sopenharmony_ci/*
11133141cc406Sopenharmony_ci * check the scanner model. Return 1220 for
11134141cc406Sopenharmony_ci * a 1220P, or 2000 for a 2000P.
11135141cc406Sopenharmony_ci * and 610 for a 610p
11136141cc406Sopenharmony_ci * values less than 610 are errors
11137141cc406Sopenharmony_ci */
11138141cc406Sopenharmony_ciint
11139141cc406Sopenharmony_cisanei_umax_pp_checkModel (void)
11140141cc406Sopenharmony_ci{
11141141cc406Sopenharmony_ci  int *dest = NULL;
11142141cc406Sopenharmony_ci  int state[16];
11143141cc406Sopenharmony_ci  int err = 0;
11144141cc406Sopenharmony_ci  int i;
11145141cc406Sopenharmony_ci
11146141cc406Sopenharmony_ci  int opsc35[37] =
11147141cc406Sopenharmony_ci    { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80,
11148141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
11149141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00,
11150141cc406Sopenharmony_ci    -1
11151141cc406Sopenharmony_ci  };
11152141cc406Sopenharmony_ci
11153141cc406Sopenharmony_ci  /* if we have already detected a scanner different from */
11154141cc406Sopenharmony_ci  /* default type, no need to check again                 */
11155141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra ())
11156141cc406Sopenharmony_ci    return sanei_umax_pp_getastra ();
11157141cc406Sopenharmony_ci
11158141cc406Sopenharmony_ci  /* get scanner status */
11159141cc406Sopenharmony_ci  CMDGET (0x02, 16, state);
11160141cc406Sopenharmony_ci  CMDSETGET (0x08, 36, opsc35);
11161141cc406Sopenharmony_ci  CMDSYNC (0xC2);
11162141cc406Sopenharmony_ci
11163141cc406Sopenharmony_ci  dest = (int *) malloc (65536 * sizeof (int));
11164141cc406Sopenharmony_ci  if (dest == NULL)
11165141cc406Sopenharmony_ci    {
11166141cc406Sopenharmony_ci      DBG (0, "%s:%d failed to allocate 256 Ko !\n", __FILE__, __LINE__);
11167141cc406Sopenharmony_ci      return 0;
11168141cc406Sopenharmony_ci    }
11169141cc406Sopenharmony_ci
11170141cc406Sopenharmony_ci  /* init some buffer : default calibration data ? */
11171141cc406Sopenharmony_ci  dest[0] = 0x00;
11172141cc406Sopenharmony_ci  dest[1] = 0x00;
11173141cc406Sopenharmony_ci  dest[2] = 0x00;
11174141cc406Sopenharmony_ci  for (i = 0; i < 768; i++)
11175141cc406Sopenharmony_ci    dest[i + 3] = i % 256;
11176141cc406Sopenharmony_ci  dest[768 + 3] = 0xAA;
11177141cc406Sopenharmony_ci  dest[768 + 4] = 0xAA;
11178141cc406Sopenharmony_ci  dest[768 + 5] = -1;
11179141cc406Sopenharmony_ci  CMDSETGET (0x04, 768 + 5, dest);
11180141cc406Sopenharmony_ci
11181141cc406Sopenharmony_ci
11182141cc406Sopenharmony_ci  /* check buffer returned */
11183141cc406Sopenharmony_ci  for (i = 0; i < 768; i++)
11184141cc406Sopenharmony_ci    {
11185141cc406Sopenharmony_ci      if (dest[i + 3] != (i % 256))
11186141cc406Sopenharmony_ci	{
11187141cc406Sopenharmony_ci	  DBG
11188141cc406Sopenharmony_ci	    (0,
11189141cc406Sopenharmony_ci	     "Error data altered: byte %d=0x%02X, should be 0x%02X !    (%s:%d)\n",
11190141cc406Sopenharmony_ci	     i, dest[i + 3], i % 256, __FILE__, __LINE__);
11191141cc406Sopenharmony_ci	  err = 1;
11192141cc406Sopenharmony_ci	}
11193141cc406Sopenharmony_ci    }
11194141cc406Sopenharmony_ci  if (err)
11195141cc406Sopenharmony_ci    return 0;
11196141cc406Sopenharmony_ci
11197141cc406Sopenharmony_ci
11198141cc406Sopenharmony_ci  /* new part of buffer ... */
11199141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
11200141cc406Sopenharmony_ci    {
11201141cc406Sopenharmony_ci      dest[i * 2] = i;
11202141cc406Sopenharmony_ci      dest[i * 2 + 1] = 0x00;
11203141cc406Sopenharmony_ci    }
11204141cc406Sopenharmony_ci  CMDSETGET (0x08, 36, opsc35);
11205141cc406Sopenharmony_ci  CMDSYNC (0xC2);
11206141cc406Sopenharmony_ci  CMDSET (0x04, 512, dest);
11207141cc406Sopenharmony_ci
11208141cc406Sopenharmony_ci  /* another new part ... */
11209141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
11210141cc406Sopenharmony_ci    {
11211141cc406Sopenharmony_ci      dest[i * 2] = i;
11212141cc406Sopenharmony_ci      dest[i * 2 + 1] = 0x04;	/* instead of 0x00 */
11213141cc406Sopenharmony_ci    }
11214141cc406Sopenharmony_ci  opsc35[2] = 0x06;		/* instead of 0x04, write flag ? */
11215141cc406Sopenharmony_ci  CMDSETGET (0x08, 36, opsc35);
11216141cc406Sopenharmony_ci  CMDSYNC (0xC2);
11217141cc406Sopenharmony_ci  CMDSET (0x04, 512, dest);
11218141cc406Sopenharmony_ci
11219141cc406Sopenharmony_ci  opsc35[2] = 0x04;		/* return to initial value, read flag? */
11220141cc406Sopenharmony_ci  CMDSETGET (0x08, 36, opsc35);
11221141cc406Sopenharmony_ci  CMDGET (0x04, 512, dest);
11222141cc406Sopenharmony_ci
11223141cc406Sopenharmony_ci  /* check buffer returned */
11224141cc406Sopenharmony_ci  /* if 0x4 are still 0x04, we got a 1220P, else it is a 2000P */
11225141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
11226141cc406Sopenharmony_ci    {
11227141cc406Sopenharmony_ci      if ((dest[2 * i] != i)
11228141cc406Sopenharmony_ci	  || ((dest[2 * i + 1] != 0x04) && (dest[2 * i + 1] != 0x00)))
11229141cc406Sopenharmony_ci	{
11230141cc406Sopenharmony_ci	  DBG
11231141cc406Sopenharmony_ci	    (0,
11232141cc406Sopenharmony_ci	     "Error data altered: expected %d=(0x%02X,0x04), found (0x%02X,0x%02X) !    (%s:%d)\n",
11233141cc406Sopenharmony_ci	     i, i, dest[i * 2], dest[i * 2 + 1], __FILE__, __LINE__);
11234141cc406Sopenharmony_ci	  err = 0;
11235141cc406Sopenharmony_ci	}
11236141cc406Sopenharmony_ci    }
11237141cc406Sopenharmony_ci
11238141cc406Sopenharmony_ci  /* if buffer unchanged, we have a 1600P, or a 1220P */
11239141cc406Sopenharmony_ci  /* if data has turned into 0, we have a 2000P       */
11240141cc406Sopenharmony_ci  if (dest[1] == 0x00)
11241141cc406Sopenharmony_ci    {
11242141cc406Sopenharmony_ci      sanei_umax_pp_setastra (2000);
11243141cc406Sopenharmony_ci      err = 2000;
11244141cc406Sopenharmony_ci    }
11245141cc406Sopenharmony_ci  else
11246141cc406Sopenharmony_ci    {
11247141cc406Sopenharmony_ci      /* detects 1600  by finding black scans */
11248141cc406Sopenharmony_ci      /* we defaults to 1220 */
11249141cc406Sopenharmony_ci      sanei_umax_pp_setastra (1220);
11250141cc406Sopenharmony_ci      moveToOrigin ();
11251141cc406Sopenharmony_ci      err = sanei_umax_pp_getastra ();
11252141cc406Sopenharmony_ci
11253141cc406Sopenharmony_ci      /* parking */
11254141cc406Sopenharmony_ci      CMDSYNC (0xC2);
11255141cc406Sopenharmony_ci      CMDSYNC (0x00);
11256141cc406Sopenharmony_ci      if (sanei_umax_pp_park () == 0)
11257141cc406Sopenharmony_ci	DBG (0, "Park failed !!! (%s:%d)\n", __FILE__, __LINE__);
11258141cc406Sopenharmony_ci
11259141cc406Sopenharmony_ci      /* poll parking */
11260141cc406Sopenharmony_ci      do
11261141cc406Sopenharmony_ci	{
11262141cc406Sopenharmony_ci	  sleep (1);
11263141cc406Sopenharmony_ci	  CMDSYNC (0x40);
11264141cc406Sopenharmony_ci	}
11265141cc406Sopenharmony_ci      while ((sanei_umax_pp_scannerStatus () & MOTOR_BIT) == 0x00);
11266141cc406Sopenharmony_ci    }
11267141cc406Sopenharmony_ci
11268141cc406Sopenharmony_ci  /* return guessed model number */
11269141cc406Sopenharmony_ci  CMDSYNC (0x00);
11270141cc406Sopenharmony_ci  return err;
11271141cc406Sopenharmony_ci}
11272141cc406Sopenharmony_ci
11273141cc406Sopenharmony_ci
11274141cc406Sopenharmony_ci
11275141cc406Sopenharmony_ci/* sets, resets gamma tables */
11276141cc406Sopenharmony_ci
11277141cc406Sopenharmony_civoid
11278141cc406Sopenharmony_cisanei_umax_pp_gamma (int *red, int *green, int *blue)
11279141cc406Sopenharmony_ci{
11280141cc406Sopenharmony_ci  if (red != NULL)
11281141cc406Sopenharmony_ci    {
11282141cc406Sopenharmony_ci      ggRed = red;
11283141cc406Sopenharmony_ci    }
11284141cc406Sopenharmony_ci  else
11285141cc406Sopenharmony_ci    {
11286141cc406Sopenharmony_ci      ggRed = ggamma;
11287141cc406Sopenharmony_ci    }
11288141cc406Sopenharmony_ci
11289141cc406Sopenharmony_ci  if (green != NULL)
11290141cc406Sopenharmony_ci    {
11291141cc406Sopenharmony_ci      ggGreen = green;
11292141cc406Sopenharmony_ci    }
11293141cc406Sopenharmony_ci  else
11294141cc406Sopenharmony_ci    {
11295141cc406Sopenharmony_ci      ggGreen = ggamma;
11296141cc406Sopenharmony_ci    }
11297141cc406Sopenharmony_ci
11298141cc406Sopenharmony_ci  if (blue != NULL)
11299141cc406Sopenharmony_ci    {
11300141cc406Sopenharmony_ci      ggBlue = blue;
11301141cc406Sopenharmony_ci    }
11302141cc406Sopenharmony_ci  else
11303141cc406Sopenharmony_ci    {
11304141cc406Sopenharmony_ci      ggBlue = ggamma;
11305141cc406Sopenharmony_ci    }
11306141cc406Sopenharmony_ci}
11307141cc406Sopenharmony_ci
11308141cc406Sopenharmony_ci/* initialize scanner by loading default transformation table */
11309141cc406Sopenharmony_ci/* O: failure
11310141cc406Sopenharmony_ci * 1: OK
11311141cc406Sopenharmony_ci */
11312141cc406Sopenharmony_ciint
11313141cc406Sopenharmony_ciloadDefaultTables (void)
11314141cc406Sopenharmony_ci{
11315141cc406Sopenharmony_ci  int cmd01[36] = {
11316141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11317141cc406Sopenharmony_ci    0x00, 0x03, 0xC1, 0x80, 0x60, 0x20, 0x00, 0x00,
11318141cc406Sopenharmony_ci    0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
11319141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11320141cc406Sopenharmony_ci    0x00, 0xF0, 0x13, -1
11321141cc406Sopenharmony_ci  };
11322141cc406Sopenharmony_ci  int opsc35[37] = {
11323141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11324141cc406Sopenharmony_ci    0x00, 0x03, 0xC1, 0x80, 0x00, 0x00, 0x04, 0x00,
11325141cc406Sopenharmony_ci    0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
11326141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68,
11327141cc406Sopenharmony_ci    0xDF, 0x13, 0x1A, 0x00,
11328141cc406Sopenharmony_ci    -1
11329141cc406Sopenharmony_ci  };
11330141cc406Sopenharmony_ci  int i, len, *cmd, err;
11331141cc406Sopenharmony_ci  int buffer[774];
11332141cc406Sopenharmony_ci  int rc = 1;
11333141cc406Sopenharmony_ci
11334141cc406Sopenharmony_ci
11335141cc406Sopenharmony_ci  /* 1600P have a different CCD command block */
11336141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 1600)
11337141cc406Sopenharmony_ci    {
11338141cc406Sopenharmony_ci      opsc35[29] = 0x1A;
11339141cc406Sopenharmony_ci      opsc35[30] = 0xEE;
11340141cc406Sopenharmony_ci    }
11341141cc406Sopenharmony_ci
11342141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () <= 610)
11343141cc406Sopenharmony_ci    {
11344141cc406Sopenharmony_ci      len = 0x22;
11345141cc406Sopenharmony_ci      cmd = cmd01;
11346141cc406Sopenharmony_ci      /* XXX STEF XXX if we send F0, we get 0x10 back */
11347141cc406Sopenharmony_ci      cmd[0x21] = 0x10;
11348141cc406Sopenharmony_ci    }
11349141cc406Sopenharmony_ci  else
11350141cc406Sopenharmony_ci    {
11351141cc406Sopenharmony_ci      len = 0x24;
11352141cc406Sopenharmony_ci      cmd = opsc35;
11353141cc406Sopenharmony_ci    }
11354141cc406Sopenharmony_ci
11355141cc406Sopenharmony_ci  /* set and reread first table */
11356141cc406Sopenharmony_ci  /* since 1660P seems to have another type of CCD
11357141cc406Sopenharmony_ci   * this table is not sent/needed
11358141cc406Sopenharmony_ci   */
11359141cc406Sopenharmony_ci  err = 0;
11360141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () != 1600)
11361141cc406Sopenharmony_ci    {
11362141cc406Sopenharmony_ci      CMDSETGET (8, len, cmd);
11363141cc406Sopenharmony_ci      CMDSYNC (0xC2);
11364141cc406Sopenharmony_ci      buffer[0] = 0x00;
11365141cc406Sopenharmony_ci      buffer[1] = 0x00;
11366141cc406Sopenharmony_ci      buffer[2] = 0x00;
11367141cc406Sopenharmony_ci      for (i = 0; i < 768; i++)
11368141cc406Sopenharmony_ci	buffer[i + 3] = i % 256;
11369141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () <= 610)
11370141cc406Sopenharmony_ci	{
11371141cc406Sopenharmony_ci	  buffer[768 + 3] = 0xFF;
11372141cc406Sopenharmony_ci	  buffer[768 + 4] = 0xFF;
11373141cc406Sopenharmony_ci	}
11374141cc406Sopenharmony_ci      else
11375141cc406Sopenharmony_ci	{
11376141cc406Sopenharmony_ci	  buffer[768 + 3] = 0xAA;
11377141cc406Sopenharmony_ci	  buffer[768 + 4] = 0xAA;
11378141cc406Sopenharmony_ci	}
11379141cc406Sopenharmony_ci      buffer[768 + 5] = -1;
11380141cc406Sopenharmony_ci      CMDSETGET (4, 0x305, buffer);
11381141cc406Sopenharmony_ci
11382141cc406Sopenharmony_ci
11383141cc406Sopenharmony_ci      /* check buffer returned */
11384141cc406Sopenharmony_ci      for (i = 0; i < 768; i++)
11385141cc406Sopenharmony_ci	{
11386141cc406Sopenharmony_ci	  if (buffer[i + 3] != (i % 256))
11387141cc406Sopenharmony_ci	    {
11388141cc406Sopenharmony_ci	      DBG
11389141cc406Sopenharmony_ci		(0,
11390141cc406Sopenharmony_ci		 "Error data altered: byte %d=0x%02X, should be 0x%02X !    (%s:%d)\n",
11391141cc406Sopenharmony_ci		 i, buffer[i + 3], i % 256, __FILE__, __LINE__);
11392141cc406Sopenharmony_ci	      err = 1;
11393141cc406Sopenharmony_ci	    }
11394141cc406Sopenharmony_ci	}
11395141cc406Sopenharmony_ci      if (err)
11396141cc406Sopenharmony_ci	return 0;
11397141cc406Sopenharmony_ci    }
11398141cc406Sopenharmony_ci
11399141cc406Sopenharmony_ci  /* second table ... */
11400141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
11401141cc406Sopenharmony_ci    {
11402141cc406Sopenharmony_ci      buffer[i * 2] = i;
11403141cc406Sopenharmony_ci      buffer[i * 2 + 1] = 0;
11404141cc406Sopenharmony_ci    }
11405141cc406Sopenharmony_ci  CMDSETGET (8, len, cmd);
11406141cc406Sopenharmony_ci  CMDSYNC (0xC2);
11407141cc406Sopenharmony_ci  CMDSET (4, 0x200, buffer);
11408141cc406Sopenharmony_ci
11409141cc406Sopenharmony_ci  /* third table ... */
11410141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () <= 610)
11411141cc406Sopenharmony_ci    {
11412141cc406Sopenharmony_ci      for (i = 0; i < 256; i++)
11413141cc406Sopenharmony_ci	{
11414141cc406Sopenharmony_ci	  buffer[i * 2] = i;
11415141cc406Sopenharmony_ci	  buffer[i * 2 + 1] = 0x01;	/* instead of 0x00 */
11416141cc406Sopenharmony_ci	}
11417141cc406Sopenharmony_ci    }
11418141cc406Sopenharmony_ci  else
11419141cc406Sopenharmony_ci    {
11420141cc406Sopenharmony_ci      for (i = 0; i < 256; i++)
11421141cc406Sopenharmony_ci	{
11422141cc406Sopenharmony_ci	  buffer[i * 2] = i;
11423141cc406Sopenharmony_ci	  buffer[i * 2 + 1] = 0x04;	/* instead of 0x00 */
11424141cc406Sopenharmony_ci	}
11425141cc406Sopenharmony_ci    }
11426141cc406Sopenharmony_ci  opsc35[2] = 0x06;
11427141cc406Sopenharmony_ci  cmd01[1] = 0x80;
11428141cc406Sopenharmony_ci  CMDSETGET (8, len, cmd);
11429141cc406Sopenharmony_ci  CMDSYNC (0xC2);
11430141cc406Sopenharmony_ci  CMDSET (4, 0x200, buffer);
11431141cc406Sopenharmony_ci
11432141cc406Sopenharmony_ci  opsc35[2] = 0x04;
11433141cc406Sopenharmony_ci  cmd01[1] = 0x00;
11434141cc406Sopenharmony_ci  CMDSETGET (8, len, cmd);
11435141cc406Sopenharmony_ci  CMDGET (4, 0x200, buffer);
11436141cc406Sopenharmony_ci  /* check buffer returned */
11437141cc406Sopenharmony_ci  /* if 0x4 are still 0x0 (hum..), we got a 1220P, else it is a 2000P */
11438141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
11439141cc406Sopenharmony_ci    {
11440141cc406Sopenharmony_ci      if ((buffer[2 * i] != i)
11441141cc406Sopenharmony_ci	  || ((buffer[2 * i + 1] != 0x04) && (buffer[2 * i + 1] != 0x01)
11442141cc406Sopenharmony_ci	      && (buffer[2 * i + 1] != 0x00)))
11443141cc406Sopenharmony_ci	{
11444141cc406Sopenharmony_ci	  DBG
11445141cc406Sopenharmony_ci	    (0,
11446141cc406Sopenharmony_ci	     "Error data altered: expected %d=(0x%02X,0x04), found (0x%02X,0x%02X) !    (%s:%d)\n",
11447141cc406Sopenharmony_ci	     i, i, buffer[i * 2], buffer[i * 2 + 1], __FILE__, __LINE__);
11448141cc406Sopenharmony_ci	  err = 1;
11449141cc406Sopenharmony_ci	}
11450141cc406Sopenharmony_ci    }
11451141cc406Sopenharmony_ci  if (err)
11452141cc406Sopenharmony_ci    return 0;
11453141cc406Sopenharmony_ci
11454141cc406Sopenharmony_ci  return rc;
11455141cc406Sopenharmony_ci}
11456141cc406Sopenharmony_ci
11457141cc406Sopenharmony_ci/* inquire scanner status
11458141cc406Sopenharmony_ci * O: failure
11459141cc406Sopenharmony_ci * 1: OK
11460141cc406Sopenharmony_ci * 2: first scanner init, needs re-homing
11461141cc406Sopenharmony_ci */
11462141cc406Sopenharmony_ciint
11463141cc406Sopenharmony_ciinquire (void)
11464141cc406Sopenharmony_ci{
11465141cc406Sopenharmony_ci  int cmd01[36] = {
11466141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11467141cc406Sopenharmony_ci    0x00, 0x03, 0xC1, 0x80, 0x60, 0x20, 0x00, 0x00,
11468141cc406Sopenharmony_ci    0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00,
11469141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11470141cc406Sopenharmony_ci    0x00, 0xF0, 0x1B, -1
11471141cc406Sopenharmony_ci  };
11472141cc406Sopenharmony_ci  int buffer[37];
11473141cc406Sopenharmony_ci  int rc = 1, first, i;
11474141cc406Sopenharmony_ci  char str[106];
11475141cc406Sopenharmony_ci
11476141cc406Sopenharmony_ci
11477141cc406Sopenharmony_ci  /* inquiry: ask for RAM, CCD, ... */
11478141cc406Sopenharmony_ci  CMDSET (8, 0x23, cmd01);
11479141cc406Sopenharmony_ci  CMDGET (8, 0x23, buffer);
11480141cc406Sopenharmony_ci
11481141cc406Sopenharmony_ci  if (DBG_LEVEL > 8)
11482141cc406Sopenharmony_ci    {
11483141cc406Sopenharmony_ci      for (i = 0; i < 35; i++)
11484141cc406Sopenharmony_ci	sprintf (str + 3 * i, "%02X ", buffer[i]);
11485141cc406Sopenharmony_ci      str[105] = 0x00;
11486141cc406Sopenharmony_ci      DBG (8, "SCANNER INFORMATION=%s\n", str);
11487141cc406Sopenharmony_ci    }
11488141cc406Sopenharmony_ci
11489141cc406Sopenharmony_ci  /* get state */
11490141cc406Sopenharmony_ci  CMDGET (2, 0x10, buffer);
11491141cc406Sopenharmony_ci  first = 1;
11492141cc406Sopenharmony_ci  for (i = 0; i < 14; i++)
11493141cc406Sopenharmony_ci    {
11494141cc406Sopenharmony_ci      if (buffer[i] != 0)
11495141cc406Sopenharmony_ci	first = 0;
11496141cc406Sopenharmony_ci    }
11497141cc406Sopenharmony_ci  if (buffer[15] != 0)
11498141cc406Sopenharmony_ci    first = 0;
11499141cc406Sopenharmony_ci  if (first)
11500141cc406Sopenharmony_ci    rc = 2;
11501141cc406Sopenharmony_ci
11502141cc406Sopenharmony_ci  if (DBG_LEVEL > 8)
11503141cc406Sopenharmony_ci    {
11504141cc406Sopenharmony_ci      for (i = 0; i < 16; i++)
11505141cc406Sopenharmony_ci	sprintf (str + 3 * i, "%02X ", buffer[i]);
11506141cc406Sopenharmony_ci      str[48] = 0x00;
11507141cc406Sopenharmony_ci      DBG (8, "SCANNER STATE=%s\n", str);
11508141cc406Sopenharmony_ci    }
11509141cc406Sopenharmony_ci
11510141cc406Sopenharmony_ci  return rc;
11511141cc406Sopenharmony_ci}
11512141cc406Sopenharmony_ci
11513141cc406Sopenharmony_ci/*
11514141cc406Sopenharmony_ci * computes DC offset to have black pixel really black out of
11515141cc406Sopenharmony_ci * CCD ie black gives 0
11516141cc406Sopenharmony_ci * 1220P implements the method described in LM9811 datasheet
11517141cc406Sopenharmony_ci * returns 1 and DC offsets in the corresponding vars on success .
11518141cc406Sopenharmony_ci * On failure, returns 0.
11519141cc406Sopenharmony_ci */
11520141cc406Sopenharmony_cistatic int
11521141cc406Sopenharmony_cioffsetCalibration1220p (int color, int *offRed, int *offGreen, int *offBlue)
11522141cc406Sopenharmony_ci{
11523141cc406Sopenharmony_ci  unsigned char buffer[5300];
11524141cc406Sopenharmony_ci  int i, val;
11525141cc406Sopenharmony_ci  int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 };
11526141cc406Sopenharmony_ci  int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 };
11527141cc406Sopenharmony_ci  int opsc38[37] =
11528141cc406Sopenharmony_ci    { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
11529141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x6E, 0x18, 0x10, 0x03, 0x06, 0x00, 0x00, 0x00,
11530141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00,
11531141cc406Sopenharmony_ci    -1
11532141cc406Sopenharmony_ci  };
11533141cc406Sopenharmony_ci  int opsc48[17] =
11534141cc406Sopenharmony_ci    { 0x09, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0x00, 0x00,
11535141cc406Sopenharmony_ci    0x00, 0x40, 0xA4, 0x00, -1
11536141cc406Sopenharmony_ci  };
11537141cc406Sopenharmony_ci  float low, high;
11538141cc406Sopenharmony_ci  DBG (16, "entering offsetCalibration1220p() ... (%s:%d)\n", __FILE__,
11539141cc406Sopenharmony_ci       __LINE__);
11540141cc406Sopenharmony_ci
11541141cc406Sopenharmony_ci  /* really dirty hack: something is buggy in BW mode   */
11542141cc406Sopenharmony_ci  /* we override mode with color until the bug is found */
11543141cc406Sopenharmony_ci  /* color = RGB_MODE; */
11544141cc406Sopenharmony_ci
11545141cc406Sopenharmony_ci  /* 1600P have a different CCD command block */
11546141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 1600)
11547141cc406Sopenharmony_ci    {
11548141cc406Sopenharmony_ci      opsc04[0] = 0x19;
11549141cc406Sopenharmony_ci      opsc04[1] = 0xD5;
11550141cc406Sopenharmony_ci      opsc04[4] = 0x1B;
11551141cc406Sopenharmony_ci      opsc04[7] = 0x20;
11552141cc406Sopenharmony_ci
11553141cc406Sopenharmony_ci      opsc48[8] = 0x2B;
11554141cc406Sopenharmony_ci      opsc48[11] = 0x20;
11555141cc406Sopenharmony_ci      opsc48[12] = 0x08;
11556141cc406Sopenharmony_ci      opsc48[13] = 0x42;
11557141cc406Sopenharmony_ci    }
11558141cc406Sopenharmony_ci
11559141cc406Sopenharmony_ci  /* offset calibration, scan 24 bytes of black in each color */
11560141cc406Sopenharmony_ci  /* component see section 5.1 of LM9811 datasheet */
11561141cc406Sopenharmony_ci  if (color >= RGB_MODE)
11562141cc406Sopenharmony_ci    {
11563141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, opsc48);
11564141cc406Sopenharmony_ci      CMDSETGET (8, 0x24, opsc38);
11565141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, opsc04);	/* scan std, no 'enhancing' */
11566141cc406Sopenharmony_ci      CMDSYNC (0xC2);
11567141cc406Sopenharmony_ci      if (sanei_umax_pp_scannerStatus () & 0x80)
11568141cc406Sopenharmony_ci	{
11569141cc406Sopenharmony_ci	  CMDSYNC (0x00);
11570141cc406Sopenharmony_ci	}
11571141cc406Sopenharmony_ci      CMDSETGET (4, 0x08, commit);	/* commit ? */
11572141cc406Sopenharmony_ci      COMPLETIONWAIT;
11573141cc406Sopenharmony_ci      CMDGETBUF (4, 0x18, buffer);
11574141cc406Sopenharmony_ci      if (DBG_LEVEL >= 128)
11575141cc406Sopenharmony_ci	Dump (0x18, buffer, NULL);
11576141cc406Sopenharmony_ci      val = 0;
11577141cc406Sopenharmony_ci      for (i = 0; i < 24; i++)
11578141cc406Sopenharmony_ci	val += buffer[i];
11579141cc406Sopenharmony_ci      low = (float) val / i;	/* Vadc1 */
11580141cc406Sopenharmony_ci
11581141cc406Sopenharmony_ci
11582141cc406Sopenharmony_ci      CMDSYNC (0x00);
11583141cc406Sopenharmony_ci      opsc04[7] = opsc04[7] | 0x10;	/* enhanced ? */
11584141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, opsc04);
11585141cc406Sopenharmony_ci      COMPLETIONWAIT;
11586141cc406Sopenharmony_ci      CMDGETBUF (4, 0x18, buffer);
11587141cc406Sopenharmony_ci      val = 0;
11588141cc406Sopenharmony_ci      for (i = 0; i < 24; i++)
11589141cc406Sopenharmony_ci	val += buffer[i];
11590141cc406Sopenharmony_ci      high = (float) val / i;	/* Vadc2 */
11591141cc406Sopenharmony_ci      if (DBG_LEVEL >= 128)
11592141cc406Sopenharmony_ci	Dump (0x18, buffer, NULL);
11593141cc406Sopenharmony_ci      *offRed = 15.0 - ((high - low) * 2);
11594141cc406Sopenharmony_ci
11595141cc406Sopenharmony_ci      /* block that repeats */
11596141cc406Sopenharmony_ci      /* must be monochrome since hscan=1 */
11597141cc406Sopenharmony_ci      opsc48[0] = 0x01;
11598141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () == 1600)
11599141cc406Sopenharmony_ci	{
11600141cc406Sopenharmony_ci	  opsc48[12] = 0x0C;
11601141cc406Sopenharmony_ci	  opsc48[13] = 0x82;
11602141cc406Sopenharmony_ci	}
11603141cc406Sopenharmony_ci      else
11604141cc406Sopenharmony_ci	{
11605141cc406Sopenharmony_ci	  opsc48[12] = 0x04;
11606141cc406Sopenharmony_ci	  opsc48[13] = 0x80;
11607141cc406Sopenharmony_ci	}
11608141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, opsc48);
11609141cc406Sopenharmony_ci      CMDSETGET (8, 0x24, opsc38);
11610141cc406Sopenharmony_ci      opsc04[7] = opsc04[7] & 0x20;
11611141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, opsc04);
11612141cc406Sopenharmony_ci      CMDSYNC (0xC2);
11613141cc406Sopenharmony_ci      if (sanei_umax_pp_scannerStatus () & 0x80)
11614141cc406Sopenharmony_ci	{
11615141cc406Sopenharmony_ci	  CMDSYNC (0x00);
11616141cc406Sopenharmony_ci	}
11617141cc406Sopenharmony_ci      CMDSETGET (4, 0x08, commit);
11618141cc406Sopenharmony_ci      COMPLETIONWAIT;
11619141cc406Sopenharmony_ci      CMDGETBUF (4, 0x18, buffer);
11620141cc406Sopenharmony_ci      if (DBG_LEVEL >= 128)
11621141cc406Sopenharmony_ci	Dump (0x18, buffer, NULL);
11622141cc406Sopenharmony_ci      val = 0;
11623141cc406Sopenharmony_ci      for (i = 0; i < 24; i++)
11624141cc406Sopenharmony_ci	val += buffer[i];
11625141cc406Sopenharmony_ci      low = (float) val / i;
11626141cc406Sopenharmony_ci
11627141cc406Sopenharmony_ci      CMDSYNC (0x00);
11628141cc406Sopenharmony_ci      opsc04[7] = opsc04[7] | 0x10;	/* gain ? */
11629141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, opsc04);
11630141cc406Sopenharmony_ci      COMPLETIONWAIT;
11631141cc406Sopenharmony_ci      CMDGETBUF (4, 0x18, buffer);
11632141cc406Sopenharmony_ci      if (DBG_LEVEL >= 128)
11633141cc406Sopenharmony_ci	Dump (0x18, buffer, NULL);
11634141cc406Sopenharmony_ci      val = 0;
11635141cc406Sopenharmony_ci      for (i = 0; i < 24; i++)
11636141cc406Sopenharmony_ci	val += buffer[i];
11637141cc406Sopenharmony_ci      high = (float) val / i;
11638141cc406Sopenharmony_ci
11639141cc406Sopenharmony_ci      *offBlue = 15.0 - ((high - low) * 2);
11640141cc406Sopenharmony_ci    }
11641141cc406Sopenharmony_ci
11642141cc406Sopenharmony_ci  /* block that repeats */
11643141cc406Sopenharmony_ci  if (color < RGB_MODE)
11644141cc406Sopenharmony_ci    {
11645141cc406Sopenharmony_ci      opsc48[0] = 0x05;		/* B&H height is 5 */
11646141cc406Sopenharmony_ci      opsc48[13] = 0xC0;	/* B&W mode */
11647141cc406Sopenharmony_ci    }
11648141cc406Sopenharmony_ci  else
11649141cc406Sopenharmony_ci    {
11650141cc406Sopenharmony_ci      opsc48[0] = 0x05;		/* color height is 5 (+4 ?) */
11651141cc406Sopenharmony_ci      opsc48[13] = 0xC1;	/* some strange mode ? */
11652141cc406Sopenharmony_ci    }
11653141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 1600)
11654141cc406Sopenharmony_ci    opsc48[13] = opsc48[13] | 0x02;
11655141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, opsc48);
11656141cc406Sopenharmony_ci  CMDSETGET (8, 0x24, opsc38);
11657141cc406Sopenharmony_ci  opsc04[7] = opsc04[7] & 0x20;
11658141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, opsc04);
11659141cc406Sopenharmony_ci  CMDSYNC (0xC2);
11660141cc406Sopenharmony_ci  if (sanei_umax_pp_scannerStatus () & 0x80)
11661141cc406Sopenharmony_ci    {
11662141cc406Sopenharmony_ci      CMDSYNC (0x00);
11663141cc406Sopenharmony_ci    }
11664141cc406Sopenharmony_ci  CMDSETGET (4, 0x08, commit);
11665141cc406Sopenharmony_ci  COMPLETIONWAIT;
11666141cc406Sopenharmony_ci  CMDGETBUF (4, 0x18, buffer);
11667141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
11668141cc406Sopenharmony_ci    Dump (0x18, buffer, NULL);
11669141cc406Sopenharmony_ci  val = 0;
11670141cc406Sopenharmony_ci  for (i = 0; i < 24; i++)
11671141cc406Sopenharmony_ci    val += buffer[i];
11672141cc406Sopenharmony_ci  low = (float) val / i;
11673141cc406Sopenharmony_ci
11674141cc406Sopenharmony_ci  CMDSYNC (0x00);
11675141cc406Sopenharmony_ci  opsc04[7] = opsc04[7] | 0x10;
11676141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, opsc04);
11677141cc406Sopenharmony_ci  COMPLETIONWAIT;
11678141cc406Sopenharmony_ci  CMDGETBUF (4, 0x18, buffer);
11679141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
11680141cc406Sopenharmony_ci    Dump (0x18, buffer, NULL);
11681141cc406Sopenharmony_ci  val = 0;
11682141cc406Sopenharmony_ci  for (i = 0; i < 24; i++)
11683141cc406Sopenharmony_ci    val += buffer[i];
11684141cc406Sopenharmony_ci  high = (float) val / i;
11685141cc406Sopenharmony_ci
11686141cc406Sopenharmony_ci  *offGreen = 15.0 - ((high - low) * 2);
11687141cc406Sopenharmony_ci
11688141cc406Sopenharmony_ci  /*DBG (1, "STEF: offsets(RED,GREEN,BLUE=(%d,%d,%d)\n", *offRed, *offGreen,
11689141cc406Sopenharmony_ci   *offBlue);*/
11690141cc406Sopenharmony_ci  DBG (16, "offsetCalibration1220p() done ...\n");
11691141cc406Sopenharmony_ci  return 1;
11692141cc406Sopenharmony_ci}
11693141cc406Sopenharmony_ci
11694141cc406Sopenharmony_ci/*
11695141cc406Sopenharmony_ci * computes DC offset to have black pixel really black out of
11696141cc406Sopenharmony_ci * CCD ie black gives 0
11697141cc406Sopenharmony_ci * 610P doesn't implement method described in LM9811 datasheet
11698141cc406Sopenharmony_ci * but scan a black line with decreasing offsets until the
11699141cc406Sopenharmony_ci * scanned data reach a 'good black level'.
11700141cc406Sopenharmony_ci * returns 1 and DC offsets in the corresponding vars on success .
11701141cc406Sopenharmony_ci * On failure, returns 0.
11702141cc406Sopenharmony_ci */
11703141cc406Sopenharmony_cistatic int
11704141cc406Sopenharmony_cioffsetCalibration610p (int color, int *offRed, int *offGreen, int *offBlue)
11705141cc406Sopenharmony_ci{
11706141cc406Sopenharmony_ci  int motor[17] = {
11707141cc406Sopenharmony_ci    0x11, 0x00, 0x00, 0x70, 0x00, 0x00, 0xC0, 0x2F,
11708141cc406Sopenharmony_ci    0x17, 0x00, 0x00, 0xF0, 0x7D, 0x5F, 0xA4, 0x00,
11709141cc406Sopenharmony_ci    -1
11710141cc406Sopenharmony_ci  };
11711141cc406Sopenharmony_ci
11712141cc406Sopenharmony_ci  int ccd[37] = {
11713141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11714141cc406Sopenharmony_ci    0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00,
11715141cc406Sopenharmony_ci    0x76, 0x12, 0xB0, 0x03, 0x06, 0x00, 0x00, 0x00,
11716141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
11717141cc406Sopenharmony_ci    0xDF, 0x13, 0x1A, 0x00,
11718141cc406Sopenharmony_ci    -1
11719141cc406Sopenharmony_ci  };
11720141cc406Sopenharmony_ci
11721141cc406Sopenharmony_ci  int lm9811[9] = {
11722141cc406Sopenharmony_ci    0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x40, 0xF0,
11723141cc406Sopenharmony_ci    -1
11724141cc406Sopenharmony_ci  };
11725141cc406Sopenharmony_ci
11726141cc406Sopenharmony_ci  int commit[9] = {
11727141cc406Sopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
11728141cc406Sopenharmony_ci    -1
11729141cc406Sopenharmony_ci  };
11730141cc406Sopenharmony_ci
11731141cc406Sopenharmony_ci
11732141cc406Sopenharmony_ci  int offset;
11733141cc406Sopenharmony_ci  int level;
11734141cc406Sopenharmony_ci  unsigned char data[40];
11735141cc406Sopenharmony_ci  int i;
11736141cc406Sopenharmony_ci  int len;
11737141cc406Sopenharmony_ci  int w;
11738141cc406Sopenharmony_ci
11739141cc406Sopenharmony_ci  DBG (16, "entering offsetCalibration610P() ... (%s:%d)\n", __FILE__,
11740141cc406Sopenharmony_ci       __LINE__);
11741141cc406Sopenharmony_ci
11742141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () < 1220)
11743141cc406Sopenharmony_ci    {
11744141cc406Sopenharmony_ci      len = 0x22;
11745141cc406Sopenharmony_ci      w = 40;
11746141cc406Sopenharmony_ci    }
11747141cc406Sopenharmony_ci  else
11748141cc406Sopenharmony_ci    {
11749141cc406Sopenharmony_ci      len = 0x24;
11750141cc406Sopenharmony_ci      w = 40;
11751141cc406Sopenharmony_ci    }
11752141cc406Sopenharmony_ci
11753141cc406Sopenharmony_ci  *offRed = 0;
11754141cc406Sopenharmony_ci  *offGreen = 0;
11755141cc406Sopenharmony_ci  *offBlue = 0;
11756141cc406Sopenharmony_ci
11757141cc406Sopenharmony_ci  /* first color channel: used both in color and b&w modes */
11758141cc406Sopenharmony_ci  /* offset to the max */
11759141cc406Sopenharmony_ci  /* supposed to be green component */
11760141cc406Sopenharmony_ci  offset = 0x10;
11761141cc406Sopenharmony_ci  do
11762141cc406Sopenharmony_ci    {
11763141cc406Sopenharmony_ci      offset--;
11764141cc406Sopenharmony_ci
11765141cc406Sopenharmony_ci      /* 7D: 0111 1101 */
11766141cc406Sopenharmony_ci      /* sets for the current offset */
11767141cc406Sopenharmony_ci      motor[12] = (offset << 2) | 0x40 | 0x01;
11768141cc406Sopenharmony_ci      lm9811[7] = offset << 4;
11769141cc406Sopenharmony_ci
11770141cc406Sopenharmony_ci      /* sends commands */
11771141cc406Sopenharmony_ci      CMDSYNC (0x00);
11772141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, motor);
11773141cc406Sopenharmony_ci      CMDSETGET (8, len, ccd);
11774141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, lm9811);
11775141cc406Sopenharmony_ci      CMDSYNC (0xC2);
11776141cc406Sopenharmony_ci      CMDSETGET (4, 0x08, commit);
11777141cc406Sopenharmony_ci      COMPLETIONWAIT;
11778141cc406Sopenharmony_ci      CMDGETBUF (4, w, data);
11779141cc406Sopenharmony_ci      if (DBG_LEVEL > 128)
11780141cc406Sopenharmony_ci	{
11781141cc406Sopenharmony_ci	  DumpNB (w, 1, data, NULL);
11782141cc406Sopenharmony_ci	}
11783141cc406Sopenharmony_ci      level = 0;
11784141cc406Sopenharmony_ci      for (i = 0; i < w; i++)
11785141cc406Sopenharmony_ci	level += data[i];
11786141cc406Sopenharmony_ci    }
11787141cc406Sopenharmony_ci  /* loop while average >0.5 */
11788141cc406Sopenharmony_ci  while ((offset > 0) && ((level * 2) / w > 1));
11789141cc406Sopenharmony_ci  *offGreen = offset;
11790141cc406Sopenharmony_ci
11791141cc406Sopenharmony_ci  /* offset calibration for the two other channels when in color */
11792141cc406Sopenharmony_ci  if (color >= RGB_MODE)
11793141cc406Sopenharmony_ci    {
11794141cc406Sopenharmony_ci      motor[0] = 0x01;
11795141cc406Sopenharmony_ci
11796141cc406Sopenharmony_ci      offset = 0x10;
11797141cc406Sopenharmony_ci      do
11798141cc406Sopenharmony_ci	{
11799141cc406Sopenharmony_ci	  offset--;
11800141cc406Sopenharmony_ci
11801141cc406Sopenharmony_ci	  /* sets for the current offset */
11802141cc406Sopenharmony_ci	  motor[13] = 0x90 | offset;
11803141cc406Sopenharmony_ci	  lm9811[7] = offset << 4;
11804141cc406Sopenharmony_ci
11805141cc406Sopenharmony_ci	  /* sends commands */
11806141cc406Sopenharmony_ci	  CMDSYNC (0x00);
11807141cc406Sopenharmony_ci	  CMDSETGET (2, 0x10, motor);
11808141cc406Sopenharmony_ci	  CMDSETGET (8, len, ccd);
11809141cc406Sopenharmony_ci	  CMDSETGET (1, 0x08, lm9811);
11810141cc406Sopenharmony_ci	  CMDSYNC (0xC2);
11811141cc406Sopenharmony_ci	  CMDSETGET (4, 0x08, commit);
11812141cc406Sopenharmony_ci	  COMPLETIONWAIT;
11813141cc406Sopenharmony_ci	  CMDGETBUF (4, w, data);
11814141cc406Sopenharmony_ci	  if (DBG_LEVEL > 128)
11815141cc406Sopenharmony_ci	    {
11816141cc406Sopenharmony_ci	      DumpNB (w, 1, data, NULL);
11817141cc406Sopenharmony_ci	    }
11818141cc406Sopenharmony_ci	  level = 0;
11819141cc406Sopenharmony_ci	  for (i = 0; i < w; i++)
11820141cc406Sopenharmony_ci	    level += data[i];
11821141cc406Sopenharmony_ci	}
11822141cc406Sopenharmony_ci      /* loop while average >0.5 */
11823141cc406Sopenharmony_ci      while ((offset > 0) && ((level * 2) / w > 1));
11824141cc406Sopenharmony_ci      *offBlue = offset;
11825141cc406Sopenharmony_ci
11826141cc406Sopenharmony_ci      /* last color component */
11827141cc406Sopenharmony_ci      motor[0] = 0x09;
11828141cc406Sopenharmony_ci      ccd[13] = 0xD0 | (ccd[13] & 0x0F);
11829141cc406Sopenharmony_ci
11830141cc406Sopenharmony_ci      offset = 0x10;
11831141cc406Sopenharmony_ci      do
11832141cc406Sopenharmony_ci	{
11833141cc406Sopenharmony_ci	  offset--;
11834141cc406Sopenharmony_ci
11835141cc406Sopenharmony_ci	  /* sets for the current offset */
11836141cc406Sopenharmony_ci	  motor[11] = offset << 4;
11837141cc406Sopenharmony_ci	  lm9811[7] = offset << 4;
11838141cc406Sopenharmony_ci
11839141cc406Sopenharmony_ci	  /* sends commands */
11840141cc406Sopenharmony_ci	  CMDSYNC (0x00);
11841141cc406Sopenharmony_ci	  CMDSETGET (2, 0x10, motor);
11842141cc406Sopenharmony_ci	  CMDSETGET (8, len, ccd);
11843141cc406Sopenharmony_ci	  CMDSETGET (1, 0x08, lm9811);
11844141cc406Sopenharmony_ci	  CMDSYNC (0xC2);
11845141cc406Sopenharmony_ci	  CMDSYNC (0x00);
11846141cc406Sopenharmony_ci	  CMDSETGET (4, 0x08, commit);
11847141cc406Sopenharmony_ci
11848141cc406Sopenharmony_ci	  COMPLETIONWAIT;
11849141cc406Sopenharmony_ci	  CMDGETBUF (4, w, data);
11850141cc406Sopenharmony_ci	  if (gMode == UMAX_PP_PARPORT_EPP)
11851141cc406Sopenharmony_ci	    {
11852141cc406Sopenharmony_ci	      CMDSYNC (0x00);
11853141cc406Sopenharmony_ci	    }
11854141cc406Sopenharmony_ci	  if (DBG_LEVEL > 128)
11855141cc406Sopenharmony_ci	    {
11856141cc406Sopenharmony_ci	      DumpNB (w, 1, data, NULL);
11857141cc406Sopenharmony_ci	    }
11858141cc406Sopenharmony_ci	  level = 0;
11859141cc406Sopenharmony_ci	  for (i = 0; i < w; i++)
11860141cc406Sopenharmony_ci	    level += data[i];
11861141cc406Sopenharmony_ci	}
11862141cc406Sopenharmony_ci      /* loop while average >0.5 */
11863141cc406Sopenharmony_ci      while ((offset > 0) && ((level * 2) / w > 1));
11864141cc406Sopenharmony_ci      *offRed = offset;
11865141cc406Sopenharmony_ci    }
11866141cc406Sopenharmony_ci  else
11867141cc406Sopenharmony_ci    {
11868141cc406Sopenharmony_ci      *offRed = 0x0F;
11869141cc406Sopenharmony_ci      *offBlue = 0x0F;
11870141cc406Sopenharmony_ci    }
11871141cc406Sopenharmony_ci
11872141cc406Sopenharmony_ci  return 1;
11873141cc406Sopenharmony_ci}
11874141cc406Sopenharmony_ci
11875141cc406Sopenharmony_ci/*
11876141cc406Sopenharmony_ci * generic offset calibration function
11877141cc406Sopenharmony_ci */
11878141cc406Sopenharmony_cistatic int
11879141cc406Sopenharmony_cioffsetCalibration (int color, int *dcRed, int *dcGreen, int *dcBlue)
11880141cc406Sopenharmony_ci{
11881141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () <= 610)
11882141cc406Sopenharmony_ci    {
11883141cc406Sopenharmony_ci      if (offsetCalibration610p (color, dcRed, dcGreen, dcBlue) == 0)
11884141cc406Sopenharmony_ci	{
11885141cc406Sopenharmony_ci	  DBG (0, "offsetCalibration610p failed !!! (%s:%d)\n", __FILE__,
11886141cc406Sopenharmony_ci	       __LINE__);
11887141cc406Sopenharmony_ci	  return 0;
11888141cc406Sopenharmony_ci	}
11889141cc406Sopenharmony_ci      DBG (16, "offsetCalibration610p(%d=>%d,%d,%d) passed ... (%s:%d)\n",
11890141cc406Sopenharmony_ci	   color, *dcRed, *dcGreen, *dcBlue, __FILE__, __LINE__);
11891141cc406Sopenharmony_ci    }
11892141cc406Sopenharmony_ci  else
11893141cc406Sopenharmony_ci    {
11894141cc406Sopenharmony_ci      if (offsetCalibration1220p (color, dcRed, dcGreen, dcBlue) == 0)
11895141cc406Sopenharmony_ci	{
11896141cc406Sopenharmony_ci	  DBG (0, "offsetCalibration1220p failed !!! (%s:%d)\n", __FILE__,
11897141cc406Sopenharmony_ci	       __LINE__);
11898141cc406Sopenharmony_ci	  return 0;
11899141cc406Sopenharmony_ci	}
11900141cc406Sopenharmony_ci      DBG (16, "offsetCalibration1220p(%d=>%d,%d,%d) passed ... (%s:%d)\n",
11901141cc406Sopenharmony_ci	   color, *dcRed, *dcGreen, *dcBlue, __FILE__, __LINE__);
11902141cc406Sopenharmony_ci    }
11903141cc406Sopenharmony_ci  return 1;
11904141cc406Sopenharmony_ci}
11905141cc406Sopenharmony_ci
11906141cc406Sopenharmony_ci/*
11907141cc406Sopenharmony_ci * computes Video Gain Amplifier : LM9811 can corrects up to 3dB of
11908141cc406Sopenharmony_ci * light variation. So we must adjust VGA so that dynamic range is
11909141cc406Sopenharmony_ci * within 3db. It is achieved when min white pixel >= max white pixel / 2.8
11910141cc406Sopenharmony_ci * So we scan a white area and decrease gain until this condition is met.
11911141cc406Sopenharmony_ci * returns 1 and VGA values in the corresponding vars on success .
11912141cc406Sopenharmony_ci * On failure, returns 0.
11913141cc406Sopenharmony_ci */
11914141cc406Sopenharmony_cistatic int
11915141cc406Sopenharmony_cicoarseGainCalibration610p (int color, int dcRed, int dcGreen, int dcBlue,
11916141cc406Sopenharmony_ci			   int *vgaRed, int *vgaGreen, int *vgaBlue)
11917141cc406Sopenharmony_ci{
11918141cc406Sopenharmony_ci  int motor[17] = {
11919141cc406Sopenharmony_ci    0x11, 0x00, 0x00, 0x70, 0x00, 0x00, 0xC0, 0x2F,
11920141cc406Sopenharmony_ci    0x17, 0x00, 0xFF, 0xAF, 0xAA, 0x6A, 0xA4, 0x00,
11921141cc406Sopenharmony_ci    -1
11922141cc406Sopenharmony_ci  };
11923141cc406Sopenharmony_ci
11924141cc406Sopenharmony_ci  int ccd[37] = {
11925141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
11926141cc406Sopenharmony_ci    0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00,
11927141cc406Sopenharmony_ci    0x76, 0x41, 0xE0, 0xAC, 0x06, 0x00, 0x00, 0x9C,
11928141cc406Sopenharmony_ci    0x4A, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
11929141cc406Sopenharmony_ci    0xDF, 0x13, 0x1A, 0x00,
11930141cc406Sopenharmony_ci    -1
11931141cc406Sopenharmony_ci  };
11932141cc406Sopenharmony_ci
11933141cc406Sopenharmony_ci  /*
11934141cc406Sopenharmony_ci   * lm9811[7]= VGA << 4
11935141cc406Sopenharmony_ci   * lm9811[6]= 0x40 | DC offset
11936141cc406Sopenharmony_ci   */
11937141cc406Sopenharmony_ci  int lm9811[9] = {
11938141cc406Sopenharmony_ci    0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x40, 0xF0,
11939141cc406Sopenharmony_ci    -1
11940141cc406Sopenharmony_ci  };
11941141cc406Sopenharmony_ci
11942141cc406Sopenharmony_ci  int commit[9] = {
11943141cc406Sopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
11944141cc406Sopenharmony_ci    -1
11945141cc406Sopenharmony_ci  };
11946141cc406Sopenharmony_ci
11947141cc406Sopenharmony_ci  unsigned char data[5400];
11948141cc406Sopenharmony_ci  int i, len;
11949141cc406Sopenharmony_ci  int w, xstart, xend;
11950141cc406Sopenharmony_ci  int min, max;
11951141cc406Sopenharmony_ci
11952141cc406Sopenharmony_ci  TRACE (16, "entering coarseGainCalibration610p ...\n");
11953141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () < 1220)
11954141cc406Sopenharmony_ci    {
11955141cc406Sopenharmony_ci      w = 2700;
11956141cc406Sopenharmony_ci      len = 0x22;
11957141cc406Sopenharmony_ci    }
11958141cc406Sopenharmony_ci  else
11959141cc406Sopenharmony_ci    {
11960141cc406Sopenharmony_ci      w = 5400;
11961141cc406Sopenharmony_ci      len = 0x24;
11962141cc406Sopenharmony_ci    }
11963141cc406Sopenharmony_ci
11964141cc406Sopenharmony_ci  /* move back to desired area */
11965141cc406Sopenharmony_ci  MOVE (-69, PRECISION_OFF, NULL);
11966141cc406Sopenharmony_ci
11967141cc406Sopenharmony_ci  /* first scan : taking a reference full width scan to
11968141cc406Sopenharmony_ci   * find usable full width of the CCD
11969141cc406Sopenharmony_ci   */
11970141cc406Sopenharmony_ci  *vgaRed = 0x08;
11971141cc406Sopenharmony_ci  *vgaGreen = 0x00;
11972141cc406Sopenharmony_ci  *vgaBlue = 0x00;
11973141cc406Sopenharmony_ci
11974141cc406Sopenharmony_ci  /* scanning red component -> h=1 */
11975141cc406Sopenharmony_ci  motor[0] = 0x01;
11976141cc406Sopenharmony_ci  motor[13] = 0xAA;		/* will be 6A below */
11977141cc406Sopenharmony_ci
11978141cc406Sopenharmony_ci  encodeDC (dcRed, dcGreen, dcBlue, motor);
11979141cc406Sopenharmony_ci  encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor);
11980141cc406Sopenharmony_ci
11981141cc406Sopenharmony_ci  lm9811[7] = dcRed << 4;
11982141cc406Sopenharmony_ci  lm9811[6] = 0x40 | *vgaRed;
11983141cc406Sopenharmony_ci
11984141cc406Sopenharmony_ci  CMDSYNC (0x00);
11985141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, motor);
11986141cc406Sopenharmony_ci  CMDSETGET (8, len, ccd);
11987141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, lm9811);
11988141cc406Sopenharmony_ci  CMDSYNC (0xC2);
11989141cc406Sopenharmony_ci  CMDSETGET (4, 0x08, commit);
11990141cc406Sopenharmony_ci
11991141cc406Sopenharmony_ci  COMPLETIONWAIT;
11992141cc406Sopenharmony_ci  CMDGETBUF (4, w, data);
11993141cc406Sopenharmony_ci  if (gMode == UMAX_PP_PARPORT_EPP)
11994141cc406Sopenharmony_ci    {
11995141cc406Sopenharmony_ci      CMDSYNC (0x00);
11996141cc406Sopenharmony_ci    }
11997141cc406Sopenharmony_ci  if (DBG_LEVEL > 128)
11998141cc406Sopenharmony_ci    {
11999141cc406Sopenharmony_ci      DumpNB (w, 1, data, NULL);
12000141cc406Sopenharmony_ci    }
12001141cc406Sopenharmony_ci
12002141cc406Sopenharmony_ci  /* find usable CCD area */
12003141cc406Sopenharmony_ci  i = 0;
12004141cc406Sopenharmony_ci  while ((i < w) && (data[i] <= (targetCode * 2) / 5))
12005141cc406Sopenharmony_ci    i++;
12006141cc406Sopenharmony_ci  xstart = i;
12007141cc406Sopenharmony_ci  i = w - 1;
12008141cc406Sopenharmony_ci  while ((i > 0) && (data[i] <= (targetCode * 2) / 5))
12009141cc406Sopenharmony_ci    i--;
12010141cc406Sopenharmony_ci  xend = i;
12011141cc406Sopenharmony_ci  DBG (32, "coarseGainCalibration610p: xstart=%d, xend=%d ->left=%d\n",
12012141cc406Sopenharmony_ci       xstart, xend, ((xend + xstart - w) / 2));
12013141cc406Sopenharmony_ci  /* choose best 'left' position */
12014141cc406Sopenharmony_ci  sanei_umax_pp_setLeft ((xend + xstart - w) / 2);
12015141cc406Sopenharmony_ci
12016141cc406Sopenharmony_ci  /* now do VGA calibration for green (=B&W channel) */
12017141cc406Sopenharmony_ci  motor[0] = 0x11;
12018141cc406Sopenharmony_ci  motor[13] = 0x60 | (motor[13] & 0x0F);
12019141cc406Sopenharmony_ci
12020141cc406Sopenharmony_ci  *vgaRed = 0x0F;
12021141cc406Sopenharmony_ci  *vgaGreen = 0x0F;
12022141cc406Sopenharmony_ci  *vgaBlue = 0x0F;
12023141cc406Sopenharmony_ci
12024141cc406Sopenharmony_ci  for (*vgaGreen = 0x0F; *vgaGreen > 0; (*vgaGreen)--)
12025141cc406Sopenharmony_ci    {
12026141cc406Sopenharmony_ci      encodeDC (dcRed, dcGreen, dcBlue, motor);
12027141cc406Sopenharmony_ci      encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor);
12028141cc406Sopenharmony_ci
12029141cc406Sopenharmony_ci      lm9811[7] = dcGreen << 4;
12030141cc406Sopenharmony_ci      lm9811[6] = 0x40 | *vgaGreen;
12031141cc406Sopenharmony_ci
12032141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, motor);
12033141cc406Sopenharmony_ci      CMDSETGET (8, len, ccd);
12034141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, lm9811);
12035141cc406Sopenharmony_ci      CMDSYNC (0xC2);
12036141cc406Sopenharmony_ci      CMDSYNC (0x00);
12037141cc406Sopenharmony_ci      CMDSETGET (4, 0x08, commit);
12038141cc406Sopenharmony_ci
12039141cc406Sopenharmony_ci      COMPLETIONWAIT;
12040141cc406Sopenharmony_ci      CMDGETBUF (4, w, data);
12041141cc406Sopenharmony_ci      if (gMode == UMAX_PP_PARPORT_EPP)
12042141cc406Sopenharmony_ci	{
12043141cc406Sopenharmony_ci	  CMDSYNC (0x00);
12044141cc406Sopenharmony_ci	}
12045141cc406Sopenharmony_ci
12046141cc406Sopenharmony_ci      if (DBG_LEVEL > 128)
12047141cc406Sopenharmony_ci	{
12048141cc406Sopenharmony_ci	  DumpNB (w, 1, data, NULL);
12049141cc406Sopenharmony_ci	}
12050141cc406Sopenharmony_ci
12051141cc406Sopenharmony_ci      min = 0xFF;
12052141cc406Sopenharmony_ci      max = 0x00;
12053141cc406Sopenharmony_ci      for (i = xstart; i <= xend; i++)
12054141cc406Sopenharmony_ci	{
12055141cc406Sopenharmony_ci	  if (data[i] < min)
12056141cc406Sopenharmony_ci	    min = data[i];
12057141cc406Sopenharmony_ci	  if (data[i] > max)
12058141cc406Sopenharmony_ci	    max = data[i];
12059141cc406Sopenharmony_ci	}
12060141cc406Sopenharmony_ci      if ((max <= targetCode) && (min > (((float) targetCode) / 2.8)))
12061141cc406Sopenharmony_ci	break;
12062141cc406Sopenharmony_ci      DBG (32, "coarseGainCalibration610p, target/2.8=%f\n",
12063141cc406Sopenharmony_ci	   (((float) targetCode) / 2.8));
12064141cc406Sopenharmony_ci      DBG (32, "coarseGainCalibration610p, green: min=%d, max=%d\n", min,
12065141cc406Sopenharmony_ci	   max);
12066141cc406Sopenharmony_ci    }
12067141cc406Sopenharmony_ci
12068141cc406Sopenharmony_ci  if (color >= RGB_MODE)
12069141cc406Sopenharmony_ci    {
12070141cc406Sopenharmony_ci      motor[0] = 0x01;
12071141cc406Sopenharmony_ci      motor[13] = 0xA0 | (motor[13] & 0x0F);
12072141cc406Sopenharmony_ci
12073141cc406Sopenharmony_ci      for (*vgaBlue = 0x0F; *vgaBlue > 0; (*vgaBlue)--)
12074141cc406Sopenharmony_ci	{
12075141cc406Sopenharmony_ci	  encodeDC (dcRed, dcGreen, dcBlue, motor);
12076141cc406Sopenharmony_ci	  encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor);
12077141cc406Sopenharmony_ci
12078141cc406Sopenharmony_ci	  lm9811[7] = dcBlue << 4;
12079141cc406Sopenharmony_ci	  lm9811[6] = 0x40 | *vgaBlue;
12080141cc406Sopenharmony_ci
12081141cc406Sopenharmony_ci	  CMDSETGET (2, 0x10, motor);
12082141cc406Sopenharmony_ci	  CMDSETGET (8, len, ccd);
12083141cc406Sopenharmony_ci	  CMDSETGET (1, 0x08, lm9811);
12084141cc406Sopenharmony_ci	  CMDSYNC (0xC2);
12085141cc406Sopenharmony_ci	  CMDSYNC (0x00);
12086141cc406Sopenharmony_ci	  CMDSETGET (4, 0x08, commit);
12087141cc406Sopenharmony_ci
12088141cc406Sopenharmony_ci	  COMPLETIONWAIT;
12089141cc406Sopenharmony_ci	  CMDGETBUF (4, w, data);
12090141cc406Sopenharmony_ci	  if (gMode == UMAX_PP_PARPORT_EPP)
12091141cc406Sopenharmony_ci	    {
12092141cc406Sopenharmony_ci	      CMDSYNC (0x00);
12093141cc406Sopenharmony_ci	    }
12094141cc406Sopenharmony_ci
12095141cc406Sopenharmony_ci	  if (DBG_LEVEL > 128)
12096141cc406Sopenharmony_ci	    {
12097141cc406Sopenharmony_ci	      DumpNB (w, 1, data, NULL);
12098141cc406Sopenharmony_ci	    }
12099141cc406Sopenharmony_ci
12100141cc406Sopenharmony_ci	  min = 0xFF;
12101141cc406Sopenharmony_ci	  max = 0x00;
12102141cc406Sopenharmony_ci	  for (i = xstart; i <= xend; i++)
12103141cc406Sopenharmony_ci	    {
12104141cc406Sopenharmony_ci	      if (data[i] < min)
12105141cc406Sopenharmony_ci		min = data[i];
12106141cc406Sopenharmony_ci	      if (data[i] > max)
12107141cc406Sopenharmony_ci		max = data[i];
12108141cc406Sopenharmony_ci	    }
12109141cc406Sopenharmony_ci	  if ((max <= targetCode) && (min > (((float) targetCode) / 2.8)))
12110141cc406Sopenharmony_ci	    break;
12111141cc406Sopenharmony_ci	  DBG (32, "coarseGainCalibration610p, blue: min=%d, max=%d\n", min,
12112141cc406Sopenharmony_ci	       max);
12113141cc406Sopenharmony_ci	}
12114141cc406Sopenharmony_ci
12115141cc406Sopenharmony_ci      motor[0] = 0x09;
12116141cc406Sopenharmony_ci      motor[13] = 0xE0 | (motor[13] & 0x0F);
12117141cc406Sopenharmony_ci
12118141cc406Sopenharmony_ci      for (*vgaRed = 0x0F; *vgaRed > 0; (*vgaRed)--)
12119141cc406Sopenharmony_ci	{
12120141cc406Sopenharmony_ci	  encodeDC (dcRed, dcGreen, dcBlue, motor);
12121141cc406Sopenharmony_ci	  encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor);
12122141cc406Sopenharmony_ci
12123141cc406Sopenharmony_ci	  lm9811[7] = dcRed << 4;
12124141cc406Sopenharmony_ci	  lm9811[6] = 0x40 | *vgaRed;
12125141cc406Sopenharmony_ci
12126141cc406Sopenharmony_ci	  CMDSETGET (2, 0x10, motor);
12127141cc406Sopenharmony_ci	  CMDSETGET (8, len, ccd);
12128141cc406Sopenharmony_ci	  CMDSETGET (1, 0x08, lm9811);
12129141cc406Sopenharmony_ci	  CMDSYNC (0xC2);
12130141cc406Sopenharmony_ci	  CMDSYNC (0x00);
12131141cc406Sopenharmony_ci	  CMDSETGET (4, 0x08, commit);
12132141cc406Sopenharmony_ci
12133141cc406Sopenharmony_ci	  COMPLETIONWAIT;
12134141cc406Sopenharmony_ci	  CMDGETBUF (4, w, data);
12135141cc406Sopenharmony_ci	  if (gMode == UMAX_PP_PARPORT_EPP)
12136141cc406Sopenharmony_ci	    {
12137141cc406Sopenharmony_ci	      CMDSYNC (0x00);
12138141cc406Sopenharmony_ci	    }
12139141cc406Sopenharmony_ci
12140141cc406Sopenharmony_ci	  if (DBG_LEVEL > 128)
12141141cc406Sopenharmony_ci	    {
12142141cc406Sopenharmony_ci	      DumpNB (w, 1, data, NULL);
12143141cc406Sopenharmony_ci	    }
12144141cc406Sopenharmony_ci
12145141cc406Sopenharmony_ci	  min = 0xFF;
12146141cc406Sopenharmony_ci	  max = 0x00;
12147141cc406Sopenharmony_ci	  for (i = xstart; i <= xend; i++)
12148141cc406Sopenharmony_ci	    {
12149141cc406Sopenharmony_ci	      if (data[i] < min)
12150141cc406Sopenharmony_ci		min = data[i];
12151141cc406Sopenharmony_ci	      if (data[i] > max)
12152141cc406Sopenharmony_ci		max = data[i];
12153141cc406Sopenharmony_ci	    }
12154141cc406Sopenharmony_ci	  if ((max <= targetCode) && (min > (((float) targetCode) / 2.8)))
12155141cc406Sopenharmony_ci	    break;
12156141cc406Sopenharmony_ci	  DBG (32, "coarseGainCalibration610p, red: min=%d, max=%d\n", min,
12157141cc406Sopenharmony_ci	       max);
12158141cc406Sopenharmony_ci	}
12159141cc406Sopenharmony_ci    }
12160141cc406Sopenharmony_ci  else
12161141cc406Sopenharmony_ci    {
12162141cc406Sopenharmony_ci      *vgaRed = 0x0F;
12163141cc406Sopenharmony_ci      *vgaBlue = 0x0F;
12164141cc406Sopenharmony_ci    }
12165141cc406Sopenharmony_ci
12166141cc406Sopenharmony_ci  TRACE (16, "coarseGainCalibration610p end ...\n");
12167141cc406Sopenharmony_ci  return 1;
12168141cc406Sopenharmony_ci}
12169141cc406Sopenharmony_ci
12170141cc406Sopenharmony_ci/* same as above, but for 1220P/1600P/200P */
12171141cc406Sopenharmony_cistatic int
12172141cc406Sopenharmony_cicoarseGainCalibration1220p (int color, int dcRed, int dcGreen,
12173141cc406Sopenharmony_ci			    int dcBlue, int *vgaRed, int *vgaGreen,
12174141cc406Sopenharmony_ci			    int *vgaBlue)
12175141cc406Sopenharmony_ci{
12176141cc406Sopenharmony_ci  unsigned char buffer[5300];
12177141cc406Sopenharmony_ci  int i;
12178141cc406Sopenharmony_ci  double sum;
12179141cc406Sopenharmony_ci  int xstart = 540;
12180141cc406Sopenharmony_ci  int xend = 5100;
12181141cc406Sopenharmony_ci  int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 };
12182141cc406Sopenharmony_ci  int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 };
12183141cc406Sopenharmony_ci  int opsc10[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x08, 0x00, -1 };
12184141cc406Sopenharmony_ci  int opsc18[17] =
12185141cc406Sopenharmony_ci    { 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0x88, 0x08,
12186141cc406Sopenharmony_ci    0x00, 0x80, 0xA4, 0x00, -1
12187141cc406Sopenharmony_ci  };
12188141cc406Sopenharmony_ci  int opsc39[37] =
12189141cc406Sopenharmony_ci    { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
12190141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x6E, 0x41, 0x20, 0x24, 0x06, 0x00, 0x00, 0x00,
12191141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00,
12192141cc406Sopenharmony_ci    -1
12193141cc406Sopenharmony_ci  };
12194141cc406Sopenharmony_ci  int opsc40[37] =
12195141cc406Sopenharmony_ci    { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01,
12196141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x6E, 0x41, 0x60, 0x4F, 0x06, 0x00, 0x00, 0x00,
12197141cc406Sopenharmony_ci    0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1A, 0x00,
12198141cc406Sopenharmony_ci    -1
12199141cc406Sopenharmony_ci  };
12200141cc406Sopenharmony_ci  int motor[17] =
12201141cc406Sopenharmony_ci    { 0x09, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0xA5, 0x09,
12202141cc406Sopenharmony_ci    0x00, 0x40, 0xA4, 0x00, -1
12203141cc406Sopenharmony_ci  };
12204141cc406Sopenharmony_ci
12205141cc406Sopenharmony_ci  DBG (16, "entering coarseGainCalibration1220p() ... (%s:%d) \n", __FILE__,
12206141cc406Sopenharmony_ci       __LINE__);
12207141cc406Sopenharmony_ci
12208141cc406Sopenharmony_ci  /* temporary workaround */
12209141cc406Sopenharmony_ci  color = RGB_MODE;
12210141cc406Sopenharmony_ci
12211141cc406Sopenharmony_ci  /* initialize VGA components */
12212141cc406Sopenharmony_ci  *vgaGreen = 0;
12213141cc406Sopenharmony_ci  *vgaRed = 2;
12214141cc406Sopenharmony_ci  *vgaBlue = 2;
12215141cc406Sopenharmony_ci
12216141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, opsc18);
12217141cc406Sopenharmony_ci  CMDSETGET (8, 0x24, opsc39);
12218141cc406Sopenharmony_ci  opsc04[7] = opsc04[7] & 0x20;
12219141cc406Sopenharmony_ci  opsc04[6] = 0x06;		/* one channel gain value */
12220141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, opsc10);	/* was opsc04, extraneaous string */
12221141cc406Sopenharmony_ci  /* that prevents using move .... */
12222141cc406Sopenharmony_ci  CMDSYNC (0xC2);
12223141cc406Sopenharmony_ci  CMDSYNC (0x00);
12224141cc406Sopenharmony_ci  CMDSETGET (4, 0x08, commit);
12225141cc406Sopenharmony_ci  COMPLETIONWAIT;
12226141cc406Sopenharmony_ci  CMDGETBUF (4, 0x200, buffer);
12227141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
12228141cc406Sopenharmony_ci    Dump (0x200, buffer, NULL);
12229141cc406Sopenharmony_ci
12230141cc406Sopenharmony_ci
12231141cc406Sopenharmony_ci  /* auto correction of gain levels */
12232141cc406Sopenharmony_ci  /* first color component X        */
12233141cc406Sopenharmony_ci  if (color >= RGB_MODE)
12234141cc406Sopenharmony_ci    {
12235141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () == 1600)
12236141cc406Sopenharmony_ci	{
12237141cc406Sopenharmony_ci	  motor[11] |= 0x20;
12238141cc406Sopenharmony_ci	  motor[12] = 0x08;
12239141cc406Sopenharmony_ci	  motor[13] |= 0x02;
12240141cc406Sopenharmony_ci
12241141cc406Sopenharmony_ci	  opsc04[7] |= 0x20;
12242141cc406Sopenharmony_ci	}
12243141cc406Sopenharmony_ci      encodeDC (dcRed, dcGreen, dcBlue, motor);
12244141cc406Sopenharmony_ci      encodeVGA (*vgaRed, 0, 0, motor);
12245141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, motor);
12246141cc406Sopenharmony_ci      CMDSETGET (8, 0x24, opsc40);
12247141cc406Sopenharmony_ci      if (DBG_LEVEL >= 128)
12248141cc406Sopenharmony_ci	{
12249141cc406Sopenharmony_ci	  bloc2Decode (motor);
12250141cc406Sopenharmony_ci	  bloc8Decode (opsc40);
12251141cc406Sopenharmony_ci	}
12252141cc406Sopenharmony_ci      opsc04[6] = *vgaRed;
12253141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, opsc04);
12254141cc406Sopenharmony_ci      CMDSYNC (0xC2);
12255141cc406Sopenharmony_ci      CMDSYNC (0x00);
12256141cc406Sopenharmony_ci      CMDSETGET (4, 0x08, commit);
12257141cc406Sopenharmony_ci      COMPLETIONWAIT;
12258141cc406Sopenharmony_ci      CMDGETBUF (4, 0x14B4, buffer);
12259141cc406Sopenharmony_ci      if (DBG_LEVEL >= 128)
12260141cc406Sopenharmony_ci	Dump (0x14B4, buffer, NULL);
12261141cc406Sopenharmony_ci      sum = 0;
12262141cc406Sopenharmony_ci      for (i = xstart; i < xend; i++)
12263141cc406Sopenharmony_ci	sum += buffer[i];
12264141cc406Sopenharmony_ci      sum = sum / (xend - xstart);
12265141cc406Sopenharmony_ci      while ((opsc04[6] < 0x0F) && (sum < 140))
12266141cc406Sopenharmony_ci	{
12267141cc406Sopenharmony_ci	  CMDSYNC (0x00);
12268141cc406Sopenharmony_ci	  opsc04[6]++;
12269141cc406Sopenharmony_ci	  CMDSETGET (1, 0x000008, opsc04);
12270141cc406Sopenharmony_ci	  COMPLETIONWAIT;
12271141cc406Sopenharmony_ci	  CMDGETBUF (4, 0x0014B4, buffer);
12272141cc406Sopenharmony_ci	  if (DBG_LEVEL >= 128)
12273141cc406Sopenharmony_ci	    Dump (0x14B4, buffer, NULL);
12274141cc406Sopenharmony_ci	  sum = 0;
12275141cc406Sopenharmony_ci	  for (i = xstart; i < xend; i++)
12276141cc406Sopenharmony_ci	    sum += buffer[i];
12277141cc406Sopenharmony_ci	  sum = sum / (xend - xstart);
12278141cc406Sopenharmony_ci	}
12279141cc406Sopenharmony_ci      *vgaRed = opsc04[6];
12280141cc406Sopenharmony_ci
12281141cc406Sopenharmony_ci      /* blue */
12282141cc406Sopenharmony_ci      encodeDC (dcRed, dcGreen, dcBlue, motor);
12283141cc406Sopenharmony_ci      encodeVGA (0, 0, *vgaBlue, motor);
12284141cc406Sopenharmony_ci      if (sanei_umax_pp_getastra () == 1600)
12285141cc406Sopenharmony_ci	{
12286141cc406Sopenharmony_ci	  motor[11] |= 0x20;
12287141cc406Sopenharmony_ci	  motor[12] = 0x08;
12288141cc406Sopenharmony_ci	  motor[13] |= 0x02;
12289141cc406Sopenharmony_ci
12290141cc406Sopenharmony_ci	  opsc04[7] |= 0x20;
12291141cc406Sopenharmony_ci	}
12292141cc406Sopenharmony_ci      CMDSETGET (2, 0x10, motor);
12293141cc406Sopenharmony_ci      CMDSETGET (8, 0x24, opsc40);
12294141cc406Sopenharmony_ci      opsc04[6] = *vgaBlue;
12295141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, opsc04);
12296141cc406Sopenharmony_ci      CMDSYNC (0xC2);
12297141cc406Sopenharmony_ci      CMDSYNC (0x00);
12298141cc406Sopenharmony_ci      CMDSETGET (4, 0x08, commit);
12299141cc406Sopenharmony_ci      COMPLETIONWAIT;
12300141cc406Sopenharmony_ci      CMDGETBUF (4, 0x14B4, buffer);
12301141cc406Sopenharmony_ci      if (DBG_LEVEL >= 128)
12302141cc406Sopenharmony_ci	Dump (0x14B4, buffer, NULL);
12303141cc406Sopenharmony_ci      sum = 0;
12304141cc406Sopenharmony_ci      for (i = xstart; i < xend; i++)
12305141cc406Sopenharmony_ci	sum += buffer[i];
12306141cc406Sopenharmony_ci      sum = sum / (xend - xstart);
12307141cc406Sopenharmony_ci      while ((opsc04[6] < 0x0F) && (sum < 140))
12308141cc406Sopenharmony_ci	{
12309141cc406Sopenharmony_ci	  CMDSYNC (0x00);
12310141cc406Sopenharmony_ci	  opsc04[6]++;
12311141cc406Sopenharmony_ci	  CMDSETGET (1, 0x08, opsc04);
12312141cc406Sopenharmony_ci	  COMPLETIONWAIT;
12313141cc406Sopenharmony_ci	  CMDGETBUF (4, 0x14B4, buffer);
12314141cc406Sopenharmony_ci	  if (DBG_LEVEL >= 128)
12315141cc406Sopenharmony_ci	    Dump (0x14B4, buffer, NULL);
12316141cc406Sopenharmony_ci	  sum = 0;
12317141cc406Sopenharmony_ci	  for (i = xstart; i < xend; i++)
12318141cc406Sopenharmony_ci	    sum += buffer[i];
12319141cc406Sopenharmony_ci	  sum = sum / (xend - xstart);
12320141cc406Sopenharmony_ci	}
12321141cc406Sopenharmony_ci      *vgaBlue = opsc04[6];
12322141cc406Sopenharmony_ci    }
12323141cc406Sopenharmony_ci
12324141cc406Sopenharmony_ci
12325141cc406Sopenharmony_ci  /* component Z: B&W component (green ...) */
12326141cc406Sopenharmony_ci  encodeDC (dcRed, dcGreen, dcBlue, motor);
12327141cc406Sopenharmony_ci  encodeVGA (0, *vgaGreen, 0, motor);
12328141cc406Sopenharmony_ci  if (color < RGB_MODE)
12329141cc406Sopenharmony_ci    motor[0] = 0x01;		/* in BW, scan zone doesn't have an extra 4 points */
12330141cc406Sopenharmony_ci  else
12331141cc406Sopenharmony_ci    motor[0] = 0x05;		/*  extra 4 points */
12332141cc406Sopenharmony_ci  motor[13] = 0xC0;		/* B&W */
12333141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () == 1600)
12334141cc406Sopenharmony_ci    {
12335141cc406Sopenharmony_ci      motor[11] |= 0x20;
12336141cc406Sopenharmony_ci      motor[12] = 0x08;
12337141cc406Sopenharmony_ci      motor[13] |= 0x02;
12338141cc406Sopenharmony_ci
12339141cc406Sopenharmony_ci      opsc04[7] |= 0x20;
12340141cc406Sopenharmony_ci    }
12341141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, motor);
12342141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
12343141cc406Sopenharmony_ci    {
12344141cc406Sopenharmony_ci      bloc2Decode (motor);
12345141cc406Sopenharmony_ci    }
12346141cc406Sopenharmony_ci  CMDSETGET (8, 0x24, opsc40);
12347141cc406Sopenharmony_ci  opsc04[6] = *vgaGreen;
12348141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, opsc04);
12349141cc406Sopenharmony_ci  CMDSYNC (0xC2);
12350141cc406Sopenharmony_ci  CMDSYNC (0x00);
12351141cc406Sopenharmony_ci  CMDSETGET (4, 0x08, commit);
12352141cc406Sopenharmony_ci  COMPLETIONWAIT;
12353141cc406Sopenharmony_ci  /* B&W hangs here XXX STEF XXX */
12354141cc406Sopenharmony_ci  CMDGETBUF (4, 0x14B4, buffer);
12355141cc406Sopenharmony_ci  if (DBG_LEVEL >= 128)
12356141cc406Sopenharmony_ci    Dump (0x14B4, buffer, NULL);
12357141cc406Sopenharmony_ci  sum = 0;
12358141cc406Sopenharmony_ci  for (i = xstart; i < xend; i++)
12359141cc406Sopenharmony_ci    sum += buffer[i];
12360141cc406Sopenharmony_ci  sum = sum / (xend - xstart);
12361141cc406Sopenharmony_ci  while ((opsc04[6] < 0x07) && (sum < 110))
12362141cc406Sopenharmony_ci    {
12363141cc406Sopenharmony_ci      CMDSYNC (0x00);
12364141cc406Sopenharmony_ci      opsc04[6]++;
12365141cc406Sopenharmony_ci      CMDSETGET (1, 0x08, opsc04);
12366141cc406Sopenharmony_ci      COMPLETIONWAIT;
12367141cc406Sopenharmony_ci      CMDGETBUF (4, 0x0014B4, buffer);
12368141cc406Sopenharmony_ci      if (DBG_LEVEL >= 128)
12369141cc406Sopenharmony_ci	Dump (0x14B4, buffer, NULL);
12370141cc406Sopenharmony_ci      sum = 0;
12371141cc406Sopenharmony_ci      for (i = xstart; i < xend; i++)
12372141cc406Sopenharmony_ci	sum += buffer[i];
12373141cc406Sopenharmony_ci      sum = sum / (xend - xstart);
12374141cc406Sopenharmony_ci    }
12375141cc406Sopenharmony_ci  *vgaGreen = opsc04[6];
12376141cc406Sopenharmony_ci  DBG (1, "coarseGainCalibration1220p()=%d,%d,%d done ...\n", *vgaRed,
12377141cc406Sopenharmony_ci       *vgaGreen, *vgaBlue);
12378141cc406Sopenharmony_ci  return 1;
12379141cc406Sopenharmony_ci}
12380141cc406Sopenharmony_ci
12381141cc406Sopenharmony_ci/*
12382141cc406Sopenharmony_ci * generic function
12383141cc406Sopenharmony_ci */
12384141cc406Sopenharmony_cistatic int
12385141cc406Sopenharmony_cicoarseGainCalibration (int color, int dcRed, int dcGreen, int dcBlue,
12386141cc406Sopenharmony_ci		       int *vgaRed, int *vgaGreen, int *vgaBlue)
12387141cc406Sopenharmony_ci{
12388141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () <= 610)
12389141cc406Sopenharmony_ci    {
12390141cc406Sopenharmony_ci      if (coarseGainCalibration610p
12391141cc406Sopenharmony_ci	  (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue) == 0)
12392141cc406Sopenharmony_ci	{
12393141cc406Sopenharmony_ci	  DBG (0, "coarseGainCalibration610p failed !!! (%s:%d)\n", __FILE__,
12394141cc406Sopenharmony_ci	       __LINE__);
12395141cc406Sopenharmony_ci	  return 0;
12396141cc406Sopenharmony_ci	}
12397141cc406Sopenharmony_ci      DBG (16,
12398141cc406Sopenharmony_ci	   "coarseGainCalibration610p passed ... (%s:%d)\n", __FILE__,
12399141cc406Sopenharmony_ci	   __LINE__);
12400141cc406Sopenharmony_ci    }
12401141cc406Sopenharmony_ci  else
12402141cc406Sopenharmony_ci    {
12403141cc406Sopenharmony_ci      if (coarseGainCalibration1220p
12404141cc406Sopenharmony_ci	  (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue) == 0)
12405141cc406Sopenharmony_ci	{
12406141cc406Sopenharmony_ci	  DBG (0, "coarseGainCalibration1220p failed !!! (%s:%d)\n", __FILE__,
12407141cc406Sopenharmony_ci	       __LINE__);
12408141cc406Sopenharmony_ci	  return 0;
12409141cc406Sopenharmony_ci	}
12410141cc406Sopenharmony_ci      DBG (16,
12411141cc406Sopenharmony_ci	   "coarseGainCalibration1220p passed ... (%s:%d)\n", __FILE__,
12412141cc406Sopenharmony_ci	   __LINE__);
12413141cc406Sopenharmony_ci    }
12414141cc406Sopenharmony_ci  return 1;
12415141cc406Sopenharmony_ci}
12416141cc406Sopenharmony_ci
12417141cc406Sopenharmony_ci/*
12418141cc406Sopenharmony_ci * computes PGA offset for each pixel of the ccd.
12419141cc406Sopenharmony_ci * We scan a white area with PGA=0 and computes the
12420141cc406Sopenharmony_ci * offset to push the result in the correctable range
12421141cc406Sopenharmony_ci * returns 1 and PGA values in 'calibration' var on success .
12422141cc406Sopenharmony_ci * On failure, returns 0.
12423141cc406Sopenharmony_ci */
12424141cc406Sopenharmony_cistatic int
12425141cc406Sopenharmony_cishadingCalibration610p (int color, int dcRed, int dcGreen, int dcBlue,
12426141cc406Sopenharmony_ci			int vgaRed, int vgaGreen, int vgaBlue,
12427141cc406Sopenharmony_ci			int *calibration)
12428141cc406Sopenharmony_ci{
12429141cc406Sopenharmony_ci  int motor[17] = {
12430141cc406Sopenharmony_ci    0x5A, 0x80, 0x02, 0x70, 0x00, 0x00, 0xC0, 0x00,
12431141cc406Sopenharmony_ci    0x17, 0x05, 0x6C, 0xAB, 0xAA, 0x2A, 0xA4, 0x00,
12432141cc406Sopenharmony_ci    -1
12433141cc406Sopenharmony_ci  };
12434141cc406Sopenharmony_ci
12435141cc406Sopenharmony_ci  int ccd[37] = {
12436141cc406Sopenharmony_ci    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C,
12437141cc406Sopenharmony_ci    0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00,
12438141cc406Sopenharmony_ci    0x76, 0x5D, 0x40, 0xA5, 0x06, 0x00, 0x00, 0xE2,
12439141cc406Sopenharmony_ci    0x5E, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
12440141cc406Sopenharmony_ci    0xDF, 0x13, 0x1A, 0x00,
12441141cc406Sopenharmony_ci    -1
12442141cc406Sopenharmony_ci  };
12443141cc406Sopenharmony_ci
12444141cc406Sopenharmony_ci  /*
12445141cc406Sopenharmony_ci   * lm9811[7]= VGA << 4
12446141cc406Sopenharmony_ci   * lm9811[6]= 0x40 | DC offset
12447141cc406Sopenharmony_ci   */
12448141cc406Sopenharmony_ci  int lm9811[9] = {
12449141cc406Sopenharmony_ci    0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x0F, 0x80,
12450141cc406Sopenharmony_ci    -1
12451141cc406Sopenharmony_ci  };
12452141cc406Sopenharmony_ci
12453141cc406Sopenharmony_ci  int commit[9] = {
12454141cc406Sopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
12455141cc406Sopenharmony_ci    -1
12456141cc406Sopenharmony_ci  };
12457141cc406Sopenharmony_ci
12458141cc406Sopenharmony_ci  int len, dpi, size;
12459141cc406Sopenharmony_ci  int bpp = 3;			/* defaults to color scan value */
12460141cc406Sopenharmony_ci  int w, h, x, y;
12461141cc406Sopenharmony_ci  int sum, i;
12462141cc406Sopenharmony_ci  float avg, pct, coeff = 0;
12463141cc406Sopenharmony_ci  unsigned char *data = NULL;
12464141cc406Sopenharmony_ci  int top, bottom;
12465141cc406Sopenharmony_ci
12466141cc406Sopenharmony_ci  TRACE (16, "entering shadingCalibration610p ...\n");
12467141cc406Sopenharmony_ci  len = 0x22;
12468141cc406Sopenharmony_ci  w = 2550;
12469141cc406Sopenharmony_ci  y = 10;
12470141cc406Sopenharmony_ci  dpi = 300;
12471141cc406Sopenharmony_ci  h = 90;
12472141cc406Sopenharmony_ci  top = 8;
12473141cc406Sopenharmony_ci  bottom = 8;
12474141cc406Sopenharmony_ci
12475141cc406Sopenharmony_ci  /* move back first */
12476141cc406Sopenharmony_ci  MOVE (-31, PRECISION_OFF, NULL);
12477141cc406Sopenharmony_ci
12478141cc406Sopenharmony_ci  /* gray scanning handling */
12479141cc406Sopenharmony_ci  if (color < RGB_MODE)
12480141cc406Sopenharmony_ci    {
12481141cc406Sopenharmony_ci      lm9811[7] = dcGreen << 4;
12482141cc406Sopenharmony_ci      lm9811[6] = 0x40 | vgaGreen;
12483141cc406Sopenharmony_ci      bpp = 1;
12484141cc406Sopenharmony_ci
12485141cc406Sopenharmony_ci      motor[13] = 0x6F;
12486141cc406Sopenharmony_ci    }
12487141cc406Sopenharmony_ci
12488141cc406Sopenharmony_ci  data = (unsigned char *) malloc (w * h * bpp);
12489141cc406Sopenharmony_ci  if (data == NULL)
12490141cc406Sopenharmony_ci    {
12491141cc406Sopenharmony_ci      DBG (0, "shadingCalibration610p: failed to allocate memory (%s:%d)\n",
12492141cc406Sopenharmony_ci	   __FILE__, __LINE__);
12493141cc406Sopenharmony_ci      return 0;
12494141cc406Sopenharmony_ci    }
12495141cc406Sopenharmony_ci  memset (data, 0x00, w * h * bpp);
12496141cc406Sopenharmony_ci
12497141cc406Sopenharmony_ci  /* prepare scan command */
12498141cc406Sopenharmony_ci  x = sanei_umax_pp_getLeft ();
12499141cc406Sopenharmony_ci  encodeWX (w, x, dpi, color, ccd, bpp * w);
12500141cc406Sopenharmony_ci  encodeHY (h, y, motor);
12501141cc406Sopenharmony_ci  encodeDC (dcRed, dcGreen, dcBlue, motor);
12502141cc406Sopenharmony_ci  encodeVGA (vgaRed, vgaGreen, vgaBlue, motor);
12503141cc406Sopenharmony_ci  if (DBG_LEVEL > 128)
12504141cc406Sopenharmony_ci    {
12505141cc406Sopenharmony_ci      bloc2Decode (motor);
12506141cc406Sopenharmony_ci      bloc8Decode (ccd);
12507141cc406Sopenharmony_ci    }
12508141cc406Sopenharmony_ci
12509141cc406Sopenharmony_ci  CMDSYNC (0x00);
12510141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, motor);
12511141cc406Sopenharmony_ci  CMDSETGET (8, len, ccd);
12512141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, lm9811);
12513141cc406Sopenharmony_ci  CMDSYNC (0xC2);
12514141cc406Sopenharmony_ci  CMDSETGET (4, 0x08, commit);
12515141cc406Sopenharmony_ci  COMPLETIONWAIT;
12516141cc406Sopenharmony_ci
12517141cc406Sopenharmony_ci  /* picture height is scan area height minus y          */
12518141cc406Sopenharmony_ci  /* then we subtract 14 or 6 lines that aren't scanned  */
12519141cc406Sopenharmony_ci  if (color < RGB_MODE)
12520141cc406Sopenharmony_ci    h = h - y - 14;
12521141cc406Sopenharmony_ci  else
12522141cc406Sopenharmony_ci    h = h - y - 6;
12523141cc406Sopenharmony_ci  size = w * bpp * h;
12524141cc406Sopenharmony_ci
12525141cc406Sopenharmony_ci  DBG (128,
12526141cc406Sopenharmony_ci       "shadingCalibration610p: trying to read 0x%06X bytes ... (%s:%d)\n",
12527141cc406Sopenharmony_ci       size, __FILE__, __LINE__);
12528141cc406Sopenharmony_ci  /* since we know that each scan line matches CCD width, we signals
12529141cc406Sopenharmony_ci   * that data reading doesn't need to sync on each byte, but at each
12530141cc406Sopenharmony_ci   * row end
12531141cc406Sopenharmony_ci   */
12532141cc406Sopenharmony_ci  sanei_umax_pp_setfull (1);
12533141cc406Sopenharmony_ci  CMDGETBUF (4, size, data);
12534141cc406Sopenharmony_ci  sanei_umax_pp_setfull (0);
12535141cc406Sopenharmony_ci
12536141cc406Sopenharmony_ci  /* computes correction here ... */
12537141cc406Sopenharmony_ci  /* debug image files */
12538141cc406Sopenharmony_ci  /* data is in R B G order */
12539141cc406Sopenharmony_ci  if (DBG_LEVEL > 128)
12540141cc406Sopenharmony_ci    DumpNB (w * bpp, h, data, NULL);
12541141cc406Sopenharmony_ci
12542141cc406Sopenharmony_ci  /* zeroes all shading coefficients first */
12543141cc406Sopenharmony_ci  memset (calibration, 0x00, 3 * w * sizeof (int));
12544141cc406Sopenharmony_ci
12545141cc406Sopenharmony_ci  /* in gray scans, we have only green component (i=3) */
12546141cc406Sopenharmony_ci  if (color < RGB_MODE)
12547141cc406Sopenharmony_ci    {
12548141cc406Sopenharmony_ci
12549141cc406Sopenharmony_ci      /* build green only coefficients */
12550141cc406Sopenharmony_ci      for (x = 4; x < w; x++)
12551141cc406Sopenharmony_ci	{
12552141cc406Sopenharmony_ci	  sum = 0;
12553141cc406Sopenharmony_ci	  for (y = top; y < h - bottom; y++)
12554141cc406Sopenharmony_ci	    sum += data[(y * bpp) * w + x];
12555141cc406Sopenharmony_ci	  avg = ((float) (sum)) / ((float) (h - (top + bottom)));
12556141cc406Sopenharmony_ci	  /* XXX ICI XXX avg=128==>2 */
12557141cc406Sopenharmony_ci	  /*coeff = (256.0 * (targetCode / avg - 1.0)) / 2.00;*/
12558141cc406Sopenharmony_ci	  coeff = (256.0 * (targetCode / avg - 1.0)) / ((avg*3.5)/targetCode);
12559141cc406Sopenharmony_ci	  if (coeff < 0)
12560141cc406Sopenharmony_ci	    coeff = 0;
12561141cc406Sopenharmony_ci	  if (coeff > 255)
12562141cc406Sopenharmony_ci	    coeff = 255;
12563141cc406Sopenharmony_ci	  calibration[x + 2 * w - 4] = (int) (coeff + 0.5);
12564141cc406Sopenharmony_ci	}
12565141cc406Sopenharmony_ci    }
12566141cc406Sopenharmony_ci  else
12567141cc406Sopenharmony_ci    {
12568141cc406Sopenharmony_ci      for (i = 0; i < 3; i++)
12569141cc406Sopenharmony_ci	{
12570141cc406Sopenharmony_ci	  for (x = 4; x < w; x++)
12571141cc406Sopenharmony_ci	    {
12572141cc406Sopenharmony_ci	      sum = 0;
12573141cc406Sopenharmony_ci	      for (y = top; y < h - bottom; y++)
12574141cc406Sopenharmony_ci		sum += data[(y * bpp + i) * w + x];
12575141cc406Sopenharmony_ci	      avg = ((float) (sum)) / ((float) (h - (top + bottom)));
12576141cc406Sopenharmony_ci	      /* one step increase means a 0.71% increase of the final
12577141cc406Sopenharmony_ci	         pixel */
12578141cc406Sopenharmony_ci	      pct = 100.0 - (avg * 100.0) / targetCode;
12579141cc406Sopenharmony_ci	      switch (i)
12580141cc406Sopenharmony_ci		{
12581141cc406Sopenharmony_ci		case 0:	/* RED  1.80 */
12582141cc406Sopenharmony_ci		case 1:	/* BLUE : 2.10 */
12583141cc406Sopenharmony_ci		  coeff = (int) (pct / 0.57 + 0.5);
12584141cc406Sopenharmony_ci		  break;
12585141cc406Sopenharmony_ci		case 2:	/* GREEN 1.50 */
12586141cc406Sopenharmony_ci		  coeff = (int) (pct / 0.45 + 0.5);
12587141cc406Sopenharmony_ci		  break;
12588141cc406Sopenharmony_ci		}
12589141cc406Sopenharmony_ci	      if (coeff < 0)
12590141cc406Sopenharmony_ci		coeff = 0;
12591141cc406Sopenharmony_ci	      if (coeff > 255)
12592141cc406Sopenharmony_ci		coeff = 255;
12593141cc406Sopenharmony_ci	      calibration[x + i * w - 4] = (int) (coeff + 0.5);
12594141cc406Sopenharmony_ci	    }
12595141cc406Sopenharmony_ci	  /* 100 in coeffs -> +104 on picture */
12596141cc406Sopenharmony_ci	}
12597141cc406Sopenharmony_ci    }
12598141cc406Sopenharmony_ci
12599141cc406Sopenharmony_ci  /* use default color tables */
12600141cc406Sopenharmony_ci  for (x = 0; x < 256; x++)
12601141cc406Sopenharmony_ci    {
12602141cc406Sopenharmony_ci      calibration[3 * w + x] = ggRed[x];
12603141cc406Sopenharmony_ci      calibration[3 * w + x + 256] = ggGreen[x];
12604141cc406Sopenharmony_ci      calibration[3 * w + x + 512] = ggBlue[x];
12605141cc406Sopenharmony_ci    }
12606141cc406Sopenharmony_ci
12607141cc406Sopenharmony_ci  if (DBG_LEVEL > 128)
12608141cc406Sopenharmony_ci    {
12609141cc406Sopenharmony_ci      DumpNB (w * bpp, h, data, NULL);
12610141cc406Sopenharmony_ci      DumpNB (w, h * bpp, data, NULL);
12611141cc406Sopenharmony_ci    }
12612141cc406Sopenharmony_ci
12613141cc406Sopenharmony_ci  free (data);
12614141cc406Sopenharmony_ci  TRACE (16, "shadingCalibration610p end ...\n");
12615141cc406Sopenharmony_ci  return 1;
12616141cc406Sopenharmony_ci}
12617141cc406Sopenharmony_ci
12618141cc406Sopenharmony_ci/*
12619141cc406Sopenharmony_ci * build CCD correction: a white area below the top is scanned without
12620141cc406Sopenharmony_ci * correction, and the data are used to compute the coefficients needed
12621141cc406Sopenharmony_ci * to correct the light/CCD variations
12622141cc406Sopenharmony_ci */
12623141cc406Sopenharmony_cistatic int
12624141cc406Sopenharmony_cishadingCalibration (int color, int dcRed, int dcGreen, int dcBlue,
12625141cc406Sopenharmony_ci		    int vgaRed, int vgaGreen, int vgaBlue, int *calibration)
12626141cc406Sopenharmony_ci{
12627141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () < 1220)
12628141cc406Sopenharmony_ci    return shadingCalibration610p (color, dcRed, dcGreen, dcBlue, vgaRed,
12629141cc406Sopenharmony_ci				   vgaGreen, vgaBlue, calibration);
12630141cc406Sopenharmony_ci  return shadingCalibration1220p (color, dcRed, dcGreen, dcBlue, vgaRed,
12631141cc406Sopenharmony_ci				  vgaGreen, vgaBlue, calibration);
12632141cc406Sopenharmony_ci}
12633141cc406Sopenharmony_ci
12634141cc406Sopenharmony_ci
12635141cc406Sopenharmony_ci/*
12636141cc406Sopenharmony_ci * this is certainly gamma calibration
12637141cc406Sopenharmony_ci * We scan a white area with PGA=0 and computes the
12638141cc406Sopenharmony_ci * offset to push the result in the correctable range
12639141cc406Sopenharmony_ci * returns 1 and PGA values in 'calibration' var on success .
12640141cc406Sopenharmony_ci * On failure, returns 0.
12641141cc406Sopenharmony_ci */
12642141cc406Sopenharmony_cistatic int
12643141cc406Sopenharmony_cileftShadingCalibration610p (int color, int dcRed, int dcGreen, int dcBlue,
12644141cc406Sopenharmony_ci			    int vgaRed, int vgaGreen, int vgaBlue,
12645141cc406Sopenharmony_ci			    int *calibration)
12646141cc406Sopenharmony_ci{
12647141cc406Sopenharmony_ci  int motor[17] = {
12648141cc406Sopenharmony_ci    0x14, 0x80, 0x02, 0x60, 0xDE, 0x01, 0xC0, 0x2F,
12649141cc406Sopenharmony_ci    0x17, 0x00, 0x6C, 0xAB, 0xAA, 0x2A, 0xA4, 0x00,
12650141cc406Sopenharmony_ci    -1
12651141cc406Sopenharmony_ci  };
12652141cc406Sopenharmony_ci
12653141cc406Sopenharmony_ci  int ccd[37] = {
12654141cc406Sopenharmony_ci    0x00, 0x00, 0xD8, 0x27, 0xEC, 0x53, 0x7D, 0x8A,
12655141cc406Sopenharmony_ci    0x77, 0xE3, 0x1D, 0x79, 0x07, 0x20, 0x02, 0x00,
12656141cc406Sopenharmony_ci    0x76, 0x41, 0x80, 0xA3, 0xE5, 0x1D, 0x00, 0xF2,
12657141cc406Sopenharmony_ci    0x5D, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68,
12658141cc406Sopenharmony_ci    0xDF, 0x13, 0x1A, 0x00,
12659141cc406Sopenharmony_ci    -1
12660141cc406Sopenharmony_ci  };
12661141cc406Sopenharmony_ci
12662141cc406Sopenharmony_ci  /*
12663141cc406Sopenharmony_ci   * lm9811[7]= VGA << 4
12664141cc406Sopenharmony_ci   * lm9811[6]= 0x40 | DC offset
12665141cc406Sopenharmony_ci   * lm9811[6].bit7 = use shading data
12666141cc406Sopenharmony_ci   */
12667141cc406Sopenharmony_ci  int lm9811[9] = {
12668141cc406Sopenharmony_ci    0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x8F, 0x80,
12669141cc406Sopenharmony_ci    -1
12670141cc406Sopenharmony_ci  };
12671141cc406Sopenharmony_ci
12672141cc406Sopenharmony_ci  int *commit = NULL;
12673141cc406Sopenharmony_ci
12674141cc406Sopenharmony_ci  int len, dpi, size;
12675141cc406Sopenharmony_ci  int w, h, x, y;
12676141cc406Sopenharmony_ci  int ofst;
12677141cc406Sopenharmony_ci  unsigned char *data = NULL;
12678141cc406Sopenharmony_ci
12679141cc406Sopenharmony_ci  TRACE (16, "entering leftShadingCalibration610p ...\n");
12680141cc406Sopenharmony_ci  if (sanei_umax_pp_getastra () < 1220)
12681141cc406Sopenharmony_ci    {
12682141cc406Sopenharmony_ci      len = 0x22;
12683141cc406Sopenharmony_ci      ofst = 28;
12684141cc406Sopenharmony_ci      w = 2550;
12685141cc406Sopenharmony_ci      x = 94 - ofst;		/* left shift compared to shading calibration */
12686141cc406Sopenharmony_ci      y = 10;
12687141cc406Sopenharmony_ci      dpi = 75;
12688141cc406Sopenharmony_ci      h = 20;
12689141cc406Sopenharmony_ci    }
12690141cc406Sopenharmony_ci  else
12691141cc406Sopenharmony_ci    {
12692141cc406Sopenharmony_ci      len = 0x24;
12693141cc406Sopenharmony_ci      ofst = 28;
12694141cc406Sopenharmony_ci      w = 5100;
12695141cc406Sopenharmony_ci      x = 180;
12696141cc406Sopenharmony_ci      y = 10;
12697141cc406Sopenharmony_ci      dpi = 600;
12698141cc406Sopenharmony_ci      h = 67;
12699141cc406Sopenharmony_ci    }
12700141cc406Sopenharmony_ci
12701141cc406Sopenharmony_ci  commit = (int *) malloc ((w * 3 + 5) * sizeof (int));
12702141cc406Sopenharmony_ci  if (commit == NULL)
12703141cc406Sopenharmony_ci    {
12704141cc406Sopenharmony_ci      DBG (0,
12705141cc406Sopenharmony_ci	   "leftShadingCalibration610p: failed to allocate memory (%s:%d)\n",
12706141cc406Sopenharmony_ci	   __FILE__, __LINE__);
12707141cc406Sopenharmony_ci      return 0;
12708141cc406Sopenharmony_ci    }
12709141cc406Sopenharmony_ci
12710141cc406Sopenharmony_ci  data = (unsigned char *) malloc (w * h * 3);
12711141cc406Sopenharmony_ci  if (data == NULL)
12712141cc406Sopenharmony_ci    {
12713141cc406Sopenharmony_ci      DBG (0,
12714141cc406Sopenharmony_ci	   "leftShadingCalibration610p: failed to allocate memory (%s:%d)\n",
12715141cc406Sopenharmony_ci	   __FILE__, __LINE__);
12716141cc406Sopenharmony_ci      free (commit);
12717141cc406Sopenharmony_ci      return 0;
12718141cc406Sopenharmony_ci    }
12719141cc406Sopenharmony_ci
12720141cc406Sopenharmony_ci  /* prepare scan command */
12721141cc406Sopenharmony_ci  encodeWX (w, x, dpi, color, ccd, 7410);
12722141cc406Sopenharmony_ci  encodeHY (h, y, motor);
12723141cc406Sopenharmony_ci  encodeDC (dcRed, dcGreen, dcBlue, motor);
12724141cc406Sopenharmony_ci  encodeVGA (vgaRed, vgaGreen, vgaBlue, motor);
12725141cc406Sopenharmony_ci  if (DBG_LEVEL > 128)
12726141cc406Sopenharmony_ci    {
12727141cc406Sopenharmony_ci      bloc2Decode (motor);
12728141cc406Sopenharmony_ci      bloc8Decode (ccd);
12729141cc406Sopenharmony_ci    }
12730141cc406Sopenharmony_ci
12731141cc406Sopenharmony_ci  /* build shading calibration data */
12732141cc406Sopenharmony_ci  memset (commit, 0x00, (3 * w + 5) * sizeof (int));
12733141cc406Sopenharmony_ci  for (x = ofst; x < w; x++)
12734141cc406Sopenharmony_ci    {
12735141cc406Sopenharmony_ci      commit[x] = calibration[x - ofst];
12736141cc406Sopenharmony_ci      commit[x + w] = calibration[x - ofst + w];
12737141cc406Sopenharmony_ci      commit[x + 2 * w] = calibration[x - ofst + 2 * w];
12738141cc406Sopenharmony_ci    }
12739141cc406Sopenharmony_ci  /* image data cropping coefficient  */
12740141cc406Sopenharmony_ci  commit[3 * w + 3] = 0xFF;
12741141cc406Sopenharmony_ci  commit[3 * w + 4] = 0xFF;
12742141cc406Sopenharmony_ci
12743141cc406Sopenharmony_ci  CMDSYNC (0x00);
12744141cc406Sopenharmony_ci  CMDSETGET (2, 0x10, motor);
12745141cc406Sopenharmony_ci  CMDSETGET (8, len, ccd);
12746141cc406Sopenharmony_ci  CMDSETGET (1, 0x08, lm9811);
12747141cc406Sopenharmony_ci  CMDSYNC (0xC2);
12748141cc406Sopenharmony_ci  CMDSETGET (4, 3 * w + 5, commit);
12749141cc406Sopenharmony_ci  free (commit);
12750141cc406Sopenharmony_ci  COMPLETIONWAIT;
12751141cc406Sopenharmony_ci
12752141cc406Sopenharmony_ci  if (color >= RGB_MODE)
12753141cc406Sopenharmony_ci    {
12754141cc406Sopenharmony_ci      /* picture height is scan area height minus y    */
12755141cc406Sopenharmony_ci      h = h - y;
12756141cc406Sopenharmony_ci      size = w * 3 * h;
12757141cc406Sopenharmony_ci    }
12758141cc406Sopenharmony_ci  else
12759141cc406Sopenharmony_ci    {
12760141cc406Sopenharmony_ci      h = h - y - 1;
12761141cc406Sopenharmony_ci      size = w * h;
12762141cc406Sopenharmony_ci    }
12763141cc406Sopenharmony_ci  DBG (128,
12764141cc406Sopenharmony_ci       "leftShadingCalibration610p: trying to read 0x%06X bytes ... (%s:%d)\n",
12765141cc406Sopenharmony_ci       size, __FILE__, __LINE__);
12766141cc406Sopenharmony_ci  CMDGETBUF (4, size, data);
12767141cc406Sopenharmony_ci  if (DBG_LEVEL > 128)
12768141cc406Sopenharmony_ci    DumpNB (3 * w, h, data, NULL);
12769141cc406Sopenharmony_ci
12770141cc406Sopenharmony_ci  /* XXX STEF XXX */
12771141cc406Sopenharmony_ci  /* build coefficients for the 25 left pixels */
12772141cc406Sopenharmony_ci  /* and compute gamma correction ?            */
12773141cc406Sopenharmony_ci
12774141cc406Sopenharmony_ci  free (data);
12775141cc406Sopenharmony_ci  TRACE (16, "leftShadingCalibration610p end ...\n");
12776141cc406Sopenharmony_ci  return 1;
12777141cc406Sopenharmony_ci}
12778