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