• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* @file plustek-pp_motor.c
2  * @brief all functions for motor control
3  *
4  * based on sources acquired from Plustek Inc.
5  * Copyright (C) 1998 Plustek Inc.
6  * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de>
7  * also based on the work done by Rick Bronson
8  *
9  * History:
10  * - 0.30 - initial version
11  * - 0.31 - no changes
12  * - 0.32 - slight cosmetic changes
13  *        - added function MotorToHomePosition()
14  * - 0.33 - added additional debug-messages
15  *        - increased speed for returning to homeposition for Models >= 9630
16  *          (and ASIC 96003)
17  * - 0.34 - added FIFO overflow check in motorP96SetSpeed
18  *        - removed WaitBack() function from pScanData structure
19  *        - removed wStayMaxStep from pScanData structure
20  * - 0.35 - changed motorP96UpdateDataCurrentReadLine() to handle proper
21  *        - work of ASIC96003 based 600dpi models
22  * - 0.36 - merged motorP96WaitBack and motorP98WaitBack to motorWaitBack
23  *        - merged motorP96SetSpeed and motorP98SetSpedd to motorSetSpeed
24  *        - added Sensor-Check in function MotorToHomePosition
25  *        - reduced number of forward steps for MotorToHomePosition
26  * - 0.37 - removed function motorP96GetStartStopGap() - no longer used
27  *        - removed a_bStepDown1Table and a_bStepUp1Table
28  *        - removed // comments
29  *        - added A3I stuff
30  * - 0.38 - cosmetic changes
31  *        - added P12 stuff
32  * - 0.39 - Did some finetuning in MotorP98003ModuleForwardBackward()
33  *        - Fixed a problem, that could cause the driver to throw a
34  *          kernel exception
35  * - 0.40 - changed back to build 0.39-3 (disabled A3I stuff)
36  * - 0.41 - no changes
37  * - 0.42 - changed include names
38  * - 0.43 - no changes
39  * - 0.44 - fix format string issues, as Long types default to int32_t
40  *          now
41  * .
42  * <hr>
43  * This file is part of the SANE package.
44  *
45  * This program is free software; you can redistribute it and/or
46  * modify it under the terms of the GNU General Public License as
47  * published by the Free Software Foundation; either version 2 of the
48  * License, or (at your option) any later version.
49  *
50  * This program is distributed in the hope that it will be useful, but
51  * WITHOUT ANY WARRANTY; without even the implied warranty of
52  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
53  * General Public License for more details.
54  *
55  * You should have received a copy of the GNU General Public License
56  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
57  *
58  * As a special exception, the authors of SANE give permission for
59  * additional uses of the libraries contained in this release of SANE.
60  *
61  * The exception is that, if you link a SANE library with other files
62  * to produce an executable, this does not by itself cause the
63  * resulting executable to be covered by the GNU General Public
64  * License.  Your use of that executable is in no way restricted on
65  * account of linking the SANE library code into it.
66  *
67  * This exception does not, however, invalidate any other reasons why
68  * the executable file might be covered by the GNU General Public
69  * License.
70  *
71  * If you submit changes to SANE to the maintainers to be included in
72  * a subsequent release, you agree by submitting the changes that
73  * those changes may be distributed with this exception intact.
74  *
75  * If you write modifications of your own for SANE, it is your choice
76  * whether to permit this exception to apply to your modifications.
77  * If you do not wish that, delete this exception notice.
78  * <hr>
79  */
80 #include "plustek-pp_scan.h"
81 
82 /*************************** some definitions *********************************/
83 
84 /* #define _A3I_EN */
85 
86 /*
87  * adjustments for scanning in negative and tranparency mode
88  */
89 #define _NEG_SCANNINGPOS 	    770
90 #define _POS_SCANNINGPOS 	    660        /* original value was 710 */
91 
92 #define _P98_BACKMOVES			0x3d
93 #define _P98_FORWARDMOVES		0x3b		/* Origin = 3c */
94 
95 #define _P98003_BACKSTEPS	    120
96 #define _P98003_FORWARDSTEPS    120
97 
98 #define _P96_BACKMOVES			130
99 #define _P96_FORWARDMOVES		87   /* 95 */
100 #define _P96_FIFOOVERFLOWTHRESH	180
101 
102 
103 #define _COLORRUNTABLE_RED		0x11
104 #define _COLORRUNTABLE_GREEN	0x22
105 #define _COLORRUNTABLE_BLUE		0x44
106 
107 #define	_BW_ORIGIN				0x0D
108 #define	_GRAY_ORIGIN			0x0B
109 #define	_COLOR_ORIGIN			0x0B
110 
111 #define _P98003_YOFFSET			300
112 
113 /**************************** local vars *************************************/
114 
115 static TimerDef p98003MotorTimer;
116 
117 static UShort 	a_wMoveStepTable [_NUMBER_OF_SCANSTEPS];
118 static Byte		a_bScanStateTable[_SCANSTATE_TABLE_SIZE];
119 static Byte		a_bHalfStepTable [_NUMBER_OF_SCANSTEPS];
120 static Byte		a_bColorByteTable[_NUMBER_OF_SCANSTEPS];
121 static Byte		a_bColorsSum[8] = {0, 1, 1, 2, 1, 2, 2, 3};
122 
123 static pUShort	pwEndMoveStepTable  = a_wMoveStepTable  + _NUMBER_OF_SCANSTEPS;
124 static pUChar	pbEndColorByteTable = a_bColorByteTable + _NUMBER_OF_SCANSTEPS;
125 static pUChar	pbEndHalfStepTable  = a_bHalfStepTable  + _NUMBER_OF_SCANSTEPS;
126 
127 /*
128  * for the 96001/3 based units
129  */
130 static UShort wP96BaseDpi = 0;
131 
132 static Byte	a_bStepDown1Table[20]  = {3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
133 static Byte a_bStepUp1Table[20]    = {4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
134 static Byte	a_bMotorDown2Table[20] = {0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
135 
136 #ifndef _A3I_EN
137 static Byte	a_bHalfStep2Table[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
138 									 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
139 static Byte	a_bHalfStep4Table[16] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
140 static Byte	a_bHalfStep6Table[12] = {3,3,3,3,3,3,3,3,3,3,3,3};
141 static Byte	a_bHalfStep8Table[8]  = {4,4,4,4,4,4,4,4};
142 static Byte	a_bHalfStep10Table[8] = {5,5,5,5,5,5,5,5};
143 static Byte	a_bHalfStep12Table[6] = {6,6,6,6,6,6};
144 static Byte	a_bHalfStep14Table[6] = {7,7,7,7,7,7};
145 static Byte	a_bHalfStep16Table[4] = {8,8,8,8};
146 static Byte	a_bHalfStep18Table[4] = {9,9,9,9};
147 static Byte	a_bHalfStep20Table[4] = {10,10,10,10};
148 static Byte	a_bHalfStep22Table[4] = {11,11,11,11};
149 static Byte	a_bHalfStep24Table[4] = {12,12,12,12};
150 static Byte	a_bHalfStep26Table[4] = {13,13,13,13};
151 static Byte	a_bHalfStep28Table[4] = {14,14,14,14};
152 static Byte	a_bHalfStep30Table[4] = {15,15,15,15};
153 static Byte	a_bHalfStep32Table[2] = {16,16};
154 static Byte	a_bHalfStep34Table[2] = {17,17};
155 static Byte	a_bHalfStep36Table[2] = {18,18};
156 static Byte	a_bHalfStep38Table[2] = {19,19};
157 static Byte	a_bHalfStep40Table[2] = {20,20};
158 
159 
160 static pUChar a_pbHalfStepTables[20] = {
161 	a_bHalfStep2Table,  a_bHalfStep4Table,
162 	a_bHalfStep6Table,  a_bHalfStep8Table,
163 	a_bHalfStep10Table, a_bHalfStep12Table,
164 	a_bHalfStep14Table, a_bHalfStep16Table,
165 	a_bHalfStep18Table, a_bHalfStep20Table,
166 	a_bHalfStep22Table, a_bHalfStep24Table,
167 	a_bHalfStep26Table, a_bHalfStep28Table,
168 	a_bHalfStep30Table, a_bHalfStep32Table,
169 	a_bHalfStep34Table, a_bHalfStep36Table,
170 	a_bHalfStep38Table, a_bHalfStep40Table
171 };
172 #endif
173 
174 /*************************** local functions *********************************/
175 
176 /*.............................................................................
177  *
178  */
motorP96GetStartStopGap(pScanData ps,Bool fCheckState)179 static void motorP96GetStartStopGap( pScanData ps, Bool fCheckState )
180 {
181 	UChar bMotorCountDownIndex;
182 
183     if( fCheckState ) {
184 
185 		ps->bMotorStepTableNo = 0xff;
186 		if( ps->Scan.bModuleState == _MotorInNormalState )
187 	    	return;
188     }
189 
190     bMotorCountDownIndex = ps->bMotorSpeedData / 2;
191 
192     if( ps->bCurrentSpeed == 4 && ps->AsicReg.RD_Dpi < 80 )
193 		ps->bMotorStepTableNo = 4;
194     else
195 		if( ps->Scan.bModuleState == _MotorGoBackward )
196 		    ps->bMotorStepTableNo = a_bStepUp1Table[bMotorCountDownIndex];
197 		else
198 	    	ps->bMotorStepTableNo = a_bStepDown1Table[bMotorCountDownIndex];
199 }
200 
201 
202 
203 /*.............................................................................
204  * wait for the ScanState stop or ScanState reaches the dwScanStateCount
205  */
motorCheckMotorPresetLength(pScanData ps)206 static Bool motorCheckMotorPresetLength( pScanData ps )
207 {
208     Byte	 bScanState;
209 	TimerDef timer;
210 
211 	MiscStartTimer( &timer, (_SECOND * 4));
212     do {
213 
214 		bScanState = IOGetScanState( ps, _FALSE );
215 
216 		if (ps->fFullLength) {
217 		    if (!(bScanState & _SCANSTATE_STOP)) /* still running */
218 				if ((ULong)(bScanState & _SCANSTATE_MASK) != ps->dwScanStateCount )
219 				    continue;
220 		    return ps->fFullLength;
221 		}
222 
223  		if (bScanState & _SCANSTATE_STOP)
224 		    break;
225 
226 		/*
227 		 * the code may work for all units
228 		 */
229 		if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
230 
231 			if (bScanState < ps->bOldStateCount)
232 			    bScanState += _NUMBER_OF_SCANSTEPS;
233 
234 			bScanState -= ps->bOldStateCount;
235 
236 			if (bScanState >= 40)
237 			    return ps->fFullLength;
238 		}
239 
240     } while ( !MiscCheckTimer( &timer ));
241 
242 	_DODELAY(1);			 /* delay one ms */
243 
244     return ps->fFullLength;
245 }
246 
247 /*.............................................................................
248  * 1) Keep the valid content of a_bColorByteTable, and fill others to 0:
249  * BeginFill = ((bCurrentLineCount + DL) < 64) ? bCurrentLineCount + DL :
250  *						  bCurrentLineCount + DL - 64;
251  *	FillLength = 64 - DL
252  *	[NOTE] Keep the content of a_bColorByteTable that begin at
253  *	       bCurrentLineCount and in DL bytes
254  * 2) Keep the valid content of a_bHalfStepTable, and fill the others to 0:
255  * BeginFill = ((bCurrentLineCount + bCurrentSpeed / 2 + 1) < 64) ?
256  *		      bCurrentLineCount + bCurrentSpeed / 2 + 1 :
257  *		      bCurrentLineCount + bCurrentSpeed / 2 + 1 - 64;
258  *	FillLength = 64 - (bMotorSpeedData / 2 + 1);
259  */
motorClearColorByteTableLoop0(pScanData ps,Byte bColors)260 static void motorClearColorByteTableLoop0( pScanData ps, Byte bColors )
261 {
262 	ULong  dw;
263    	pUChar pb;
264 
265     if ((ps->bCurrentLineCount + bColors) >= _NUMBER_OF_SCANSTEPS) {
266 		pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + bColors -
267 							 _NUMBER_OF_SCANSTEPS);
268 	} else {
269 		pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + bColors);
270 	}
271 
272     for (dw = _NUMBER_OF_SCANSTEPS - bColors; dw; dw--) {
273 
274 		*pb++ = 0;
275 		if (pb >= pbEndColorByteTable)
276 	    	pb = a_bColorByteTable;
277     }
278 
279     if ((ps->bCurrentLineCount+ps->bCurrentSpeed/2+1) >= _NUMBER_OF_SCANSTEPS) {
280 
281 		pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount +
282 								ps->bCurrentSpeed / 2 + 1 - _NUMBER_OF_SCANSTEPS);
283 	} else {
284 		pb = a_bHalfStepTable +
285 			 (ULong)(ps->bCurrentLineCount + ps->bCurrentSpeed / 2 + 1);
286 	}
287 
288     for (dw = _NUMBER_OF_SCANSTEPS - ps->bMotorSpeedData / 2 - 1; dw; dw--) {
289 		*pb++ = 0;
290 		if (pb >= pbEndHalfStepTable)
291 	    	pb = a_bHalfStepTable;
292     }
293 }
294 
295 /*.............................................................................
296  * motorClearColorByteTableLoop1 ()
297  *   1) Adjust bNewGap:
298  *	bNewGap = (bNewGap <= bNewCurrentLineCountGap) ?
299  *			0 : bNewGap - bNewCurrentLineCount - 1;
300  *   2) Fill the 0 to a_bColorByteTable:
301  *	FillIndex = ((bCurrentLineCount + bNewGap + 1) < 64) ?
302  *				 bCurrentLineCount + bNewGap + 1 :
303  *				 bCurrentLineCount + bNewGap + 1 - 64;
304  *	FillCount = 64 - bNewGap - 1;
305  *   3) Adjust bNewGap:
306  *	bNewGap = (bCurrentLineCount <= bNewCurrentLineCountGap) ?
307  *			0 : bNewGap - bNewCurrentLineCount - 1;
308  *   4) Fill the a_bHalfStepTable:
309  *	FillIndex = ((bCurrentLineCount + bNewGap + 1) < 64) ?
310  *				 bCurrentLineCount + bNewGap + 1 :
311  *				 bCurrentLineCount + bNewGap + 1 - 64;
312  *	FillCount = 64 - bNewGap - 1;
313  */
motorClearColorByteTableLoop1(pScanData ps)314 static void motorClearColorByteTableLoop1( pScanData ps )
315 {
316 	ULong  dw = _NUMBER_OF_SCANSTEPS - 1;
317     pUChar pb;
318 
319     if (ps->bNewGap > ps->bNewCurrentLineCountGap) {
320 		ps->bNewGap = ps->bNewGap - ps->bNewCurrentLineCountGap - 1;
321 		dw -= (ULong)ps->bNewGap;
322     } else {
323 		ps->bNewGap = 0;
324 	}
325 
326     if ((ps->bCurrentLineCount + ps->bNewGap + 1) >= _NUMBER_OF_SCANSTEPS) {
327 		pb = a_bColorByteTable +
328 				(ULong)(ps->bCurrentLineCount+ps->bNewGap+1-_NUMBER_OF_SCANSTEPS);
329     } else {
330 		pb = a_bColorByteTable +
331 							(ULong)(ps->bCurrentLineCount + ps->bNewGap + 1);
332 	}
333 
334     for (; dw; dw--) {
335 		*pb++ = 0;
336 		if (pb >= pbEndColorByteTable)
337 	    	pb = a_bColorByteTable;
338     }
339 
340    	if (ps->bCurrentSpeed > ps->bNewCurrentLineCountGap) {
341 		ps->bNewGap = ps->bCurrentSpeed - ps->bNewCurrentLineCountGap;
342 		dw = _NUMBER_OF_SCANSTEPS - 1 - (ULong)ps->bNewGap;
343     } else {
344 		dw = _NUMBER_OF_SCANSTEPS - 1;
345 		ps->bNewGap = 0;
346     }
347 
348    	if ((ps->bCurrentLineCount + ps->bNewGap + 1) >= _NUMBER_OF_SCANSTEPS) {
349 		pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount +
350 								ps->bNewGap + 1 - _NUMBER_OF_SCANSTEPS);
351 	} else {
352 		pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount+ps->bNewGap +1);
353 	}
354 
355     for (; dw; dw--) {
356 		*pb++ = 0;
357 		if (pb >= pbEndHalfStepTable)
358 	    	pb = a_bHalfStepTable;
359     }
360 }
361 
362 /*.............................................................................
363  * According the flag to set motor direction
364  */
motorSetRunPositionRegister(pScanData ps)365 static void motorSetRunPositionRegister( pScanData ps )
366 {
367 	Byte bData;
368 
369 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
370 	    if( ps->Scan.fMotorBackward ) {
371 			bData = ps->AsicReg.RD_Motor0Control & ~_MotorDirForward;
372 		} else {
373 			bData = ps->AsicReg.RD_Motor0Control | _MotorDirForward;
374 		}
375 
376 	    IOCmdRegisterToScanner( ps, ps->RegMotor0Control, bData );
377 
378 	} else {
379 
380 		if( ps->Scan.fMotorBackward ) {
381 			bData = ps->Asic96Reg.RD_MotorControl & ~_MotorDirForward;
382 		} else {
383 			bData = ps->Asic96Reg.RD_MotorControl | _MotorDirForward;
384 		}
385 
386 	    IOCmdRegisterToScanner( ps, ps->RegMotorControl, bData );
387 	}
388 }
389 
390 /*.............................................................................
391  *
392  */
motorPauseColorMotorRunStates(pScanData ps)393 static void motorPauseColorMotorRunStates( pScanData ps )
394 {
395 	memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES);
396 
397 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
398 
399 	    ps->a_nbNewAdrPointer[2] = 0x77;	/* Read color at the same time */
400 
401 	} else {
402 	    ps->a_nbNewAdrPointer[2] = 1;
403 	    ps->a_nbNewAdrPointer[3] = 3;
404     	ps->a_nbNewAdrPointer[4] = 2;
405 	}
406 
407 	MotorSetConstantMove( ps, 0 );
408 }
409 
410 /*.............................................................................
411  * Setup the a_nbNewAdrPointer for ASIC stepping register
412  */
motorP98FillDataToColorTable(pScanData ps,Byte bIndex,ULong dwSteps)413 static void motorP98FillDataToColorTable( pScanData ps,
414 										  Byte bIndex, ULong dwSteps)
415 {
416 	pUChar	pb;
417     pUShort	pw;
418     Byte	bColor;
419     UShort	w;
420 
421     for ( pb = &a_bColorByteTable[bIndex],
422 				 		pw = &a_wMoveStepTable[bIndex]; dwSteps; dwSteps-- ) {
423 
424 		if (*pw) {				/* valid state */
425 
426 			if( *pw >= ps->BufferForColorRunTable ) {
427 				DBG( DBG_LOW, "*pw = %u > %u !!\n",
428 						*pw, ps->BufferForColorRunTable );
429 			} else {
430 			    bColor = ps->pColorRunTable[*pw];  		/* get the colors 	 */
431 			    if (a_bColorsSum[bColor & 7])		    /* need to read data */
432 					*pb = bColor & 7;
433 			}
434 		}
435 
436 		if (++pw >= pwEndMoveStepTable)	{
437 		    pw = a_wMoveStepTable;
438 		    pb = a_bColorByteTable;
439 		} else
440 		    pb++;
441     }
442 
443     /* ToCondense */
444     pb = a_bColorByteTable;
445 
446     for (w = 0; w < _SCANSTATE_BYTES; w++, pb += 2)
447 		ps->a_nbNewAdrPointer[w] = (Byte)((*pb & 7) + ((*(pb + 1) & 7) << 4));
448 
449     /* ToCondenseMotor */
450     for (pb = a_bHalfStepTable, w = 0; w < _SCANSTATE_BYTES; w++) {
451 		if (*pb++)
452 			ps->a_nbNewAdrPointer [w] |= 8;
453 
454 		if (*pb++)
455 		    ps->a_nbNewAdrPointer [w] |= 0x80;
456     }
457 }
458 
459 /*.............................................................................
460  *
461  */
motorP98FillHalfStepTable(pScanData ps)462 static void motorP98FillHalfStepTable( pScanData ps )
463 {
464 	pUChar	 pbHalfStepTbl, pb;
465     pUShort	 pwMoveStep;
466     DataType Data;
467     ULong	 dw;
468 
469     if (1 == ps->bMotorSpeedData) {
470 		for (dw = 0; dw < _NUMBER_OF_SCANSTEPS; dw++)
471 		    a_bHalfStepTable [dw] =
472 						(a_wMoveStepTable [dw] > ps->wMaxMoveStep) ? 0: 1;
473     } else {
474 		pwMoveStep 	  = &a_wMoveStepTable[ps->bCurrentLineCount];
475 		pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount];
476 
477 		if (ps->DataInf.wAppDataType >= COLOR_TRUE24)
478 		    Data.dwValue = _NUMBER_OF_SCANSTEPS - 1;
479 		else
480 		    Data.dwValue = _NUMBER_OF_SCANSTEPS;
481 
482 		for (; Data.dwValue; Data.dwValue--, pbHalfStepTbl++, pwMoveStep++ ) {
483 
484 		    if (pwMoveStep >= pwEndMoveStepTable) {
485 				pbHalfStepTbl = a_bHalfStepTable;
486 				pwMoveStep    = a_wMoveStepTable;
487 		    }
488 
489 		    if (*pwMoveStep) {		/* need to exposure */
490 
491 				dw = (ULong)ps->bMotorSpeedData;
492 				if (Data.bValue < ps->bMotorSpeedData)
493 				    *pwMoveStep = 0;
494 				else {
495 				    *pbHalfStepTbl = 1;
496 
497 				    if (ps->dwFullStateSpeed) {
498 						dw -= ps->dwFullStateSpeed;
499 						for (pb = pbHalfStepTbl; dw;
500 												dw -= ps->dwFullStateSpeed) {
501 						    pb += ps->dwFullStateSpeed;
502 						    if (pb >= pbEndHalfStepTable)
503 								pb -= _NUMBER_OF_SCANSTEPS;
504 			    			*pb = 1;
505 						}
506 				    }
507 				}
508 		    }
509 		}
510     }
511 }
512 
513 /*.............................................................................
514  *
515  */
motorP98FillBackColorDataTable(pScanData ps)516 static void motorP98FillBackColorDataTable( pScanData ps )
517 {
518 	Byte bIndex;
519 
520     if ((bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1) >=
521                         							     _NUMBER_OF_SCANSTEPS) {
522 		bIndex -= _NUMBER_OF_SCANSTEPS;
523 	}
524 
525 	motorP98FillDataToColorTable( ps, bIndex, (ULong)(_NUMBER_OF_SCANSTEPS -
526 								  ps->bNewCurrentLineCountGap));
527 }
528 
529 /*.............................................................................
530  * i/p:
531  *	pScanStep = pColorRunTable if forward, a_bScanStateTable if backward
532  *	dwState = how many states is requested to process
533  * NOTE:
534  *	The content of pScanStep contain:
535  *  0: Idle state
536  *  0xff: End mark
537  *  others: The motor speed value
538  */
motorP98FillBackLoop(pScanData ps,pUChar pScanStep,ULong dwStates)539 static void motorP98FillBackLoop( pScanData ps,
540 								  pUChar pScanStep, ULong dwStates )
541 {
542     for (ps->fFullLength = _FALSE; dwStates; dwStates--) {
543 
544 		if (*pScanStep == 0xff ) {
545 
546 		    ULong dw = ps->dwScanStateCount;
547 
548 		    for (; dwStates; dwStates--) {
549 				ps->a_nbNewAdrPointer [dw / 2] &= ((dw & 1) ? 0x7f: 0xf7);
550 				dw = (dw + 1U) & _SCANSTATE_MASK;
551 		    }
552 		    if (!ps->dwScanStateCount)
553 				ps->dwScanStateCount = _NUMBER_OF_SCANSTEPS;
554 
555 		    ps->dwScanStateCount--;
556 		    ps->fFullLength = _TRUE;
557 	    	break;
558 		} else {
559 		    ps->a_nbNewAdrPointer [ps->dwScanStateCount / 2] |=
560 					       ((ps->dwScanStateCount & 1) ? 0x80 : 0x08);
561 	    	if (++ps->dwScanStateCount == _NUMBER_OF_SCANSTEPS)
562 				ps->dwScanStateCount = 0;	/* reset to begin */
563 
564 			pScanStep++;
565 		}
566     }
567     IOSetToMotorStepCount( ps );		/* put all scan states to ASIC */
568 }
569 
570 /*.............................................................................
571  *
572  */
motorP98SetRunFullStep(pScanData ps)573 static void motorP98SetRunFullStep( pScanData ps )
574 {
575     ps->OpenScanPath( ps );
576 
577 	ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE;
578     IODataToRegister( ps, ps->RegStepControl,
579 					  ps->AsicReg.RD_StepControl );
580     IODataToRegister( ps, ps->RegLineControl, 96 );
581 
582     if ( ps->bFastMoveFlag == _FastMove_Low_C75_G150_Back ) {
583 		IODataToRegister( ps, ps->RegMotor0Control,
584 						  (_MotorHQuarterStep + _MotorOn + _MotorDirBackward));
585 	} else {
586 		IODataToRegister( ps, ps->RegMotor0Control,
587 						  (_MotorHQuarterStep + _MotorOn + _MotorDirForward));
588 	}
589 
590     if (ps->bFastMoveFlag == _FastMove_Film_150) {
591 		ps->AsicReg.RD_XStepTime = 12;
592 	} else {
593 		if (ps->bFastMoveFlag == _FastMove_Fast_C50_G100) {
594 		    ps->AsicReg.RD_XStepTime =
595 				((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? 4 : 8);
596 		} else {
597 		    ps->AsicReg.RD_XStepTime =
598 				((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? 6 : 12);
599 		}
600 	}
601 
602 	DBG( DBG_LOW, "XStepTime = %u\n", ps->AsicReg.RD_XStepTime );
603 	IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime);
604     ps->CloseScanPath( ps );
605 }
606 
607 /*.............................................................................
608  * moves the sensor back home...
609  */
motorP98BackToHomeSensor(pScanData ps)610 static int motorP98BackToHomeSensor( pScanData ps )
611 {
612 	int		 result = _OK;
613 	TimerDef timer;
614 
615     MotorSetConstantMove( ps, 1 );
616 
617 	ps->OpenScanPath( ps );
618 
619 	ps->AsicReg.RD_StepControl =
620                          (_MOTOR_FREERUN + _MOTOR0_SCANSTATE+ _MOTOR0_ONESTEP);
621     IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl);
622 
623     ps->AsicReg.RD_ModeControl = _ModeScan;
624     IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
625 
626     ps->AsicReg.RD_Motor0Control = _MotorHQuarterStep +
627 												_MotorOn + _MotorDirBackward;
628     IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control );
629 
630 
631     if( ps->DataInf.wPhyDataType >= COLOR_TRUE24) {
632 		ps->AsicReg.RD_XStepTime = ps->bSpeed24;
633 	} else {
634 		ps->AsicReg.RD_XStepTime = ps->bSpeed12;
635 	}
636 
637 	DBG( DBG_HIGH, "XStepTime = %u\n", ps->AsicReg.RD_XStepTime );
638 
639 	IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime );
640     IORegisterToScanner( ps, ps->RegRefreshScanState );
641 
642 	/* CHANGE: We allow up to 25 seconds for returning (org. val was 10) */
643 	MiscStartTimer( &timer, _SECOND * 25 );
644 
645     do {
646 		if (IODataFromRegister( ps, ps->RegStatus) & _FLAG_P98_PAPER ) {
647 		    IODataToRegister( ps, ps->RegModelControl,
648 				   	(Byte)(ps->AsicReg.RD_ModelControl | _HOME_SENSOR_POLARITY));
649 		    if(!(IODataFromRegister(ps, ps->RegStatus) & _FLAG_P98_PAPER))
650 				break;
651 		}
652 		_DODELAY( 10 );			/* delay 10 ms */
653 
654     } while ( !(result = MiscCheckTimer( &timer )));
655 
656     ps->CloseScanPath( ps );
657 
658 	if( _OK != result )
659 		return result;
660 
661     memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
662 
663 	IOSetToMotorRegister( ps );
664 
665 	return _OK;
666 }
667 
668 /*.............................................................................
669  * 1) Clear scan states
670  * 2) Adjust the new scan state
671  */
motorP98FillRunNewAdrPointer1(pScanData ps)672 static void motorP98FillRunNewAdrPointer1( pScanData ps )
673 {
674     ScanState sState;
675     Byte	  bTemp;
676 
677     IOGetCurrentStateCount( ps, &sState);
678     bTemp = sState.bStep;
679     if (sState.bStep < ps->bOldStateCount) {
680 		sState.bStep += _NUMBER_OF_SCANSTEPS;/* over table (table just can	 */
681 	}										 /* holds 64 step, then reset to */
682 											 /* 0, so if less than means over*/
683 											 /* the table)                   */
684     sState.bStep   -= ps->bOldStateCount;	 /* how many states passed   	 */
685     ps->pScanState += sState.bStep;
686 
687     /*
688 	 * if current state != no stepped or stepped a cycle, fill the table with
689      * 1 in NOT STEPPED length. (1 means to this state has to be processing).
690 	 */
691 	ps->bOldStateCount   = bTemp;
692 	ps->dwScanStateCount = (ULong)((bTemp + 1) & _SCANSTATE_MASK);
693 
694 	motorP98FillBackLoop( ps, ps->pScanState, _NUMBER_OF_SCANSTEPS );
695 }
696 
697 /*.............................................................................
698  *
699  */
motorP98FillRunNewAdrPointer(pScanData ps)700 static void motorP98FillRunNewAdrPointer( pScanData ps )
701 {
702     memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
703 
704     motorP98FillRunNewAdrPointer1( ps );
705 }
706 
707 /*.............................................................................
708  * move the sensor to a specific Y-position
709  */
motorP98PositionYProc(pScanData ps,ULong dwStates)710 static void motorP98PositionYProc( pScanData ps, ULong dwStates )
711 {
712     ScanState sState;
713 
714     memset( ps->pColorRunTable, 1, dwStates );
715     memset( ps->pColorRunTable + dwStates, 0xff, (3800UL - dwStates));
716 
717 	IOGetCurrentStateCount( ps, &sState);
718 
719 	ps->bOldStateCount = sState.bStep;
720 
721     ps->OpenScanPath( ps );
722     IODataToRegister( ps, ps->RegMotor0Control,
723 					  (Byte)(_MotorOn + _MotorHEightStep +(ps->Scan.fMotorBackward)?
724 						_MotorDirBackward :  _MotorDirForward));
725 
726 	DBG( DBG_LOW, "XStepTime = %u\n", ps->bSpeed6 );
727     IODataToRegister( ps, ps->RegXStepTime, ps->bSpeed6 );
728 	ps->CloseScanPath( ps );
729 
730     ps->pScanState = ps->pColorRunTable;
731 
732     ps->FillRunNewAdrPointer( ps );
733 
734     while(!motorCheckMotorPresetLength( ps ))
735 		motorP98FillRunNewAdrPointer1( ps );
736 }
737 
738 /*.............................................................................
739  * checks if the sensor is in it´s home position and moves it back if necessary
740  */
motorP98CheckSensorInHome(pScanData ps)741 static int motorP98CheckSensorInHome( pScanData ps )
742 {
743 	int result;
744 
745     if (!(IODataRegisterFromScanner(ps,ps->RegStatus) & _FLAG_P98_PAPER)){
746 
747 		MotorSetConstantMove( ps, 1 );
748 		ps->Scan.fMotorBackward  = _FALSE;
749 		ps->bExtraMotorCtrl = 0;
750 		motorP98PositionYProc( ps, 20 );
751 
752 		result = motorP98BackToHomeSensor( ps );
753 		if( _OK != result )
754 			return result;
755 
756 		_DODELAY( 250 );
757     }
758 
759 	return _OK;
760 }
761 
762 /*.............................................................................
763  * move the sensor to the scan-start position
764  */
motorP98WaitForPositionY(pScanData ps)765 static void motorP98WaitForPositionY( pScanData ps )
766 {
767 	ULong dw;
768     ULong dwBX, dwDX;
769 
770     if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
771 
772 		motorP98BackToHomeSensor( ps );
773 		_DODELAY( 100 );
774 
775 /* CHECK do we need this block ? was test code in the original source code */
776 		ps->OpenScanPath( ps );
777 		IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl);
778 		IODataToRegister( ps, ps->RegStepControl, (Byte)(_MOTOR_FREERUN +
779                                          _MOTOR0_SCANSTATE + _MOTOR0_ONESTEP));
780 		IODataToRegister( ps, ps->RegMotor0Control, (Byte)(_MotorOn +
781 						  _MotorHQuarterStep + _MotorDirForward));
782 		ps->CloseScanPath( ps );
783 
784 		for (dw=1000; dw; dw--) {
785 	    	if (IODataRegisterFromScanner( ps, ps->RegStatus) & _FLAG_P98_PAPER) {
786 				IORegisterDirectToScanner( ps, ps->RegForceStep );
787 				_DODELAY( 1000 / 400 );
788 	    	}
789 		}
790 /*-*/
791 		ps->AsicReg.RD_ModeControl = _ModeScan;
792 		IOCmdRegisterToScanner( ps, ps->RegModeControl,
793 								ps->AsicReg.RD_ModeControl );
794 
795 		memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
796 
797 		ps->Scan.fMotorBackward	= _FALSE;
798 		ps->bExtraMotorCtrl = 0;
799 		ps->bFastMoveFlag 	= _FastMove_Film_150;
800 
801 		if (ps->DataInf.dwScanFlag & SCANDEF_Negative) {
802 	    	MotorP98GoFullStep(ps, (ps->DataInf.crImage.y+_NEG_SCANNINGPOS)/2);
803 		} else {
804 		    MotorP98GoFullStep(ps, (ps->DataInf.crImage.y+_POS_SCANNINGPOS)/2);
805 		}
806 
807 		return;
808     }
809 
810     ps->AsicReg.RD_ModeControl = _ModeScan;
811 
812     IOCmdRegisterToScanner( ps, ps->RegModeControl,
813 							ps->AsicReg.RD_ModeControl );
814 
815     memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
816 
817     ps->Scan.fMotorBackward = _FALSE;
818     ps->bExtraMotorCtrl     = 0;
819 
820     /* SetStartPoint */
821 	dw = ps->wInitialStep + ps->DataInf.crImage.y;
822 
823 	/*
824 	 * CHANGE: when checking out the values from the NT registry
825 	 *		   I found that the values are NOT 0
826 	 */
827     switch (ps->DataInf.wPhyDataType) {
828 		case COLOR_BW:		dw += _BW_ORIGIN;    break;
829 		case COLOR_256GRAY:	dw += _GRAY_ORIGIN;	 break;
830 		default:			dw += _COLOR_ORIGIN; break;
831     }
832 
833     if (dw & 0x80000000)
834 		dw = 0; 		/* negative */
835 
836     if (dw > 180) {
837 		if (ps->bSetScanModeFlag & _ScanMode_Mono) {
838 		    dwBX = 90;				/* go via 150 dpi, so 180 / 2 = 90 */
839 		    dwDX = (dw -180) % 3;
840 	    	dw   = (dw -180) / 3; 	/* 100 dpi */
841 		} else {
842 		    dwBX = 45;				/* go via 75 dpi, so 180 / 4 = 45 */
843 		    dwDX = (dw -180) % 6;
844 	    	dw 	 = (dw -180) / 6; 	/* 50 dpi */
845 		}
846 
847 		dwDX = (dwDX * 3 + 1) / 2 + dwBX;
848 
849 		/*
850 		 * 100/50 dpi lines is 3/2 times of 150/75
851 		 * eax = (remainder * 3 + 1) / 2 + 180 / (2 or 4) lines
852 		 */
853 		ps->bFastMoveFlag = _FastMove_Low_C75_G150;
854 		MotorP98GoFullStep( ps, dwDX);
855 
856 		if (dw) {
857 			DBG( DBG_LOW, "FAST MOVE MODE !!!\n" );
858 		    ps->bFastMoveFlag = _FastMove_Fast_C50_G100;
859 	    	MotorP98GoFullStep( ps, dw);
860 		}
861     } else {
862 		dwBX = ((ps->bSetScanModeFlag & _ScanMode_Mono) ? 2: 4);
863 		dw 	 = (dw + dwBX/2) / dwBX;
864 		ps->bFastMoveFlag = _FastMove_Low_C75_G150;
865 
866 		MotorP98GoFullStep(ps, dw);
867     }
868 }
869 
870 /*.............................................................................
871  * PreMove/EndMove
872  * PreMove is only in ADF and CFB mode
873  * In ADF version, there is a distance gap between Paper flag and Real initial
874  * position and it need premove to real initial position and turn the motor
875  * Inverse and start Fast move to start scan position
876  * In CFB version , PreMove 1 mm to avoid bouncing of PaperFlag sensor then
877  * fast move
878  * In CIS and CSP although there have not PreMove but there have End move
879  * when paper out there still have several mm need to read,
880  * So it need EndMove 2mm and set Inverse Paper
881  */
motorP98GotoShadingPosition(pScanData ps)882 static Bool motorP98GotoShadingPosition( pScanData ps )
883 {
884 	int result;
885 
886 	DBG( DBG_LOW, "motorP98GotoShadingPosition()\n" );
887 
888 	/* Modify Lamp Back to Home step for Scan twice in short time */
889 	result =  motorP98CheckSensorInHome( ps );
890 
891 	if( _OK != result )
892 		return _FALSE;
893 
894     MotorSetConstantMove( ps, 0 );		/* clear scan states */
895 
896     IOCmdRegisterToScanner( ps, ps->RegModelControl,
897 							ps->AsicReg.RD_ModelControl );
898 
899 	ps->Scan.fMotorBackward = _FALSE;	/* forward */
900     ps->bExtraMotorCtrl     = 0;
901 
902     if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
903 
904 		ps->bFastMoveFlag = _FastMove_Low_C75_G150;
905 		MotorP98GoFullStep( ps, 0x40 );
906 
907 		ps->bFastMoveFlag = _FastMove_Middle_C75_G150;
908 		MotorP98GoFullStep( ps, ps->Device.dwModelOriginY );
909     }
910 
911 	memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
912     IOSetToMotorRegister( ps );
913 
914     return _TRUE;
915 }
916 
917 /*.............................................................................
918  * round to the next physical available value
919  */
motorP98SetMaxDpiAndLength(pScanData ps,pUShort wLengthY,pUShort wBaseDpi)920 static void motorP98SetMaxDpiAndLength( pScanData ps,
921 									    pUShort wLengthY, pUShort wBaseDpi )
922 {
923     if (ps->DataInf.xyAppDpi.y > 600)
924 		*wLengthY = ps->LensInf.rExtentY.wMax * 4 + 200;
925     else
926 		*wLengthY = ps->LensInf.rExtentY.wMax * 2 + 200;
927 
928     if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) &&
929 							     (ps->DataInf.xyAppDpi.y <= ps->wMinCmpDpi)) {
930 		*wBaseDpi = ps->wMinCmpDpi;
931 	} else {
932 		if ((ps->DataInf.wPhyDataType < COLOR_TRUE24) &&
933 											(ps->DataInf.xyAppDpi.y <= 75)) {
934 	    	*wBaseDpi = 75;
935 		} else {
936 		    if (ps->DataInf.xyAppDpi.y <= 150) {
937 				*wBaseDpi = 150;
938 			} else {
939 				if (ps->DataInf.xyAppDpi.y <= 300) {
940 				    *wBaseDpi = 300;
941 				} else {
942 				    if (ps->DataInf.xyAppDpi.y <= 600)
943 						*wBaseDpi = 600;
944 		    		else
945 						*wBaseDpi = 1200;
946 				}
947 			}
948 		}
949 	}
950 
951 	DBG( DBG_LOW, "wBaseDPI = %u, %u\n", *wBaseDpi, ps->wMinCmpDpi );
952 }
953 
954 /*.............................................................................
955  *
956  */
motorP98FillGBColorRunTable(pScanData ps,pUChar pTable,Byte bHi,Byte bLo,UShort wBaseDpi)957 static void motorP98FillGBColorRunTable( pScanData ps, pUChar pTable,
958 									     Byte bHi, Byte bLo, UShort wBaseDpi )
959 {
960 
961     if( ps->Device.f0_8_16 ) {
962 
963 		if (wBaseDpi == ps->wMinCmpDpi) {
964 		    *pTable |= bHi;
965 		    *(pTable + 1) |= bLo;
966 		} else {
967 			switch (wBaseDpi) {
968 		    case 150:
969 				*(pTable + 2) |= bHi;
970 				*(pTable + 4) |= bLo;
971 				break;
972 
973 		    case 300:
974 				*(pTable + 4) |= bHi;
975 				*(pTable + 8) |= bLo;
976 				break;
977 
978 		    case 600:
979 				*(pTable + 8) |= bHi;
980 				*(pTable + 16) |= bLo;
981 				break;
982 
983 		    default:
984 				*(pTable + 16) |= bHi;
985 				*(pTable + 32) |= bLo;
986 				break;
987 			}
988 		}
989     } else {
990 
991 		if (wBaseDpi == ps->wMinCmpDpi) {
992 		    *pTable |= bHi;
993 		    *(pTable + 1) |= bLo;
994 		} else {
995 		    switch(wBaseDpi) {
996 
997 			case 150:
998 			    *(pTable + 1) |= bHi;
999 			    *(pTable + 2) |= bLo;
1000 		    	break;
1001 
1002 			case 300:
1003 			    *(pTable + 2) |= bHi;
1004 			    *(pTable + 4) |= bLo;
1005 			    break;
1006 
1007 			case 600:
1008 			    *(pTable + 4) |= bHi;
1009 			    *(pTable + 8) |= bLo;
1010 		    	break;
1011 
1012 			default:
1013 			    *(pTable + 8) |= bHi;
1014 			    *(pTable + 16) |= bLo;
1015 			    break;
1016 		    }
1017 		}
1018     }
1019 }
1020 
1021 /*.............................................................................
1022  *
1023  */
motorP98SetupRunTable(pScanData ps)1024 static void motorP98SetupRunTable( pScanData ps )
1025 {
1026 	UShort wDpi, w, wBaseDpi, wLengthY;
1027 	pUChar pTable;
1028 
1029 	motorP98SetMaxDpiAndLength( ps, &wLengthY, &wBaseDpi );
1030 
1031 	/*ClearColorRunTable(); */
1032     memset( ps->pColorRunTable, 0, ps->BufferForColorRunTable );
1033 
1034     wDpi = wBaseDpi;
1035     w 	 = wLengthY + 1000;
1036     pTable = ps->pColorRunTable + (_NUMBER_OF_SCANSTEPS / 4);
1037 
1038     if( ps->DataInf.wPhyDataType >= COLOR_TRUE24) {
1039 
1040 		for(; w; w--, pTable++) {
1041 		    if((short)(wDpi -= ps->DataInf.xyPhyDpi.y) <= 0) {
1042 				wDpi += wBaseDpi;
1043 				*pTable |= 0x44;
1044 				motorP98FillGBColorRunTable( ps, pTable, 0x22, 0x11, wBaseDpi );
1045 		    }
1046 		}
1047     } else {
1048 		for(; w; w--, pTable++) {
1049 		    if((short)(wDpi -= ps->DataInf.xyPhyDpi.y) <= 0) {
1050 				wDpi += wBaseDpi;
1051 				*pTable = 0x22;
1052 		    }
1053 		}
1054     }
1055 	ps->dwColorRunIndex = 0;
1056 }
1057 
1058 /*.............................................................................
1059  *
1060  */
motorP98UpdateDataCurrentReadLine(pScanData ps)1061 static void motorP98UpdateDataCurrentReadLine( pScanData ps )
1062 {
1063     if(!(ps->Scan.bNowScanState & _SCANSTATE_STOP)) {
1064 
1065 		Byte b;
1066 
1067 		if (ps->Scan.bNowScanState >= ps->bCurrentLineCount)
1068 		    b = ps->Scan.bNowScanState - ps->bCurrentLineCount;
1069 		else
1070 	    	b = ps->Scan.bNowScanState + _NUMBER_OF_SCANSTEPS - ps->bCurrentLineCount;
1071 
1072 		if (b < 40)
1073 		    return;
1074     }
1075 
1076 	ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE );
1077     IOSetToMotorRegister( ps );
1078 
1079     ps->Scan.bModuleState = _MotorAdvancing;
1080 }
1081 
1082 /*.............................................................................
1083  *	Byte - Scan State Index (0-63) and StopStep bit
1084  *	pScanState->bStep - Scan State Index (0-63)
1085  *	pScanState->bStatus - Scanner Status Register value
1086  */
motorP96GetScanStateAndStatus(pScanData ps,pScanState pScanStep)1087 static void motorP96GetScanStateAndStatus( pScanData ps, pScanState pScanStep )
1088 {
1089     ps->OpenScanPath( ps );
1090 
1091     pScanStep->bStep   = IOGetScanState(ps, _TRUE);
1092 	pScanStep->bStep  &= _SCANSTATE_MASK;		/* org was. ~_ScanStateStop; */
1093     pScanStep->bStatus = IODataFromRegister( ps, ps->RegStatus );
1094 
1095     ps->CloseScanPath( ps );
1096 }
1097 
1098 /*.............................................................................
1099  * Capture the image data and average them.
1100  */
motorP96ReadDarkData(pScanData ps)1101 static Byte motorP96ReadDarkData( pScanData ps )
1102 {
1103 	Byte	 bFifoOffset;
1104     UShort	 wSum, w;
1105     TimerDef timer;
1106 
1107 	MiscStartTimer( &timer, _SECOND/2);
1108 
1109     do {
1110 
1111 		bFifoOffset = IODataRegisterFromScanner( ps, ps->RegFifoOffset );
1112 
1113 		/* stepped 1 block */
1114 		if( bFifoOffset ) {
1115 
1116 			/* read data */
1117 			IOReadScannerImageData( ps, ps->pScanBuffer1, 512UL);
1118 
1119 		    /* 320 = 192 + 128 (128 is size to fetch data) */
1120 		    for (w = 192, wSum = 0; w < 320; w++)
1121 				wSum += (UShort)ps->pScanBuffer1[w];/* average data from 	  */
1122 													/* offset 192 and size 128*/
1123 		    return (Byte)(wSum >> 7);				/* divided by 128 		  */
1124 		}
1125 
1126     } while (!MiscCheckTimer(&timer));
1127 
1128     return 0xff;					/* timed-out */
1129 }
1130 
1131 /*.............................................................................
1132  * move the sensor to a specific Y-position
1133  */
motorP96PositionYProc(pScanData ps,ULong dwStates)1134 static void motorP96PositionYProc( pScanData ps, ULong dwStates )
1135 {
1136 	ScanState sState;
1137 
1138 	memset( ps->pColorRunTable, 1, dwStates );
1139 
1140 #ifdef DEBUG
1141 	if( dwStates > 800UL )
1142 		DBG( DBG_HIGH, "!!!!! RUNTABLE OVERFLOW !!!!!\n" );
1143 #endif
1144 	memset( ps->pColorRunTable + dwStates, 0xff, 800UL - dwStates );
1145 
1146 	IOGetCurrentStateCount( ps, &sState );
1147     ps->bOldStateCount = sState.bStep;
1148 
1149     /* TurnOnMotorAndSetDirection (); */
1150     if( ps->Scan.fMotorBackward ) {
1151 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1152 										(Byte)(ps->IgnorePF | ps->MotorOn));
1153 	} else {
1154 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1155 				      (Byte)(ps->IgnorePF | ps->MotorOn | _MotorDirForward));
1156 	}
1157 
1158     ps->pScanState = ps->pColorRunTable;
1159     do {
1160 		ps->FillRunNewAdrPointer( ps );
1161 
1162     } while (!motorCheckMotorPresetLength( ps ));
1163 }
1164 
1165 /*.............................................................................
1166  * move the sensor to the scan-start position
1167  */
motorP96WaitForPositionY(pScanData ps)1168 static void motorP96WaitForPositionY( pScanData ps )
1169 {
1170 /* scheint OKAY zu sein fuer OP4830 */
1171 #ifdef _A3I_EN
1172 #warning "compiling for A3I"
1173 	ULong     dw;
1174 	ScanState sState;
1175 
1176 	memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1177 
1178     ps->Asic96Reg.RD_MotorControl = ps->IgnorePF|ps->MotorOn|_MotorDirForward;
1179     ps->Scan.fMotorBackward = _FALSE;
1180     ps->bExtraMotorCtrl     = ps->IgnorePF;
1181 
1182     if( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi )
1183 		dw = 30UL;
1184     else
1185 		dw = 46UL;
1186 
1187     dw = (dw + ps->DataInf.crImage.y) * 4 / 3;
1188 
1189     if( ps->DataInf.wPhyDataType == COLOR_TRUE24 )
1190 		dw += 99; /* dwStepsForColor; */
1191 
1192     else if( ps->DataInf.wPhyDataType == COLOR_256GRAY )
1193 	    dw += 99; /* dwStepsForGray; */
1194 	else
1195 	    dw += 99; /* dwStepsForBW; */
1196 
1197     if( dw >= 130UL ) {
1198 
1199 		dw -= 100UL;
1200 		dw <<= 1;
1201 	    /* GoFullStep (dw); */
1202 
1203 		memset( ps->pColorRunTable, 1, dw );
1204 		memset( ps->pColorRunTable + dw, 0xff, ps->BufferForColorRunTable - dw );
1205 
1206 		IOGetCurrentStateCount( ps, &sState );
1207 		ps->bOldStateCount = sState.bStep;
1208 
1209 		/* AdjustMotorTime () */
1210 		IOCmdRegisterToScanner( ps, ps->RegLineControl, 31 );
1211 
1212 		/* SetRunHalfStep () */
1213 		if( ps->Scan.fMotorBackward )
1214 		    IOCmdRegisterToScanner( ps, ps->RegMotorControl, _Motor1FullStep |
1215 								    ps->IgnorePF | ps->MotorOn );
1216 		else
1217 		    IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->IgnorePF |
1218 										    ps->MotorOn | _MotorDirForward );
1219 
1220 		ps->pScanState = ps->pColorRunTable;
1221 
1222 		do {
1223 			ps->FillRunNewAdrPointer( ps );
1224 
1225 		} while (!motorCheckMotorPresetLength(ps));
1226 
1227 		/* RestoreMotorTime () */
1228 		IOCmdRegisterToScanner( ps, ps->RegLineControl,
1229 								ps->AsicReg.RD_LineControl );
1230 
1231 		dw = 100UL;
1232     }
1233 
1234     if( ps->DataInf.wPhyDataType != COLOR_TRUE24 )
1235 		dw += 20;
1236 
1237 	motorP96PositionYProc( ps, dw );
1238 
1239 #else
1240 
1241 	ULong	  dw;
1242     ScanState sState;
1243 
1244 	TimerDef  timer;
1245 
1246 	MiscStartTimer( &timer, _SECOND / 4);
1247     while (!MiscCheckTimer( &timer ));
1248 
1249     memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1250 
1251     ps->Asic96Reg.RD_MotorControl = ps->IgnorePF|ps->MotorOn|_MotorDirForward;
1252     ps->Scan.fMotorBackward = _FALSE;
1253     ps->bExtraMotorCtrl     = ps->IgnorePF;
1254 
1255     if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ||
1256 											(ps->DataInf.xyAppDpi.y <= 300)) {
1257 		dw = 6UL;
1258 
1259     } else {
1260 
1261 		if (ps->DataInf.xyAppDpi.y <= 600) {
1262 			/* 50 is from 6/300 */
1263 		    dw = (ULong)ps->DataInf.xyAppDpi.y / 50UL + 3UL;
1264 		} else
1265 		    dw = 15;	/* 6UL * 600UL / 300UL + 3; */
1266     }
1267 
1268     dw += ps->DataInf.crImage.y;
1269 
1270     if (dw >= 180UL) {
1271 
1272 		dw -= 180UL;
1273     	/* GoFullStep (ps, dw);----------------------------------------------*/
1274 		memset( ps->pColorRunTable, 1, dw );
1275 #ifdef DEBUG
1276 		if( dw > 8000UL )
1277 			DBG( DBG_HIGH, "!!!!! RUNTABLE OVERFLOW !!!!!\n" );
1278 #endif
1279 		memset( ps->pColorRunTable + dw, 0xff, 8000UL - dw );
1280 
1281 		IOGetCurrentStateCount( ps, &sState );
1282 		ps->bOldStateCount = sState.bStep;
1283 
1284 		/* SetRunFullStep (ps) */
1285 		if( ps->Scan.fMotorBackward ) {
1286 		    IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1287 						  (Byte)(ps->FullStep | ps->IgnorePF | ps->MotorOn));
1288 		} else {
1289 		    IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1290 						  (Byte)(ps->FullStep | ps->IgnorePF | ps->MotorOn |
1291 															_MotorDirForward));
1292 		}
1293 
1294 		ps->pScanState = ps->pColorRunTable;
1295 
1296 		do {
1297 			ps->FillRunNewAdrPointer (ps);
1298 
1299 		} while (!motorCheckMotorPresetLength(ps));
1300 
1301 		/*-------------------------------------------------------------------*/
1302 
1303 		dw = 180UL;
1304     }
1305 
1306 	if (ps->DataInf.wPhyDataType != COLOR_TRUE24)
1307 		dw = dw * 2 + 16;
1308     else
1309 		dw *= 2;
1310 
1311 	motorP96PositionYProc( ps, dw );
1312 #endif
1313 }
1314 
1315 /*.............................................................................
1316  * Position Scan Module to specified line number (Forward or Backward & wait
1317  * for paper flag ON)
1318  */
motorP96ConstantMoveProc1(pScanData ps,ULong dwLines)1319 static void motorP96ConstantMoveProc1( pScanData ps, ULong dwLines )
1320 {
1321 	Byte	  bRemainder, bLastState;
1322     UShort	  wQuotient;
1323     ULong	  dwDelayMaxTime;
1324     ScanState StateStatus;
1325 	TimerDef  timer;
1326 	Bool	  fTimeout = _FALSE;
1327 
1328 	/* state cycles */
1329     wQuotient  = (UShort)(dwLines / _NUMBER_OF_SCANSTEPS);
1330     bRemainder = (Byte)(dwLines % _NUMBER_OF_SCANSTEPS);
1331 
1332 	/* 3.3 ms per line */
1333 #ifdef _A3I_EN
1334     dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 2;
1335 #else
1336     dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 20;
1337 #endif
1338 
1339 	/* step every time */
1340 	MotorSetConstantMove( ps, 1 );
1341 
1342     ps->OpenScanPath( ps );
1343 
1344     ps->AsicReg.RD_ModeControl = _ModeScan;
1345     IODataToRegister( ps, ps->RegModeControl, _ModeScan );
1346 
1347     ps->Asic96Reg.RD_MotorControl = ps->MotorFreeRun |
1348 											ps->MotorOn | _MotorDirForward;
1349 	IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl );
1350 
1351     ps->CloseScanPath( ps );
1352 
1353     bLastState = 0;
1354 
1355 	MiscStartTimer( &timer, dwDelayMaxTime );
1356 
1357     do {
1358 
1359 		/* GetStatusAndScanStateAddr () */
1360 		motorP96GetScanStateAndStatus( ps, &StateStatus );
1361 		if (StateStatus.bStatus & _FLAG_P96_PAPER ) {
1362 		    if (wQuotient)  {
1363 
1364 				if (StateStatus.bStep != bLastState) {
1365 				    bLastState = StateStatus.bStep;
1366 
1367 				    if (!bLastState)
1368 						wQuotient--;
1369 				}
1370 		    } else
1371 				if (StateStatus.bStep >= bRemainder)
1372 				    break;
1373 			} else
1374 			    break;
1375     } while (!(fTimeout = MiscCheckTimer( &timer )));
1376 
1377     if (!fTimeout) {
1378 		memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1379 		IOSetToMotorRegister( ps );
1380     }
1381 }
1382 
1383 /*.............................................................................
1384  * PreMove/EndMove
1385  * PreMove is only in ADF and CFB mode
1386  * In ADF version, there is a distance gap between Paper flag and Real initial
1387  *   position and it need premove to real initial position and turn the motor
1388  *   Inverse and start Fast move to start scan position
1389  * In CFB version , PreMove 1 mm to avoid bouncing of PaperFlag sensor then
1390  *   fast move
1391  * In CIS and CSP although there have not PreMove but there have End move
1392  *   when paper out there still have several mm need to read,
1393  *   So it need EndMove 2mm and set Inverse Paper
1394  */
motorP96GotoShadingPosition(pScanData ps)1395 static Bool motorP96GotoShadingPosition( pScanData ps )
1396 {
1397 	DBG( DBG_LOW, "motorP96GotoShadingPosition()\n" );
1398 
1399 	MotorSetConstantMove( ps, 0 );		/* clear scan states */
1400     ps->Scan.fMotorBackward = _FALSE;	/* forward			 */
1401     ps->bExtraMotorCtrl     = ps->IgnorePF;
1402 
1403 	MotorP96ConstantMoveProc( ps, 15 * 12 ); 	/* forward 180 lines */
1404 
1405     if (IODataRegisterFromScanner(ps, ps->RegStatus) & _FLAG_P96_PAPER ) {
1406 		ps->Asic96Reg.RD_MotorControl = 0;
1407 		IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
1408 
1409 		DBG( DBG_LOW, "motorP96GotoShadingPosition() failed\n" );
1410 		return _FALSE;
1411     }
1412     ps->Scan.fMotorBackward = _TRUE;	/* backward					 */
1413     ps->bExtraMotorCtrl     = 0;	    /* no extra action for motor */
1414 
1415 	/* backward a few thousand lines to touch sensor */
1416  	MotorP96ConstantMoveProc( ps, ps->BackwardSteps );
1417 
1418 	_DODELAY( 250 );
1419 
1420 	IOCmdRegisterToScanner( ps, ps->RegModelControl,
1421 					  (Byte)(ps->AsicReg.RD_ModelControl | _ModelInvertPF));
1422 
1423     ps->Scan.fMotorBackward = _FALSE;				/* forward 			*/
1424     motorP96ConstantMoveProc1( ps, 14 * 12 * 2);	/* ahead 336 lines	*/
1425 
1426 	if( MODEL_OP_A3I == ps->sCaps.Model ) {
1427 
1428 		motorP96PositionYProc( ps, 80 );
1429 
1430 	} else {
1431 		/* forward 24 + pScanData->wOverBlue lines */
1432     	if (!ps->fColorMoreRedFlag)
1433 			motorP96PositionYProc( ps, ps->wOverBlue + 12 * 2);
1434 	}
1435 
1436     if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
1437 		ps->Scan.fMotorBackward = _FALSE;
1438 		ps->bExtraMotorCtrl     = ps->IgnorePF;
1439 		MotorP96ConstantMoveProc( ps, 1200 );
1440     }
1441 
1442 	IOCmdRegisterToScanner( ps, ps->RegModelControl,
1443 												ps->AsicReg.RD_ModelControl );
1444     return _TRUE;
1445 }
1446 
1447 /*.............................................................................
1448  *
1449  */
motorP96FillHalfStepTable(pScanData ps)1450 static void motorP96FillHalfStepTable( pScanData ps )
1451 {
1452 #ifdef _A3I_EN
1453 	if ( ps->Scan.bModuleState == _MotorInStopState ) {
1454 
1455 		/* clear the table and get the step value */
1456 		memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS );
1457 		ps->bMotorStepTableNo = a_bMotorDown2Table[(ps->bMotorSpeedData-1)/2];
1458     }
1459 
1460 	/* the fastest stepping */
1461     if( ps->bMotorSpeedData & 1 ) {
1462 
1463 		memset( a_bHalfStepTable,
1464 		       ((ps->Scan.bModuleState != _MotorInStopState) ? 1 : 0),
1465 														_NUMBER_OF_SCANSTEPS );
1466 	} else {
1467 
1468 		pUChar   pbHalfStepTbl;
1469 		Byte     bHalfSteps;
1470 		pUShort	 pwMoveStep;
1471 		DataType Data;
1472 
1473 		bHalfSteps    = ps->bMotorSpeedData / 2;
1474 		pwMoveStep    = &a_wMoveStepTable[ps->bCurrentLineCount];
1475 		pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount];
1476 
1477 		if( ps->DataInf.wAppDataType == COLOR_TRUE24)
1478 		    Data.dwValue = _NUMBER_OF_SCANSTEPS - 1;
1479 		else
1480 		    Data.dwValue = _NUMBER_OF_SCANSTEPS;
1481 
1482 		/* FillDataToHalfStepTable */
1483 		for(; Data.dwValue; Data.dwValue-- ) {
1484 
1485 		    if( *pwMoveStep ) {		/* need to exposure */
1486 
1487 				if( Data.bValue >= bHalfSteps ) {
1488 
1489 				    pUChar pb = pbHalfStepTbl + bHalfSteps;
1490 
1491 				    /* AdjustHalfStepStart */
1492 				    if( ps->DataInf.wAppDataType == COLOR_TRUE24 ) {
1493 
1494 						if (bHalfSteps >= 2)
1495 						    pb -= (bHalfSteps - 1);
1496 				    }
1497 				    if( pb >= pbEndHalfStepTable )
1498 						pb -= _NUMBER_OF_SCANSTEPS;
1499 
1500 				    if( wP96BaseDpi <= ps->PhysicalDpi && *pwMoveStep != 2 )
1501 						*pb = 1;
1502 
1503 		    		pb += bHalfSteps;
1504 
1505 				    if( pb >= pbEndHalfStepTable )
1506 						pb -= _NUMBER_OF_SCANSTEPS;
1507 
1508 				    *pb = 1;
1509 				}
1510 				else
1511 				    *pwMoveStep = 0;		/* idle state */
1512 		    }
1513 		    if( ++pwMoveStep >= pwEndMoveStepTable ) {
1514 				pwMoveStep = a_wMoveStepTable;
1515 
1516 				pbHalfStepTbl = a_bHalfStepTable;
1517 		    }
1518 		    else
1519 				pbHalfStepTbl++;
1520 		}
1521     }
1522 
1523 #else
1524 
1525 #ifdef DEBUG
1526 	if( 0 == wP96BaseDpi )
1527 		DBG( DBG_HIGH, "!!!! WARNING - motorP96FillHalfStepTable(), "
1528 					   "wP96BaseDpi == 0 !!!!\n" );
1529 #endif
1530 
1531 	if ( ps->Scan.bModuleState == _MotorInStopState ) {
1532 
1533 		/* clear the table and get the step value */
1534 		memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS );
1535 		ps->bMotorStepTableNo = a_bMotorDown2Table[(ps->bMotorSpeedData-1)/2];
1536     }
1537 
1538 	/* the fastest stepping */
1539     if( ps->bMotorSpeedData & 1 ) {
1540 
1541 		memset( a_bHalfStepTable,
1542 		       ((ps->Scan.bModuleState != _MotorInStopState) ? 1 : 0),
1543 														_NUMBER_OF_SCANSTEPS );
1544 	} else {
1545 
1546 		pUChar   pbHalfStepTbl, pbHalfStepContent;
1547 		pUShort	 pwMoveStep;
1548 		DataType Data;
1549 
1550 		pbHalfStepContent = a_pbHalfStepTables[ps->bMotorSpeedData / 2 - 1];
1551 
1552 		pwMoveStep    = &a_wMoveStepTable[ps->bCurrentLineCount];
1553 		pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount];
1554 
1555 		if (ps->DataInf.wAppDataType == COLOR_TRUE24)
1556 		    Data.dwValue = _NUMBER_OF_SCANSTEPS - 1;
1557 		else
1558 		    Data.dwValue = _NUMBER_OF_SCANSTEPS;
1559 
1560 		/* FillDataToHalfStepTable */
1561 		for (; Data.dwValue; Data.dwValue--) {
1562 
1563 		    if (*pwMoveStep) {		/* need to exposure */
1564 
1565 				if (Data.bValue >= *pbHalfStepContent) {
1566 
1567 				    pUChar pb = pbHalfStepTbl + *pbHalfStepContent;
1568 
1569 					if (pb >= pbEndHalfStepTable)
1570 						pb -= _NUMBER_OF_SCANSTEPS;
1571 
1572 				    /* JudgeStep1 () */
1573 				    if ((wP96BaseDpi != 600) && (*pwMoveStep != 2)) {
1574 						if (ps->Scan.bModuleState != _MotorInStopState) {
1575 						    *pb = 1;
1576 						} else {
1577 						    if (ps->bMotorStepTableNo) {
1578 								ps->bMotorStepTableNo--;
1579 								*pb = 1;
1580 			    			}
1581 						}
1582 					}
1583 
1584 				    pb += *pbHalfStepContent;
1585 				    if (pb >= pbEndHalfStepTable)
1586 						pb -= _NUMBER_OF_SCANSTEPS;
1587 
1588 				    /* JudgeStep2 () */
1589 				    if (ps->Scan.bModuleState == _MotorInStopState) {
1590 						if (ps->bMotorStepTableNo) {
1591 						    ps->bMotorStepTableNo--;
1592 						    *pb = 1;
1593 						}
1594 				    } else {
1595 						*pb = 1;
1596 					}
1597 
1598 					pbHalfStepContent++;
1599 				} else {
1600 				    *pwMoveStep = 0;		/* idle state */
1601 				}
1602 			}
1603 
1604 		    if (++pwMoveStep >= pwEndMoveStepTable) {
1605 				pwMoveStep = a_wMoveStepTable;
1606 				pbHalfStepTbl = a_bHalfStepTable;
1607 		    } else {
1608 				pbHalfStepTbl++;
1609 			}
1610 		}
1611     }
1612 #endif
1613 }
1614 
1615 /*.............................................................................
1616  *
1617  */
motorP96FillDataToColorTable(pScanData ps,Byte bIndex,ULong dwSteps)1618 static void motorP96FillDataToColorTable( pScanData ps,
1619 										  Byte bIndex, ULong dwSteps)
1620 {
1621     Byte	 bColor, bColors;
1622 	pUChar	 pb, pb1;
1623 	pUShort	 pw;
1624     DataType Data;
1625 
1626     for (pb = &a_bColorByteTable[bIndex],
1627 		 pw = &a_wMoveStepTable[bIndex]; dwSteps; dwSteps--) {
1628 
1629 		if (*pw) {				/* valid state */
1630 
1631 			if( *pw >= ps->BufferForColorRunTable ) {
1632 				DBG( DBG_LOW, "*pw = %u > %u !!\n",
1633 						*pw, ps->BufferForColorRunTable );
1634 			} else {
1635 
1636 			    bColor  = ps->pColorRunTable [*pw];	/* get the colors	*/
1637 			    bColors = a_bColorsSum [bColor & 7];/* number of colors */
1638 
1639 			    if (bColors) {						/* need to read data */
1640 					if (dwSteps >= bColors) { 		/* enough room 		 */
1641 
1642 		    			/* separate the colors to byte */
1643 					    pb1 = pb;
1644 				    	if (bColor & ps->b1stColor) {
1645 
1646 							*pb1 = ps->b1stColorByte;
1647 							if (++pb1 >= pbEndColorByteTable)
1648 							    pb1 = a_bColorByteTable;
1649 					    }
1650 
1651 					    if (bColor & ps->b2ndColor) {
1652 
1653 							*pb1 = ps->b2ndColorByte;
1654 							if (++pb1 >= pbEndColorByteTable)
1655 							    pb1 = a_bColorByteTable;
1656 					    }
1657 
1658 				    	if (bColor & ps->b3rdColor)
1659 							*pb1 = ps->b3rdColorByte;
1660 					} else
1661 					    *pw = 0;
1662 	    		}
1663 			}
1664 		}
1665 
1666 		if (++pw >= pwEndMoveStepTable) {
1667 		    pw = a_wMoveStepTable;
1668 		    pb = a_bColorByteTable;
1669 		} else
1670 		    pb++;
1671     }
1672 
1673 /*     ps->bOldSpeed = ps->bMotorRunStatus; non functional */
1674 
1675     /* ToCondense, CondenseColorByteTable */
1676     for (dwSteps = _SCANSTATE_BYTES, pw = (pUShort)a_bColorByteTable,
1677 		 pb = ps->a_nbNewAdrPointer; dwSteps; dwSteps--, pw++, pb++) {
1678 
1679 		Data.wValue = *pw & 0x0303;
1680 		*pb = Data.wOverlap.b1st | (Data.wOverlap.b2nd << 4);
1681     }
1682 
1683     /* ToCondenseMotor */
1684     for (dwSteps = _SCANSTATE_BYTES, pb1 = a_bHalfStepTable,
1685 		 pb = ps->a_nbNewAdrPointer; dwSteps; dwSteps--, pb1++, pb++) {
1686 
1687 		if (*pb1++)
1688 		    *pb |= 4;
1689 
1690 		if (*pb1)
1691 		    *pb |= 0x40;
1692     }
1693 }
1694 
1695 /*.............................................................................
1696  *
1697  */
motorP96FillBackColorDataTable(pScanData ps)1698 static void motorP96FillBackColorDataTable( pScanData ps )
1699 {
1700 	Byte	bIndex;
1701 	ULong	dw;
1702 
1703     if ((ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1) >=
1704     													_NUMBER_OF_SCANSTEPS){
1705 		bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1 -
1706 				 _NUMBER_OF_SCANSTEPS;
1707 	} else {
1708 		bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1;
1709 	}
1710     dw = _NUMBER_OF_SCANSTEPS - ps->bNewCurrentLineCountGap;
1711 
1712     motorP96FillDataToColorTable( ps, bIndex, dw );
1713 }
1714 
1715 /*.............................................................................
1716  * i/p:
1717  *    pScanStep = pScanData->pColorRunTable if forward, a_bScanStateTable if backward
1718  *    dwState = how many states is requested to process
1719  * NOTE:
1720  *    The content of pScanStep contain:
1721  *    0: Idle state
1722  *    0xff: End mark
1723  *    others: The motor speed value
1724  */
motorP96FillBackLoop(pScanData ps,pUChar pScanStep,ULong dwStates)1725 static void motorP96FillBackLoop( pScanData ps,
1726 								  pUChar pScanStep, ULong dwStates )
1727 {
1728     for (; dwStates; dwStates--) {
1729 
1730 		if (*pScanStep == 0xff)
1731 		    break;					/* end of states */
1732 
1733 		if (*pScanStep) {
1734 		    if (*pScanStep == 1) {	/* speed == 1, this state has to step */
1735 
1736 				if (ps->dwScanStateCount & 1)
1737 				    ps->a_nbNewAdrPointer[ps->dwScanStateCount / 2] |= 0x40;
1738 				else
1739 				    ps->a_nbNewAdrPointer[ps->dwScanStateCount / 2] |= 0x04;
1740 			}
1741 
1742 		    *pScanStep -= 1;		/* speed decrease by 1 */
1743 
1744 		    if (!(*pScanStep))
1745 				pScanStep++;		/* state processed */
1746 		} else
1747 		    pScanStep++;			/* skip this state */
1748 
1749 		if (++ps->dwScanStateCount == _NUMBER_OF_SCANSTEPS)
1750 		    ps->dwScanStateCount = 0;					/* reset to begin */
1751 	}
1752 
1753     if (*pScanStep != 0xff)
1754 		ps->fFullLength = _FALSE;
1755     else
1756 		ps->fFullLength = _TRUE;
1757 
1758     IOSetToMotorStepCount( ps );		/* put all scan states to ASIC */
1759 }
1760 
1761 /*.............................................................................
1762  * 1) Clear scan states
1763  * 2) Adjust the new scan state
1764  */
motorP96FillRunNewAdrPointer(pScanData ps)1765 static void motorP96FillRunNewAdrPointer( pScanData ps )
1766 {
1767 	ScanState sState;
1768 
1769 	memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES);
1770 
1771 	IOGetCurrentStateCount( ps, &sState );
1772 
1773     if (sState.bStep < ps->bOldStateCount )
1774 		sState.bStep += _NUMBER_OF_SCANSTEPS;/* over table (table just can   */
1775 											 /* holds 64 step, then reset to */
1776 											 /* 0, so if less than means over*/
1777 											 /* the table)					*/
1778 
1779 	sState.bStep -= ps->bOldStateCount;		 /* how many states passed */
1780     ps->pScanState += sState.bStep;
1781 
1782     /*
1783 	 * if current state != no stepped or stepped a cycle, fill the table with
1784 	 * 1 in NOT STEPPED length. (1 means to this state has to be processing).
1785 	 */
1786     if (sState.bStep && sState.bStep != (_NUMBER_OF_SCANSTEPS - 1))
1787 		memset( ps->pScanState, 1, _NUMBER_OF_SCANSTEPS - sState.bStep - 1 );
1788 
1789 	IOGetCurrentStateCount( ps, &sState);
1790     ps->bOldStateCount   = sState.bStep;			/* update current state */
1791     ps->dwScanStateCount = (ULong)((sState.bStep + 1) & (_NUMBER_OF_SCANSTEPS - 1));
1792 
1793 	/* fill begin at next step */
1794  	motorP96FillBackLoop( ps, ps->pScanState, (_NUMBER_OF_SCANSTEPS - 1));
1795 }
1796 
1797 /*.............................................................................
1798  *
1799  */
motorP96SetupRunTable(pScanData ps)1800 static void motorP96SetupRunTable( pScanData ps )
1801 {
1802 	Short		siSum;
1803 	UShort		wLoop;
1804 	UShort		wLengthY;
1805 	DataPointer	p;
1806 
1807 	DBG( DBG_LOW, "motorP96SetupRunTable()\n" );
1808 
1809     /* SetMaxDpiAndLength (ps) */
1810 #ifdef _A3I_EN
1811     if( ps->DataInf.xyPhyDpi.y > ps->PhysicalDpi ) {
1812 
1813 		wLengthY    = 6800 * 2;
1814 		wP96BaseDpi = ps->PhysicalDpi *2;
1815     } else {
1816 		wLengthY    = 6800;
1817 		wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax >> 1;
1818     }
1819 #else
1820     if( ps->DataInf.xyPhyDpi.y > (ps->LensInf.rDpiY.wPhyMax / 2)) {
1821 
1822 		wLengthY    = ps->LensInf.rExtentY.wMax << 1;
1823 		wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax;
1824     } else {
1825 		wLengthY    = ps->LensInf.rExtentY.wMax;
1826 		wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax >> 1;
1827     }
1828 #endif
1829 
1830 	DBG( DBG_LOW, "wLengthY = %u, wP96BaseDpi = %u\n", wLengthY, wP96BaseDpi );
1831 
1832     /* ClearColorRunTable (ps) */
1833 	memset( ps->pColorRunTable, 0, ps->BufferForColorRunTable ); /*wLengthY + 0x60 ); */
1834 
1835     p.pb = ps->pColorRunTable + _SCANSTATE_BYTES;
1836 #ifdef _A3I_EN
1837     wLoop = wLengthY + 200;
1838 #else
1839     wLoop = wLengthY + 0x20;
1840 #endif
1841     siSum = (Short)wP96BaseDpi;
1842 
1843     if (ps->DataInf.wPhyDataType != COLOR_TRUE24) {
1844 		for (; wLoop; wLoop--, p.pb++)	{
1845 		    if ((siSum -= (Short)ps->DataInf.xyPhyDpi.y) <= 0) {
1846 				siSum += (Short)wP96BaseDpi;
1847 				*p.pb = _COLORRUNTABLE_GREEN;
1848 	    	}
1849 		}
1850 
1851 #ifdef _A3I_EN
1852 		memset( ps->pColorRunTable + _NUMBER_OF_SCANSTEPS / 8 + wLengthY,
1853 																0x77, 0x100 );
1854 #endif
1855     } else {
1856 		/* CalColorRunTable */
1857 		DataType Data;
1858 
1859 		if (ps->fSonyCCD) {
1860 
1861 			if((ps->sCaps.Model == MODEL_OP_12000P) ||
1862                                            (ps->sCaps.Model == MODEL_OP_A3I)) {
1863 				Data.wValue = (_COLORRUNTABLE_RED << 8) | _COLORRUNTABLE_BLUE;
1864 			} else {
1865 				Data.wValue = (_COLORRUNTABLE_GREEN << 8) | _COLORRUNTABLE_BLUE;
1866 			}
1867 		} else {
1868 			Data.wValue = (_COLORRUNTABLE_BLUE << 8) | _COLORRUNTABLE_GREEN;
1869 		}
1870 
1871 		for (; wLoop; wLoop--, p.pb++)	{
1872 
1873 		    if ((siSum -= (Short)ps->DataInf.xyPhyDpi.y) <= 0) {
1874 				siSum += (Short)wP96BaseDpi;
1875 
1876     			if((ps->sCaps.Model == MODEL_OP_12000P)||
1877                                            (ps->sCaps.Model == MODEL_OP_A3I)) {
1878 					*p.pb |= _COLORRUNTABLE_GREEN;
1879                 } else {
1880 					*p.pb |= _COLORRUNTABLE_RED;
1881                 }
1882 
1883 				/* Sony:Green,Toshiba:Blue */
1884 				*(p.pb + 8)  |= Data.wOverlap.b2nd;
1885 				*(p.pb + 16) |= Data.wOverlap.b1st;
1886 		    }
1887 		}
1888 
1889 #ifdef _A3I_EN
1890 		memset( ps->pColorRunTable + _NUMBER_OF_SCANSTEPS / 8 + wLengthY,
1891 																0x77, 0x100 );
1892 #endif
1893 		if (ps->DataInf.xyPhyDpi.y < 100) {
1894 
1895 		    Byte bColor;
1896 
1897 		    /* CheckColorTable () */
1898 		    if (ps->fSonyCCD)
1899 				Data.wValue = 0xdd22;
1900 		    else
1901 				Data.wValue = 0xbb44;
1902 
1903 		    for (wLoop = wLengthY - _SCANSTATE_BYTES,
1904 				 p.pb = ps->pColorRunTable + _SCANSTATE_BYTES;
1905 												 wLoop; wLoop--, p.pb++) {
1906 				bColor = 0;
1907 
1908 				switch (a_bColorsSum[*p.pb & 0x0f]) {
1909 
1910 			    case 3:
1911 					if (*(p.pb + 2))
1912 					    bColor = 1;
1913                                         // fall through
1914 			    case 2:
1915 					if (*(p.pb + 1))
1916 			    		bColor++;
1917 					if (bColor == 2) {
1918 					    *p.pb &= ~_COLORRUNTABLE_RED;
1919 					    *(p.pb - 2) = _COLORRUNTABLE_RED;
1920 					}
1921 
1922 					if (bColor) {
1923 				    	if (*p.pb & ps->RedDataReady) {
1924 							*p.pb &= ~_COLORRUNTABLE_RED;
1925 							*(p.pb - 1) = _COLORRUNTABLE_RED;
1926 					    } else {
1927 							*p.pb &= Data.wOverlap.b2nd;
1928 							*(p.pb - 1) = Data.wOverlap.b1st;
1929 				    	}
1930 					}
1931 				}
1932 	    	}
1933 		}
1934 	}
1935 }
1936 
1937 /*.............................................................................
1938  *
1939  */
motorP96UpdateDataCurrentReadLine(pScanData ps)1940 static void motorP96UpdateDataCurrentReadLine( pScanData ps )
1941 {
1942 	ScanState	State1, State2;
1943 	TimerDef	timer;
1944 
1945 	IOGetCurrentStateCount( ps, &State1 );
1946 	IOGetCurrentStateCount( ps, &State2 );
1947 
1948     if (State1.bStatus == State2.bStatus) {
1949 
1950 		if (!(State2.bStatus & _SCANSTATE_STOP)) {
1951 
1952 		    /* motor still running */
1953 		    if (State2.bStep < ps->bCurrentLineCount) {
1954 				State2.bStep = State2.bStep + _NUMBER_OF_SCANSTEPS -
1955 												       ps->bCurrentLineCount;
1956 			} else
1957 				State2.bStep -= ps->bCurrentLineCount;
1958 
1959 		    if (State2.bStep >= (_NUMBER_OF_SCANSTEPS - 3)) {
1960 
1961 				MiscStartTimer( &timer, _SECOND );
1962 
1963 				do {
1964 				    State2.bStatus = IOGetScanState( ps, _FALSE );
1965 
1966 				} while (!(State2.bStatus & _SCANSTATE_STOP) &&
1967 						 !MiscCheckTimer( &timer ));
1968 		    } else
1969 				if (State2.bStep < 40)
1970 				    return;
1971 		}
1972 
1973 #ifdef _A3I_EN
1974 		if( ps->bFifoCount >= 140) {
1975 #else
1976 		if( ps->bFifoCount >= 20) {
1977 #endif
1978 		    if( 1 == ps->bCurrentSpeed ) {
1979 				ps->bCurrentSpeed *= 2;
1980 		    } else {
1981 				if( COLOR_TRUE24 == ps->DataInf.wPhyDataType )
1982 		    		ps->bCurrentSpeed += 4;
1983 				else
1984 				    ps->bCurrentSpeed += 2;
1985 			}
1986 
1987 	    	MotorP96AdjustCurrentSpeed( ps, ps->bCurrentSpeed );
1988 		}
1989 
1990 		/*
1991 		 * when using the full-step speed on 600 dpi models, then set
1992 		 * the motor into half-step mode, to avoid that the scanner hits
1993 		 * the back of its bed
1994 		 */
1995 /* HEINER:A3I */
1996 #if 1
1997     	if((600 == ps->PhysicalDpi) && (1 == ps->bCurrentSpeed)) {
1998 
1999 			if( ps->Asic96Reg.RD_MotorControl & ps->FullStep ) {
2000 				ps->Asic96Reg.RD_MotorControl &= ~ps->FullStep;
2001     			IOCmdRegisterToScanner( ps, ps->RegMotorControl,
2002 											   ps->Asic96Reg.RD_MotorControl );
2003 			}
2004 		}
2005 #endif
2006 		ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE );
2007 
2008 		IOSetToMotorRegister( ps);
2009     }
2010 }
2011 
2012 /*.............................................................................
2013  * 1) Save the current scan state
2014  * 2) Set the motor direction
2015  */
2016 static void motorGoHalfStep1( pScanData ps )
2017 {
2018 	ScanState sState;
2019 
2020     IOGetCurrentStateCount( ps, &sState );
2021 
2022 	ps->bOldStateCount = sState.bStep;
2023 
2024 	motorSetRunPositionRegister(ps);
2025    	ps->pScanState = a_bScanStateTable;
2026 
2027 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2028 
2029 		ps->FillRunNewAdrPointer( ps );
2030 
2031 		while (!motorCheckMotorPresetLength(ps))
2032 			motorP98FillRunNewAdrPointer1( ps );
2033 	} else {
2034 
2035 	    while (!motorCheckMotorPresetLength( ps ))
2036 			ps->FillRunNewAdrPointer( ps );
2037 	}
2038 }
2039 
2040 /*.............................................................................
2041  * when losing data, we use this function to go back some lines and read them
2042  * again...
2043  */
2044 static void motorP96WaitBack( pScanData ps )
2045 {
2046 	DataPointer	p;
2047 	DataType	Data;
2048 	ULong		dw;
2049 	UShort		w;
2050 	UShort		wStayMaxStep;
2051 
2052     /* FindMaxMoveStepIndex () */
2053 
2054     p.pw = a_wMoveStepTable;
2055 
2056     for( Data.dwValue = _NUMBER_OF_SCANSTEPS, wStayMaxStep = 1; Data.dwValue;
2057 													 Data.dwValue--, p.pw++ )
2058 		if( *p.pw > wStayMaxStep )
2059 		    wStayMaxStep = *p.pw;	/* save the largest step number */
2060 
2061     if( ps->DataInf.xyPhyDpi.y > ps->PhysicalDpi )
2062 		wStayMaxStep -= 40;
2063     else
2064 		wStayMaxStep -= 20;
2065 
2066     IORegisterDirectToScanner( ps, ps->RegInitDataFifo );
2067 
2068     memset( a_bScanStateTable, 1, _P96_BACKMOVES );
2069     memset(&a_bScanStateTable[_P96_BACKMOVES], 0xff, 250 - _P96_BACKMOVES );
2070 
2071     ps->Scan.fMotorBackward = _TRUE;
2072     motorGoHalfStep1( ps );			/* backward 130 lines */
2073 
2074     _DODELAY(200);			/* let the motor stable */
2075 
2076     if( ps->DataInf.xyPhyDpi.y <= ps->PhysicalDpi ) {
2077 		if( ps->DataInf.wPhyDataType == COLOR_TRUE24 ) {
2078 		    dw = _P96_FORWARDMOVES - 1;
2079 		} else {
2080 	    	dw = _P96_FORWARDMOVES - 2;
2081 		}
2082     } else {
2083 		dw = _P96_FORWARDMOVES;
2084 	}
2085 
2086 	memset( a_bScanStateTable, 1, dw );
2087     memset(&a_bScanStateTable[dw], 0xff, 250 - dw );
2088 
2089     ps->Scan.fMotorBackward = _FALSE;
2090     motorGoHalfStep1( ps );			/* move forward */
2091 
2092     /* GetNowStepTable () */
2093     ps->bCurrentLineCount = IOGetScanState( ps, _FALSE ) & _SCANSTATE_MASK;
2094     ps->bNewCurrentLineCountGap = 0;
2095 
2096     /* ClearColorByteTable () */
2097     memset( a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS );
2098 
2099     /* ClearHalfStepTable () */
2100     memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS );
2101 
2102     /* FillWaitMoveStepTable () */
2103     p.pw = &a_wMoveStepTable[((ps->bCurrentLineCount + 1) & 0x3f)];
2104     *p.pw = 1;
2105     p.pw++;
2106 
2107     for(w = wStayMaxStep, Data.bValue = ps->bMotorSpeedData, dw = 60;dw;dw--) {
2108 
2109 		if( p.pw >= pwEndMoveStepTable ) /* make sure pointer in range */
2110 		    p.pw = a_wMoveStepTable;
2111 
2112 		if (--Data.bValue)
2113 		    *p.pw = 0;			    			/* don't step */
2114 		else {
2115 		    Data.bValue = ps->bMotorSpeedData;  /* speed value       		 */
2116 		    *p.pw = w;			    			/* the ptr to pColorRunTable */
2117 		    w++;			    				/* pointer++ 				 */
2118 		}
2119 
2120 		p.pw++; 			    				/* to next entry */
2121     }
2122 	motorP96FillHalfStepTable( ps );
2123 	motorP96FillBackColorDataTable( ps );
2124 }
2125 
2126 /*.............................................................................
2127  * when losing data, we use this function to go back some lines and read them
2128  * again...
2129  */
2130 static void motorP98WaitBack( pScanData ps )
2131 {
2132 	DataPointer	p;
2133 	DataType	Data;
2134 	ULong		dw;
2135 	UShort		w;
2136 	UShort		wStayMaxStep;
2137 	UShort		back, forward;
2138 
2139     p.pw = &a_wMoveStepTable[ps->bCurrentLineCount];
2140 
2141     if (0 == *p.pw) {
2142 
2143 		for (w = _NUMBER_OF_SCANSTEPS; w && !*p.pw; w--) {
2144 		    p.pw--;
2145 		    if (p.pw < a_wMoveStepTable)
2146 				p.pw = &a_wMoveStepTable[_NUMBER_OF_SCANSTEPS - 1];
2147 		}
2148 		wStayMaxStep = *p.pw + 1;
2149     } else {
2150 		wStayMaxStep = *p.pw;	    /* save the largest step number */
2151 	}
2152 
2153 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2154 
2155 		forward = _P98_FORWARDMOVES;
2156 		back	= _P98_BACKMOVES;
2157 	} else {
2158 		forward = _P96_FORWARDMOVES;
2159 		back	= _P96_BACKMOVES;
2160 	}
2161 
2162 	/*
2163 	 * Off to avoid the problem of block data re-read/lost
2164 	 */
2165 	memset( a_bScanStateTable, 1, back );
2166 	memset( &a_bScanStateTable[back], 0xff, (_SCANSTATE_TABLE_SIZE - back));
2167 	ps->Scan.fMotorBackward = _TRUE;
2168     motorGoHalfStep1( ps );
2169 
2170     _DODELAY(200);			/* let the motor stable */
2171 
2172     memset(a_bScanStateTable, 1, forward );
2173     memset(&a_bScanStateTable[forward], 0xff, (_SCANSTATE_TABLE_SIZE-forward));
2174 	ps->Scan.fMotorBackward = _FALSE;
2175 	motorGoHalfStep1( ps );
2176 
2177     ps->bNewCurrentLineCountGap = 0;
2178 
2179     memset( a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS );
2180 	memset( a_bHalfStepTable,  0, _NUMBER_OF_SCANSTEPS );
2181 
2182 	ps->bCurrentLineCount = (ps->bCurrentLineCount + 1) & 0x3f;
2183 
2184     p.pw = &a_wMoveStepTable[ps->bCurrentLineCount];
2185 
2186     for (w = wStayMaxStep, Data.bValue = ps->bMotorSpeedData,
2187 							    			dw = _NUMBER_OF_SCANSTEPS; dw; dw--) {
2188 		if (--Data.bValue) {
2189 		    *p.pw = 0;			    	/* don't step */
2190 		} else {
2191 
2192 			/* speed value */
2193 		    Data.bValue = ps->bMotorSpeedData;
2194 	    	*p.pw = w;	    		    	/* the pointer to pColorRunTable*/
2195 		    w++;			    			/* pointer++                    */
2196 	}
2197 	/* make sure pointer in range */
2198 	if (++p.pw >= pwEndMoveStepTable)
2199 	    p.pw = a_wMoveStepTable;
2200     }
2201 
2202 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2203 		motorP98FillHalfStepTable( ps );
2204 		motorP98FillBackColorDataTable( ps );
2205 	} else {
2206 		motorP96FillHalfStepTable( ps );
2207 		motorP96FillBackColorDataTable( ps );
2208 	}
2209 }
2210 
2211 /*.............................................................................
2212  *
2213  */
2214 static void motorFillMoveStepTable( pScanData ps,
2215 								    UShort wIndex, Byte bStep, pUShort pw )
2216 {
2217     UShort w;
2218     Byte   b;
2219 
2220     if (++pw >= pwEndMoveStepTable )
2221 		pw = a_wMoveStepTable;
2222 
2223     wIndex++;
2224 
2225     b = ps->bMotorSpeedData;
2226 
2227     for (w = _NUMBER_OF_SCANSTEPS - bStep; w; w--) {
2228 		if (b == 1) {
2229 		    b = ps->bMotorSpeedData;
2230 		    *pw = wIndex;
2231 	    	wIndex++;
2232 		} else {
2233 		    b--;
2234 		    *pw = 0;
2235 		}
2236 		if (++pw >= pwEndMoveStepTable)
2237 	    	pw = a_wMoveStepTable;
2238     }
2239 
2240 	if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2241 		motorP98FillHalfStepTable( ps );
2242 	else
2243 		motorP96FillHalfStepTable( ps );
2244 
2245     if ((ps->bCurrentLineCount + 1) >= _NUMBER_OF_SCANSTEPS) {
2246 		b = ps->bCurrentLineCount + 1 - _NUMBER_OF_SCANSTEPS;
2247     } else {
2248 		b = ps->bCurrentLineCount + 1;
2249 	}
2250 
2251 	if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2252 		motorP98FillDataToColorTable( ps, b, _NUMBER_OF_SCANSTEPS - 1);
2253 	else
2254 		motorP96FillDataToColorTable( ps, b, _NUMBER_OF_SCANSTEPS - 1);
2255 }
2256 
2257 /*.............................................................................
2258  *
2259  */
2260 static void noMotorRunStatusStop( pScanData ps, Byte bScanState )
2261 {
2262     Byte  	b, b1, bCur;
2263     pUShort pw;
2264     pByte	pb;
2265     UShort  w;
2266 
2267     ps->bCurrentLineCount = (bScanState & _SCANSTATE_MASK);
2268 
2269     ps->Scan.fRefreshState  = _FALSE;
2270 
2271     IORegisterDirectToScanner( ps, ps->RegRefreshScanState );
2272 
2273     bCur = ps->bCurrentLineCount;
2274     pw 	 = &a_wMoveStepTable[bCur];
2275     pb 	 = ps->pColorRunTable;
2276 	b    = 0;
2277     b1 	 = 0;
2278     w 	 = _NUMBER_OF_SCANSTEPS;
2279 
2280     if (*pw) {
2281 		b = a_bColorsSum[pb [*pw] >> 4];
2282 		if (b) {
2283 		    motorClearColorByteTableLoop0( ps, b );
2284 		    ps->bNewCurrentLineCountGap = b;
2285 
2286 	    	motorFillMoveStepTable( ps, *pw, 1, pw );
2287 		    return;
2288 		}
2289 		b1++;
2290 		bCur--;
2291 
2292 		if (--pw < a_wMoveStepTable) {
2293 		    pw = &a_wMoveStepTable [_NUMBER_OF_SCANSTEPS - 1];
2294 		    bCur = _NUMBER_OF_SCANSTEPS - 1;
2295 		}
2296     }
2297 
2298     for(; w; w--) {
2299 		if (*pw) {
2300 		    if (*pw < _SCANSTATE_BYTES) {
2301 				b = 0;
2302 				break;
2303 		    } else
2304 				if ((b = a_bColorsSum [pb [*pw] >> 4]))
2305 				    break;
2306 		}
2307 		b1++;
2308 		bCur--;
2309 
2310 		if (--pw < a_wMoveStepTable) {
2311 		    pw = &a_wMoveStepTable [_NUMBER_OF_SCANSTEPS - 1];
2312 	   		bCur = _NUMBER_OF_SCANSTEPS - 1;
2313 		}
2314 	}
2315 
2316 	if (b1 == _NUMBER_OF_SCANSTEPS) {
2317 		ps->bNewCurrentLineCountGap = 0;
2318 		ps->bNewGap = 0;
2319 	} else {
2320 		ps->bNewCurrentLineCountGap = b1;
2321 		ps->bNewGap = b;
2322 	}
2323 
2324     motorClearColorByteTableLoop1( ps );
2325 
2326 	motorFillMoveStepTable( ps, *pw, 0, pw);
2327 }
2328 
2329 /*.............................................................................
2330  *
2331  */
2332 static void motorP96SetSpeed( pScanData ps, Byte bSpeed, Bool fSetRunState )
2333 {
2334 #if 0
2335     PUCHAR	pb;
2336     Byte	 bScanState;
2337 #endif
2338 	Byte     bState, bData;
2339 	UShort   wMoveStep;
2340 	pUShort  pw;
2341 	ULong    dw;
2342 	TimerDef timer;
2343 
2344     if( fSetRunState )
2345 		ps->Scan.bModuleState = _MotorInNormalState;
2346 
2347     ps->bMotorSpeedData = bSpeed;
2348 
2349     if( ps->bMoveDataOutFlag == _DataAfterRefreshState) {
2350 
2351 		ps->bMoveDataOutFlag = _DataInNormalState;
2352 
2353 		MiscStartTimer( &timer, (_SECOND /2));
2354 
2355 		while (!MiscCheckTimer(&timer)) {
2356 		    if ((bState = IOGetScanState( ps, _FALSE)) & _SCANSTATE_STOP) {
2357 				ps->bCurrentLineCount = bState & ~_SCANSTATE_STOP;
2358 				motorP96WaitBack( ps );
2359 				return;
2360 	    	}
2361 		}
2362     }
2363 
2364     bState = IOGetScanState( ps, _FALSE );
2365 
2366     if((ps->Scan.bModuleState != _MotorInStopState) ||
2367 												!(bState & _SCANSTATE_STOP)) {
2368 
2369 		/* Try to find the available step for all rest steps.
2370 		 * 1) if current step is valid (with data request), fill all steps
2371 		 *    after it
2372 		 * 2) if current step is NULL (for delay purpose), backward search the
2373 		 *    valid entry, then fill all steps after it
2374 		 * 3) if no step is valid, fill all entries
2375     	 */
2376 		Byte   bColors = 0;
2377    		UShort w;
2378 
2379 		/* NoMotorRunStatusStop () */
2380 		ps->bCurrentLineCount  = (bState &= _SCANSTATE_MASK);
2381 		ps->Scan.fRefreshState = _TRUE;
2382 
2383 		IORegisterDirectToScanner( ps, ps->RegRefreshScanState );
2384 
2385 		pw     = &a_wMoveStepTable[bState];
2386 		bData  = 0;
2387 		bState = ps->bCurrentLineCount;
2388 		dw     = _NUMBER_OF_SCANSTEPS;
2389 
2390 		if( (wMoveStep = *pw) ) {
2391 
2392 		    bColors = a_bColorsSum[ ps->pColorRunTable[*pw] / 16];
2393 
2394 	    	if( bColors ) {
2395 
2396 				motorClearColorByteTableLoop0( ps, bColors );
2397 				ps->bNewCurrentLineCountGap = bColors;
2398 				bColors = 1;
2399 				goto FillMoveStepTable;
2400 
2401 		    } else {
2402 
2403 				bData++;
2404 				dw--;
2405 				if( --pw < a_wMoveStepTable ) {
2406 				    pw     = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS - 1;
2407 				    bState = _NUMBER_OF_SCANSTEPS - 1;
2408 				}
2409 				else
2410 				    bState--;
2411 		    }
2412 		}
2413 
2414 		/* FindNextStep */
2415 		while( dw-- ) {
2416 
2417 		    if( (wMoveStep = *pw) ) {
2418 				if (wMoveStep < (_NUMBER_OF_SCANSTEPS / 2)) {
2419 				    bColors = 0;
2420 				    break;
2421 				}
2422 				if((bColors = a_bColorsSum [ps->pColorRunTable[wMoveStep] / 16]))
2423 				    break;
2424 		    }
2425 
2426 		    bData++;
2427 	    	if( --pw < a_wMoveStepTable ) {
2428 				pw     = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS - 1;
2429 				bState = _NUMBER_OF_SCANSTEPS - 1;
2430 		    }
2431 	    	else
2432 				bState--;
2433 		}
2434 
2435 		if (bData == _NUMBER_OF_SCANSTEPS )
2436 		    bData = bColors = 0;
2437 
2438 		ps->bNewCurrentLineCountGap = bData;
2439 		ps->bNewGap = bColors;
2440 		motorClearColorByteTableLoop1( ps );
2441 		bColors = 0;
2442 
2443 		/* use pw (new pointer) and new speed to recreate MoveStepTable
2444 		 * wMoveStep = Index number from a_wMoveStepTable ([esi])
2445 		 * bColors = number of steps should be reserved
2446 		 * pw = where to fill
2447 		 */
2448 
2449 FillMoveStepTable:
2450 
2451 		motorP96GetStartStopGap( ps, _TRUE );
2452 
2453 		if( !ps->bMotorStepTableNo )
2454 		    ps->bMotorStepTableNo = 1;
2455 
2456 		if( ps->bMotorStepTableNo != 0xff && ps->IO.portMode == _PORT_SPP &&
2457 													    ps->DataInf.xyPhyDpi.y <= 200) {
2458 	    	ps->bMotorStepTableNo++;
2459 		}
2460 
2461 		if (++pw >= pwEndMoveStepTable)
2462 		    pw = a_wMoveStepTable;
2463 
2464 		for( dw = _NUMBER_OF_SCANSTEPS - bColors, wMoveStep++,
2465 								     bData = ps->bMotorSpeedData; dw; dw-- ) {
2466 		    if( bData == 1 ) {
2467 
2468 				bData = ps->bMotorSpeedData;
2469 				if( ps->bMotorStepTableNo ) {
2470 
2471 					ps->bMotorStepTableNo--;
2472 				    w = wMoveStep;
2473 				    wMoveStep++;
2474 
2475 				} else {
2476 				    bData--;
2477 				    w = 0;
2478 				}
2479 		    } else {
2480 				bData--;
2481 				w = 0;
2482 		    }
2483 		    *pw = w;
2484 
2485 		    if (++pw >= pwEndMoveStepTable)
2486 				pw = a_wMoveStepTable;
2487 		}
2488 
2489 		motorP96FillHalfStepTable( ps );
2490 
2491 		/* FillColorBytesTable */
2492 		if((ps->bCurrentLineCount + 1) < _NUMBER_OF_SCANSTEPS )
2493 		    bState = ps->bCurrentLineCount + 1;
2494 		else
2495 		    bState = ps->bCurrentLineCount + 1 - _NUMBER_OF_SCANSTEPS;
2496 
2497 		motorP96FillDataToColorTable( ps, bState, _NUMBER_OF_SCANSTEPS - 1);
2498 	}
2499 }
2500 
2501 /*.............................................................................
2502  *
2503  */
2504 static void motorP98SetSpeed( pScanData ps, Byte bSpeed, Bool fSetRunState )
2505 {
2506 	static Byte lastFifoState = 0;
2507 
2508 	Bool overflow;
2509 	Byte bOld1ScanState, bData;
2510 
2511     if( fSetRunState )
2512 		ps->Scan.bModuleState = _MotorInNormalState;
2513 
2514     ps->bMotorSpeedData  = bSpeed;
2515 	overflow 			 = _FALSE;
2516 
2517 	if( _ASIC_IS_98001 != ps->sCaps.AsicID ) {
2518 		ps->bMoveDataOutFlag = _DataInNormalState;
2519 
2520 		bData = IODataRegisterFromScanner( ps, ps->RegFifoOffset );
2521 
2522 		if((lastFifoState > _P96_FIFOOVERFLOWTHRESH) &&
2523 													(bData < lastFifoState)) {
2524 			DBG( DBG_HIGH, "FIFO OVERFLOW, losing data !!\n" );
2525 			overflow = _TRUE;
2526         }
2527         lastFifoState = bData;
2528 	}
2529 
2530     bOld1ScanState = IOGetScanState( ps, _FALSE );
2531 
2532     if(!(bOld1ScanState & _SCANSTATE_STOP) && !overflow)
2533 		noMotorRunStatusStop( ps, bOld1ScanState );
2534     else {
2535 		ps->bCurrentLineCount = (bOld1ScanState & 0x3f);
2536 		ps->Scan.bModuleState = _MotorGoBackward;
2537 
2538 		motorP98WaitBack( ps );
2539 
2540 		if( overflow )
2541 	        lastFifoState = 0;
2542 
2543 		if( _ASIC_IS_98001 != ps->sCaps.AsicID )
2544 			ps->bMoveDataOutFlag = _DataFromStopState;
2545     }
2546 }
2547 
2548 /*.............................................................................
2549  *
2550  */
2551 static void motorP98003ModuleFreeRun( pScanData ps, ULong steps )
2552 {
2553     IODataToRegister( ps, ps->RegMotorFreeRunCount1, (_HIBYTE(steps)));
2554     IODataToRegister( ps, ps->RegMotorFreeRunCount0, (_LOBYTE(steps)));
2555     IORegisterToScanner( ps, ps->RegMotorFreeRunTrigger );
2556 }
2557 
2558 /*.............................................................................
2559  *
2560  */
2561 static void motorP98003ModuleToHome( pScanData ps )
2562 {
2563     if(!(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) {
2564 
2565     	IODataToRegister( ps, ps->RegMotor0Control,
2566             			(Byte)(ps->AsicReg.RD_Motor0Control|_MotorDirForward));
2567 
2568     	MotorP98003PositionYProc( ps, 40 );
2569     	MotorP98003BackToHomeSensor( ps );
2570 	    _DODELAY( 250 );
2571     }
2572 }
2573 
2574 /*.............................................................................
2575  *
2576  */
2577 static void motorP98003DownloadNullScanStates( pScanData ps )
2578 {
2579     memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
2580     IODownloadScanStates( ps );
2581 }
2582 
2583 /*.............................................................................
2584  *
2585  */
2586 static void motorP98003Force16Steps( pScanData ps )
2587 {
2588     ULong dw;
2589 
2590     IODataToRegister( ps, ps->RegStepControl, _MOTOR0_ONESTEP);
2591     IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR );
2592 
2593     for(dw = 16; dw; dw--) {
2594     	IORegisterToScanner( ps, ps->RegForceStep );
2595     	_DODELAY( 10 );
2596     }
2597 
2598     IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE );
2599 }
2600 
2601 /*.............................................................................
2602  *
2603  */
2604 static void motorP98003WaitForPositionY( pScanData ps )
2605 {
2606     Byte  bXStep;
2607     ULong dwBeginY;
2608 
2609     dwBeginY = (ULong)ps->DataInf.crImage.y * 4 + ps->Scan.dwScanOrigin;
2610 
2611     if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) {
2612     	if( ps->Device.f0_8_16 )
2613 	        dwBeginY += 16;
2614     	else
2615 	        dwBeginY += 8;
2616     }
2617 
2618     bXStep = (Byte)((ps->DataInf.wPhyDataType <= COLOR_256GRAY) ?
2619 				      ps->Device.XStepMono : ps->Device.XStepColor);
2620 
2621     if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
2622     	bXStep = 8;
2623 
2624     motorP98003Force16Steps( ps);
2625     dwBeginY -= 16;
2626 
2627     if (dwBeginY > (_RFT_SCANNING_ORG + _P98003_YOFFSET) &&
2628                 						  bXStep < ps->AsicReg.RD_XStepTime) {
2629 
2630     	IODataToRegister( ps, ps->RegMotorDriverType, ps->Scan.motorPower );
2631         _DODELAY( 12 );
2632     	IODataToRegister( ps, ps->RegXStepTime, bXStep);
2633 	    IODataToRegister( ps, ps->RegExtendedXStep, 0 );
2634     	IODataToRegister( ps, ps->RegScanControl1,
2635 	            		(UChar)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
2636     	MotorP98003PositionYProc( ps, dwBeginY - 64 );
2637 	    dwBeginY = 64;
2638     }
2639 
2640     IODataToRegister( ps, ps->RegFifoFullLength0, _LOBYTE(ps->AsicReg.RD_BufFullSize));
2641     IODataToRegister( ps, ps->RegFifoFullLength1, _HIBYTE(ps->AsicReg.RD_BufFullSize));
2642     IODataToRegister( ps, ps->RegFifoFullLength2, _LOBYTE(_HIWORD(ps->AsicReg.RD_BufFullSize)));
2643 
2644     IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType);
2645     _DODELAY( 12 );
2646 
2647     if(!ps->Device.f2003 || (ps->Shade.bIntermediate & _ScanMode_AverageOut) ||
2648 		    (  ps->DataInf.xyAppDpi.y <= 75 &&
2649                                   ps->DataInf.wPhyDataType <= COLOR_256GRAY)) {
2650 	    IODataToRegister( ps, ps->RegMotorDriverType,
2651                    (Byte)(ps->Scan.motorPower & (_MOTORR_MASK | _MOTORR_STRONG)));
2652     } else {
2653     	IODataToRegister( ps, ps->RegMotorDriverType,
2654                           ps->AsicReg.RD_MotorDriverType );
2655     }
2656 
2657     IODataToRegister( ps, ps->RegXStepTime,     ps->AsicReg.RD_XStepTime );
2658     IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime );
2659     IODataToRegister( ps, ps->RegScanControl1,
2660                     (Byte)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
2661 
2662     if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) {
2663 
2664         TimerDef timer;
2665 
2666 	    motorP98003ModuleFreeRun( ps, dwBeginY );
2667         _DODELAY( 15 );
2668 
2669     	MiscStartTimer( &timer, (_SECOND * 20));
2670 
2671 	    while(( IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING) &&
2672                                                       !MiscCheckTimer(&timer));
2673 	    IODataToRegister( ps, ps->RegModeControl, _ModeScan );
2674     } else {
2675     	MotorP98003PositionYProc( ps, dwBeginY );
2676         IORegisterToScanner( ps, ps->RegRefreshScanState );
2677     }
2678 }
2679 
2680 /*.............................................................................
2681  * move the sensor to the appropriate shading position
2682  */
2683 static Bool motorP98003GotoShadingPosition( pScanData ps )
2684 {
2685     motorP98003ModuleToHome( ps );
2686 
2687     /* position to somewhere under the transparency adapter */
2688     if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
2689 
2690     	MotorP98003ForceToLeaveHomePos( ps );
2691         motorP98003DownloadNullScanStates( ps );
2692 
2693     	IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE );
2694 	    IODataToRegister( ps, ps->RegModeControl, _ModeScan);
2695     	IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR );
2696 	    IODataToRegister( ps, ps->RegXStepTime, 6);
2697     	IODataToRegister( ps, ps->RegExtendedXStep, 0);
2698 	    IODataToRegister( ps, ps->RegScanControl1, _MFRC_BY_XSTEP);
2699 
2700     	MotorP98003PositionYProc( ps, _TPA_P98003_SHADINGORG );
2701     }
2702 
2703     return _TRUE;
2704 }
2705 
2706 /*.............................................................................
2707  * initialize this module and setup the correct function pointer according
2708  * to the ASIC
2709  */
2710 static void motorP98003PositionModuleToHome( pScanData ps )
2711 {
2712     Byte save, saveModel;
2713 
2714     saveModel = ps->AsicReg.RD_ModelControl;
2715 
2716     ps->Scan.fRefreshState = _FALSE;
2717 	motorP98003DownloadNullScanStates( ps );
2718 
2719 	_DODELAY( 1000UL / 8UL);
2720 
2721 	save = ps->Shade.bIntermediate;
2722 
2723 	ps->Shade.bIntermediate = _ScanMode_AverageOut;
2724 	ps->ReInitAsic( ps, _FALSE );
2725     ps->Shade.bIntermediate = save;
2726 
2727 	IODataToRegister( ps, ps->RegModeControl, _ModeScan );
2728 	IORegisterToScanner( ps, ps->RegResetMTSC );
2729 	IODataToRegister( ps, ps->RegScanControl1, 0 );
2730 
2731 	IODataToRegister( ps, ps->RegModelControl,
2732                           ps->Device.ModelCtrl | _ModelDpi300 );
2733 
2734 	IODataToRegister( ps, ps->RegLineControl, 80);
2735 	IODataToRegister( ps, ps->RegXStepTime, ps->Device.XStepBack);
2736 	IODataToRegister( ps, ps->RegMotorDriverType, ps->Scan.motorPower);
2737 
2738 	_DODELAY( 12 );
2739 
2740 	IODataToRegister( ps, ps->RegMotor0Control,
2741                 			(_MotorHHomeStop | _MotorOn | _MotorHQuarterStep |
2742 							 _MotorPowerEnable));
2743 	IODataToRegister( ps, ps->RegStepControl,
2744                                         (_MOTOR0_SCANSTATE | _MOTOR_FREERUN));
2745 
2746     memset( ps->a_nbNewAdrPointer, 0x88, _SCANSTATE_BYTES );
2747 	IODownloadScanStates( ps );
2748 	IORegisterToScanner( ps, ps->RegRefreshScanState );
2749 
2750     ps->AsicReg.RD_ModelControl = saveModel;
2751 }
2752 
2753 /************************ exported functions *********************************/
2754 
2755 /*.............................................................................
2756  * initialize this module and setup the correct function pointer according
2757  * to the ASIC
2758  */
2759 _LOC int MotorInitialize( pScanData ps )
2760 {
2761 	DBG( DBG_HIGH, "MotorInitialize()\n" );
2762 
2763 	if( NULL == ps )
2764 		return _E_NULLPTR;
2765 
2766 	ps->a_wMoveStepTable  = a_wMoveStepTable;
2767 	ps->a_bColorByteTable =	a_bColorByteTable;
2768 	wP96BaseDpi 		  = 0;
2769 
2770 	ps->PauseColorMotorRunStates = motorPauseColorMotorRunStates;
2771 
2772 	/*
2773 	 * depending on the asic, we set some functions
2774 	 */
2775 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2776 
2777 		ps->WaitForPositionY	 	  = motorP98WaitForPositionY;
2778 		ps->GotoShadingPosition	 	  = motorP98GotoShadingPosition;
2779 		ps->FillRunNewAdrPointer   	  = motorP98FillRunNewAdrPointer;
2780 		ps->SetupMotorRunTable	      = motorP98SetupRunTable;
2781 		ps->UpdateDataCurrentReadLine = motorP98UpdateDataCurrentReadLine;
2782 		ps->SetMotorSpeed 		 	  = motorP98SetSpeed;
2783 
2784 	} else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
2785 
2786 		ps->WaitForPositionY    = motorP98003WaitForPositionY;
2787 		ps->GotoShadingPosition	= motorP98003GotoShadingPosition;
2788 		ps->SetMotorSpeed 	    = motorP98SetSpeed;
2789 
2790     } else if( _IS_ASIC96(ps->sCaps.AsicID)) {
2791 
2792 		ps->WaitForPositionY		  = motorP96WaitForPositionY;
2793 		ps->GotoShadingPosition	 	  = motorP96GotoShadingPosition;
2794 		ps->FillRunNewAdrPointer   	  = motorP96FillRunNewAdrPointer;
2795 		ps->SetupMotorRunTable	      = motorP96SetupRunTable;
2796 		ps->UpdateDataCurrentReadLine = motorP96UpdateDataCurrentReadLine;
2797 		ps->SetMotorSpeed 		 	  = motorP96SetSpeed;
2798 
2799 	} else {
2800 
2801 		DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" );
2802 		return _E_NOSUPP;
2803 	}
2804 	return _OK;
2805 }
2806 
2807 /*.............................................................................
2808  *
2809  */
2810 _LOC void MotorSetConstantMove( pScanData ps, Byte bMovePerStep )
2811 {
2812 	DataPointer p;
2813     ULong	    dw;
2814 
2815     p.pb = ps->a_nbNewAdrPointer;
2816 
2817     switch( bMovePerStep )
2818     {
2819 	case 0: 	/* doesn't move at all */
2820 	    for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) {
2821 
2822 			if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2823 				*p.pdw &= 0x77777777;
2824 			else
2825 				*p.pdw &= 0xbbbbbbbb;
2826 		}
2827 	    break;
2828 
2829 	case 1:
2830 	    for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) {
2831 			if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2832 				*p.pdw |= 0x88888888;
2833 			else
2834 				*p.pdw |= 0x44444444;
2835 		}
2836 	    break;
2837 
2838 	case 2:
2839 	    for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) {
2840 			if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2841 				*p.pdw |= 0x80808080;
2842 			else
2843 				*p.pdw |= 0x40404040;
2844 		}
2845 	    break;
2846 
2847 	default:
2848 	    {
2849 			Byte bMoves = bMovePerStep;
2850 
2851 			for (dw = _SCANSTATE_BYTES; dw; dw--, p.pb++) {
2852 		    	if (!(--bMoves)) {
2853 					if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2854 						*p.pb |= 8;
2855 					else
2856 						*p.pb |= 4;
2857 					bMoves = bMovePerStep;
2858 			    }
2859 			    if (!(--bMoves)) {
2860 					if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2861 						*p.pb |= 0x80;
2862 					else
2863 						*p.pb |= 0x40;
2864 					bMoves = bMovePerStep;
2865 			    }
2866 			}
2867 	    }
2868     }
2869 	IOSetToMotorRegister( ps );
2870 }
2871 
2872 /*.............................................................................
2873  * function to bring the sensor back home
2874  */
2875 _LOC void MotorToHomePosition( pScanData ps )
2876 {
2877     TimerDef    timer;
2878     ScanState	StateStatus;
2879 
2880 	DBG( DBG_HIGH, "Waiting for Sensor to be back in position\n" );
2881 	_DODELAY( 250 );
2882 
2883 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2884 
2885     	if (!(IODataRegisterFromScanner(ps,ps->RegStatus) & _FLAG_P98_PAPER)){
2886 			ps->GotoShadingPosition( ps );
2887 		}
2888     } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
2889 
2890         ps->OpenScanPath( ps );
2891 
2892 	    if( !(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) {
2893 
2894             motorP98003PositionModuleToHome( ps );
2895 
2896             MiscStartTimer( &timer, _SECOND * 20);
2897             do {
2898 
2899                 if( IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)
2900                     break;
2901             } while( !MiscCheckTimer( &timer));
2902         }
2903         ps->CloseScanPath( ps );
2904 
2905 	} else {
2906 
2907 		if( ps->sCaps.Model >= MODEL_OP_9630P ) {
2908 			if( ps->sCaps.Model == MODEL_OP_A3I )
2909 				IOCmdRegisterToScanner( ps, ps->RegLineControl, 0x34 );
2910 			else
2911 				IOCmdRegisterToScanner( ps, ps->RegLineControl, 0x30 );
2912 		}
2913 
2914 		ps->bExtraMotorCtrl     = 0;
2915     	ps->Scan.fMotorBackward = _FALSE;
2916 		MotorP96ConstantMoveProc( ps, 25 );
2917 
2918 	    ps->Scan.fMotorBackward = _TRUE;
2919 		for(;;) {
2920 
2921 			motorP96GetScanStateAndStatus( ps, &StateStatus );
2922 
2923 			if ( StateStatus.bStatus & _FLAG_P96_PAPER ) {
2924 			    break;
2925 			}
2926 
2927  			MotorP96ConstantMoveProc( ps, 50000 );
2928 		}
2929 
2930     	ps->Scan.fMotorBackward = _FALSE;
2931 		ps->Asic96Reg.RD_MotorControl = 0;
2932 		IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
2933 
2934 	    memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
2935 		IOSetToMotorRegister( ps );
2936 		_DODELAY(250);
2937 
2938 	    ps->Asic96Reg.RD_LedControl = 0;
2939     	IOCmdRegisterToScanner(ps, ps->RegLedControl, ps->Asic96Reg.RD_LedControl);
2940 	}
2941 
2942 	DBG( DBG_HIGH, "- done !\n" );
2943 }
2944 
2945 /*.............................................................................
2946  *
2947  */
2948 _LOC void MotorP98GoFullStep( pScanData ps, ULong dwStep )
2949 {
2950 	memset( ps->pColorRunTable, 1, dwStep );
2951     memset( ps->pColorRunTable + dwStep, 0xff, 0x40);
2952 
2953     ps->bOldStateCount = IOGetScanState( ps, _FALSE ) & _SCANSTATE_MASK;
2954     motorP98SetRunFullStep( ps );
2955 
2956     ps->pScanState = ps->pColorRunTable;
2957     ps->FillRunNewAdrPointer( ps );
2958 
2959     while(!motorCheckMotorPresetLength( ps ))
2960 		motorP98FillRunNewAdrPointer1( ps );
2961 }
2962 
2963 /*.............................................................................
2964  *
2965  */
2966 _LOC void MotorP96SetSpeedToStopProc( pScanData ps )
2967 {
2968 	Byte	 bData;
2969     TimerDef timer;
2970 
2971 	MiscStartTimer( &timer, _SECOND);
2972     while( !MiscCheckTimer( &timer )) {
2973 
2974 		bData = IODataRegisterFromScanner( ps, ps->RegFifoOffset );
2975 
2976 		if ((bData > ps->bMinReadFifo) && (bData != ps->bFifoCount))
2977 		    break;
2978     }
2979     bData = IOGetScanState( ps, _FALSE );
2980 
2981     if (!(bData & _SCANSTATE_STOP)) {
2982 
2983 		MiscStartTimer( &timer, (_SECOND / 2));
2984 
2985 		while (!MiscCheckTimer( &timer )) {
2986 
2987 		    if (IOGetScanState( ps, _FALSE) != bData )
2988 				break;
2989 		}
2990     }
2991 
2992     ps->Scan.bModuleState = _MotorInStopState;
2993     ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _FALSE );
2994 
2995 	IOSetToMotorRegister( ps );
2996 }
2997 
2998 /*.............................................................................
2999  * Position Scan Module to specified line number (Forward or Backward & wait
3000  * for paper flag ON)
3001  */
3002 _LOC void MotorP96ConstantMoveProc( pScanData ps, ULong dwLines )
3003 {
3004 	Byte		bRemainder, bLastState;
3005     UShort		wQuotient;
3006     ULong		dwDelayMaxTime;
3007     ScanState	StateStatus;
3008 	TimerDef	timer;
3009 	Bool		fTimeout = _FALSE;
3010 
3011     wQuotient  = (UShort)(dwLines / _NUMBER_OF_SCANSTEPS);	/* state cycles */
3012     bRemainder = (Byte)(dwLines % _NUMBER_OF_SCANSTEPS);
3013 
3014 	/* 3.3 ms per line */
3015     dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 2;
3016 
3017 	MotorSetConstantMove( ps, 1 );	/* step every time */
3018 
3019     ps->OpenScanPath( ps );
3020 
3021     ps->AsicReg.RD_ModeControl = _ModeScan;
3022     IODataToRegister( ps, ps->RegModeControl, _ModeScan );
3023 
3024     if( ps->Scan.fMotorBackward ) {
3025 		ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->MotorOn |
3026 										   ps->FullStep | ps->bExtraMotorCtrl);
3027     } else {
3028 		ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->MotorOn |
3029 									  _MotorDirForward | ps->bExtraMotorCtrl);
3030 	}
3031 
3032 	IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl );
3033     ps->CloseScanPath( ps );
3034 
3035     bLastState = 0;
3036 
3037 	MiscStartTimer( &timer, dwDelayMaxTime );
3038 
3039     do {
3040 
3041 		motorP96GetScanStateAndStatus( ps, &StateStatus );
3042 
3043 		if( ps->Scan.fMotorBackward && (StateStatus.bStatus&_FLAG_P96_PAPER)) {
3044 		    break;
3045 		} else {
3046 
3047 		    /*
3048 			 * 1) Forward will not reach the sensor.
3049 			 * 2) Backwarding, doesn't reach the sensor
3050 			 */
3051 		    if (wQuotient) {
3052 
3053 				/* stepped */
3054 				if (StateStatus.bStep != bLastState) {
3055 				    bLastState = StateStatus.bStep;
3056 				    if (!bLastState)	/* done a cycle! */
3057 						wQuotient--;
3058 				}
3059 		    } else {
3060 				if (StateStatus.bStep >= bRemainder) {
3061 			    	break;
3062 				}
3063 			}
3064 		}
3065 
3066 		fTimeout = MiscCheckTimer( &timer );
3067 
3068 	} while ( _OK == fTimeout );
3069 
3070     if ( _OK == fTimeout ) {
3071 		memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
3072 		IOSetToMotorRegister( ps );
3073     }
3074 }
3075 
3076 /*.............................................................................
3077  *
3078  */
3079 _LOC Bool MotorP96AheadToDarkArea( pScanData ps )
3080 {
3081 	Byte	 bDark;
3082 	UShort   wTL;
3083     UShort 	 wTotalLastLine;
3084     TimerDef timer;
3085 
3086     ps->fColorMoreRedFlag  = _FALSE;
3087 	ps->fColorMoreBlueFlag = _FALSE;
3088     ps->wOverBlue = 0;
3089 
3090     /* FillToDarkCounter () */
3091     memset( ps->a_nbNewAdrPointer, 0x30, _SCANSTATE_BYTES);
3092     MotorSetConstantMove( ps, 2 );
3093 
3094     /* SetToDarkRegister () */
3095     ps->AsicReg.RD_ModeControl    = _ModeScan;
3096     ps->AsicReg.RD_ScanControl    = ps->bLampOn | _SCAN_BYTEMODE;
3097     ps->Asic96Reg.RD_MotorControl = _MotorDirForward | ps->FullStep;
3098 	ps->AsicReg.RD_ModelControl   = ps->Device.ModelCtrl | _ModelWhiteIs0;
3099 
3100     ps->AsicReg.RD_Dpi = 300;
3101 	wTL = 296;
3102 /*	if( MODEL_OP_A3I == ps->sCaps.Model ) { */
3103 	if( ps->PhysicalDpi > 300 ) {
3104 		wTL = 400;
3105 	    ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + 64 + 8 + 2048);
3106 	} else {
3107 	    ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + 64 + 8 + 1024);
3108 	}
3109     ps->AsicReg.RD_Pixels = 512;
3110 
3111 	IOPutOnAllRegisters( ps );
3112 
3113     ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->IgnorePF |
3114 											 ps->MotorOn | _MotorDirForward );
3115 
3116 	IOCmdRegisterToScanner( ps, ps->RegMotorControl,
3117 											  ps->Asic96Reg.RD_MotorControl );
3118 
3119 	MiscStartTimer( &timer, _SECOND * 2 );
3120     wTotalLastLine = 0;
3121 
3122 #ifdef _A3I_EN
3123     while( !MiscCheckTimer( &timer )) {
3124 
3125 		bDark = motorP96ReadDarkData( ps );
3126 
3127 		wTotalLastLine++;
3128 		if((bDark < 0x80) || (wTotalLastLine==wTL)) {
3129 
3130 		    IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
3131 		    return _TRUE;
3132 		}
3133     }
3134 #else
3135     while (!MiscCheckTimer( &timer )) {
3136 
3137 		bDark = motorP96ReadDarkData( ps );
3138 
3139 		wTotalLastLine++;
3140 		if (((ps->sCaps.AsicID == _ASIC_IS_96001) && (bDark > 0x80)) ||
3141 			((ps->sCaps.AsicID != _ASIC_IS_96001) && (bDark < 0x80)) ||
3142                                             (wTotalLastLine==wTL)) {
3143 
3144 		    IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeProgram );
3145 
3146 		    if (wTotalLastLine <= 24)
3147 				ps->fColorMoreRedFlag = _TRUE;
3148 		    else
3149 				if (wTotalLastLine >= 120) {
3150 				    ps->wOverBlue = wTotalLastLine - 80;
3151 				    ps->fColorMoreBlueFlag = _TRUE;
3152 				}
3153 
3154 	    	return _TRUE;
3155 		}
3156     }
3157 #endif
3158 
3159     return _FALSE;	/* already timed out */
3160 }
3161 
3162 /*.............................................................................
3163  * limit the speed settings for 96001/3 based models
3164  */
3165 _LOC void MotorP96AdjustCurrentSpeed( pScanData ps, Byte bSpeed )
3166 {
3167     if (bSpeed != 1) {
3168 
3169 		if (bSpeed > 34)
3170 		    ps->bCurrentSpeed = 34;
3171 		else
3172 		    ps->bCurrentSpeed = (bSpeed + 1) & 0xfe;
3173     }
3174 }
3175 
3176 /*.............................................................................
3177  *
3178  */
3179 _LOC void MotorP98003ForceToLeaveHomePos( pScanData ps )
3180 {
3181     TimerDef timer;
3182 
3183     IODataToRegister( ps, ps->RegStepControl, _MOTOR0_ONESTEP );
3184     IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR );
3185 
3186 	MiscStartTimer( &timer, _SECOND );
3187 
3188     do {
3189         if( !(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER))
3190     	    break;
3191 
3192         IORegisterToScanner( ps, ps->RegForceStep );
3193     	_DODELAY( 10 );
3194 
3195     } while( _OK == MiscCheckTimer( &timer ));
3196 
3197     IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE );
3198 }
3199 
3200 /*.............................................................................
3201  *
3202  */
3203 _LOC void MotorP98003BackToHomeSensor( pScanData ps )
3204 {
3205     TimerDef timer;
3206 
3207 	DBG( DBG_HIGH, "MotorP98003BackToHomeSensor()\n" );
3208 
3209     IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE );
3210     IODataToRegister( ps, ps->RegModeControl, _ModeScan );
3211 
3212     /* stepping every state */
3213     memset( ps->a_nbNewAdrPointer, 0x88, _SCANSTATE_BYTES );
3214     IODownloadScanStates( ps );
3215 
3216 	MiscStartTimer( &timer, _SECOND * 2 );
3217 
3218     while(!(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP) &&
3219                                                      !MiscCheckTimer( &timer ))
3220 	    ;
3221 
3222     _DODELAY( 1000UL );
3223 
3224     ps->AsicReg.RD_ModeControl = _ModeScan;
3225 
3226     if (!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) {
3227         IODataToRegister( ps, ps->RegLineControl, _LOBYTE(ps->Shade.wExposure));
3228         IODataToRegister( ps, ps->RegXStepTime,   _LOBYTE(ps->Shade.wXStep));
3229 
3230     } else {
3231     	IODataToRegister( ps, ps->RegLineControl, _DEFAULT_LINESCANTIME );
3232 	    IODataToRegister( ps, ps->RegXStepTime, 6);
3233     }
3234 
3235     IODataToRegister( ps, ps->RegStepControl,
3236                                          (_MOTOR_FREERUN | _MOTOR0_SCANSTATE));
3237     IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
3238     IODataToRegister( ps, ps->RegMotor0Control,
3239                   	    (_MotorHQuarterStep | _MotorOn | _MotorDirBackward |
3240                                     	_MotorPowerEnable | _MotorHHomeStop));
3241     IORegisterToScanner( ps, ps->RegRefreshScanState );
3242 
3243 	MiscStartTimer( &timer, _SECOND * 5 );
3244 
3245     do {
3246         if( IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER )
3247     	    break;
3248 
3249     	_DODELAY( 55 );
3250 
3251     } while( !MiscCheckTimer( &timer ));
3252 
3253     IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl);
3254     IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime);
3255 
3256    	DBG( DBG_HIGH, "LineCtrl=%u, XStepTime=%u\n",
3257                     ps->AsicReg.RD_LineControl, ps->AsicReg.RD_XStepTime );
3258 
3259     motorP98003DownloadNullScanStates( ps );
3260 }
3261 
3262 /*.............................................................................
3263  *
3264  */
3265 _LOC void MotorP98003ModuleForwardBackward( pScanData ps )
3266 {
3267     switch( ps->Scan.bModuleState ) {
3268 
3269 	case _MotorInNormalState:
3270 	    ps->Scan.bModuleState = _MotorGoBackward;
3271 	    IODataToRegister( ps, ps->RegScanControl1,
3272     			   (UChar)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
3273 	    IODataToRegister( ps, ps->RegMotor0Control,
3274     			    (UChar)(ps->AsicReg.RD_Motor0Control & ~_MotorDirForward));
3275 	    motorP98003ModuleFreeRun( ps, _P98003_BACKSTEPS );
3276 	    MiscStartTimer( &p98003MotorTimer, (15 * _MSECOND));
3277 	    break;
3278 
3279 	case _MotorGoBackward:
3280 	    if( MiscCheckTimer(& p98003MotorTimer)) {
3281     		if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING )) {
3282     		    ps->Scan.bModuleState = _MotorInStopState;
3283 	    	    MiscStartTimer( &p98003MotorTimer, (50 *_MSECOND));
3284 		    }
3285 	    }
3286 	    break;
3287 
3288 	case _MotorInStopState:
3289 	    if( MiscCheckTimer(&p98003MotorTimer)) {
3290 
3291     		if( IOReadFifoLength( ps ) < ps->Scan.dwMaxReadFifo ) {
3292     		    ps->Scan.bModuleState = _MotorAdvancing;
3293 	    	    IODataToRegister( ps, ps->RegScanControl1, ps->AsicReg.RD_ScanControl1);
3294 		        IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control);
3295         	    motorP98003ModuleFreeRun( ps, _P98003_FORWARDSTEPS );
3296         	    MiscStartTimer( &p98003MotorTimer, (15 * _MSECOND));
3297 		    }
3298 	    }
3299 	    break;
3300 
3301 	case _MotorAdvancing:
3302 	    if( MiscCheckTimer(&p98003MotorTimer)) {
3303     		if( !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP))
3304 	    	    ps->Scan.bModuleState = _MotorInNormalState;
3305     		else {
3306     		    if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING )) {
3307         			IORegisterToScanner( ps, ps->RegRefreshScanState );
3308 		        	ps->Scan.bModuleState = _MotorInNormalState;
3309                 }
3310 		    }
3311 		}
3312         break;
3313     }
3314 }
3315 
3316 /*.............................................................................
3317  *
3318  */
3319 _LOC void MotorP98003PositionYProc( pScanData ps, ULong steps)
3320 {
3321     TimerDef timer;
3322 
3323 	DBG( DBG_HIGH, "MotorP98003PositionYProc()\n" );
3324 
3325 	MiscStartTimer( &timer, _SECOND * 5 );
3326 
3327     while(!(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP) &&
3328                                                      !MiscCheckTimer( &timer ))
3329 	    ;
3330 
3331     _DODELAY( 12 );
3332 
3333     motorP98003ModuleFreeRun( ps, steps );
3334 
3335     _DODELAY( 15 );
3336 
3337 	MiscStartTimer( &timer, _SECOND * 30 );
3338 
3339     do  {
3340     	if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING) ||
3341                     	        !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP))
3342 	    break;
3343 
3344     } while( !MiscCheckTimer( &timer ));
3345 
3346 	DBG( DBG_HIGH, "MotorP98003PositionYProc() - done\n" );
3347 }
3348 
3349 /* END PLUSTEK-PP_MOTOR.C ...................................................*/
3350