• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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