1 /** @file u12-hw.c
2 * @brief The HW-access functions to the U12 backend stuff.
3 *
4 * Copyright (c) 2003-2004 Gerhard Jaeger <gerhard@gjaeger.de>
5 *
6 * History:
7 * - 0.01 - initial version
8 * - 0.02 - cleanup
9 * - added lampTimer stuff
10 * - fixed issue for Genius device - reported by
11 * Jose Alberto Reguero <jareguero@telefonica.net>
12 * .
13 * <hr>
14 * This file is part of the SANE package.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of the
19 * License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28 *
29 * As a special exception, the authors of SANE give permission for
30 * additional uses of the libraries contained in this release of SANE.
31 *
32 * The exception is that, if you link a SANE library with other files
33 * to produce an executable, this does not by itself cause the
34 * resulting executable to be covered by the GNU General Public
35 * License. Your use of that executable is in no way restricted on
36 * account of linking the SANE library code into it.
37 *
38 * This exception does not, however, invalidate any other reasons why
39 * the executable file might be covered by the GNU General Public
40 * License.
41 *
42 * If you submit changes to SANE to the maintainers to be included in
43 * a subsequent release, you agree by submitting the changes that
44 * those changes may be distributed with this exception intact.
45 *
46 * If you write modifications of your own for SANE, it is your choice
47 * whether to permit this exception to apply to your modifications.
48 * If you do not wish that, delete this exception notice.
49 * <hr>
50 */
51
52 #define _TEST_SIZE 1000
53
54 /*************************** some local vars *********************************/
55
56 static RegDef u12CcdStop[] = {
57 /* this was the original sequence from parport backend*/
58 #if 0
59 #define _STOP_LEN 13
60
61 {0x41, 0xff}, {0x42, 0xff}, {0x60, 0xff}, {0x61, 0xff},
62 {0x4b, 0xff}, {0x4c, 0xff}, {0x4d, 0xff}, {0x4e, 0xff},
63 {0x2a, 0x01}, {0x2b, 0x00}, {0x2d, 0x00}, {0x1b, 0x19}, {0x15, 0x00}
64 #else
65 #define _STOP_LEN 29
66 /* this is what we see from usb-snoop... */
67 {0x60, 0xff}, {0x61, 0xff}, {0x1b, 0x19}, {0x15, 0x00}, {0x20, 0x14},
68 {0x2c, 0x02}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00}, {0x3c, 0x00},
69 {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00}, {0x44, 0x00}, {0x45, 0x01},
70 {0x46, 0x00}, {0x47, 0x00}, {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x09},
71 {0x4b, 0x00}, {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x01}, {0x50, 0x00},
72 {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x01}, {0x67, 0x00}
73 #endif
74 };
75
76 /**
77 */
u12hw_SelectLampSource(U12_Device * dev)78 static void u12hw_SelectLampSource( U12_Device *dev )
79 {
80 dev->regs.RD_ScanControl &= (~_SCAN_LAMPS_ON);
81
82 if( dev->DataInf.dwScanFlag & (_SCANDEF_TPA)) {
83 dev->regs.RD_ScanControl |= _SCAN_TPALAMP_ON;
84 } else {
85 dev->regs.RD_ScanControl |= _SCAN_NORMALLAMP_ON;
86 }
87 }
88
89 /** as the function name says
90 */
u12hw_PutToIdleMode(U12_Device * dev)91 static void u12hw_PutToIdleMode( U12_Device *dev )
92 {
93 DBG( _DBG_INFO, "CCD-Stop\n" );
94 u12io_DataToRegs( dev, (SANE_Byte*)u12CcdStop, _STOP_LEN );
95 }
96
97 /** program the CCD relevant stuff
98 */
u12hw_ProgramCCD(U12_Device * dev)99 static void u12hw_ProgramCCD( U12_Device *dev )
100 {
101 SANE_Byte *reg_val;
102
103 DBG( _DBG_INFO, "u12hw_ProgramCCD: 0x%08lx[%lu]\n",
104 (u_long)dev->CCDRegs,
105 ((u_long)dev->numCCDRegs * dev->shade.intermediate));
106
107 DBG( _DBG_INFO, " * %u regs * %u (intermediate)\n",
108 dev->numCCDRegs, dev->shade.intermediate );
109
110 reg_val = (SANE_Byte*)(dev->CCDRegs +
111 (u_long)dev->numCCDRegs * dev->shade.intermediate);
112
113 u12io_DataToRegs( dev, reg_val, dev->numCCDRegs );
114 }
115
116 /** init the stuff according to the buttons
117 */
u12hw_ButtonSetup(U12_Device * dev,SANE_Byte numButtons)118 static void u12hw_ButtonSetup( U12_Device *dev, SANE_Byte numButtons )
119 {
120 dev->Buttons = numButtons;
121
122 dev->regs.RD_MotorDriverType |= _BUTTON_DISABLE;
123 dev->MotorPower |= _BUTTON_DISABLE;
124 }
125
126 /** According to what we have detected, set the other stuff
127 */
u12hw_InitiateComponentModel(U12_Device * dev)128 static void u12hw_InitiateComponentModel( U12_Device *dev )
129 {
130 /* preset some stuff and do the differences later */
131 dev->Buttons = 0;
132 dev->ModelOriginY = 64;
133 dev->Tpa = SANE_FALSE;
134 dev->ModelCtrl = (_LED_ACTIVITY | _LED_CONTROL);
135
136 switch( dev->PCBID ) {
137
138 /* typical for Plustek OpticPro U12 and 1212U */
139 case _PLUSTEK_SCANNER:
140 DBG( _DBG_INFO, "We have a Plustek Scanner ;-)\n" );
141 break;
142
143 case _SCANNER_WITH_TPA:
144 DBG( _DBG_INFO, "Scanner has TPA\n" );
145 dev->Tpa = SANE_TRUE;
146 break;
147
148 case _SCANNER4Button:
149 DBG( _DBG_INFO, "Scanner has 4 Buttons\n" );
150 u12hw_ButtonSetup( dev, 4 );
151 break;
152
153 /* typical for Plustek OpticPro UT12 */
154 case _SCANNER4ButtonTPA:
155 DBG( _DBG_INFO, "Scanner has 4 Buttons & TPA\n" );
156 dev->Tpa = SANE_TRUE;
157 u12hw_ButtonSetup( dev, 4 );
158 break;
159
160 case _SCANNER5Button:
161 DBG( _DBG_INFO, "Scanner has 5 Buttons\n" );
162 dev->ModelOriginY += 20;
163 u12hw_ButtonSetup( dev, 5 );
164 break;
165
166 /* typical for Genius Colorpage HR6 */
167 case _SCANNER5ButtonTPA:
168 DBG( _DBG_INFO, "Scanner has 5 Buttons & TPA\n" );
169 dev->ModelOriginY += 20;
170 dev->Tpa = SANE_TRUE;
171 u12hw_ButtonSetup( dev, 5 );
172 break;
173
174 case _SCANNER1Button:
175 DBG( _DBG_INFO, "Scanner has 1 Button\n" );
176 u12hw_ButtonSetup( dev, 1 );
177 break;
178
179 case _SCANNER1ButtonTPA:
180 DBG( _DBG_INFO, "Scanner has 1 Button & TPA\n" );
181 dev->Tpa = SANE_TRUE;
182 u12hw_ButtonSetup( dev, 1 );
183 break;
184
185 case _AGFA_SCANNER:
186 DBG( _DBG_INFO, "Agfa Scanner\n" );
187 dev->ModelOriginY = 24; /* 1200 dpi */
188 break;
189
190 case _SCANNER2Button:
191 DBG( _DBG_INFO, "Scanner has 2 Buttons\n" );
192 dev->ModelOriginY -= 33;
193 u12hw_ButtonSetup( dev, 2 );
194 break;
195
196 default:
197 DBG( _DBG_INFO, "Default Model: U12\n" );
198 break;
199 }
200
201 #if 0
202 if( _MOTOR0_2003 == dev->MotorID ) {
203 dev->f2003 = SANE_TRUE;
204 dev->XStepMono = 10;
205 dev->XStepColor = 6;
206 dev->XStepBack = 5;
207 dev->regs.RD_MotorDriverType |= _MOTORR_STRONG;
208 } else {
209 #endif
210 dev->f2003 = SANE_FALSE;
211 dev->XStepMono = 8;
212 dev->XStepColor = 4;
213 dev->XStepBack = 5;
214 dev->regs.RD_MotorDriverType |= _MOTORR_WEAK;
215 /* } */
216 }
217
218 /**
219 */
220 static SANE_Status u12hw_InitAsic( U12_Device *dev, SANE_Bool shading )
221 {
222 SANE_Byte rb[6];
223 int c;
224
225 DBG( _DBG_INFO, "u12hw_InitAsic(%d)\n", shading );
226
227 /* get DAC and motor stuff */
228 dev->DACType = u12io_DataFromRegister( dev, REG_RESETCONFIG );
229 dev->MotorID = (SANE_Byte)(dev->DACType & _MOTOR0_MASK);
230
231 dev->regs.RD_MotorDriverType =
232 (SANE_Byte)((dev->DACType & _MOTOR0_MASK) >> 3);
233 dev->regs.RD_MotorDriverType |=
234 (SANE_Byte)((dev->DACType & _MOTOR1_MASK) >> 1);
235 dev->DACType &= _ADC_MASK;
236
237 dev->MotorPower = dev->regs.RD_MotorDriverType | _MOTORR_STRONG;
238
239 /*get CCD and PCB ID */
240 dev->PCBID = u12io_DataFromRegister( dev, REG_CONFIG );
241 dev->CCDID = dev->PCBID & 0x07;
242 dev->PCBID &= 0xf0;
243
244 if( _AGFA_SCANNER == dev->PCBID )
245 dev->DACType = _DA_WOLFSON8141;
246
247 DBG( _DBG_INFO, "* PCB-ID=0x%02x, CCD-ID=0x%02x, DAC-TYPE=0x%02x\n",
248 dev->PCBID, dev->CCDID, dev->DACType );
249
250 u12hw_InitiateComponentModel( dev );
251 u12ccd_InitCCDandDAC( dev, shading );
252
253 dev->regs.RD_Model1Control = _CCD_SHIFT_GATE;
254 if( dev->Buttons != 0 )
255 dev->regs.RD_Model1Control += _BUTTON_MODE;
256
257 if( dev->shade.intermediate & _ScanMode_Mono )
258 dev->regs.RD_Model1Control += _SCAN_GRAYTYPE;
259
260 DBG( _DBG_INFO, "* MotorDrvType = 0x%02x\n", dev->regs.RD_MotorDriverType);
261 DBG( _DBG_INFO, "* Model1Cntrl = 0x%02x\n", dev->regs.RD_Model1Control );
262
263 #if 0
264 u12io_DataToRegister( dev, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType);
265 u12io_DataToRegister( dev, REG_WAITSTATEINSERT, 4 );
266 u12io_DataToRegister( dev, REG_MODEL1CONTROL, dev->regs.RD_Model1Control );
267 #else
268 c = 0;
269 _SET_REG( rb, c, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType);
270 _SET_REG( rb, c, REG_WAITSTATEINSERT, 4 );
271 _SET_REG( rb, c, REG_MODEL1CONTROL, dev->regs.RD_Model1Control );
272 u12io_DataToRegs( dev, rb, c );
273 #endif
274
275 u12hw_ProgramCCD( dev );
276 DBG( _DBG_INFO, "u12hw_InitAsic done.\n" );
277 return SANE_STATUS_GOOD;
278 }
279
280 /**
281 */
282 static void u12hw_ControlLampOnOff( U12_Device *dev )
283 {
284 SANE_Byte lampStatus;
285
286 dev->warmupNeeded = SANE_TRUE;
287
288 lampStatus = dev->regs.RD_ScanControl & _SCAN_LAMPS_ON;
289
290 if ( dev->lastLampStatus != lampStatus ) {
291
292 DBG( _DBG_INFO, "* Using OTHER Lamp --> warmup needed\n" );
293 dev->lastLampStatus = lampStatus;
294
295 u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl );
296 return;
297 }
298
299 dev->warmupNeeded = SANE_FALSE;
300 DBG( _DBG_INFO, "* Using SAME Lamp --> no warmup needed\n" );
301 }
302
303 /** set all necessary register contents
304 */
305 static void u12hw_SetGeneralRegister( U12_Device *dev )
306 {
307 DBG( _DBG_INFO, "u12hw_SetGeneralRegister()\n" );
308
309 dev->scan.motorBackward = SANE_FALSE;
310 dev->scan.refreshState = SANE_FALSE;
311
312 if( COLOR_BW == dev->DataInf.wPhyDataType )
313 dev->regs.RD_ScanControl = _SCAN_BITMODE;
314 else {
315 if( dev->DataInf.wPhyDataType <= COLOR_TRUE24 )
316 dev->regs.RD_ScanControl = _SCAN_BYTEMODE;
317 else
318 dev->regs.RD_ScanControl = _SCAN_12BITMODE;
319 }
320
321 u12hw_SelectLampSource( dev );
322
323 dev->regs.RD_ModelControl = (_LED_CONTROL | _LED_ACTIVITY);
324 if( dev->shade.intermediate & _ScanMode_AverageOut )
325 dev->regs.RD_ModelControl |= _MODEL_DPI300;
326 else
327 dev->regs.RD_ModelControl |= _MODEL_DPI600;
328
329 dev->regs.RD_Motor0Control = _MotorOn | _MotorHQuarterStep | _MotorPowerEnable;
330 dev->regs.RD_ScanControl1 = _SCANSTOPONBUFFULL | _MFRC_BY_XSTEP;
331 dev->regs.RD_StepControl = _MOTOR0_SCANSTATE;
332 }
333
334 /**
335 */
336 static void u12hw_SetupPreviewCondition( U12_Device *dev )
337 {
338 int i, c;
339 SANE_Byte rb[100];
340
341 DBG( _DBG_INFO, "u12_SetupPreviewCondition()\n" );
342
343 u12hw_SetGeneralRegister( dev );
344
345 u12io_RegisterToScanner( dev, REG_RESETMTSC );
346 _DODELAY(250);
347
348 /* ------- Set the max. read fifo to Asic ------- */
349 memset( dev->scanStates, 0, _SCANSTATE_BYTES );
350 if( dev->DataInf.xyAppDpi.x >= 38 ) { /* 38 <= x <= 75 */
351
352 for(i = 0; i < _SCANSTATE_BYTES; i++ )
353 dev->scanStates[i] = 0xad;
354
355 } else if( dev->DataInf.xyAppDpi.x >= 19 ) { /* 19 <= x <= 30(37) */
356
357 u_short *pState = (u_short*)dev->scanStates;
358
359 for( i = 0; i < (_SCANSTATE_BYTES / 2); i++ )
360 pState[i] = 0x89ac;
361
362 } else { /* 16 <= x <= 18 */
363
364 u_long *pState = (u_long*)dev->scanStates;
365
366 for(i = 0; i < (_SCANSTATE_BYTES / 4); i++)
367 pState[i] = 0x888889ac;
368 }
369
370 dev->regs.RD_BufFullSize = dev->DataInf.dwAppPixelsPerLine *
371 ((dev->DataInf.xyPhyDpi.y * dev->max_y + 299) / 300) + 1;
372 if( dev->regs.RD_BufFullSize > _SIZE_BLUEFIFO )
373 dev->regs.RD_BufFullSize = _SIZE_BLUEFIFO -
374 dev->DataInf.dwAppPixelsPerLine - 1;
375
376 dev->scan.dwMaxReadFifo =
377 dev->scan.dwMinReadFifo = dev->DataInf.dwAppPixelsPerLine *2 ;
378
379 if( dev->scan.dwMinReadFifo < 1024)
380 dev->scan.dwMinReadFifo = dev->scan.dwMaxReadFifo = 1024;
381
382 dev->scan.dwMaxReadFifo += (dev->DataInf.dwAsicBytesPerPlane / 2);
383
384 if( dev->DataInf.wPhyDataType > COLOR_256GRAY )
385 dev->scan.bFifoSelect = REG_BFIFOOFFSET;
386 else
387 dev->scan.bFifoSelect = REG_GFIFOOFFSET;
388
389 dev->regs.RD_BufFullSize = _SIZE_BLUEFIFO;
390
391 dev->regs.RD_LineControl = _LOBYTE(dev->shade.wExposure);
392 dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure);
393 dev->regs.RD_XStepTime = _LOBYTE(dev->shade.wXStep);
394 dev->regs.RD_ExtXStepTime = _HIBYTE(dev->shade.wXStep);
395 dev->regs.RD_Motor0Control = _FORWARD_MOTOR;
396 dev->regs.RD_StepControl = _MOTOR0_SCANSTATE | _MOTOR_FREERUN;
397 dev->regs.RD_ModeControl = _ModeScan;
398
399 if( dev->DataInf.wPhyDataType == COLOR_BW ) {
400 dev->regs.RD_ScanControl = _SCAN_BITMODE;
401 } else if( dev->DataInf.wPhyDataType <= COLOR_TRUE24 )
402 dev->regs.RD_ScanControl = _SCAN_BYTEMODE;
403 else {
404 dev->regs.RD_ScanControl = _SCAN_12BITMODE;
405 }
406
407 dev->regs.RD_ScanControl |= _SCAN_1ST_AVERAGE;
408 u12hw_SelectLampSource( dev );
409
410 dev->regs.RD_MotorTotalSteps = (dev->DataInf.crImage.cy * 4) +
411 (dev->f0_8_16 ? 32 : 16) +
412 (dev->scan.bDiscardAll ? 32 : 0);
413 DBG( _DBG_INFO, "* RD_MotorTotalSteps = 0x%04x\n",
414 dev->regs.RD_MotorTotalSteps);
415
416 dev->regs.RD_ScanControl1 = (_MTSC_ENABLE | _SCANSTOPONBUFFULL |
417 _MFRC_RUNSCANSTATE | _MFRC_BY_XSTEP);
418 DBG( _DBG_INFO, "* RD_ScanControl1 = 0x%02x\n", dev->regs.RD_ScanControl1);
419
420 dev->regs.RD_Dpi = dev->DataInf.xyPhyDpi.x;
421
422 dev->regs.RD_Origin = (u_short)(dev->adj.leftNormal*2+_DATA_ORIGIN_X);
423 dev->regs.RD_Origin += dev->DataInf.crImage.x;
424
425 if( dev->shade.intermediate & _ScanMode_AverageOut )
426 dev->regs.RD_Origin >>= 1;
427
428 if( dev->DataInf.wPhyDataType == COLOR_BW )
429 dev->regs.RD_Pixels = dev->DataInf.dwAsicBytesPerPlane;
430 else
431 dev->regs.RD_Pixels = dev->DataInf.dwAppPixelsPerLine;
432
433 /* ------- Wait for scan state stop ------- */
434 u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle );
435
436 u12io_DownloadScanStates( dev );
437
438 c = 0;
439 _SET_REG( rb, c, REG_LINECONTROL, dev->regs.RD_LineControl );
440 _SET_REG( rb, c, REG_EXTENDEDLINECONTROL,
441 dev->regs.RD_ExtLineControl);
442 _SET_REG( rb, c, REG_XSTEPTIME, dev->regs.RD_XStepTime );
443 _SET_REG( rb, c, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime );
444 _SET_REG( rb, c, REG_MOTORDRVTYPE,
445 dev->regs.RD_MotorDriverType );
446 _SET_REG( rb, c, REG_STEPCONTROL, dev->regs.RD_StepControl );
447 _SET_REG( rb, c, REG_MOTOR0CONTROL, dev->regs.RD_Motor0Control );
448 _SET_REG( rb, c, REG_MODELCONTROL, dev->regs.RD_ModelControl );
449 _SET_REG( rb, c, REG_DPILO, (_LOBYTE(dev->regs.RD_Dpi)));
450 _SET_REG( rb, c, REG_DPIHI, (_HIBYTE(dev->regs.RD_Dpi)));
451 _SET_REG( rb, c, REG_SCANPOSLO, (_LOBYTE(dev->regs.RD_Origin)));
452 _SET_REG( rb, c, REG_SCANPOSHI,(_HIBYTE(dev->regs.RD_Origin)));
453 _SET_REG( rb, c, REG_WIDTHPIXELLO,(_LOBYTE(dev->regs.RD_Pixels)));
454 _SET_REG( rb, c, REG_WIDTHPIXELHI,(_HIBYTE(dev->regs.RD_Pixels)));
455 _SET_REG( rb, c, REG_THRESHOLDLO,
456 (_LOBYTE(dev->regs.RD_ThresholdControl)));
457 _SET_REG( rb, c, REG_THRESHOLDHI,
458 (_HIBYTE(dev->regs.RD_ThresholdControl)));
459 _SET_REG( rb, c, REG_MOTORTOTALSTEP0,
460 (_LOBYTE(dev->regs.RD_MotorTotalSteps)));
461 _SET_REG( rb, c, REG_MOTORTOTALSTEP1,
462 (_HIBYTE(dev->regs.RD_MotorTotalSteps)));
463 _SET_REG( rb, c, REG_SCANCONTROL, dev->regs.RD_ScanControl);
464 u12io_DataToRegs( dev, rb, c );
465 _DODELAY(100);
466
467 u12io_RegisterToScanner( dev, REG_INITDATAFIFO );
468 }
469
470 /**
471 */
472 static void u12hw_SetupScanningCondition( U12_Device *dev )
473 {
474 TimerDef timer;
475 u_long channel;
476 int c;
477 SANE_Byte state;
478 SANE_Byte rb[100];
479 SANE_Byte *pState;
480
481 DBG( _DBG_INFO, "u12_SetupScanningCondition()\n" );
482
483 u12hw_SetGeneralRegister( dev );
484
485 u12io_RegisterToScanner( dev, REG_RESETMTSC );
486 _DODELAY(250);
487
488 /* ------- Setup MinRead/MaxRead Fifo size ------- */
489 if( dev->DataInf.wPhyDataType <= COLOR_TRUE24 ) {
490 dev->scan.dwMaxReadFifo =
491 dev->scan.dwMinReadFifo = dev->DataInf.dwAsicBytesPerPlane * 2;
492 } else {
493 dev->scan.dwMaxReadFifo =
494 dev->scan.dwMinReadFifo = dev->DataInf.dwAppPixelsPerLine << 1;
495 }
496
497 if( dev->scan.dwMinReadFifo < 1024)
498 dev->scan.dwMinReadFifo = dev->scan.dwMaxReadFifo = 1024;
499
500 dev->scan.dwMaxReadFifo += (dev->DataInf.dwAsicBytesPerPlane / 2);
501
502 DBG( _DBG_INFO, "* MinReadFifo=%lu, MaxReadFifo=%lu\n",
503 dev->scan.dwMinReadFifo, dev->scan.dwMaxReadFifo );
504
505 /* ------- Set the max. read fifo to asic ------- */
506 if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
507
508 dev->scan.bFifoSelect = REG_BFIFOOFFSET;
509
510 if( !dev->scan.p48BitBuf.pb ) {
511
512 long lRed, lGreen;
513
514 lRed = (_SIZE_REDFIFO - _SIZE_BLUEFIFO) /
515 dev->DataInf.dwAsicBytesPerPlane - dev->scan.bd_rk.wRedKeep;
516
517 lGreen = (_SIZE_GREENFIFO - _SIZE_BLUEFIFO) /
518 dev->DataInf.dwAsicBytesPerPlane - dev->scan.gd_gk.wGreenKeep;
519
520 if((lRed < 0) || (lGreen < 0)) {
521
522 if( lRed < lGreen ) {
523 channel = _RED_FULLSIZE << 16;
524 dev->regs.RD_BufFullSize = _SIZE_REDFIFO;
525 lGreen = lRed;
526 } else {
527 channel = _GREEN_FULLSIZE << 16;
528 dev->regs.RD_BufFullSize = _SIZE_GREENFIFO;
529 }
530
531 lGreen = (u_long)(-lGreen * dev->DataInf.dwAsicBytesPerPlane);
532
533 if( dev->DataInf.wPhyDataType > COLOR_TRUE24 )
534 lGreen >>= 1;
535
536 dev->scan.dwMinReadFifo += (u_long)lGreen;
537 dev->scan.dwMaxReadFifo += (u_long)lGreen;
538
539 } else {
540 channel = _BLUE_FULLSIZE << 16;
541 dev->regs.RD_BufFullSize = _SIZE_BLUEFIFO;
542 }
543 } else {
544 channel = _BLUE_FULLSIZE << 16;
545 dev->regs.RD_BufFullSize = _SIZE_BLUEFIFO;
546 }
547 } else {
548 dev->scan.bFifoSelect = REG_GFIFOOFFSET;
549 channel = _GREEN_FULLSIZE << 16;
550 dev->regs.RD_BufFullSize = _SIZE_GRAYFIFO;
551 }
552
553 dev->regs.RD_BufFullSize -= (dev->DataInf.dwAsicBytesPerPlane << 1);
554
555 if( dev->DataInf.wPhyDataType > COLOR_TRUE24 )
556 dev->regs.RD_BufFullSize >>= 1;
557
558 dev->regs.RD_BufFullSize |= channel;
559
560 dev->scan.bRefresh = (SANE_Byte)(dev->scan.dwInterval << 1);
561 dev->regs.RD_LineControl = _LOBYTE(dev->shade.wExposure);
562 dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure);
563 dev->regs.RD_XStepTime = _LOBYTE(dev->shade.wXStep);
564 dev->regs.RD_ExtXStepTime = _HIBYTE(dev->shade.wXStep);
565 dev->regs.RD_Motor0Control = _FORWARD_MOTOR;
566 dev->regs.RD_StepControl = _MOTOR0_SCANSTATE;
567 dev->regs.RD_ModeControl = _ModeScan/*(_ModeScan | _ModeFifoGSel)*/;
568
569 DBG( _DBG_INFO, "* bRefresh = %i\n", dev->scan.bRefresh );
570
571 if( dev->DataInf.wPhyDataType == COLOR_BW ) {
572 dev->regs.RD_ScanControl = _SCAN_BITMODE;
573 } else if( dev->DataInf.wPhyDataType <= COLOR_TRUE24 )
574 dev->regs.RD_ScanControl = _SCAN_BYTEMODE;
575 else {
576 dev->regs.RD_ScanControl = _SCAN_12BITMODE;
577 }
578
579 dev->regs.RD_ScanControl |= _SCAN_1ST_AVERAGE;
580 u12hw_SelectLampSource( dev );
581
582 DBG( _DBG_INFO, "* RD_ScanControl = 0x%02x\n", dev->regs.RD_ScanControl );
583
584 DBG( _DBG_INFO, "* ImageInfo: x=%u,y=%u,dx=%u,dy=%u\n",
585 dev->DataInf.crImage.x, dev->DataInf.crImage.y,
586 dev->DataInf.crImage.cx, dev->DataInf.crImage.cy );
587
588 dev->regs.RD_MotorTotalSteps = (dev->DataInf.crImage.cy * 4) +
589 (dev->f0_8_16 ? 32 : 16) +
590 (dev->scan.bDiscardAll ? 32 : 0);
591 DBG( _DBG_INFO, "* RD_MotorTotalSteps = 0x%04x\n",
592 dev->regs.RD_MotorTotalSteps);
593
594 dev->regs.RD_ScanControl1 = (_MTSC_ENABLE | _SCANSTOPONBUFFULL |
595 _MFRC_RUNSCANSTATE | _MFRC_BY_XSTEP);
596 DBG( _DBG_INFO, "* RD_ScanControl1 = 0x%02x\n", dev->regs.RD_ScanControl1);
597
598 dev->regs.RD_Dpi = dev->DataInf.xyPhyDpi.x;
599
600 if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA )) {
601 dev->regs.RD_Origin = (u_short)(dev->adj.leftNormal*2+_DATA_ORIGIN_X);
602
603 } else if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency ) {
604 dev->regs.RD_Origin = (u_short)dev->scan.posBegin;
605 } else {
606 dev->regs.RD_Origin = (u_short)dev->scan.negBegin;
607 }
608 dev->regs.RD_Origin += dev->DataInf.crImage.x;
609
610 if( dev->shade.intermediate & _ScanMode_AverageOut )
611 dev->regs.RD_Origin >>= 1;
612
613 if( dev->DataInf.wPhyDataType == COLOR_BW )
614 dev->regs.RD_Pixels = (u_short)dev->DataInf.dwAsicBytesPerPlane;
615 else
616 dev->regs.RD_Pixels = (u_short)dev->DataInf.dwAppPixelsPerLine;
617
618 DBG( _DBG_INFO, "* RD_Origin = %u, RD_Pixels = %u\n",
619 dev->regs.RD_Origin, dev->regs.RD_Pixels );
620
621 /* ------- Prepare scan states ------- */
622 memset( dev->scanStates, 0, _SCANSTATE_BYTES );
623 memset( dev->bufs.b1.pReadBuf, 0, _NUMBER_OF_SCANSTEPS );
624
625 if( dev->DataInf.wPhyDataType <= COLOR_256GRAY )
626 state = (_SS_MONO | _SS_STEP);
627 else
628 state = (_SS_COLOR | _SS_STEP);
629
630 for( channel = _NUMBER_OF_SCANSTEPS, pState = dev->bufs.b1.pReadBuf;
631 channel; channel -= dev->scan.dwInterval ) {
632 *pState = state;
633 pState += dev->scan.dwInterval;
634 }
635 for( channel = 0, pState = dev->bufs.b1.pReadBuf;
636 channel < _SCANSTATE_BYTES; channel++) {
637 dev->scanStates[channel] = pState[0] | (pState[1] << 4);
638 pState += 2;
639 }
640
641 /* ------- Wait for scan state stop ------- */
642 u12io_StartTimer( &timer, _SECOND * 2 );
643
644 u12io_ResetFifoLen();
645 while(!(u12io_GetScanState( dev ) & _SCANSTATE_STOP) &&
646 !u12io_CheckTimer(&timer));
647 u12io_DownloadScanStates( dev );
648
649 c = 0;
650 _SET_REG( rb, c, REG_LINECONTROL, dev->regs.RD_LineControl );
651 _SET_REG( rb, c, REG_EXTENDEDLINECONTROL,
652 dev->regs.RD_ExtLineControl);
653 _SET_REG( rb, c, REG_XSTEPTIME, dev->regs.RD_XStepTime );
654 _SET_REG( rb, c, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime );
655 _SET_REG( rb, c, REG_MOTORDRVTYPE,
656 dev->regs.RD_MotorDriverType );
657 _SET_REG( rb, c, REG_STEPCONTROL, dev->regs.RD_StepControl );
658 _SET_REG( rb, c, REG_MOTOR0CONTROL, dev->regs.RD_Motor0Control );
659 _SET_REG( rb, c, REG_MODELCONTROL, dev->regs.RD_ModelControl );
660 _SET_REG( rb, c, REG_DPILO, (_LOBYTE(dev->regs.RD_Dpi)));
661 _SET_REG( rb, c, REG_DPIHI, (_HIBYTE(dev->regs.RD_Dpi)));
662 _SET_REG( rb, c, REG_SCANPOSLO, (_LOBYTE(dev->regs.RD_Origin)));
663 _SET_REG( rb, c, REG_SCANPOSHI,(_HIBYTE(dev->regs.RD_Origin)));
664 _SET_REG( rb, c, REG_WIDTHPIXELLO,(_LOBYTE(dev->regs.RD_Pixels)));
665 _SET_REG( rb, c, REG_WIDTHPIXELHI,(_HIBYTE(dev->regs.RD_Pixels)));
666 _SET_REG( rb, c, REG_THRESHOLDLO,
667 (_LOBYTE(dev->regs.RD_ThresholdControl)));
668 _SET_REG( rb, c, REG_THRESHOLDHI,
669 (_HIBYTE(dev->regs.RD_ThresholdControl)));
670 _SET_REG( rb, c, REG_MOTORTOTALSTEP0,
671 (_LOBYTE(dev->regs.RD_MotorTotalSteps)));
672 _SET_REG( rb, c, REG_MOTORTOTALSTEP1,
673 (_HIBYTE(dev->regs.RD_MotorTotalSteps)));
674 _SET_REG( rb, c, REG_SCANCONTROL, dev->regs.RD_ScanControl);
675 u12io_DataToRegs( dev, rb, c );
676 _DODELAY(100);
677
678 u12io_RegisterToScanner( dev, REG_INITDATAFIFO );
679 }
680
681 /**
682 */
683 static SANE_Status u12hw_Memtest( U12_Device *dev )
684 {
685 SANE_Byte tmp;
686 SANE_Byte buf[_TEST_SIZE];
687 int i;
688
689 DBG( _DBG_INFO, "u12hw_Memtest()\n" );
690
691 /* prepare buffer */
692 for( i = 0; i < _TEST_SIZE; i++ ) {
693 buf[i] = (SANE_Byte)((i * 3) & 0xff);
694 }
695
696 /* avoid switching to Lamp0, when previously scanned in transp./neg mode */
697 tmp = dev->lastLampStatus + _SCAN_BYTEMODE;
698 u12io_DataToRegister( dev, REG_SCANCONTROL, tmp );
699
700 u12io_DataToRegister( dev, REG_MODECONTROL, _ModeMappingMem );
701 u12io_DataToRegister( dev, REG_MEMORYLO, 0 );
702 u12io_DataToRegister( dev, REG_MEMORYHI, 0 );
703
704 /* fill to buffer */
705 u12io_MoveDataToScanner( dev, buf, _TEST_SIZE );
706
707 u12io_DataToRegister( dev, REG_MODECONTROL, _ModeMappingMem );
708 u12io_DataToRegister( dev, REG_MEMORYLO, 0 );
709 u12io_DataToRegister( dev, REG_MEMORYHI, 0 );
710
711 u12io_DataToRegister( dev, REG_WIDTHPIXELLO, 0 );
712 u12io_DataToRegister( dev, REG_WIDTHPIXELHI, 5 );
713
714 memset( buf, 0, _TEST_SIZE );
715
716 dev->regs.RD_ModeControl = _ModeReadMappingMem;
717 u12io_ReadData( dev, buf, _TEST_SIZE );
718
719 for( i = 0; i < _TEST_SIZE; i++ ) {
720 if((SANE_Byte)((i * 3) & 0xff) != buf[i] ) {
721 DBG( _DBG_ERROR, "* Memtest failed at pos %u: %u != %u\n",
722 i+1, buf[i], (SANE_Byte)((i * 3) & 0xff) );
723 return SANE_STATUS_INVAL;
724 }
725 }
726 DBG( _DBG_INFO, "* Memtest passed.\n" );
727 return SANE_STATUS_GOOD;
728 }
729
730 /** check if ASIC can be accessed, if the version is supported and the memory
731 * is also accessible...
732 */
733 static SANE_Status u12hw_CheckDevice( U12_Device *dev )
734 {
735 #ifndef _FAKE_DEVICE
736 SANE_Byte tmp;
737 SANE_Byte rb[8];
738 int c;
739
740 #if 1
741 if( !u12io_IsConnected( dev )) {
742
743 if( !u12io_OpenScanPath( dev ))
744 return SANE_STATUS_IO_ERROR;
745 }
746 #else
747 /* u12io_IsConnected( dev ); */
748 if( !u12io_OpenScanPath( dev ))
749 return SANE_STATUS_IO_ERROR;
750 #endif
751
752 /* some setup stuff... */
753 tmp = u12io_GetExtendedStatus( dev );
754 DBG( _DBG_INFO, "* REG_STATUS2 = 0x%02x\n", tmp );
755 if( tmp & _REFLECTIONLAMP_ON ) {
756 DBG( _DBG_INFO, "* Normal lamp is ON\n" );
757 dev->lastLampStatus = _SCAN_NORMALLAMP_ON;
758 } else if( tmp & _TPALAMP_ON ) {
759 dev->lastLampStatus = _SCAN_TPALAMP_ON;
760 DBG( _DBG_INFO, "* TPA lamp is ON\n" );
761 }
762
763 c = 0;
764 _SET_REG( rb, c, REG_PLLPREDIV, 1 );
765 _SET_REG( rb, c, REG_PLLMAINDIV, 0x20 );
766 _SET_REG( rb, c, REG_PLLPOSTDIV, 2 );
767 _SET_REG( rb, c, REG_CLOCKSELECTOR, 2 );
768 u12io_DataToRegs( dev, rb, c );
769
770 #if 0
771 return u12hw_Memtest( dev );
772 #else
773 if( !dev->initialized )
774 return u12hw_Memtest( dev );
775 else
776 return SANE_STATUS_GOOD;
777 #endif
778 #else
779 _VAR_NOT_USED( dev );
780 return SANE_STATUS_GOOD;
781 #endif
782 }
783
784 /* prototypes... */
785 static void u12motor_PositionModuleToHome( U12_Device *);
786 static void u12motor_ToHomePosition( U12_Device *, SANE_Bool );
787
788 /**
789 */
790 static void u12hw_CancelSequence( U12_Device *dev )
791 {
792 int c = 0;
793 SANE_Byte rb[6];
794
795 DBG( _DBG_INFO, "u12hw_CancelSequence()\n" );
796
797 u12motor_PositionModuleToHome( dev );
798
799 u12motor_ToHomePosition( dev, SANE_TRUE );
800
801 u12io_DataToRegister( dev, REG_MOTOR0CONTROL, 0 );
802 u12io_DataToRegister( dev, REG_MODELCONTROL, 0x1a );
803
804 u12hw_PutToIdleMode( dev );
805
806 if( strcmp( dev->usbId, "0x0458-0x2004" ))
807 u12io_SoftwareReset( dev );
808
809 u12motor_PositionModuleToHome( dev );
810
811 u12io_DataToRegister( dev, REG_SCANCONTROL, 0x05 );
812 u12io_DataToRegister( dev, REG_MODELCONTROL, 0x1f );
813
814 u12hw_PutToIdleMode( dev );
815
816 u12io_DataToRegister( dev, REG_MODELCONTROL, 0x00 );
817
818 u12io_DataToRegister( dev, REG_ADCADDR, 0x01 );
819 u12io_DataToRegister( dev, REG_ADCDATA, 0x00 );
820 u12io_DataToRegister( dev, REG_ADCSERIALOUT, 0x00 );
821
822 _SET_REG( rb, c, REG_MODECONTROL, 0x19 );
823 _SET_REG( rb, c, REG_STEPCONTROL, 0xff );
824 _SET_REG( rb, c, REG_MOTOR0CONTROL, 0 );
825 u12io_DataToRegs( dev, rb, c );
826
827 u12io_CloseScanPath( dev );
828 }
829
830 /**
831 */
832 static SANE_Status u12hw_WarmupLamp( U12_Device *dev )
833 {
834 TimerDef timer;
835
836 DBG( _DBG_INFO, "u12hw_WarmupLamp()\n" );
837
838 if( dev->warmupNeeded ) {
839 DBG( _DBG_INFO, "* warming up...\n" );
840 u12io_StartTimer( &timer, _SECOND * dev->adj.warmup );
841 while( !u12io_CheckTimer( &timer )) {
842 if( u12io_IsEscPressed()) {
843 DBG( _DBG_INFO, "* CANCEL detected!\n" );
844 return SANE_STATUS_CANCELLED;
845 }
846 }
847 } else {
848 DBG( _DBG_INFO, "* skipped\n" );
849 }
850 return SANE_STATUS_GOOD;
851 }
852
853 /* FIXME: replace!!! */
854 static U12_Device *dev_xxx = NULL;
855
856 /** ISR to switch lamp off after time has elapsed
857 */
858 static void usb_LampTimerIrq( int sig )
859 {
860 SANE_Byte tmp;
861 int handle = -1;
862
863 if( NULL == dev_xxx )
864 return;
865
866 _VAR_NOT_USED( sig );
867 DBG( _DBG_INFO, "*** LAMP OFF!!! ***\n" );
868
869 if( -1 == dev_xxx->fd ) {
870
871 if( SANE_STATUS_GOOD == sanei_usb_open(dev_xxx->sane.name, &handle)) {
872 dev_xxx->fd = handle;
873 }
874 }
875
876 if( -1 != dev_xxx->fd ) {
877
878 if( !u12io_IsConnected( dev_xxx )) {
879
880 if( u12io_OpenScanPath( dev_xxx )) {
881
882 /* some setup stuff... */
883 tmp = u12io_GetExtendedStatus( dev_xxx );
884 if( tmp & _REFLECTIONLAMP_ON ) {
885 DBG( _DBG_INFO, "* Normal lamp is ON\n" );
886 } else if( tmp & _TPALAMP_ON ) {
887 DBG( _DBG_INFO, "* TPA lamp is ON\n" );
888 }
889
890 u12io_DataToRegister( dev_xxx, REG_SCANCONTROL, 0 );
891 u12io_CloseScanPath( dev_xxx );
892 }
893 }
894 }
895
896 if( -1 != handle ) {
897 dev_xxx->fd = -1;
898 sanei_usb_close( handle );
899 }
900 }
901
902 /**
903 */
904 static void u12hw_StartLampTimer( U12_Device *dev )
905 {
906 sigset_t block, pause_mask;
907 struct sigaction s;
908 #ifdef HAVE_SETITIMER
909 struct itimerval interval;
910 #endif
911
912 /* block SIGALRM */
913 sigemptyset( &block );
914 sigaddset ( &block, SIGALRM );
915 sigprocmask( SIG_BLOCK, &block, &pause_mask );
916
917 /* setup handler */
918 sigemptyset( &s.sa_mask );
919 sigaddset ( &s.sa_mask, SIGALRM );
920 s.sa_flags = 0;
921 s.sa_handler = usb_LampTimerIrq;
922
923 if( sigaction( SIGALRM, &s, NULL ) < 0 )
924 DBG( _DBG_ERROR, "Can't setup timer-irq handler\n" );
925
926 sigprocmask( SIG_UNBLOCK, &block, &pause_mask );
927
928 #ifdef HAVE_SETITIMER
929 /*
930 * define a one-shot timer
931 */
932 interval.it_value.tv_usec = 0;
933 interval.it_value.tv_sec = dev->adj.lampOff;
934 interval.it_interval.tv_usec = 0;
935 interval.it_interval.tv_sec = 0;
936
937 if( 0 != dev->adj.lampOff ) {
938 dev_xxx = dev;
939 setitimer( ITIMER_REAL, &interval, &dev->saveSettings );
940 DBG( _DBG_INFO, "Lamp-Timer started (using ITIMER)\n" );
941 }
942 #else
943 if( 0 != dev->adj.lampOff ) {
944 dev_xxx = dev;
945 alarm( dev->adj.lampOff );
946 DBG( _DBG_INFO, "Lamp-Timer started (using ALARM)\n" );
947 }
948 #endif
949 }
950
951 /**
952 */
953 static void u12hw_StopLampTimer( U12_Device *dev )
954 {
955 sigset_t block, pause_mask;
956
957 /* block SIGALRM */
958 sigemptyset( &block );
959 sigaddset ( &block, SIGALRM );
960 sigprocmask( SIG_BLOCK, &block, &pause_mask );
961
962 dev_xxx = NULL;
963
964 #ifdef HAVE_SETITIMER
965 if( 0 != dev->adj.lampOff )
966 setitimer( ITIMER_REAL, &dev->saveSettings, NULL );
967 #else
968 _VAR_NOT_USED( dev );
969 alarm( 0 );
970 #endif
971 DBG( _DBG_INFO, "Lamp-Timer stopped\n" );
972 }
973
974 /* END U12-HW.C .............................................................*/
975