1 /* @file plustekpp-io.c
2 * @brief as the name says, here we have all the I/O
3 * functions according to the parallel port hardware
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 *
9 * History:
10 * - 0.37 - initial version
11 * - added Kevins' suggestions
12 * - 0.38 - added Asic 98003 stuff and ioP98ReadWriteTest()
13 * - added IODataRegisterToDAC()
14 * - replaced function IOSPPWrite by IOMoveDataToScanner
15 * - modified ioP98OpenScanPath again and reuse V0.36 stuff again
16 * - added IO functions
17 * - 0.39 - added IO functions
18 * - added f97003 stuff from A3I code
19 * - 0.40 - no changes
20 * - 0.41 - no changes
21 * - 0.42 - changed include names
22 * - 0.43 - no changes
23 * - 0.44 - fix format string issues, as Long types default to int32_t
24 * now
25 * .
26 * <hr>
27 * This file is part of the SANE package.
28 *
29 * This program is free software; you can redistribute it and/or
30 * modify it under the terms of the GNU General Public License as
31 * published by the Free Software Foundation; either version 2 of the
32 * License, or (at your option) any later version.
33 *
34 * This program is distributed in the hope that it will be useful, but
35 * WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 * General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program. If not, see <https://www.gnu.org/licenses/>.
41 *
42 * As a special exception, the authors of SANE give permission for
43 * additional uses of the libraries contained in this release of SANE.
44 *
45 * The exception is that, if you link a SANE library with other files
46 * to produce an executable, this does not by itself cause the
47 * resulting executable to be covered by the GNU General Public
48 * License. Your use of that executable is in no way restricted on
49 * account of linking the SANE library code into it.
50 *
51 * This exception does not, however, invalidate any other reasons why
52 * the executable file might be covered by the GNU General Public
53 * License.
54 *
55 * If you submit changes to SANE to the maintainers to be included in
56 * a subsequent release, you agree by submitting the changes that
57 * those changes may be distributed with this exception intact.
58 *
59 * If you write modifications of your own for SANE, it is your choice
60 * whether to permit this exception to apply to your modifications.
61 * If you do not wish that, delete this exception notice.
62 * <hr>
63 */
64 #include "plustek-pp_scan.h"
65
66 /*************************** some prototypes *********************************/
67
68 static Bool fnEPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize );
69 static Bool fnSPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize );
70 static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize );
71
72 typedef struct {
73 pFnReadData func;
74 char *name;
75 } ioReadFuncDef;
76
77 static ioReadFuncDef ioReadFunc[3] = {
78 { fnEPPRead, "fnEPPRead" },
79 { fnSPPRead, "fnSPPRead" },
80 { fnBiDirRead, "fnBiDirRead" }
81 };
82
83 /*************************** some definitions ********************************/
84
85 #define _MEMTEST_SIZE 1280
86
87 /*************************** local functions *********************************/
88
89 /** we provide some functions to read data from SPP port according to
90 * the speed we have detected (ReadWriteTest!!)
91 */
ioDataFromSPPFast(pScanData ps)92 static Byte ioDataFromSPPFast( pScanData ps )
93 {
94 Byte bData, tmp;
95
96 /* notify asic we will read the high nibble data from status port */
97 if( _FALSE == ps->f97003 ) {
98 _OUTB_CTRL( ps, ps->CtrlReadHighNibble );
99 _DO_UDELAY( 1 );
100 }
101
102 /* read high nibble */
103 bData = _INB_STATUS( ps );
104 bData &= 0xf0;
105
106 _OUTB_CTRL( ps, ps->CtrlReadLowNibble );
107 _DO_UDELAY( 1 );
108
109 /* read low nibble */
110 tmp = _INB_STATUS( ps );
111
112 /* combine with low nibble */
113 bData |= (tmp >> 4);
114
115 _OUTB_CTRL( ps, _CTRL_GENSIGNAL );
116 _DO_UDELAY( 1 );
117
118 return bData;
119 }
120
ioDataFromSPPMiddle(pScanData ps)121 static Byte ioDataFromSPPMiddle( pScanData ps )
122 {
123 Byte bData, tmp;
124
125 /* notify asic we will read the high nibble data from status port */
126 if( _FALSE == ps->f97003 ) {
127 _OUTB_CTRL( ps, ps->CtrlReadHighNibble );
128 _DO_UDELAY( 1 );
129 }
130
131 /* read high nibble */
132 _INB_STATUS( ps );
133 bData = _INB_STATUS( ps );
134 bData &= 0xf0;
135
136 _OUTB_CTRL( ps, ps->CtrlReadLowNibble );
137 _DO_UDELAY( 1 );
138
139 /* read low nibble */
140 _INB_STATUS( ps );
141 tmp = _INB_STATUS( ps );
142
143 /* combine with low nibble */
144 bData |= (tmp >> 4);
145
146 _OUTB_CTRL( ps, _CTRL_GENSIGNAL );
147 _DO_UDELAY( 1 );
148
149 return bData;
150 }
151
ioDataFromSPPSlow(pScanData ps)152 static UChar ioDataFromSPPSlow( pScanData ps )
153 {
154 Byte bData, tmp;
155
156 /* notify asic we will read the high nibble data from status port */
157 if( _FALSE == ps->f97003 ) {
158 _OUTB_CTRL( ps, ps->CtrlReadHighNibble );
159 _DO_UDELAY( 2 );
160 }
161
162 /* read high nibble */
163 _INB_STATUS( ps );
164 _INB_STATUS( ps );
165 bData = _INB_STATUS( ps );
166 bData &= 0xf0;
167
168 _OUTB_CTRL( ps, ps->CtrlReadLowNibble );
169 _DO_UDELAY( 2 );
170
171 /* read low nibble */
172 _INB_STATUS( ps );
173 _INB_STATUS( ps );
174 tmp = _INB_STATUS( ps );
175
176 /* combine with low nibble */
177 bData |= (tmp >> 4);
178
179 _OUTB_CTRL( ps, _CTRL_GENSIGNAL );
180 _DO_UDELAY( 2 );
181
182 return bData;
183 }
184
ioDataFromSPPSlowest(pScanData ps)185 static UChar ioDataFromSPPSlowest( pScanData ps )
186 {
187 Byte bData, tmp;
188
189 /* notify asic we will read the high nibble data from status port */
190 if( _FALSE == ps->f97003 ) {
191 _OUTB_CTRL( ps, ps->CtrlReadHighNibble );
192 _DO_UDELAY( 3 );
193 }
194
195 /* read high nibble */
196 _INB_STATUS( ps );
197 _INB_STATUS( ps );
198 _INB_STATUS( ps );
199 bData = _INB_STATUS( ps );
200 bData &= 0xf0;
201
202 _OUTB_CTRL( ps, ps->CtrlReadLowNibble );
203 _DO_UDELAY( 3 );
204
205 /* read low nibble */
206 _INB_STATUS( ps );
207 _INB_STATUS( ps );
208 _INB_STATUS( ps );
209 tmp = _INB_STATUS( ps );
210
211 /* combine with low nibble */
212 bData |= (tmp >> 4);
213
214 _OUTB_CTRL( ps, _CTRL_GENSIGNAL );
215 _DO_UDELAY( 3 );
216
217 return bData;
218 }
219
220 /** Read data from STATUS port. We have to read twice and combine two nibble
221 * data to one byte.
222 */
fnSPPRead(pScanData ps,pUChar pBuffer,ULong ulSize)223 static Bool fnSPPRead( pScanData ps, pUChar pBuffer, ULong ulSize )
224 {
225 switch( ps->IO.delay ) {
226
227 case 0:
228 for (; ulSize; ulSize--, pBuffer++)
229 *pBuffer = ioDataFromSPPFast( ps );
230 break;
231
232 case 1:
233 for (; ulSize; ulSize--, pBuffer++)
234 *pBuffer = ioDataFromSPPMiddle( ps );
235 break;
236
237 case 2:
238 for (; ulSize; ulSize--, pBuffer++)
239 *pBuffer = ioDataFromSPPSlow( ps );
240 break;
241
242 default:
243 for (; ulSize; ulSize--, pBuffer++)
244 *pBuffer = ioDataFromSPPSlowest( ps );
245 break;
246 }
247
248 return _TRUE;
249 }
250
251
252 /** Using buffered I/O to read data from EPP Data Port
253 */
fnEPPRead(pScanData ps,pUChar pBuffer,ULong ulSize)254 static Bool fnEPPRead( pScanData ps, pUChar pBuffer, ULong ulSize )
255 {
256 register ULong i;
257
258 if( _IS_ASIC98(ps->sCaps.AsicID)) {
259
260 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN );
261 for( i = 0; i < ulSize; i++ )
262 pBuffer[i] = _INB_EPPDATA( ps );
263
264 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT );
265 } else {
266
267 for( i = 0; i < ulSize; i++ )
268 pBuffer[i] = _INB_EPPDATA( ps );
269 }
270
271 return _TRUE;
272 }
273
274 /**
275 */
fnBiDirRead(pScanData ps,pUChar pBuffer,ULong ulSize)276 static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize )
277 {
278 UChar start, end;
279
280 start = _CTRL_START_BIDIREAD;
281 end = _CTRL_END_BIDIREAD;
282
283 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN );
284
285 if( !sanei_pp_uses_directio()) {
286 start &= ~_CTRL_DIRECTION;
287 end &= ~_CTRL_DIRECTION;
288 }
289
290 switch( ps->IO.delay ) {
291
292 case 0:
293 for( ; ulSize; ulSize--, pBuffer++ ) {
294 _OUTB_CTRL( ps, start );
295 *pBuffer = _INB_DATA( ps );
296 _OUTB_CTRL( ps, end );
297 }
298 break;
299
300 case 1:
301 _DO_UDELAY( 1 );
302 for(; ulSize; ulSize--, pBuffer++ ) {
303 _OUTB_CTRL( ps, start );
304 _DO_UDELAY( 1 );
305
306 *pBuffer = _INB_DATA( ps );
307
308 _OUTB_CTRL( ps, end );
309 _DO_UDELAY( 1 );
310 }
311 break;
312
313 default:
314 _DO_UDELAY( 2 );
315 for(; ulSize; ulSize--, pBuffer++ ) {
316 _OUTB_CTRL( ps, start );
317 _DO_UDELAY( 2 );
318
319 *pBuffer = _INB_DATA( ps );
320
321 _OUTB_CTRL( ps, end );
322 _DO_UDELAY( 2 );
323 }
324 break;
325
326 }
327
328 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT );
329 return _TRUE;
330 }
331
332 /** as the name says, we switch to SPP mode
333 */
ioSwitchToSPPMode(pScanData ps)334 static void ioSwitchToSPPMode( pScanData ps )
335 {
336 /* save the control and data port value
337 */
338 ps->IO.bOldControlValue = _INB_CTRL( ps );
339 ps->IO.bOldDataValue = _INB_DATA( ps );
340
341 _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); /* 0xc4 */
342 _DO_UDELAY( 2 );
343 }
344
345 /** restore the port settings
346 */
ioRestoreParallelMode(pScanData ps)347 static void ioRestoreParallelMode( pScanData ps )
348 {
349 _OUTB_CTRL( ps, ps->IO.bOldControlValue & 0x3f );
350 _DO_UDELAY( 1 );
351
352 _OUTB_DATA( ps, ps->IO.bOldDataValue );
353 _DO_UDELAY( 1 );
354 }
355
356 /** try to connect to scanner (ASIC 9600x and 98001)
357 */
ioP98001EstablishScannerConnection(pScanData ps,ULong delTime)358 _LOC void ioP98001EstablishScannerConnection( pScanData ps, ULong delTime )
359 {
360 _OUTB_DATA( ps, _ID_TO_PRINTER );
361 _DO_UDELAY( delTime );
362
363 _OUTB_DATA( ps, _ID1ST );
364 _DO_UDELAY( delTime );
365
366 _OUTB_DATA( ps, _ID2ND );
367 _DO_UDELAY( delTime );
368
369 _OUTB_DATA( ps, _ID3RD );
370 _DO_UDELAY( delTime );
371
372 _OUTB_DATA( ps, _ID4TH );
373 _DO_UDELAY( delTime );
374 }
375
376 /** try to connect to scanner (ASIC 98003)
377 */
ioP98003EstablishScannerConnection(pScanData ps,ULong delTime)378 static void ioP98003EstablishScannerConnection( pScanData ps, ULong delTime )
379 {
380 _OUTB_DATA( ps, _ID1ST );
381 _DO_UDELAY( delTime );
382
383 _OUTB_DATA( ps, _ID2ND );
384 _DO_UDELAY( delTime );
385
386 _OUTB_DATA( ps, _ID3RD );
387 _DO_UDELAY( delTime );
388
389 _OUTB_DATA( ps, _ID4TH );
390 _DO_UDELAY( delTime );
391 }
392
393 /** switch the printer interface to scanner
394 */
ioP96OpenScanPath(pScanData ps)395 static Bool ioP96OpenScanPath( pScanData ps )
396 {
397 if( 0 == ps->IO.bOpenCount ) {
398
399 /* not established */
400 ioSwitchToSPPMode( ps );
401
402 /* Scanner command sequence to open scanner path */
403 ioP98001EstablishScannerConnection( ps, 5 );
404 }
405 #ifdef DEBUG
406 else
407 DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount );
408 #endif
409
410 ps->IO.bOpenCount++; /* increment the opened count */
411
412 /*
413 * CHECK to we really need that !!
414 */
415 ps->IO.useEPPCmdMode = _FALSE;
416 return _TRUE;
417 }
418
419 /** try to connect to scanner
420 */
ioP98OpenScanPath(pScanData ps)421 static Bool ioP98OpenScanPath( pScanData ps )
422 {
423 Byte tmp;
424 ULong dw;
425 ULong dwTime = 1;
426
427 if( 0 == ps->IO.bOpenCount ) {
428
429 /* not established */
430 ioSwitchToSPPMode( ps );
431
432 for( dw = 10; dw; dw-- ) {
433
434 /*
435 * this seems to be necessary...
436 */
437 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
438 ioP98001EstablishScannerConnection( ps, dw );
439 #if 0
440 ioP98001EstablishScannerConnection( ps, dw );
441 ioP98001EstablishScannerConnection( ps, dw );
442 #endif
443 } else {
444 ioP98003EstablishScannerConnection( ps, dw );
445 }
446
447 _INB_STATUS( ps );
448 tmp = _INB_STATUS( ps );
449
450 if( 0x50 == ( tmp & 0xf0 )) {
451
452 ps->IO.bOpenCount = 1;
453
454 if( ps->sCaps.AsicID == IODataFromRegister(ps, ps->RegAsicID)) {
455 return _TRUE;
456 }
457 ps->IO.bOpenCount = 0;
458 }
459
460 dwTime++;
461 }
462 DBG( DBG_IO, "ioP98OpenScanPath() failed!\n" );
463 return _FALSE;
464 }
465 #ifdef DEBUG
466 else
467 DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount );
468 #endif
469
470 ps->IO.bOpenCount++; /* increment the opened count */
471 return _TRUE;
472 }
473
474 /** Switch back to printer mode.
475 * Restore the printer control/data port value.
476 */
ioCloseScanPath(pScanData ps)477 static void ioCloseScanPath( pScanData ps )
478 {
479 if( ps->IO.bOpenCount && !(--ps->IO.bOpenCount)) {
480
481 #ifdef DEBUG
482 ps->IO.bOpenCount = 1;
483 #endif
484 IORegisterToScanner( ps, 0xff );
485
486 /*
487 * back to pass-through printer mode
488 */
489 IORegisterToScanner( ps, ps->RegSwitchBus );
490 #ifdef DEBUG
491 ps->IO.bOpenCount = 0;
492 #endif
493 ps->IO.useEPPCmdMode = _FALSE;
494
495 ioRestoreParallelMode( ps );
496 }
497 }
498
499 /** check the memory to see that the data-transfers will work.
500 * (ASIC 9800x only)
501 */
ioP98ReadWriteTest(pScanData ps)502 static int ioP98ReadWriteTest( pScanData ps )
503 {
504 UChar tmp;
505 ULong ul;
506 pUChar buffer;
507 int retval;
508
509 DBG( DBG_LOW, "ioP98ReadWriteTest()\n" );
510
511 /* _MEMTEST_SIZE: Read, _MEMTEST_SIZE:Write */
512 buffer = _KALLOC( sizeof(UChar) * _MEMTEST_SIZE*2, GFP_KERNEL );
513 if( NULL == buffer )
514 return _E_ALLOC;
515
516 /* prepare content */
517 for( ul = 0; ul < _MEMTEST_SIZE; ul++ )
518 buffer[ul] = (UChar)ul;
519
520 ps->OpenScanPath(ps);
521
522 /* avoid switching to Lamp0, when previously scanned in transp./neg mode */
523 tmp = ps->bLastLampStatus + _SCAN_BYTEMODE;
524 IODataToRegister( ps, ps->RegScanControl, tmp );
525
526 IODataToRegister( ps, ps->RegModelControl, (_LED_ACTIVITY | _LED_CONTROL));
527
528 IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem );
529 IODataToRegister( ps, ps->RegMemoryLow, 0 );
530 IODataToRegister( ps, ps->RegMemoryHigh, 0 );
531
532 /* fill to buffer */
533 IOMoveDataToScanner( ps, buffer, _MEMTEST_SIZE );
534
535 IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem );
536 IODataToRegister( ps, ps->RegMemoryLow, 0 );
537 IODataToRegister( ps, ps->RegMemoryHigh, 0 );
538 IODataToRegister( ps, ps->RegWidthPixelsLow, 0 );
539 IODataToRegister( ps, ps->RegWidthPixelsHigh, 5 );
540
541 ps->AsicReg.RD_ModeControl = _ModeReadMappingMem;
542
543 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
544 ps->CloseScanPath( ps );
545
546 IOReadScannerImageData( ps, buffer + _MEMTEST_SIZE, _MEMTEST_SIZE );
547
548 if( _ASIC_IS_98003 == ps->sCaps.AsicID )
549 ps->CloseScanPath( ps );
550
551 /* check the result ! */
552 retval = _OK;
553
554 for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) {
555 if( buffer[ul] != buffer[ul+_MEMTEST_SIZE] ) {
556 DBG( DBG_HIGH, "Error in memory test at pos %u (%u != %u)\n",
557 ul, buffer[ul], buffer[ul+_MEMTEST_SIZE] );
558 retval = _E_NO_DEV;
559 break;
560 }
561 }
562
563 _KFREE(buffer);
564 return retval;
565 }
566
567 /** Put data to DATA port and trigger hardware through CONTROL port to read it.
568 */
ioSPPWrite(pScanData ps,pUChar pBuffer,ULong size)569 static void ioSPPWrite( pScanData ps, pUChar pBuffer, ULong size )
570 {
571 DBG( DBG_IO , "Moving %u bytes to scanner, IODELAY = %u...\n",
572 size, ps->IO.delay );
573 switch( ps->IO.delay ) {
574
575 case 0:
576 for (; size; size--, pBuffer++) {
577 _OUTB_DATA( ps, *pBuffer );
578 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
579 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
580 }
581 break;
582
583 case 1:
584 case 2:
585 for (; size; size--, pBuffer++) {
586 _OUTB_DATA( ps, *pBuffer );
587 _DO_UDELAY( 1 );
588 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
589 _DO_UDELAY( 1 );
590 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
591 _DO_UDELAY( 2 );
592 }
593 break;
594
595 default:
596 for (; size; size--, pBuffer++) {
597 _OUTB_DATA( ps, *pBuffer );
598 _DO_UDELAY( 1 );
599 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
600 _DO_UDELAY( 2 );
601 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
602 _DO_UDELAY( 3 );
603 }
604 break;
605 }
606 DBG( DBG_IO , "... done.\n" );
607 }
608
609 /** set the scanner to "read" data mode
610 */
ioEnterReadMode(pScanData ps)611 static void ioEnterReadMode( pScanData ps )
612 {
613 if( ps->IO.portMode != _PORT_SPP ) {
614
615 _DO_UDELAY( 1 );
616 IORegisterToScanner( ps, ps->RegEPPEnable );
617
618 if( _IS_ASIC98( ps->sCaps.AsicID ))
619 ps->IO.useEPPCmdMode = _TRUE;
620 }
621
622 if( _ASIC_IS_98003 == ps->sCaps.AsicID )
623 ps->IO.bOldControlValue = _INB_CTRL( ps );
624
625 /* ask ASIC to enter read mode */
626 IORegisterToScanner( ps, ps->RegReadDataMode );
627 }
628
629 /************************ exported functions *********************************/
630
631 /** here we do some init work
632 */
IOInitialize(pScanData ps)633 _LOC int IOInitialize( pScanData ps )
634 {
635 DBG( DBG_HIGH, "IOInitialize()\n" );
636
637 if( NULL == ps )
638 return _E_NULLPTR;
639
640 if( _IS_ASIC98(ps->sCaps.AsicID)) {
641
642 ps->OpenScanPath = ioP98OpenScanPath;
643 ps->ReadWriteTest = ioP98ReadWriteTest;
644
645 } else if( _IS_ASIC96(ps->sCaps.AsicID)) {
646
647 ps->OpenScanPath = ioP96OpenScanPath;
648
649 } else {
650
651 DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" );
652 return _E_NOSUPP;
653 }
654
655 ps->CloseScanPath = ioCloseScanPath;
656 ps->Device.ReadData = ioReadFunc[ps->IO.portMode].func;
657 DBG( DBG_HIGH, "* using readfunction >%s<\n",
658 ioReadFunc[ps->IO.portMode].name );
659 return _OK;
660 }
661
662 /** Write specific length buffer to scanner
663 * The scan path is already established
664 */
IOMoveDataToScanner(pScanData ps,pUChar pBuffer,ULong size)665 _LOC void IOMoveDataToScanner( pScanData ps, pUChar pBuffer, ULong size )
666 {
667 #ifdef DEBUG
668 if( 0 == ps->IO.bOpenCount )
669 DBG( DBG_IO, "IOMoveDataToScanner - no connection!\n" );
670 #endif
671
672 IORegisterToScanner( ps, ps->RegInitDataFifo );
673 IORegisterToScanner( ps, ps->RegWriteDataMode );
674
675 ioSPPWrite( ps, pBuffer, size );
676 }
677
678 /** Calling SITUATION: Scanner path is established.
679 * download a scanstate-table
680 */
IODownloadScanStates(pScanData ps)681 _LOC void IODownloadScanStates( pScanData ps )
682 {
683 TimerDef timer;
684 #ifdef DEBUG
685 if( 0 == ps->IO.bOpenCount )
686 DBG( DBG_IO, "IODownloadScanStates - no connection!\n" );
687 #endif
688
689 IORegisterToScanner( ps, ps->RegScanStateControl );
690
691 ioSPPWrite( ps, ps->a_nbNewAdrPointer, _SCANSTATE_BYTES );
692
693 if( ps->Scan.fRefreshState ) {
694
695 IORegisterToScanner( ps, ps->RegRefreshScanState );
696
697 MiscStartTimer( &timer, (_SECOND/2));
698 do {
699
700 if (!( IOGetScanState( ps, _TRUE) & _SCANSTATE_STOP))
701 break;
702 }
703 while( !MiscCheckTimer(&timer));
704 }
705 }
706
707 /** Calling SITUATION: Scanner path is established.
708 * Write a data to asic
709 */
IODataToScanner(pScanData ps,Byte bValue)710 _LOC void IODataToScanner( pScanData ps, Byte bValue )
711 {
712 ULong deltime = 4;
713
714 #ifdef DEBUG
715 if( 0 == ps->IO.bOpenCount )
716 DBG( DBG_IO, "IODataToScanner - no connection!\n" );
717 #endif
718
719 if( ps->IO.delay < 2 )
720 deltime = 2;
721
722 /* output data */
723 _OUTB_DATA( ps, bValue );
724 _DO_UDELAY( deltime );
725
726 /* notify asic there is data */
727 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
728 _DO_UDELAY( deltime );
729
730 /* end write cycle */
731 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
732 _DO_UDELAY( deltime-1 );
733 }
734
735 /** Calling SITUATION: Scanner path is established.
736 * Write a data to specific asic's register
737 */
IODataToRegister(pScanData ps,Byte bReg,Byte bData)738 _LOC void IODataToRegister( pScanData ps, Byte bReg, Byte bData )
739 {
740 #ifdef DEBUG
741 if( 0 == ps->IO.bOpenCount )
742 DBG( DBG_IO, "IODataToRegister - no connection!\n" );
743 #endif
744
745 /* specify register */
746 IORegisterToScanner( ps, bReg );
747
748 /* then write the content */
749 IODataToScanner( ps, bData );
750 }
751
752 /** Calling SITUATION: Scanner path is established.
753 * Read the content of specific asic's register
754 */
IODataFromRegister(pScanData ps,Byte bReg)755 _LOC Byte IODataFromRegister( pScanData ps, Byte bReg )
756 {
757 IORegisterToScanner( ps, bReg );
758
759 if( 0 == ps->IO.delay )
760 return ioDataFromSPPFast( ps );
761 else if( 1 == ps->IO.delay )
762 return ioDataFromSPPMiddle( ps );
763 else if( 2 == ps->IO.delay )
764 return ioDataFromSPPSlow( ps );
765 else
766 return ioDataFromSPPSlowest( ps );
767 }
768
769 /** Calling SITUATION: Scanner path is established.
770 * Write a register to asic (used for a command without parameter)
771 */
IORegisterToScanner(pScanData ps,Byte bReg)772 _LOC void IORegisterToScanner( pScanData ps, Byte bReg )
773 {
774 #ifdef DEBUG
775 if( 0 == ps->IO.bOpenCount )
776 DBG( DBG_IO, "IORegisterToScanner - no connection!\n" );
777 #endif
778
779 /*
780 * write data to port
781 */
782 _OUTB_DATA( ps, bReg );
783
784 /*
785 * depending on the mode, generate the trigger signals
786 */
787 if( ps->IO.useEPPCmdMode ) {
788
789 _DO_UDELAY( 5 );
790
791 _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */
792 _DO_UDELAY( 5 );
793
794 _OUTB_CTRL( ps, _CTRL_EPPTRIG_REGWRITE);/* 0xcd */
795 _DO_UDELAY( 5 );
796
797 _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */
798 _DO_UDELAY( 5 );
799
800 _OUTB_CTRL( ps, _CTRL_END_REGWRITE); /* 0xc4 */
801
802 } else {
803 if( ps->IO.delay < 2 ) {
804
805 _DO_UDELAY( 1 );
806 _OUTB_CTRL( ps, _CTRL_START_REGWRITE);
807 _DO_UDELAY( 1 );
808 _OUTB_CTRL( ps, _CTRL_END_REGWRITE);
809 } else {
810
811 _DO_UDELAY( 2 );
812 _OUTB_CTRL( ps, _CTRL_START_REGWRITE);
813 _DO_UDELAY( 2 );
814 _OUTB_CTRL( ps, _CTRL_END_REGWRITE);
815 _DO_UDELAY( 2 );
816 }
817 }
818 }
819
820 /** write data to the DAC - ASIC 98001/3 only
821 */
IODataRegisterToDAC(pScanData ps,Byte bReg,Byte bData)822 _LOC void IODataRegisterToDAC( pScanData ps, Byte bReg, Byte bData )
823 {
824 ULong i;
825
826 IODataToRegister( ps, ps->RegADCAddress, bReg );
827 IODataToRegister( ps, ps->RegADCData, bData );
828 IODataToRegister( ps, ps->RegADCSerialOutStr, bData );
829
830 /* TEST: ORG was 1 ms for ASIC 98001 */
831 _DO_UDELAY( 12 );
832
833 for( i = 4; i; i-- ) {
834
835 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
836 _DO_UDELAY( 5 );
837 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
838 _DO_UDELAY( 12 );
839 }
840 }
841
842 /** Calling SITUATION: Scanner path was not established.
843 * Read the content of specific asics' register
844 */
IODataRegisterFromScanner(pScanData ps,Byte bReg)845 _LOC Byte IODataRegisterFromScanner( pScanData ps, Byte bReg )
846 {
847 Byte bData;
848
849 ps->OpenScanPath( ps );
850 bData = IODataFromRegister( ps, bReg );
851 ps->CloseScanPath( ps );
852
853 return bData;
854 }
855
856 /** Calling SITUATION: Scanner path not established.
857 * Write a value of register to asic
858 */
IOCmdRegisterToScanner(pScanData ps,Byte bReg,Byte bData)859 _LOC void IOCmdRegisterToScanner( pScanData ps, Byte bReg, Byte bData )
860 {
861 ps->OpenScanPath( ps );
862 IODataToRegister( ps, bReg, bData );
863 ps->CloseScanPath( ps );
864 }
865
866 /** Calling SITUATION: Scanner path not established.
867 * Write a register to asic (used for a command without parameter)
868 */
IORegisterDirectToScanner(pScanData ps,Byte bReg)869 _LOC void IORegisterDirectToScanner( pScanData ps, Byte bReg )
870 {
871 ps->OpenScanPath( ps ); /* establish the connection */
872 IORegisterToScanner( ps, bReg ); /* write register to asic */
873 ps->CloseScanPath( ps ); /* disconnect */
874 }
875
876 /** perform a SW reset of ASIC 98003 models
877 */
IOSoftwareReset(pScanData ps)878 _LOC void IOSoftwareReset( pScanData ps )
879 {
880 if( _ASIC_IS_98003 != ps->sCaps.AsicID )
881 return;
882
883 ps->OpenScanPath( ps );
884
885 IODataToRegister( ps, ps->RegTestMode, _SW_TESTMODE );
886
887 ioSwitchToSPPMode( ps );
888
889 _OUTB_DATA( ps, _RESET1ST );
890 _DODELAY( 5 );
891
892 _OUTB_DATA( ps, _RESET2ND );
893 _DODELAY( 5 );
894
895 _OUTB_DATA( ps, _RESET3RD );
896 _DODELAY( 5 );
897
898 _OUTB_DATA( ps, _RESET4TH );
899 _DODELAY( 5 );
900
901 ioRestoreParallelMode( ps );
902
903 /* reset test mode register */
904 IODataToRegister( ps, ps->RegTestMode, 0 );
905 IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl );
906
907 ps->CloseScanPath( ps );
908 }
909
910 /** Read specific length data from scanner and the method depends on the
911 * mode defined in registry.
912 */
IOReadScannerImageData(pScanData ps,pUChar pBuf,ULong size)913 _LOC void IOReadScannerImageData( pScanData ps, pUChar pBuf, ULong size )
914 {
915 if( _ASIC_IS_98003 != ps->sCaps.AsicID )
916 ps->OpenScanPath( ps);
917
918 if( _IS_ASIC98( ps->sCaps.AsicID))
919 IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
920
921 /* enter read mode */
922 ioEnterReadMode( ps );
923
924 /* call corresponding read proc */
925 ps->Device.ReadData( ps, pBuf, size );
926
927 /* Clear EPP/ECP read mode by simply close scanner path and re-open it */
928 ps->CloseScanPath( ps );
929
930 if( _ASIC_IS_98003 == ps->sCaps.AsicID )
931 ps->OpenScanPath( ps );
932 }
933
934 /* END PLUSTEK-PP_IO.C ......................................................*/
935