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 #ifndef __KERNEL__
261 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN );
262 #else
263 _OUTB_CTRL( ps, (_CTRL_GENSIGNAL + _CTRL_DIRECTION));
264 _DO_UDELAY( 1 );
265 #endif
266 for( i = 0; i < ulSize; i++ )
267 pBuffer[i] = _INB_EPPDATA( ps );
268
269 #ifndef __KERNEL__
270 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT );
271 #else
272 _OUTB_CTRL( ps, _CTRL_GENSIGNAL );
273 _DO_UDELAY( 1 );
274 #endif
275 } else {
276
277 for( i = 0; i < ulSize; i++ )
278 pBuffer[i] = _INB_EPPDATA( ps );
279 }
280
281 return _TRUE;
282 }
283
284 /**
285 */
fnBiDirRead(pScanData ps,pUChar pBuffer,ULong ulSize)286 static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize )
287 {
288 UChar start, end;
289
290 start = _CTRL_START_BIDIREAD;
291 end = _CTRL_END_BIDIREAD;
292
293 #ifndef __KERNEL__
294 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN );
295
296 if( !sanei_pp_uses_directio()) {
297 start &= ~_CTRL_DIRECTION;
298 end &= ~_CTRL_DIRECTION;
299 }
300 #else
301 if( _IS_ASIC98(ps->sCaps.AsicID)) {
302 _OUTB_CTRL( ps, (_CTRL_GENSIGNAL + _CTRL_DIRECTION));
303 }
304 #endif
305
306 switch( ps->IO.delay ) {
307
308 case 0:
309 for( ; ulSize; ulSize--, pBuffer++ ) {
310 _OUTB_CTRL( ps, start );
311 *pBuffer = _INB_DATA( ps );
312 _OUTB_CTRL( ps, end );
313 }
314 break;
315
316 case 1:
317 _DO_UDELAY( 1 );
318 for(; ulSize; ulSize--, pBuffer++ ) {
319 _OUTB_CTRL( ps, start );
320 _DO_UDELAY( 1 );
321
322 *pBuffer = _INB_DATA( ps );
323
324 _OUTB_CTRL( ps, end );
325 _DO_UDELAY( 1 );
326 }
327 break;
328
329 default:
330 _DO_UDELAY( 2 );
331 for(; ulSize; ulSize--, pBuffer++ ) {
332 _OUTB_CTRL( ps, start );
333 _DO_UDELAY( 2 );
334
335 *pBuffer = _INB_DATA( ps );
336
337 _OUTB_CTRL( ps, end );
338 _DO_UDELAY( 2 );
339 }
340 break;
341
342 }
343
344 #ifndef __KERNEL__
345 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT );
346 #else
347 if( _IS_ASIC98(ps->sCaps.AsicID)) {
348 _OUTB_CTRL( ps, _CTRL_GENSIGNAL );
349 }
350 #endif
351 return _TRUE;
352 }
353
354 /** as the name says, we switch to SPP mode
355 */
ioSwitchToSPPMode(pScanData ps)356 static void ioSwitchToSPPMode( pScanData ps )
357 {
358 /* save the control and data port value
359 */
360 ps->IO.bOldControlValue = _INB_CTRL( ps );
361 ps->IO.bOldDataValue = _INB_DATA( ps );
362
363 _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); /* 0xc4 */
364 _DO_UDELAY( 2 );
365 }
366
367 /** restore the port settings
368 */
ioRestoreParallelMode(pScanData ps)369 static void ioRestoreParallelMode( pScanData ps )
370 {
371 _OUTB_CTRL( ps, ps->IO.bOldControlValue & 0x3f );
372 _DO_UDELAY( 1 );
373
374 _OUTB_DATA( ps, ps->IO.bOldDataValue );
375 _DO_UDELAY( 1 );
376 }
377
378 /** try to connect to scanner (ASIC 9600x and 98001)
379 */
ioP98001EstablishScannerConnection(pScanData ps,ULong delTime)380 _LOC void ioP98001EstablishScannerConnection( pScanData ps, ULong delTime )
381 {
382 _OUTB_DATA( ps, _ID_TO_PRINTER );
383 _DO_UDELAY( delTime );
384
385 _OUTB_DATA( ps, _ID1ST );
386 _DO_UDELAY( delTime );
387
388 _OUTB_DATA( ps, _ID2ND );
389 _DO_UDELAY( delTime );
390
391 _OUTB_DATA( ps, _ID3RD );
392 _DO_UDELAY( delTime );
393
394 _OUTB_DATA( ps, _ID4TH );
395 _DO_UDELAY( delTime );
396 }
397
398 /** try to connect to scanner (ASIC 98003)
399 */
ioP98003EstablishScannerConnection(pScanData ps,ULong delTime)400 static void ioP98003EstablishScannerConnection( pScanData ps, ULong delTime )
401 {
402 _OUTB_DATA( ps, _ID1ST );
403 _DO_UDELAY( delTime );
404
405 _OUTB_DATA( ps, _ID2ND );
406 _DO_UDELAY( delTime );
407
408 _OUTB_DATA( ps, _ID3RD );
409 _DO_UDELAY( delTime );
410
411 _OUTB_DATA( ps, _ID4TH );
412 _DO_UDELAY( delTime );
413 }
414
415 /** switch the printer interface to scanner
416 */
ioP96OpenScanPath(pScanData ps)417 static Bool ioP96OpenScanPath( pScanData ps )
418 {
419 if( 0 == ps->IO.bOpenCount ) {
420
421 /* not established */
422 ioSwitchToSPPMode( ps );
423
424 /* Scanner command sequence to open scanner path */
425 ioP98001EstablishScannerConnection( ps, 5 );
426 }
427 #ifdef DEBUG
428 else
429 DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount );
430 #endif
431
432 ps->IO.bOpenCount++; /* increment the opened count */
433
434 /*
435 * CHECK to we really need that !!
436 */
437 ps->IO.useEPPCmdMode = _FALSE;
438 return _TRUE;
439 }
440
441 /** try to connect to scanner
442 */
ioP98OpenScanPath(pScanData ps)443 static Bool ioP98OpenScanPath( pScanData ps )
444 {
445 Byte tmp;
446 ULong dw;
447 ULong dwTime = 1;
448
449 if( 0 == ps->IO.bOpenCount ) {
450
451 /* not established */
452 ioSwitchToSPPMode( ps );
453
454 for( dw = 10; dw; dw-- ) {
455
456 /*
457 * this seems to be necessary...
458 */
459 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
460 ioP98001EstablishScannerConnection( ps, dw );
461 #if 0
462 ioP98001EstablishScannerConnection( ps, dw );
463 ioP98001EstablishScannerConnection( ps, dw );
464 #endif
465 } else {
466 ioP98003EstablishScannerConnection( ps, dw );
467 }
468
469 _INB_STATUS( ps );
470 tmp = _INB_STATUS( ps );
471
472 if( 0x50 == ( tmp & 0xf0 )) {
473
474 ps->IO.bOpenCount = 1;
475
476 if( ps->sCaps.AsicID == IODataFromRegister(ps, ps->RegAsicID)) {
477 return _TRUE;
478 }
479 ps->IO.bOpenCount = 0;
480 }
481
482 dwTime++;
483 }
484 DBG( DBG_IO, "ioP98OpenScanPath() failed!\n" );
485 return _FALSE;
486 }
487 #ifdef DEBUG
488 else
489 DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount );
490 #endif
491
492 ps->IO.bOpenCount++; /* increment the opened count */
493 return _TRUE;
494 }
495
496 /** Switch back to printer mode.
497 * Restore the printer control/data port value.
498 */
ioCloseScanPath(pScanData ps)499 static void ioCloseScanPath( pScanData ps )
500 {
501 if( ps->IO.bOpenCount && !(--ps->IO.bOpenCount)) {
502
503 #ifdef DEBUG
504 ps->IO.bOpenCount = 1;
505 #endif
506 IORegisterToScanner( ps, 0xff );
507
508 /*
509 * back to pass-through printer mode
510 */
511 IORegisterToScanner( ps, ps->RegSwitchBus );
512 #ifdef DEBUG
513 ps->IO.bOpenCount = 0;
514 #endif
515 ps->IO.useEPPCmdMode = _FALSE;
516
517 ioRestoreParallelMode( ps );
518 }
519 }
520
521 /** check the memory to see that the data-transfers will work.
522 * (ASIC 9800x only)
523 */
ioP98ReadWriteTest(pScanData ps)524 static int ioP98ReadWriteTest( pScanData ps )
525 {
526 UChar tmp;
527 ULong ul;
528 pUChar buffer;
529 int retval;
530
531 DBG( DBG_LOW, "ioP98ReadWriteTest()\n" );
532
533 /* _MEMTEST_SIZE: Read, _MEMTEST_SIZE:Write */
534 buffer = _KALLOC( sizeof(UChar) * _MEMTEST_SIZE*2, GFP_KERNEL );
535 if( NULL == buffer )
536 return _E_ALLOC;
537
538 /* prepare content */
539 for( ul = 0; ul < _MEMTEST_SIZE; ul++ )
540 buffer[ul] = (UChar)ul;
541
542 ps->OpenScanPath(ps);
543
544 /* avoid switching to Lamp0, when previously scanned in transp./neg mode */
545 tmp = ps->bLastLampStatus + _SCAN_BYTEMODE;
546 IODataToRegister( ps, ps->RegScanControl, tmp );
547
548 IODataToRegister( ps, ps->RegModelControl, (_LED_ACTIVITY | _LED_CONTROL));
549
550 IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem );
551 IODataToRegister( ps, ps->RegMemoryLow, 0 );
552 IODataToRegister( ps, ps->RegMemoryHigh, 0 );
553
554 /* fill to buffer */
555 IOMoveDataToScanner( ps, buffer, _MEMTEST_SIZE );
556
557 IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem );
558 IODataToRegister( ps, ps->RegMemoryLow, 0 );
559 IODataToRegister( ps, ps->RegMemoryHigh, 0 );
560 IODataToRegister( ps, ps->RegWidthPixelsLow, 0 );
561 IODataToRegister( ps, ps->RegWidthPixelsHigh, 5 );
562
563 ps->AsicReg.RD_ModeControl = _ModeReadMappingMem;
564
565 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
566 ps->CloseScanPath( ps );
567
568 IOReadScannerImageData( ps, buffer + _MEMTEST_SIZE, _MEMTEST_SIZE );
569
570 if( _ASIC_IS_98003 == ps->sCaps.AsicID )
571 ps->CloseScanPath( ps );
572
573 /* check the result ! */
574 retval = _OK;
575
576 for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) {
577 if( buffer[ul] != buffer[ul+_MEMTEST_SIZE] ) {
578 DBG( DBG_HIGH, "Error in memory test at pos %u (%u != %u)\n",
579 ul, buffer[ul], buffer[ul+_MEMTEST_SIZE] );
580 retval = _E_NO_DEV;
581 break;
582 }
583 }
584
585 _KFREE(buffer);
586 return retval;
587 }
588
589 /** Put data to DATA port and trigger hardware through CONTROL port to read it.
590 */
ioSPPWrite(pScanData ps,pUChar pBuffer,ULong size)591 static void ioSPPWrite( pScanData ps, pUChar pBuffer, ULong size )
592 {
593 DBG( DBG_IO , "Moving %u bytes to scanner, IODELAY = %u...\n",
594 size, ps->IO.delay );
595 switch( ps->IO.delay ) {
596
597 case 0:
598 for (; size; size--, pBuffer++) {
599 _OUTB_DATA( ps, *pBuffer );
600 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
601 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
602 }
603 break;
604
605 case 1:
606 case 2:
607 for (; size; size--, pBuffer++) {
608 _OUTB_DATA( ps, *pBuffer );
609 _DO_UDELAY( 1 );
610 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
611 _DO_UDELAY( 1 );
612 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
613 _DO_UDELAY( 2 );
614 }
615 break;
616
617 default:
618 for (; size; size--, pBuffer++) {
619 _OUTB_DATA( ps, *pBuffer );
620 _DO_UDELAY( 1 );
621 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
622 _DO_UDELAY( 2 );
623 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
624 _DO_UDELAY( 3 );
625 }
626 break;
627 }
628 DBG( DBG_IO , "... done.\n" );
629 }
630
631 /** set the scanner to "read" data mode
632 */
ioEnterReadMode(pScanData ps)633 static void ioEnterReadMode( pScanData ps )
634 {
635 if( ps->IO.portMode != _PORT_SPP ) {
636
637 _DO_UDELAY( 1 );
638 IORegisterToScanner( ps, ps->RegEPPEnable );
639
640 if( _IS_ASIC98( ps->sCaps.AsicID ))
641 ps->IO.useEPPCmdMode = _TRUE;
642 }
643
644 if( _ASIC_IS_98003 == ps->sCaps.AsicID )
645 ps->IO.bOldControlValue = _INB_CTRL( ps );
646
647 /* ask ASIC to enter read mode */
648 IORegisterToScanner( ps, ps->RegReadDataMode );
649 }
650
651 /************************ exported functions *********************************/
652
653 /** here we do some init work
654 */
IOInitialize(pScanData ps)655 _LOC int IOInitialize( pScanData ps )
656 {
657 DBG( DBG_HIGH, "IOInitialize()\n" );
658
659 if( NULL == ps )
660 return _E_NULLPTR;
661
662 if( _IS_ASIC98(ps->sCaps.AsicID)) {
663
664 ps->OpenScanPath = ioP98OpenScanPath;
665 ps->ReadWriteTest = ioP98ReadWriteTest;
666
667 } else if( _IS_ASIC96(ps->sCaps.AsicID)) {
668
669 ps->OpenScanPath = ioP96OpenScanPath;
670
671 } else {
672
673 DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" );
674 return _E_NOSUPP;
675 }
676
677 ps->CloseScanPath = ioCloseScanPath;
678 ps->Device.ReadData = ioReadFunc[ps->IO.portMode].func;
679 DBG( DBG_HIGH, "* using readfunction >%s<\n",
680 ioReadFunc[ps->IO.portMode].name );
681 return _OK;
682 }
683
684 /** Write specific length buffer to scanner
685 * The scan path is already established
686 */
IOMoveDataToScanner(pScanData ps,pUChar pBuffer,ULong size)687 _LOC void IOMoveDataToScanner( pScanData ps, pUChar pBuffer, ULong size )
688 {
689 #ifdef DEBUG
690 if( 0 == ps->IO.bOpenCount )
691 DBG( DBG_IO, "IOMoveDataToScanner - no connection!\n" );
692 #endif
693
694 IORegisterToScanner( ps, ps->RegInitDataFifo );
695 IORegisterToScanner( ps, ps->RegWriteDataMode );
696
697 ioSPPWrite( ps, pBuffer, size );
698 }
699
700 /** Calling SITUATION: Scanner path is established.
701 * download a scanstate-table
702 */
IODownloadScanStates(pScanData ps)703 _LOC void IODownloadScanStates( pScanData ps )
704 {
705 TimerDef timer;
706 #ifdef DEBUG
707 if( 0 == ps->IO.bOpenCount )
708 DBG( DBG_IO, "IODownloadScanStates - no connection!\n" );
709 #endif
710
711 IORegisterToScanner( ps, ps->RegScanStateControl );
712
713 ioSPPWrite( ps, ps->a_nbNewAdrPointer, _SCANSTATE_BYTES );
714
715 if( ps->Scan.fRefreshState ) {
716
717 IORegisterToScanner( ps, ps->RegRefreshScanState );
718
719 MiscStartTimer( &timer, (_SECOND/2));
720 do {
721
722 if (!( IOGetScanState( ps, _TRUE) & _SCANSTATE_STOP))
723 break;
724 }
725 while( !MiscCheckTimer(&timer));
726 }
727 }
728
729 /** Calling SITUATION: Scanner path is established.
730 * Write a data to asic
731 */
IODataToScanner(pScanData ps,Byte bValue)732 _LOC void IODataToScanner( pScanData ps, Byte bValue )
733 {
734 ULong deltime = 4;
735
736 #ifdef DEBUG
737 if( 0 == ps->IO.bOpenCount )
738 DBG( DBG_IO, "IODataToScanner - no connection!\n" );
739 #endif
740
741 if( ps->IO.delay < 2 )
742 deltime = 2;
743
744 /* output data */
745 _OUTB_DATA( ps, bValue );
746 _DO_UDELAY( deltime );
747
748 /* notify asic there is data */
749 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
750 _DO_UDELAY( deltime );
751
752 /* end write cycle */
753 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
754 _DO_UDELAY( deltime-1 );
755 }
756
757 /** Calling SITUATION: Scanner path is established.
758 * Write a data to specific asic's register
759 */
IODataToRegister(pScanData ps,Byte bReg,Byte bData)760 _LOC void IODataToRegister( pScanData ps, Byte bReg, Byte bData )
761 {
762 #ifdef DEBUG
763 if( 0 == ps->IO.bOpenCount )
764 DBG( DBG_IO, "IODataToRegister - no connection!\n" );
765 #endif
766
767 /* specify register */
768 IORegisterToScanner( ps, bReg );
769
770 /* then write the content */
771 IODataToScanner( ps, bData );
772 }
773
774 /** Calling SITUATION: Scanner path is established.
775 * Read the content of specific asic's register
776 */
IODataFromRegister(pScanData ps,Byte bReg)777 _LOC Byte IODataFromRegister( pScanData ps, Byte bReg )
778 {
779 IORegisterToScanner( ps, bReg );
780
781 if( 0 == ps->IO.delay )
782 return ioDataFromSPPFast( ps );
783 else if( 1 == ps->IO.delay )
784 return ioDataFromSPPMiddle( ps );
785 else if( 2 == ps->IO.delay )
786 return ioDataFromSPPSlow( ps );
787 else
788 return ioDataFromSPPSlowest( ps );
789 }
790
791 /** Calling SITUATION: Scanner path is established.
792 * Write a register to asic (used for a command without parameter)
793 */
IORegisterToScanner(pScanData ps,Byte bReg)794 _LOC void IORegisterToScanner( pScanData ps, Byte bReg )
795 {
796 #ifdef DEBUG
797 if( 0 == ps->IO.bOpenCount )
798 DBG( DBG_IO, "IORegisterToScanner - no connection!\n" );
799 #endif
800
801 /*
802 * write data to port
803 */
804 _OUTB_DATA( ps, bReg );
805
806 /*
807 * depending on the mode, generate the trigger signals
808 */
809 if( ps->IO.useEPPCmdMode ) {
810
811 _DO_UDELAY( 5 );
812
813 _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */
814 _DO_UDELAY( 5 );
815
816 _OUTB_CTRL( ps, _CTRL_EPPTRIG_REGWRITE);/* 0xcd */
817 _DO_UDELAY( 5 );
818
819 _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */
820 _DO_UDELAY( 5 );
821
822 _OUTB_CTRL( ps, _CTRL_END_REGWRITE); /* 0xc4 */
823
824 } else {
825 if( ps->IO.delay < 2 ) {
826
827 _DO_UDELAY( 1 );
828 _OUTB_CTRL( ps, _CTRL_START_REGWRITE);
829 _DO_UDELAY( 1 );
830 _OUTB_CTRL( ps, _CTRL_END_REGWRITE);
831 } else {
832
833 _DO_UDELAY( 2 );
834 _OUTB_CTRL( ps, _CTRL_START_REGWRITE);
835 _DO_UDELAY( 2 );
836 _OUTB_CTRL( ps, _CTRL_END_REGWRITE);
837 _DO_UDELAY( 2 );
838 }
839 }
840 }
841
842 /** write data to the DAC - ASIC 98001/3 only
843 */
IODataRegisterToDAC(pScanData ps,Byte bReg,Byte bData)844 _LOC void IODataRegisterToDAC( pScanData ps, Byte bReg, Byte bData )
845 {
846 ULong i;
847
848 IODataToRegister( ps, ps->RegADCAddress, bReg );
849 IODataToRegister( ps, ps->RegADCData, bData );
850 IODataToRegister( ps, ps->RegADCSerialOutStr, bData );
851
852 /* TEST: ORG was 1 ms for ASIC 98001 */
853 _DO_UDELAY( 12 );
854
855 for( i = 4; i; i-- ) {
856
857 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE );
858 _DO_UDELAY( 5 );
859 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
860 _DO_UDELAY( 12 );
861 }
862 }
863
864 /** Calling SITUATION: Scanner path was not established.
865 * Read the content of specific asics' register
866 */
IODataRegisterFromScanner(pScanData ps,Byte bReg)867 _LOC Byte IODataRegisterFromScanner( pScanData ps, Byte bReg )
868 {
869 Byte bData;
870
871 ps->OpenScanPath( ps );
872 bData = IODataFromRegister( ps, bReg );
873 ps->CloseScanPath( ps );
874
875 return bData;
876 }
877
878 /** Calling SITUATION: Scanner path not established.
879 * Write a value of register to asic
880 */
IOCmdRegisterToScanner(pScanData ps,Byte bReg,Byte bData)881 _LOC void IOCmdRegisterToScanner( pScanData ps, Byte bReg, Byte bData )
882 {
883 ps->OpenScanPath( ps );
884 IODataToRegister( ps, bReg, bData );
885 ps->CloseScanPath( ps );
886 }
887
888 /** Calling SITUATION: Scanner path not established.
889 * Write a register to asic (used for a command without parameter)
890 */
IORegisterDirectToScanner(pScanData ps,Byte bReg)891 _LOC void IORegisterDirectToScanner( pScanData ps, Byte bReg )
892 {
893 ps->OpenScanPath( ps ); /* establish the connection */
894 IORegisterToScanner( ps, bReg ); /* write register to asic */
895 ps->CloseScanPath( ps ); /* disconnect */
896 }
897
898 /** perform a SW reset of ASIC 98003 models
899 */
IOSoftwareReset(pScanData ps)900 _LOC void IOSoftwareReset( pScanData ps )
901 {
902 if( _ASIC_IS_98003 != ps->sCaps.AsicID )
903 return;
904
905 ps->OpenScanPath( ps );
906
907 IODataToRegister( ps, ps->RegTestMode, _SW_TESTMODE );
908
909 ioSwitchToSPPMode( ps );
910
911 _OUTB_DATA( ps, _RESET1ST );
912 _DODELAY( 5 );
913
914 _OUTB_DATA( ps, _RESET2ND );
915 _DODELAY( 5 );
916
917 _OUTB_DATA( ps, _RESET3RD );
918 _DODELAY( 5 );
919
920 _OUTB_DATA( ps, _RESET4TH );
921 _DODELAY( 5 );
922
923 ioRestoreParallelMode( ps );
924
925 /* reset test mode register */
926 IODataToRegister( ps, ps->RegTestMode, 0 );
927 IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl );
928
929 ps->CloseScanPath( ps );
930 }
931
932 /** Read specific length data from scanner and the method depends on the
933 * mode defined in registry.
934 */
IOReadScannerImageData(pScanData ps,pUChar pBuf,ULong size)935 _LOC void IOReadScannerImageData( pScanData ps, pUChar pBuf, ULong size )
936 {
937 if( _ASIC_IS_98003 != ps->sCaps.AsicID )
938 ps->OpenScanPath( ps);
939
940 if( _IS_ASIC98( ps->sCaps.AsicID))
941 IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
942
943 /* enter read mode */
944 ioEnterReadMode( ps );
945
946 /* call corresponding read proc */
947 ps->Device.ReadData( ps, pBuf, size );
948
949 /* Clear EPP/ECP read mode by simply close scanner path and re-open it */
950 ps->CloseScanPath( ps );
951
952 if( _ASIC_IS_98003 == ps->sCaps.AsicID )
953 ps->OpenScanPath( ps );
954 }
955
956 #ifdef __KERNEL__
957
958 /** the wrapper functions to support delayed and non-delayed I/O
959 */
IOOut(Byte data,UShort port)960 _LOC void IOOut( Byte data, UShort port )
961 {
962 DBG( DBG_IOF, "outb(0x%04x, 0x%02x)\n", port, data );
963 outb( data, port );
964 }
965
IOOutDelayed(Byte data,UShort port)966 _LOC void IOOutDelayed( Byte data, UShort port )
967 {
968 DBG( DBG_IOF, "outb_p(0x%04x, 0x%02x)\n", port, data );
969 outb_p( data, port );
970 }
971
IOIn(UShort port)972 _LOC Byte IOIn( UShort port )
973 {
974 #ifdef DEBUG
975 Byte data = inb( port );
976
977 DBG( DBG_IOF, "inb(0x%04x) = 0x%02x\n", port, data );
978 return data;
979 #else
980 return inb( port );
981 #endif
982 }
983
IOInDelayed(UShort port)984 _LOC Byte IOInDelayed( UShort port )
985 {
986 #ifdef DEBUG
987 Byte data = inb_p( port );
988
989 DBG( DBG_IOF, "inb_p(0x%04x) = 0x%02x\n", port, data );
990 return data;
991 #else
992 return inb_p( port );
993 #endif
994 }
995 #endif /* guard __KERNEL__ */
996
997 /* END PLUSTEK-PP_IO.C ......................................................*/
998