1 /* @file plustek-pp_p48xx.c
2 * @brief here we have all functionality according to the ASIC96001/3 based
3 * models.
4 *
5 * based on sources acquired from Plustek Inc.
6 * Copyright (C) 1998 Plustek Inc.
7 * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de>
8 * also based on the work done by Rick Bronson
9 *
10 * History:
11 * - 0.30 - initial version
12 * - 0.31 - fixed a bug for the return value in p48xxDoTest
13 * - added additional debug messages
14 * - added function p48xxCheck4800Memory
15 * - 0.32 - added debug messages
16 * - fixed a bug in p48xxDoTest
17 * - disabled RD_WatchDogControl, lamp will be controlled by driver
18 * - 0.33 - added function p48xxSetAsicRegisters()
19 * - fixed a bug in p48xxDoTest (reset the ASIC registers)
20 * - removed p48xxPositionLamp
21 * - 0.34 - added some comments
22 * - 0.35 - added some comments
23 * - 0.36 - added function p48xxInitAllModules() to allow reinit of the modules
24 * - switching from Full- to Halfstep at ps->PhysicalDpi now in
25 * - p48xxSetGeneralRegister
26 * - fixed the color-inverse problem for model OP4800
27 * - 0.37 - move p48xxOpenScanPath, p48xxCloseScanPath
28 * and p48xxRegisterToScanner to io.c
29 * - removed // comments
30 * - added override for A3I scanner
31 * - 0.38 - added function p48xxPutToIdleMode()
32 * - added function p48xxCalibration
33 * - 0.39 - added A3I stuff
34 * - 0.40 - disabled A3I stuff
35 * - 0.41 - no changes
36 * - 0.42 - changed include names
37 * - 0.43 - no changes
38 * - 0.44 - fix format string issues, as Long types default to int32_t
39 * now
40 * .
41 * <hr>
42 * This file is part of the SANE package.
43 *
44 * This program is free software; you can redistribute it and/or
45 * modify it under the terms of the GNU General Public License as
46 * published by the Free Software Foundation; either version 2 of the
47 * License, or (at your option) any later version.
48 *
49 * This program is distributed in the hope that it will be useful, but
50 * WITHOUT ANY WARRANTY; without even the implied warranty of
51 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
52 * General Public License for more details.
53 *
54 * You should have received a copy of the GNU General Public License
55 * along with this program. If not, see <https://www.gnu.org/licenses/>.
56 *
57 * As a special exception, the authors of SANE give permission for
58 * additional uses of the libraries contained in this release of SANE.
59 *
60 * The exception is that, if you link a SANE library with other files
61 * to produce an executable, this does not by itself cause the
62 * resulting executable to be covered by the GNU General Public
63 * License. Your use of that executable is in no way restricted on
64 * account of linking the SANE library code into it.
65 *
66 * This exception does not, however, invalidate any other reasons why
67 * the executable file might be covered by the GNU General Public
68 * License.
69 *
70 * If you submit changes to SANE to the maintainers to be included in
71 * a subsequent release, you agree by submitting the changes that
72 * those changes may be distributed with this exception intact.
73 *
74 * If you write modifications of your own for SANE, it is your choice
75 * whether to permit this exception to apply to your modifications.
76 * If you do not wish that, delete this exception notice.
77 * <hr>
78 */
79 #include "plustek-pp_scan.h"
80
81 /*************************** some definitions ********************************/
82
83 #define _TEST_SZ 2048 /* always use 2048 for mem size (= one bank) */
84 #define _START_VAL 0x12345678 /* pick a non-zero starting value for our long */
85
86 #define _BankAndSizeForTest _MemBankSize2k /* always use 2k for mem test */
87
88 /*************************** local functions *********************************/
89
90 /*.............................................................................
91 * 1) Set asic to PROGRAM mode
92 * 2) Select the memory bank and size
93 * 3) Initiate data fifo
94 */
p48xxSetMemoryBankForProgram(pScanData ps,Byte bBankAndSize)95 static void p48xxSetMemoryBankForProgram( pScanData ps , Byte bBankAndSize )
96 {
97 /* enter program mode */
98 IODataToRegister( ps, ps->RegModeControl, _ModeProgram );
99
100 /* bank and size */
101 IODataToRegister( ps, ps->RegMemAccessControl, bBankAndSize );
102
103 /* initiate data fifo */
104 IORegisterToScanner( ps, ps->RegInitDataFifo );
105 }
106
107 /*.............................................................................
108 * use the internal memory of a scanner to find the model
109 */
p48xxDoTest(pScanData ps)110 static int p48xxDoTest( pScanData ps )
111 {
112 UChar tmpByte;
113 int retval;
114 ULong adder, ul, cntr;
115 pULong buffer;
116
117 DBG( DBG_LOW, "p48xxDoTest()\n" );
118
119 buffer = _KALLOC( sizeof(UChar) * _TEST_SZ, GFP_KERNEL );
120 if( NULL == buffer )
121 return _E_ALLOC;
122
123 retval = _E_NO_DEV;
124
125 /*
126 * do a memory test to determine how much memory this unit has, in the
127 * process we can figure out if it's a 4830 or a 9630. NOTE: the ram
128 * seems to be mirrored such that if you have a unit with only 32k it's
129 * mirrored 4 times to fill the 128k (2k * (_MemBankMask + 1)) space,
130 * so we will run a 32 bit incrementing pattern over the entire 128k and
131 * look for the 1st page (2k) to fail
132 */
133 adder = 0;
134 for (cntr = _BankAndSizeForTest;
135 cntr < _BankAndSizeForTest + _MemBanks; cntr++) {
136
137 ps->OpenScanPath( ps );
138
139 p48xxSetMemoryBankForProgram( ps, cntr );
140
141 /* prepare content, incrementing 32 val */
142 for (ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++)
143 buffer[ul] = ul + adder + _START_VAL;
144
145 /* fill to buffer */
146 IOMoveDataToScanner( ps, (pUChar)buffer, _TEST_SZ );
147
148 /*
149 * now check bank 0 to see if it got overwritten
150 * bank 0, size 2k
151 */
152 p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest );
153
154 ps->CloseScanPath( ps );
155
156 /* read data back */
157 IOReadScannerImageData( ps, (pUChar)buffer, _TEST_SZ );
158
159 /* check */
160 for (ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++) {
161 if (buffer[ul] != ul + _START_VAL) {
162 break;
163 }
164 }
165
166 /* if fail */
167 if (ul != _TEST_SZ / sizeof (ULong)) {
168 DBG( DBG_LOW, "Bank 0 overwritten\n" );
169 break;
170 }
171
172 /* now check current bank */
173 ps->OpenScanPath( ps );
174 p48xxSetMemoryBankForProgram( ps, cntr );
175 ps->CloseScanPath( ps );
176
177 /* read data back */
178 IOReadScannerImageData( ps, (pUChar)buffer, _TEST_SZ);
179
180 /* check if fail */
181 for( ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++ ) {
182 if( buffer[ul] != ul + adder + _START_VAL )
183 break;
184 }
185
186 /* check if fail */
187 if (ul != _TEST_SZ / sizeof(ULong)) {
188 DBG( DBG_LOW, "Bank not present, error at pos %u (%u)\n", ul,
189 (ULong)(_TEST_SZ / sizeof(ULong)));
190 break;
191 }
192
193 adder += _TEST_SZ / sizeof(ULong);
194 }
195
196 _KFREE( buffer );
197
198 DBG( DBG_LOW, "found %d bytes of memory\n",
199 _TEST_SZ * (cntr - _BankAndSizeForTest));
200
201 if( cntr == _BankAndSizeForTest ) {
202 DBG( DBG_LOW, "No memory ! No scanner...\n" );
203 return retval;
204 }
205
206 #ifdef DEBUG
207 tmpByte = IODataRegisterFromScanner( ps, 0x18 );
208 DBG( DBG_LOW, "tmpByte[0x18] = 0x%02x\n",tmpByte );
209 #endif
210
211 tmpByte = IODataRegisterFromScanner( ps, 0x0e );
212 DBG( DBG_LOW, "tmpByte = 0x%02x, cntr = %u, AsicId = 0x%02x\n",
213 tmpByte, cntr, ps->sCaps.AsicID );
214
215 /* 128k */
216 if ((_TEST_SZ * (cntr - _BankAndSizeForTest) == 1 << 17) &&
217 (ps->sCaps.AsicID == _ASIC_IS_96003)) {
218
219 /*
220 * if 128k then must be a 9630 or above
221 * hack, test for 12000P, The 9630 returns an 0x08
222 */
223 if ( tmpByte == 0x02 ) {
224
225 /*
226 * as we currently can't automagically detect an A3I we have to
227 * use the override switch
228 */
229 if( _OVR_PLUSTEK_A3I == ps->ModelOverride ) {
230
231 DBG( DBG_LOW, "Model Override --> A3I\n" );
232 ModelSetA3I( ps );
233 } else {
234 ModelSet12000( ps );
235 DBG( DBG_LOW, "It seems we have a 12000P/96000P\n" );
236 }
237
238 } else {
239 ModelSet9630( ps );
240 DBG( DBG_LOW, "It seems we have a 9630\n" );
241 }
242
243 retval = _OK;
244
245 } else {
246
247 DBG( DBG_LOW, "Scanner is not a 9630 or above\n");
248
249 if ( tmpByte != 0x0f ) {
250
251 DBG( DBG_LOW, "Looks like a 600!\n" );
252
253 if (( 0x08 == tmpByte ) &&
254 ((_TEST_SZ * (cntr - _BankAndSizeForTest)) == 32768 )) {
255 DBG( DBG_LOW, "But it is a 4830P!!! "
256 "(by mkochano@ee.pw.edu.pl)\n" );
257 ModelSet4830( ps );
258 } else {
259 ModelSet600( ps );
260 }
261 }
262 #ifdef DEBUG
263 else
264 DBG( DBG_LOW, "It seems we have a 4830\n" );
265 #endif
266
267 retval = _OK;
268 }
269
270 return retval;
271 }
272
273 /*.............................................................................
274 * setup ASIC registers and clear all scan states (no stepping)
275 */
p48xxSetAsicRegisters(pScanData ps)276 static void p48xxSetAsicRegisters( pScanData ps )
277 {
278 memset( &ps->AsicReg, 0, sizeof(ps->AsicReg));
279 memset( &ps->Asic96Reg, 0, sizeof(ps->Asic96Reg));
280 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
281
282 ps->AsicReg.RD_LineControl = ps->TimePerLine;
283 ps->AsicReg.RD_ScanControl = _SCAN_LAMP_ON;
284 ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0;
285 ps->AsicReg.RD_Origin = 0;
286 ps->AsicReg.RD_Pixels = 5110; /*ps->RdPix;*/
287 ps->Asic96Reg.RD_MotorControl = 0;
288 ps->Asic96Reg.RD_WatchDogControl = 0; /* org. val = 0x8f; */
289
290 IOPutOnAllRegisters( ps );
291 }
292
293 /*.............................................................................
294 * use the internal memory of a scanner to find the model
295 */
p48xxCheck4800Memory(pScanData ps)296 static int p48xxCheck4800Memory( pScanData ps )
297 {
298 int retval;
299 ULong ul;
300 pUChar buffer;
301
302 DBG( DBG_LOW, "p48xxCheck4800Memory()\n" );
303
304 buffer = _KALLOC( 2560, GFP_KERNEL ); /* 1280: Read,1280:Write */
305 if( NULL == buffer )
306 return _E_ALLOC;
307
308 retval = _OK;
309
310 /* bank 0, size 2k */
311 ps->OpenScanPath( ps );
312 p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest );
313
314 for (ul = 0; ul < 1280; ul++)
315 buffer[ul] = (UChar)ul; /* prepare content */
316
317 IOMoveDataToScanner( ps, buffer, 1280 ); /* fill to buffer */
318 p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest );
319 ps->CloseScanPath( ps );
320
321 /* read data back */
322 IOReadScannerImageData( ps, buffer + 1280, 1280 );
323
324 for( ul = 0; ul < 1280; ul++ ) {
325 if( buffer[ul] != buffer[ul+1280] ) {
326 DBG( DBG_HIGH, "Error in memory test at pos %u (%u != %u)\n",
327 ul, buffer[ul], buffer[ul+1280] );
328 retval = _E_NO_DEV;
329 break;
330 }
331 }
332
333 _KFREE(buffer);
334
335 return retval;
336 }
337
338 /*.............................................................................
339 * call all other modules, to initialize themselves
340 */
p48xxInitAllModules(pScanData ps)341 static int p48xxInitAllModules( pScanData ps )
342 {
343 int result;
344
345 result = DacInitialize( ps );
346 if( _OK != result )
347 return result;
348
349 result = ImageInitialize( ps );
350 if( _OK != result )
351 return result;
352
353 result = IOFuncInitialize( ps );
354 if( _OK != result )
355 return result;
356
357 result = IOInitialize( ps );
358 if( _OK != result )
359 return result;
360
361 result = MotorInitialize( ps );
362 if( _OK != result )
363 return result;
364
365 /*
366 * in debug version, check all function pointers
367 */
368 #ifdef DEBUG
369 if( _FALSE == MiscAllPointersSet( ps ))
370 return _E_INTERNAL;
371 #endif
372 return _OK;
373 }
374
375 /*.............................................................................
376 *
377 */
p48xxReadWriteTest(pScanData ps)378 static int p48xxReadWriteTest( pScanData ps )
379 {
380 int retval;
381
382 DBG( DBG_LOW, "p48xxReadWriteTest()\n" );
383
384 /*
385 * determine the model by the ASIC type (except for 4830/9630)
386 * might want to make a SetModelCommon() someday for this...
387 */
388 ps->RedDataReady = 0x01; /* normal for Red and Green */
389 ps->GreenDataReady = 0x02;
390 ps->AsicRedColor = 0x01;
391 ps->AsicGreenColor = 0x03;
392
393 /*
394 * if not already set, try to find ASIC type (96001 or 96003)
395 */
396 if ( _NO_BASE == ps->sCaps.wIOBase ) {
397
398 /* get copy of asic id */
399 ps->sCaps.AsicID = IODataRegisterFromScanner( ps, ps->RegAsicID );
400
401 if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) {
402
403 /* actually either a 4830, 9630, 12000, find out later */
404 DBG( DBG_LOW, "Found a 96003 ASIC at Reg 0x%x\n", ps->RegAsicID );
405 ModelSet4830( ps );
406
407 } else {
408
409 if ( _ASIC_IS_96001 == ps->sCaps.AsicID ) {
410 DBG( DBG_LOW, "Found a 96001 ASIC at Reg 0x%x\n",
411 ps->RegAsicID );
412 ModelSet4800( ps );
413 } else {
414 DBG( DBG_LOW, "Can't find your model, asic = 0x%x\n",
415 ps->sCaps.AsicID );
416 return _E_NO_ASIC;
417 }
418 }
419 }
420
421 /*
422 * set the registers according to the assumptions above
423 */
424 p48xxSetAsicRegisters( ps );
425
426 if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) {
427 retval = p48xxDoTest( ps );
428
429 /*
430 * as we may now have detected another model, we have to set
431 * the registers to their new values...
432 * and maybe the modules have to be reset as well
433 */
434 if( _OK == retval ) {
435 p48xxSetAsicRegisters( ps );
436 retval = p48xxInitAllModules( ps );
437 }
438
439 return retval;
440 }
441
442 /*
443 * this part will be reached only for the 4800 - ASIC 96001
444 * we check only the memory as the original driver does
445 */
446 return p48xxCheck4800Memory( ps );
447 }
448
449 /*.............................................................................
450 * 1) Setup the registers of asic.
451 * 2) Determine which type of CCD we are using
452 * 3) According to the CCD, prepare the CCD dependent veriables
453 * SONY CCD:
454 * The color exposure sequence: Red, Green (after 11 red lines),
455 * Blue (after 8 green lines)
456 * TOSHIBA CCD:
457 * The color exposure sequence: Red, Blue (after 11 red lines),
458 * Green (after 8 blue lines)
459 */
p48xxSetupScannerVariables(pScanData ps)460 static void p48xxSetupScannerVariables( pScanData ps )
461 {
462 UChar tmp;
463 TimerDef timer;
464
465 DBG( DBG_LOW, "p48xxSetupScannerVariables()\n" );
466
467 ps->OpenScanPath( ps );
468
469 IODataToRegister( ps, ps->RegModelControl2, _Model2ChannelMult );
470
471 if( 2 == IODataFromRegister( ps, ps->RegWriteIOBusDecode1 )) {
472
473 DBG( DBG_LOW, "Scanner has 97003 ASIC too.\n" );
474 ps->f97003 = _TRUE;
475 ps->b97003DarkR = 8;
476 ps->b97003DarkG = 8;
477 ps->b97003DarkB = 8;
478
479 ps->Asic96Reg.u26.RD_ModelControl2 = _Model2ChannelMult;
480 } else {
481
482 DBG( DBG_LOW, "No ASIC 97003 found.\n" );
483 ps->f97003 = _FALSE;
484 ps->Asic96Reg.u26.RD_ModelControl2 = _Model2DirectOutPort;
485 }
486
487 IODataToRegister( ps, ps->RegModelControl2,
488 ps->Asic96Reg.u26.RD_ModelControl2 );
489
490 tmp = IODataFromRegister( ps, ps->RegStatus );
491 DBG( DBG_LOW, "Status-Register = 0x%02X\n", tmp );
492 #ifdef DEBUG
493 if( tmp & _FLAG_P96_MOTORTYPE ) {
494 DBG( DBG_LOW, "Scanner has Full/Half Stepping drive\n" );
495 } else {
496 DBG( DBG_LOW, "Scanner has Micro Stepping drive\n" );
497 }
498 #endif
499
500 if( tmp & _FLAG_P96_CCDTYPE) {
501 ps->fSonyCCD = _FALSE;
502 DBG( DBG_LOW, "CCD is NEC/TOSHIBA Type\n" );
503 } else {
504 ps->fSonyCCD = _TRUE;
505 DBG( DBG_LOW, "CCD is SONY Type\n" );
506 }
507
508 ps->CloseScanPath( ps );
509
510 ps->b1stColorByte = ps->AsicRedColor;
511 ps->b1stColor = ps->RedDataReady;
512
513 if (ps->fSonyCCD) {
514
515 ps->b2ndColorByte = ps->AsicGreenColor;
516 ps->b2ndColor = ps->GreenDataReady;
517 ps->b3rdColorByte = _ASIC_BLUECOLOR;
518 ps->b3rdColor = _BLUE_DATA_READY;
519
520 } else { /* NEC/Toshiba CCD */
521
522 ps->b2ndColorByte = _ASIC_BLUECOLOR;
523 ps->b2ndColor = _BLUE_DATA_READY;
524 ps->b3rdColorByte = ps->AsicGreenColor;
525 ps->b3rdColor = ps->GreenDataReady;
526 }
527
528 ps->b1stMask = (Byte)~ps->b1stColor;
529 ps->b2ndMask = (Byte)~ps->b2ndColor;
530 ps->b3rdMask = (Byte)~ps->b3rdColor;
531
532 ps->b1stLinesOffset = 17;
533 ps->b2ndLinesOffset = 9;
534
535 /*
536 * calculate I/O Timer
537 * if we cannot read 200 lines within 1 second, the I/O time has to add 2
538 * CalculateIOTime ()
539 */
540 if( _PORT_SPP != ps->IO.portMode ) {
541
542 UShort wLines = 200;
543 pUChar pBuf;
544
545 pBuf = _KALLOC((_BUF_SIZE_BASE_CONST * 2), GFP_KERNEL );
546
547 if ( NULL != pBuf ) {
548
549 MiscStartTimer( &timer, _SECOND );
550
551 do {
552 IOReadScannerImageData( ps, pBuf, (_BUF_SIZE_BASE_CONST * 2));
553
554 wLines--;
555 } while (!MiscCheckTimer( &timer) && wLines);
556
557 if( !wLines )
558 ps->bExtraAdd = 0;
559 else
560 ps->bExtraAdd = 2;
561
562 _KFREE( pBuf );
563
564 } else {
565 ps->bExtraAdd = 2; /* poor resource */
566 }
567 } else {
568 ps->bExtraAdd = 0;
569 }
570 }
571
572 /*.............................................................................
573 *
574 */
p48xxSetGeneralRegister(pScanData ps)575 static void p48xxSetGeneralRegister( pScanData ps )
576 {
577 if( MODEL_OP_A3I == ps->sCaps.Model ) {
578 ps->AsicReg.RD_ModelControl = _ModelDpi400 | _ModelWhiteIs0 |
579 _ModelMemSize128k4;
580 }
581
582 ps->AsicReg.RD_ModeControl = _ModeScan;
583
584 /* WORK: ps->PhysicalDpi should be correct, but the we have to work
585 * on motor.c again to use other running-tables
586 * if ( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) {
587 */
588 if ( ps->DataInf.xyAppDpi.y <= 300 ) {
589 /* HEINER:A3I
590 if ( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) {
591 */
592 ps->Asic96Reg.RD_MotorControl = (ps->FullStep | ps->IgnorePF |
593 ps->MotorOn | _MotorDirForward);
594 } else {
595 ps->Asic96Reg.RD_MotorControl = (ps->IgnorePF | ps->MotorOn |
596 _MotorDirForward);
597 }
598
599 if ( ps->DataInf.wPhyDataType == COLOR_BW ) {
600 ps->AsicReg.RD_ScanControl = ps->bLampOn;
601
602 if (!(ps->DataInf.dwScanFlag & SCANDEF_Inverse))
603 ps->AsicReg.RD_ScanControl |= _P96_SCANDATA_INVERT;
604
605 } else {
606
607 ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE;
608
609 if (ps->DataInf.dwScanFlag & SCANDEF_Inverse)
610 ps->AsicReg.RD_ScanControl |= _P96_SCANDATA_INVERT;
611 }
612
613 if (ps->DataInf.xyPhyDpi.x <= 200)
614 ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE;
615
616 DBG( DBG_LOW, "RD_ModeControl = 0x%02x\n", ps->AsicReg.RD_ModeControl );
617 DBG( DBG_LOW, "RD_MotorControl = 0x%02x\n", ps->Asic96Reg.RD_MotorControl );
618 DBG( DBG_LOW, "RD_ScanControl = 0x%02x\n", ps->AsicReg.RD_ScanControl );
619 }
620
621 /*.............................................................................
622 *
623 */
p48xxSetupScanningCondition(pScanData ps)624 static void p48xxSetupScanningCondition( pScanData ps )
625 {
626 DBG( DBG_LOW, "p48xxSetupScanningCondition()\n" );
627
628 IORegisterDirectToScanner( ps, ps->RegInitDataFifo );
629
630 /* Cal64kTime (); */
631 if( MODEL_OP_A3I == ps->sCaps.Model )
632 ps->wLinesPer64kTime = (UShort)(65555UL / ps->DataInf.dwAsicBytesPerPlane *
633 5UL);
634 else
635 ps->wLinesPer64kTime = (UShort)(65555UL / ps->DataInf.dwAsicBytesPerPlane *
636 10UL / 3UL);
637
638 DBG( DBG_LOW, "wLinesPer64kTime = %u\n", ps->wLinesPer64kTime );
639
640 ps->InitialSetCurrentSpeed( ps );
641
642 DBG( DBG_LOW, "Current Speed = %u\n", ps->bCurrentSpeed );
643
644 ps->bMinReadFifo = (Byte)((ps->DataInf.dwAsicBytesPerPlane + 511) / 512);
645 DBG( DBG_LOW, "MinReadFifo = %u\n", ps->bMinReadFifo );
646
647 p48xxSetGeneralRegister( ps );
648
649 /*
650 * if speed is not the fastest and DPI is less than 400, do half steps
651 */
652 if( ps->DataInf.wPhyDataType >= COLOR_256GRAY &&
653 !(ps->bCurrentSpeed & 1) && (ps->DataInf.xyAppDpi.y <= 300)) {
654 /* HEINER:A3I
655 if( !(ps->bCurrentSpeed & 1) && (ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi)) {
656 */
657 ps->fHalfStepTableFlag = _TRUE;
658 ps->Asic96Reg.RD_MotorControl &= ps->StepMask;
659 }
660
661 ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x;
662 DBG( DBG_LOW, "RD_Dpi = %u\n", ps->AsicReg.RD_Dpi );
663
664 /* SetStartStopRegister (ps) */
665 ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + ps->Device.DataOriginX +
666 ps->DataInf.crImage.x);
667
668 if (ps->DataInf.wPhyDataType < COLOR_256GRAY) {
669 ps->AsicReg.RD_Pixels =
670 (UShort)(ps->DataInf.dwAsicPixelsPerPlane + 7) & 0xfff8;
671 } else {
672 ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicPixelsPerPlane;
673 }
674
675 DBG( DBG_LOW, "RD_Pixels = %u\n", ps->AsicReg.RD_Pixels );
676
677 /* SetupMotorStart () */
678 IORegisterDirectToScanner( ps, ps->RegInitDataFifo);
679 ps->SetupMotorRunTable( ps );
680
681 IOSetToMotorRegister( ps );
682
683 ps->pCurrentColorRunTable = ps->pColorRunTable;
684 ps->bCurrentLineCount = 0;
685
686 IOPutOnAllRegisters( ps );
687
688 ps->OpenScanPath( ps );
689
690 /*
691 * when using the full-step speed on 600 dpi models, then set
692 * the motor into half-step mode, to avoid that the scanner hits
693 * the back of its cover
694 */
695 if((600 == ps->PhysicalDpi) && (1 == ps->bCurrentSpeed)) {
696
697 ps->Asic96Reg.RD_MotorControl &= ~ps->FullStep;
698 }
699
700 IODataToRegister( ps, ps->RegMotorControl,
701 (Byte)(ps->Asic96Reg.RD_MotorControl & ~ps->MotorOn));
702 IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl);
703 IORegisterToScanner( ps, ps->RegInitDataFifo );
704
705 ps->CloseScanPath( ps );
706 }
707
708 /*.............................................................................
709 * switch the motor off and put the scanner into idle mode
710 */
p48xxPutToIdleMode(pScanData ps)711 static void p48xxPutToIdleMode( pScanData ps )
712 {
713 DBG( DBG_LOW, "Putting Scanner (ASIC 96001/3) into Idle-Mode\n" );
714
715 /*
716 * turn off motor
717 */
718 ps->Asic96Reg.RD_MotorControl = 0;
719 IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
720 }
721
722 /*.............................................................................
723 * for P96001/3 ASIC
724 * do all the preliminary stuff here (calibrate the scanner and move the
725 * sensor to it´s start position, also setup the driver for the
726 * current run)
727 */
p48xxCalibration(pScanData ps)728 static int p48xxCalibration( pScanData ps )
729 {
730 DBG( DBG_LOW, "p48xxCalibration()\n" );
731
732 ps->Scan.bFifoSelect = ps->RegGFifoOffset;
733
734 while (_TRUE) {
735
736 _ASSERT(ps->WaitForShading);
737 if (ps->WaitForShading( ps )) {
738
739 if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) {
740
741 /* HEINER:A3I disable !! */
742 MotorP96AheadToDarkArea( ps );
743
744 if( ps->Scan.fRefreshState ) {
745 ps->Scan.fRefreshState = _FALSE;
746
747 if (!ps->fReshaded) {
748 ps->fReshaded = _TRUE;
749
750 if (ps->fColorMoreRedFlag || ps->fColorMoreBlueFlag) {
751 continue;
752 }
753 }
754 }
755 }
756 break;
757
758 } else {
759 ps->fScanningStatus = _FALSE;
760 ps->DataInf.dwAppLinesPerArea = 0;
761 return _E_TIMEOUT;
762 }
763 }
764
765 if((ps->sCaps.AsicID != _ASIC_IS_96001) &&
766 (ps->DataInf.wPhyDataType != COLOR_BW)) {
767 DacP96WriteBackToGammaShadingRAM(ps);
768 }
769
770 if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
771 ps->bExtraMotorCtrl = 0;
772 ps->Scan.fMotorBackward = _TRUE;
773 MotorP96ConstantMoveProc( ps, 4000 );
774 }
775
776 /*
777 * move sensor and setup scanner for grabbing the picture
778 */
779 _ASSERT(ps->WaitForPositionY);
780 ps->WaitForPositionY(ps);
781 return _OK;
782 }
783
784 /************************ exported functions *********************************/
785
786 /*.............................................................................
787 * initialize the register values and function calls for the 96001/3 asic
788 */
P48xxInitAsic(pScanData ps)789 _LOC int P48xxInitAsic( pScanData ps )
790 {
791 DBG( DBG_LOW, "P48xxInitAsic()\n" );
792
793 ps->IO.bOpenCount = 0;
794
795 ps->RegSwitchBus = 0;
796 ps->RegReadDataMode = 1;
797 ps->RegWriteDataMode = 2;
798 ps->RegEPPEnable = 3;
799 ps->RegInitDataFifo = 4;
800 ps->RegForceStep = 5;
801 ps->RegInitScanState = 6;
802 ps->RegRefreshScanState = 7;
803 ps->RegStatus = 0x10;
804 ps->RegFifoOffset = 0x11;
805 ps->RegGetScanState = 0x12;
806 ps->RegAsicID = 0x13; /* Determine the asic */
807 ps->RegReadIOBufBus = 0x17;
808 ps->RegModeControl = 0x18;
809 ps->RegLineControl = 0x19;
810 ps->RegScanControl = 0x1a;
811 ps->RegMotorControl = 0x1b;
812 ps->RegModelControl = 0x1c;
813 ps->RegMemAccessControl = 0x1d;
814 ps->RegDpiLow = 0x1e;
815 ps->RegDpiHigh = 0x1f;
816 ps->RegScanPosLow = 0x20;
817 ps->RegScanPosHigh = 0x21;
818 ps->RegWidthPixelsLow = 0x22;
819 ps->RegWidthPixelsHigh = 0x23;
820 ps->RegThresholdControl = 0x24;
821 ps->RegWatchDogControl = 0x25;
822 ps->RegModelControl2 = 0x26;
823 ps->RegThresholdGapControl = 0x27;
824 ps->RegRedChShadingOffset = 0x28;
825 ps->RegGreenChShadingOffset = 0x29;
826 ps->RegRedDCAdjust = 0x27; /* not sure why these are dup's */
827 ps->RegGreenDCAdjust = 0x28;
828 ps->RegBlueDCAdjust = 0x29;
829 ps->RegBlueChShadingOffset = 0x2a;
830 ps->RegRedChDarkOffset = 0x2b;
831 ps->RegGreenChDarkOffset = 0x2c;
832 ps->RegBlueChDarkOffset = 0x2d;
833 ps->RegWriteIOBusDecode1 = 0x2e;
834 ps->RegWriteIOBusDecode2 = 0x2f;
835 ps->RegScanStateControl = 0x30;
836 ps->RegRedChEvenOffset = 0x31;
837 ps->RegGreenChEvenOffset = 0x32;
838 ps->RegBlueChEvenOffset = 0x33;
839 ps->RegRedChOddOffset = 0x34;
840 ps->RegGreenChOddOffset = 0x35;
841 ps->RegBlueChOddOffset = 0x36;
842 ps->RegRedGainOutDirect = 0x37;
843 ps->RegGreenGainOutDirect = 0x38;
844 ps->RegBlueGainOutDirect = 0x39;
845 ps->RegLedControl = 0x3a;
846 ps->RegShadingCorrectCtrl = 0x3b;
847 ps->RegScanStateBegin = 0x40; /* (0, 1) */
848 ps->RegScanStateEnd = 0x5f; /* (62, 63) */
849
850 /*
851 * setup function calls
852 */
853 ps->ReadWriteTest = p48xxReadWriteTest;
854 ps->SetupScannerVariables = p48xxSetupScannerVariables;
855 ps->SetupScanningCondition = p48xxSetupScanningCondition;
856 ps->PutToIdleMode = p48xxPutToIdleMode;
857 ps->Calibration = p48xxCalibration;
858
859 /*
860 * setup misc
861 */
862 ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF;
863 ps->CtrlReadLowNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE;
864
865 ps->MotorFreeRun = 0x80;
866 ps->bLampOn = _SCAN_LAMP_ON;
867 ps->f97003 = _FALSE;
868
869 /*
870 * initialize the other modules
871 */
872 return p48xxInitAllModules( ps );
873 }
874
875 /* END PLUSTEK-PP_P48xx.C ...................................................*/
876