| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  | /*.............................................................................
 | 
					
						
							| 
									
										
										
										
											2003-09-24 20:21:55 +00:00
										 |  |  |  |  * Project : SANE library for Plustek parallelport flatbed scanners. | 
					
						
							| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  |  *............................................................................. | 
					
						
							| 
									
										
										
										
											2003-09-24 20:21:55 +00:00
										 |  |  |  |  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* @file plustek-pp_p48xx.c
 | 
					
						
							|  |  |  |  |  * @brief here we have all functionality according to the ASIC96001/3 based | 
					
						
							|  |  |  |  |  *        models. | 
					
						
							| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  |  *............................................................................. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * based on sources acquired from Plustek Inc. | 
					
						
							|  |  |  |  |  * Copyright (C) 1998 Plustek Inc. | 
					
						
							|  |  |  |  |  * Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de> | 
					
						
							|  |  |  |  |  * also based on the work done by Rick Bronson | 
					
						
							|  |  |  |  |  *............................................................................. | 
					
						
							|  |  |  |  |  * History: | 
					
						
							| 
									
										
										
										
											2003-09-24 20:21:55 +00:00
										 |  |  |  |  * - 0.30 - initial version | 
					
						
							|  |  |  |  |  * - 0.31 - fixed a bug for the return value in p48xxDoTest | 
					
						
							|  |  |  |  |  *        - added additional debug messages | 
					
						
							|  |  |  |  |  *        - added function p48xxCheck4800Memory | 
					
						
							|  |  |  |  |  * - 0.32 - added debug messages | 
					
						
							|  |  |  |  |  *        - fixed a bug in p48xxDoTest | 
					
						
							|  |  |  |  |  *        - disabled RD_WatchDogControl, lamp will be controlled by driver | 
					
						
							|  |  |  |  |  * - 0.33 - added function p48xxSetAsicRegisters() | 
					
						
							|  |  |  |  |  *        - fixed a bug in p48xxDoTest (reset the ASIC registers) | 
					
						
							|  |  |  |  |  *        - removed p48xxPositionLamp | 
					
						
							|  |  |  |  |  * - 0.34 - added some comments | 
					
						
							|  |  |  |  |  * - 0.35 - added some comments | 
					
						
							|  |  |  |  |  * - 0.36 - added function p48xxInitAllModules() to allow reinit of the modules | 
					
						
							|  |  |  |  |  *        - switching from Full- to Halfstep at ps->PhysicalDpi now in | 
					
						
							|  |  |  |  |  *        - p48xxSetGeneralRegister | 
					
						
							|  |  |  |  |  *        - fixed the color-inverse problem for model OP4800 | 
					
						
							|  |  |  |  |  * - 0.37 - move p48xxOpenScanPath, p48xxCloseScanPath | 
					
						
							|  |  |  |  |  *          and p48xxRegisterToScanner to io.c | 
					
						
							|  |  |  |  |  *        - removed // comments
 | 
					
						
							|  |  |  |  |  *        - added override for A3I scanner | 
					
						
							|  |  |  |  |  * - 0.38 - added function p48xxPutToIdleMode() | 
					
						
							|  |  |  |  |  *        - added function p48xxCalibration | 
					
						
							|  |  |  |  |  * - 0.39 - added A3I stuff | 
					
						
							|  |  |  |  |  * - 0.40 - disabled A3I stuff | 
					
						
							|  |  |  |  |  * - 0.41 - no changes | 
					
						
							|  |  |  |  |  * - 0.42 - changed include names | 
					
						
							| 
									
										
										
										
											2003-09-24 14:08:01 +00:00
										 |  |  |  |  * . | 
					
						
							|  |  |  |  |  * <hr> | 
					
						
							|  |  |  |  |  * This file is part of the SANE package. | 
					
						
							| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-09-24 14:08:01 +00:00
										 |  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  |  * modify it under the terms of the GNU General Public License as | 
					
						
							|  |  |  |  |  * published by the Free Software Foundation; either version 2 of the | 
					
						
							|  |  |  |  |  * License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-09-24 14:08:01 +00:00
										 |  |  |  |  * This program is distributed in the hope that it will be useful, but | 
					
						
							|  |  |  |  |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  |  * General Public License for more details. | 
					
						
							| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  |  * | 
					
						
							|  |  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  |  * along with this program; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2003-09-24 14:08:01 +00:00
										 |  |  |  |  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, | 
					
						
							|  |  |  |  |  * MA 02111-1307, USA. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * As a special exception, the authors of SANE give permission for | 
					
						
							|  |  |  |  |  * additional uses of the libraries contained in this release of SANE. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * The exception is that, if you link a SANE library with other files | 
					
						
							|  |  |  |  |  * to produce an executable, this does not by itself cause the | 
					
						
							|  |  |  |  |  * resulting executable to be covered by the GNU General Public | 
					
						
							|  |  |  |  |  * License.  Your use of that executable is in no way restricted on | 
					
						
							|  |  |  |  |  * account of linking the SANE library code into it. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * This exception does not, however, invalidate any other reasons why | 
					
						
							|  |  |  |  |  * the executable file might be covered by the GNU General Public | 
					
						
							|  |  |  |  |  * License. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * If you submit changes to SANE to the maintainers to be included in | 
					
						
							|  |  |  |  |  * a subsequent release, you agree by submitting the changes that | 
					
						
							|  |  |  |  |  * those changes may be distributed with this exception intact. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * If you write modifications of your own for SANE, it is your choice | 
					
						
							|  |  |  |  |  * whether to permit this exception to apply to your modifications. | 
					
						
							|  |  |  |  |  * If you do not wish that, delete this exception notice. | 
					
						
							|  |  |  |  |  * <hr> | 
					
						
							| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  |  */ | 
					
						
							|  |  |  |  | #include "plustek-pp_scan.h"
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*************************** some definitions ********************************/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #define _TEST_SZ   2048  	  /* always use 2048 for mem size (= one bank)   */
 | 
					
						
							|  |  |  |  | #define _START_VAL 0x12345678 /* pick a non-zero starting value for our long */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #define _BankAndSizeForTest	_MemBankSize2k  /* always use 2k for mem test */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*************************** local functions *********************************/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * 1) Set asic to PROGRAM mode | 
					
						
							|  |  |  |  |  * 2) Select the memory bank and size | 
					
						
							|  |  |  |  |  * 3) Initiate data fifo | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static void p48xxSetMemoryBankForProgram( pScanData ps , Byte bBankAndSize ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	/* enter program mode */ | 
					
						
							|  |  |  |  | 	IODataToRegister( ps, ps->RegModeControl, _ModeProgram ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* bank and size */ | 
					
						
							|  |  |  |  |     IODataToRegister( ps, ps->RegMemAccessControl, bBankAndSize ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* initiate data fifo */ | 
					
						
							|  |  |  |  |     IORegisterToScanner( ps, ps->RegInitDataFifo ); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * use the internal memory of a scanner to find the model | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static int p48xxDoTest( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	UChar  tmpByte; | 
					
						
							|  |  |  |  | 	int	   retval; | 
					
						
							|  |  |  |  | 	ULong  adder, ul, cntr; | 
					
						
							|  |  |  |  | 	pULong buffer; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "p48xxDoTest()\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	buffer = _KALLOC( sizeof(UChar) *  _TEST_SZ, GFP_KERNEL ); | 
					
						
							|  |  |  |  | 	if( NULL == buffer ) | 
					
						
							|  |  |  |  | 		return _E_ALLOC; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	retval = _E_NO_DEV; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * do a memory test to determine how much memory this unit has, in the | 
					
						
							|  |  |  |  |      * process we can figure out if it's a 4830 or a 9630.  NOTE: the ram | 
					
						
							|  |  |  |  |      * seems to be mirrored such that if you have a unit with only 32k it's | 
					
						
							|  |  |  |  |      * mirrored 4 times to fill the 128k (2k * (_MemBankMask + 1)) space, | 
					
						
							|  |  |  |  |      * so we will run a 32 bit incrementing pattern over the entire 128k and | 
					
						
							|  |  |  |  |      * look for the 1st page (2k) to fail | 
					
						
							|  |  |  |  |   	 */ | 
					
						
							|  |  |  |  |  	adder = 0; | 
					
						
							|  |  |  |  |     for (cntr = _BankAndSizeForTest; | 
					
						
							|  |  |  |  |          cntr < _BankAndSizeForTest + _MemBanks; cntr++) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     	ps->OpenScanPath( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		p48xxSetMemoryBankForProgram( ps, cntr ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* prepare content, incrementing 32 val */ | 
					
						
							|  |  |  |  |    		for (ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++) | 
					
						
							|  |  |  |  |        		buffer[ul] = ul + adder + _START_VAL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* fill to buffer */ | 
					
						
							|  |  |  |  |    		IOMoveDataToScanner( ps, (pUChar)buffer, _TEST_SZ ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    		/*
 | 
					
						
							|  |  |  |  |  		 * now check bank 0 to see if it got overwritten | 
					
						
							|  |  |  |  | 		 * bank 0, size 2k | 
					
						
							|  |  |  |  | 		 */ | 
					
						
							|  |  |  |  | 		p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     	ps->CloseScanPath( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* read data back */ | 
					
						
							|  |  |  |  |    		IOReadScannerImageData( ps, (pUChar)buffer, _TEST_SZ ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* check */ | 
					
						
							|  |  |  |  |    		for (ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++) { | 
					
						
							|  |  |  |  |       		if (buffer[ul] != ul + _START_VAL) { | 
					
						
							|  |  |  |  |        			break; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* if fail 	*/ | 
					
						
							|  |  |  |  |    		if (ul != _TEST_SZ / sizeof (ULong)) { | 
					
						
							|  |  |  |  | 			DBG( DBG_LOW, "Bank 0 overwritten\n" ); | 
					
						
							|  |  |  |  |        		break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    		/* now check current bank */ | 
					
						
							|  |  |  |  |     	ps->OpenScanPath( ps ); | 
					
						
							|  |  |  |  | 		p48xxSetMemoryBankForProgram( ps, cntr ); | 
					
						
							|  |  |  |  |     	ps->CloseScanPath( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* read data back */ | 
					
						
							|  |  |  |  |    		IOReadScannerImageData( ps, (pUChar)buffer, _TEST_SZ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* check if fail */ | 
					
						
							|  |  |  |  |    		for( ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++ ) { | 
					
						
							|  |  |  |  |        		if( buffer[ul] != ul + adder + _START_VAL ) | 
					
						
							|  |  |  |  |        			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* check if fail */ | 
					
						
							|  |  |  |  |    		if (ul != _TEST_SZ / sizeof(ULong)) { | 
					
						
							| 
									
										
										
										
											2003-10-02 07:44:08 +00:00
										 |  |  |  | 			DBG( DBG_LOW, "Bank not present, error at pos %lu (%lu)\n", ul, | 
					
						
							|  |  |  |  | 				 (ULong)(_TEST_SZ / sizeof(ULong))); | 
					
						
							| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  |        		break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    		adder += _TEST_SZ / sizeof(ULong); | 
					
						
							|  |  |  |  |    	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	_KFREE( buffer ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "found %ld bytes of memory\n", | 
					
						
							|  |  |  |  | 					_TEST_SZ * (cntr - _BankAndSizeForTest)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if( cntr == _BankAndSizeForTest ) { | 
					
						
							|  |  |  |  | 		DBG( DBG_LOW, "No memory ! No scanner...\n" ); | 
					
						
							|  |  |  |  | 		return retval; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |  | 	tmpByte = IODataRegisterFromScanner( ps, 0x18 ); | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "tmpByte[0x18] = 0x%02x\n",tmpByte ); | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	tmpByte = IODataRegisterFromScanner( ps, 0x0e ); | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "tmpByte = 0x%02x, cntr = %lu, AsicId = 0x%02x\n", | 
					
						
							|  |  |  |  | 				   tmpByte, cntr, ps->sCaps.AsicID ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* 128k */ | 
					
						
							|  |  |  |  |     if ((_TEST_SZ * (cntr - _BankAndSizeForTest) == 1 << 17) && | 
					
						
							|  |  |  |  | 								       (ps->sCaps.AsicID ==  _ASIC_IS_96003)) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         /*
 | 
					
						
							|  |  |  |  | 		 * if 128k then must be a 9630 or above | 
					
						
							|  |  |  |  | 		 * hack, test for 12000P, The 9630 returns an 0x08 | 
					
						
							|  |  |  |  | 		 */ | 
					
						
							|  |  |  |  |        	if ( tmpByte == 0x02 ) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             /*
 | 
					
						
							|  |  |  |  |              * as we currently can't automagically detect an A3I we have to | 
					
						
							|  |  |  |  |              * use the override switch | 
					
						
							|  |  |  |  |              */ | 
					
						
							|  |  |  |  |             if( _OVR_PLUSTEK_A3I == ps->ModelOverride ) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         		DBG( DBG_LOW, "Model Override --> A3I\n" ); | 
					
						
							|  |  |  |  |     			ModelSetA3I( ps ); | 
					
						
							|  |  |  |  |             } else { | 
					
						
							|  |  |  |  |             	ModelSet12000( ps ); | 
					
						
							|  |  |  |  | 	    		DBG( DBG_LOW, "It seems we have a 12000P/96000P\n" ); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		}  	else { | 
					
						
							|  |  |  |  |         	ModelSet9630( ps ); | 
					
						
							|  |  |  |  | 			DBG( DBG_LOW, "It seems we have a 9630\n" ); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		retval = _OK; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		DBG( DBG_LOW, "Scanner is not a 9630 or above\n"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       	if ( tmpByte != 0x0f  ) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			DBG( DBG_LOW, "Looks like a 600!\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (( 0x08 == tmpByte ) && | 
					
						
							|  |  |  |  | 				((_TEST_SZ * (cntr - _BankAndSizeForTest)) == 32768 )) { | 
					
						
							|  |  |  |  | 	       		DBG( DBG_LOW, "But it is a 4830P!!! " | 
					
						
							|  |  |  |  | 							  "(by mkochano@ee.pw.edu.pl)\n" ); | 
					
						
							|  |  |  |  | 				ModelSet4830( ps ); | 
					
						
							|  |  |  |  |           	} else { | 
					
						
							|  |  |  |  |           		ModelSet600( ps ); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 			DBG( DBG_LOW, "It seems we have a 4830\n" ); | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		retval = _OK; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return retval; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * setup ASIC registers and clear all scan states (no stepping) | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static void p48xxSetAsicRegisters( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	memset( &ps->AsicReg,   0, sizeof(ps->AsicReg)); | 
					
						
							|  |  |  |  | 	memset( &ps->Asic96Reg, 0, sizeof(ps->Asic96Reg)); | 
					
						
							|  |  |  |  |     memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    	ps->AsicReg.RD_LineControl       = ps->TimePerLine; | 
					
						
							|  |  |  |  |    	ps->AsicReg.RD_ScanControl       = _SCAN_LAMP_ON; | 
					
						
							|  |  |  |  |    	ps->AsicReg.RD_ModelControl      = ps->Device.ModelCtrl | _ModelWhiteIs0; | 
					
						
							|  |  |  |  |    	ps->AsicReg.RD_Origin 	   	     = 0; | 
					
						
							|  |  |  |  |    	ps->AsicReg.RD_Pixels 	   	     = 5110; /*ps->RdPix;*/ | 
					
						
							|  |  |  |  |    	ps->Asic96Reg.RD_MotorControl    = 0; | 
					
						
							|  |  |  |  |    	ps->Asic96Reg.RD_WatchDogControl = 0; /* org. val = 0x8f; */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	IOPutOnAllRegisters( ps ); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * use the internal memory of a scanner to find the model | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static int p48xxCheck4800Memory( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int	   retval; | 
					
						
							|  |  |  |  | 	ULong  ul; | 
					
						
							|  |  |  |  | 	pUChar buffer; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "p48xxCheck4800Memory()\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	buffer = _KALLOC( 2560, GFP_KERNEL ); /* 1280: Read,1280:Write */ | 
					
						
							|  |  |  |  | 	if( NULL == buffer ) | 
					
						
							|  |  |  |  | 		return _E_ALLOC; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	retval = _OK; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* bank 0, size 2k */ | 
					
						
							|  |  |  |  | 	ps->OpenScanPath( ps ); | 
					
						
							|  |  |  |  | 	p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for (ul = 0; ul < 1280; ul++) | 
					
						
							|  |  |  |  | 	    buffer[ul] = (UChar)ul;			      /* prepare content */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	IOMoveDataToScanner( ps, buffer, 1280 );  /* fill to buffer  */ | 
					
						
							|  |  |  |  | 	p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest ); | 
					
						
							|  |  |  |  | 	ps->CloseScanPath( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* read data back */ | 
					
						
							|  |  |  |  | 	IOReadScannerImageData( ps, buffer + 1280, 1280 ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for( ul = 0; ul < 1280; ul++ ) { | 
					
						
							|  |  |  |  | 		if( buffer[ul] != buffer[ul+1280] ) { | 
					
						
							|  |  |  |  | 			DBG( DBG_HIGH, "Error in memory test at pos %lu (%u != %u)\n", | 
					
						
							|  |  |  |  | 							 ul, buffer[ul], buffer[ul+1280] ); | 
					
						
							|  |  |  |  | 			retval = _E_NO_DEV; | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	_KFREE(buffer); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return retval; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * call all other modules, to initialize themselves | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static int p48xxInitAllModules( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result = DacInitialize( ps ); | 
					
						
							|  |  |  |  | 	if( _OK != result ) | 
					
						
							|  |  |  |  | 		return result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result = ImageInitialize( ps ); | 
					
						
							|  |  |  |  | 	if( _OK != result ) | 
					
						
							|  |  |  |  | 		return result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result = IOFuncInitialize( ps ); | 
					
						
							|  |  |  |  | 	if( _OK != result ) | 
					
						
							|  |  |  |  | 		return result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result = IOInitialize( ps ); | 
					
						
							|  |  |  |  | 	if( _OK != result ) | 
					
						
							|  |  |  |  | 		return result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	result = MotorInitialize( ps ); | 
					
						
							|  |  |  |  | 	if( _OK != result ) | 
					
						
							|  |  |  |  | 		return result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * in debug version, check all function pointers | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |  | 	if(	_FALSE == MiscAllPointersSet( ps )) | 
					
						
							|  |  |  |  | 		return _E_INTERNAL; | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 	return _OK; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static int p48xxReadWriteTest( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int retval; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "p48xxReadWriteTest()\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  |      * determine the model by the ASIC type (except for 4830/9630) | 
					
						
							|  |  |  |  |      * might want to make a SetModelCommon() someday for this... | 
					
						
							|  |  |  |  |    	 */ | 
					
						
							|  |  |  |  | 	ps->RedDataReady   = 0x01;  /* normal for Red and Green */ | 
					
						
							|  |  |  |  |   	ps->GreenDataReady = 0x02; | 
					
						
							|  |  |  |  | 	ps->AsicRedColor   = 0x01; | 
					
						
							|  |  |  |  | 	ps->AsicGreenColor = 0x03; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  |  	 * if not already set, try to find ASIC type (96001 or 96003) | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  |   	if ( _NO_BASE == ps->sCaps.wIOBase ) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/* get copy of asic id */ | 
					
						
							|  |  |  |  | 	    ps->sCaps.AsicID = IODataRegisterFromScanner( ps, ps->RegAsicID ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     	if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			/* actually either a 4830, 9630, 12000, find out later */ | 
					
						
							|  |  |  |  |        		DBG( DBG_LOW, "Found a 96003 ASIC at Reg 0x%x\n", ps->RegAsicID ); | 
					
						
							|  |  |  |  |       		ModelSet4830( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     	} else { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       		if ( _ASIC_IS_96001 == ps->sCaps.AsicID ) { | 
					
						
							|  |  |  |  | 	       		DBG( DBG_LOW, "Found a 96001 ASIC at Reg 0x%x\n", | 
					
						
							|  |  |  |  | 															   ps->RegAsicID ); | 
					
						
							|  |  |  |  |         		ModelSet4800( ps ); | 
					
						
							|  |  |  |  |       		} else { | 
					
						
							|  |  |  |  |         		DBG( DBG_LOW, "Can't find your model, asic = 0x%x\n", | 
					
						
							|  |  |  |  | 														    ps->sCaps.AsicID ); | 
					
						
							|  |  |  |  |         		return _E_NO_ASIC; | 
					
						
							|  |  |  |  |         	} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * set the registers according to the assumptions above | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	p48xxSetAsicRegisters( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    	if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) { | 
					
						
							|  |  |  |  | 		retval = p48xxDoTest( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		/*
 | 
					
						
							|  |  |  |  | 		 * as we may now have detected another model, we have to set | 
					
						
							|  |  |  |  | 		 * the registers to their new values... | 
					
						
							|  |  |  |  | 		 * and maybe the modules have to be reset as well | 
					
						
							|  |  |  |  | 		 */ | 
					
						
							|  |  |  |  | 		if( _OK == retval ) { | 
					
						
							|  |  |  |  | 			p48xxSetAsicRegisters( ps ); | 
					
						
							|  |  |  |  | 			retval = p48xxInitAllModules( ps ); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		return retval; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * this part will be reached only for the 4800 - ASIC 96001 | 
					
						
							|  |  |  |  |      * we check only the memory as the original driver does | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	return p48xxCheck4800Memory( ps ); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * 1) Setup the registers of asic. | 
					
						
							|  |  |  |  |  * 2) Determine which type of CCD we are using | 
					
						
							|  |  |  |  |  * 3) According to the CCD, prepare the CCD dependent veriables | 
					
						
							|  |  |  |  |  *  SONY CCD: | 
					
						
							|  |  |  |  |  *	The color exposure sequence: Red, Green (after 11 red lines), | 
					
						
							|  |  |  |  |  *	Blue (after 8 green lines) | 
					
						
							|  |  |  |  |  *  TOSHIBA CCD: | 
					
						
							|  |  |  |  |  *  The color exposure sequence: Red, Blue (after 11 red lines), | 
					
						
							|  |  |  |  |  *	Green (after 8 blue lines) | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static void p48xxSetupScannerVariables( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	UChar    tmp; | 
					
						
							|  |  |  |  | 	TimerDef timer; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "p48xxSetupScannerVariables()\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->OpenScanPath( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	IODataToRegister( ps, ps->RegModelControl2, _Model2ChannelMult ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if( 2 == IODataFromRegister( ps, ps->RegWriteIOBusDecode1 )) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		DBG( DBG_LOW, "Scanner has 97003 ASIC too.\n" ); | 
					
						
							|  |  |  |  | 		ps->f97003 = _TRUE; | 
					
						
							|  |  |  |  | 		ps->b97003DarkR = 8; | 
					
						
							|  |  |  |  | 		ps->b97003DarkG = 8; | 
					
						
							|  |  |  |  | 		ps->b97003DarkB = 8; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	    ps->Asic96Reg.u26.RD_ModelControl2 = _Model2ChannelMult; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		DBG( DBG_LOW, "No ASIC 97003 found.\n" ); | 
					
						
							|  |  |  |  | 		ps->f97003 = _FALSE; | 
					
						
							|  |  |  |  | 	    ps->Asic96Reg.u26.RD_ModelControl2 = _Model2DirectOutPort; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	IODataToRegister( ps, ps->RegModelControl2, | 
					
						
							|  |  |  |  | 				  	  ps->Asic96Reg.u26.RD_ModelControl2 ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	tmp = IODataFromRegister( ps, ps->RegStatus ); | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "Status-Register = 0x%02X\n", tmp ); | 
					
						
							|  |  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |  | 	if( tmp & _FLAG_P96_MOTORTYPE ) { | 
					
						
							|  |  |  |  | 		DBG( DBG_LOW, "Scanner has Full/Half Stepping drive\n" ); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		DBG( DBG_LOW, "Scanner has Micro Stepping drive\n" ); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if( tmp & _FLAG_P96_CCDTYPE) { | 
					
						
							|  |  |  |  | 		ps->fSonyCCD = _FALSE; | 
					
						
							|  |  |  |  | 		DBG( DBG_LOW, "CCD is NEC/TOSHIBA Type\n" ); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		ps->fSonyCCD = _TRUE; | 
					
						
							|  |  |  |  | 		DBG( DBG_LOW, "CCD is SONY Type\n" ); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->CloseScanPath( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->b1stColorByte = ps->AsicRedColor; | 
					
						
							|  |  |  |  |     ps->b1stColor 	  = ps->RedDataReady; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (ps->fSonyCCD) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ps->b2ndColorByte = ps->AsicGreenColor; | 
					
						
							|  |  |  |  | 		ps->b2ndColor 	  = ps->GreenDataReady; | 
					
						
							|  |  |  |  | 		ps->b3rdColorByte = _ASIC_BLUECOLOR; | 
					
						
							|  |  |  |  | 		ps->b3rdColor 	  = _BLUE_DATA_READY; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	}  else  { /* NEC/Toshiba CCD */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ps->b2ndColorByte = _ASIC_BLUECOLOR; | 
					
						
							|  |  |  |  | 		ps->b2ndColor 	  = _BLUE_DATA_READY; | 
					
						
							|  |  |  |  | 		ps->b3rdColorByte = ps->AsicGreenColor; | 
					
						
							|  |  |  |  | 		ps->b3rdColor 	  = ps->GreenDataReady; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->b1stMask = (Byte)~ps->b1stColor; | 
					
						
							|  |  |  |  |     ps->b2ndMask = (Byte)~ps->b2ndColor; | 
					
						
							|  |  |  |  | 	ps->b3rdMask = (Byte)~ps->b3rdColor; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->b1stLinesOffset = 17; | 
					
						
							|  |  |  |  |     ps->b2ndLinesOffset = 9; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     /*
 | 
					
						
							|  |  |  |  | 	 * calculate I/O Timer | 
					
						
							|  |  |  |  |      * if we cannot read 200 lines within 1 second, the I/O time has to add 2 | 
					
						
							|  |  |  |  |      * CalculateIOTime () | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  |     if( _PORT_SPP != ps->IO.portMode ) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		UShort wLines = 200; | 
					
						
							|  |  |  |  | 		pUChar pBuf; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		pBuf = _KALLOC((_BUF_SIZE_BASE_CONST * 2), GFP_KERNEL ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if ( NULL != pBuf ) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			MiscStartTimer( &timer, _SECOND ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		    do { | 
					
						
							|  |  |  |  | 				IOReadScannerImageData( ps, pBuf, (_BUF_SIZE_BASE_CONST * 2)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				wLines--; | 
					
						
							|  |  |  |  | 		    } while (!MiscCheckTimer( &timer) && wLines); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		    if( !wLines ) | 
					
						
							|  |  |  |  | 				ps->bExtraAdd = 0; | 
					
						
							|  |  |  |  | 		    else | 
					
						
							|  |  |  |  | 				ps->bExtraAdd = 2; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			_KFREE( pBuf ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 	    	ps->bExtraAdd = 2;	/* poor resource */ | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		ps->bExtraAdd = 0; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static void p48xxSetGeneralRegister( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if( MODEL_OP_A3I == ps->sCaps.Model ) { | 
					
						
							|  |  |  |  | 		ps->AsicReg.RD_ModelControl = _ModelDpi400 | _ModelWhiteIs0 | | 
					
						
							|  |  |  |  | 									  _ModelMemSize128k4; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->AsicReg.RD_ModeControl = _ModeScan; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* WORK: ps->PhysicalDpi should be correct, but the we have to work
 | 
					
						
							|  |  |  |  |  *       on motor.c again to use other running-tables | 
					
						
							|  |  |  |  |  *    if ( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) { | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | 	if ( ps->DataInf.xyAppDpi.y <= 300 ) { | 
					
						
							|  |  |  |  | /* HEINER:A3I
 | 
					
						
							|  |  |  |  |  	if ( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) { | 
					
						
							|  |  |  |  | */ | 
					
						
							|  |  |  |  | 		ps->Asic96Reg.RD_MotorControl = (ps->FullStep | ps->IgnorePF | | 
					
						
							|  |  |  |  | 									     ps->MotorOn | _MotorDirForward); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		ps->Asic96Reg.RD_MotorControl = (ps->IgnorePF | ps->MotorOn | | 
					
						
							|  |  |  |  | 										 _MotorDirForward); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if ( ps->DataInf.wPhyDataType == COLOR_BW ) { | 
					
						
							|  |  |  |  |         ps->AsicReg.RD_ScanControl = ps->bLampOn; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	    if (!(ps->DataInf.dwScanFlag & SCANDEF_Inverse)) | 
					
						
							|  |  |  |  |     	    ps->AsicReg.RD_ScanControl |= _P96_SCANDATA_INVERT; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     } else { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	    if (ps->DataInf.dwScanFlag & SCANDEF_Inverse) | 
					
						
							|  |  |  |  |     	    ps->AsicReg.RD_ScanControl |=  _P96_SCANDATA_INVERT; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (ps->DataInf.xyPhyDpi.x <= 200) | 
					
						
							|  |  |  |  |         ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "RD_ModeControl  = 0x%02x\n", ps->AsicReg.RD_ModeControl  ); | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "RD_MotorControl = 0x%02x\n", ps->Asic96Reg.RD_MotorControl ); | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "RD_ScanControl  = 0x%02x\n", ps->AsicReg.RD_ScanControl  ); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static void p48xxSetupScanningCondition( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "p48xxSetupScanningCondition()\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	IORegisterDirectToScanner( ps, ps->RegInitDataFifo ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    /* Cal64kTime (); */ | 
					
						
							|  |  |  |  | 	if( MODEL_OP_A3I == ps->sCaps.Model ) | 
					
						
							|  |  |  |  | 	    ps->wLinesPer64kTime = (UShort)(65555UL / ps->DataInf.dwAsicBytesPerPlane * | 
					
						
							|  |  |  |  | 				 			        5UL); | 
					
						
							|  |  |  |  |     else | 
					
						
							|  |  |  |  | 	    ps->wLinesPer64kTime = (UShort)(65555UL / ps->DataInf.dwAsicBytesPerPlane * | 
					
						
							|  |  |  |  | 				 			        10UL / 3UL); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "wLinesPer64kTime = %u\n", ps->wLinesPer64kTime ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->InitialSetCurrentSpeed( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "Current Speed = %u\n", ps->bCurrentSpeed ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->bMinReadFifo = (Byte)((ps->DataInf.dwAsicBytesPerPlane + 511) / 512); | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "MinReadFifo = %u\n", ps->bMinReadFifo ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     p48xxSetGeneralRegister( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * if speed is not the fastest and DPI is less than 400, do half steps | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  |     if( ps->DataInf.wPhyDataType >= COLOR_256GRAY && | 
					
						
							|  |  |  |  | 		!(ps->bCurrentSpeed & 1) && (ps->DataInf.xyAppDpi.y <= 300)) { | 
					
						
							|  |  |  |  | /* HEINER:A3I
 | 
					
						
							|  |  |  |  | 	if( !(ps->bCurrentSpeed & 1) && (ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi)) { | 
					
						
							|  |  |  |  | */ | 
					
						
							|  |  |  |  | 		ps->fHalfStepTableFlag = _TRUE; | 
					
						
							|  |  |  |  | 		ps->Asic96Reg.RD_MotorControl &= ps->StepMask; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x; | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "RD_Dpi = %u\n", ps->AsicReg.RD_Dpi ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     /* SetStartStopRegister (ps) */ | 
					
						
							|  |  |  |  |     ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + ps->Device.DataOriginX + | 
					
						
							|  |  |  |  | 					                 ps->DataInf.crImage.x); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (ps->DataInf.wPhyDataType < COLOR_256GRAY) { | 
					
						
							|  |  |  |  | 		ps->AsicReg.RD_Pixels = | 
					
						
							|  |  |  |  | 					(UShort)(ps->DataInf.dwAsicPixelsPerPlane + 7) & 0xfff8; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicPixelsPerPlane; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "RD_Pixels = %u\n", ps->AsicReg.RD_Pixels ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     /* SetupMotorStart () */ | 
					
						
							|  |  |  |  | 	IORegisterDirectToScanner( ps, ps->RegInitDataFifo); | 
					
						
							|  |  |  |  |     ps->SetupMotorRunTable( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     IOSetToMotorRegister( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->pCurrentColorRunTable = ps->pColorRunTable; | 
					
						
							|  |  |  |  |     ps->bCurrentLineCount = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     IOPutOnAllRegisters( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->OpenScanPath( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * when using the full-step speed on 600 dpi models, then set | 
					
						
							|  |  |  |  | 	 * the motor into half-step mode, to avoid that the scanner hits | 
					
						
							|  |  |  |  | 	 * the back of its cover | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  |    	if((600 == ps->PhysicalDpi) && (1 == ps->bCurrentSpeed)) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ps->Asic96Reg.RD_MotorControl &= ~ps->FullStep; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  	IODataToRegister( ps, ps->RegMotorControl, | 
					
						
							|  |  |  |  | 					    (Byte)(ps->Asic96Reg.RD_MotorControl & ~ps->MotorOn)); | 
					
						
							|  |  |  |  | 	IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl); | 
					
						
							|  |  |  |  |     IORegisterToScanner( ps, ps->RegInitDataFifo ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->CloseScanPath( ps ); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * switch the motor off and put the scanner into idle mode | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static void p48xxPutToIdleMode( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     DBG( DBG_LOW, "Putting Scanner (ASIC 96001/3) into Idle-Mode\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     /*
 | 
					
						
							|  |  |  |  |      * turn off motor | 
					
						
							|  |  |  |  |      */ | 
					
						
							|  |  |  |  | 	ps->Asic96Reg.RD_MotorControl = 0; | 
					
						
							|  |  |  |  | 	IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * for P96001/3 ASIC | 
					
						
							|  |  |  |  |  * do all the preliminary stuff here (calibrate the scanner and move the | 
					
						
							|  |  |  |  |  * sensor to it<EFBFBD>s start position, also setup the driver for the | 
					
						
							|  |  |  |  |  * current run) | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | static int p48xxCalibration( pScanData ps ) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "p48xxCalibration()\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ps->Scan.bFifoSelect = ps->RegGFifoOffset; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while (_TRUE) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		_ASSERT(ps->WaitForShading); | 
					
						
							|  |  |  |  |         if (ps->WaitForShading( ps )) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         	if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* HEINER:A3I disable !! */ | 
					
						
							|  |  |  |  | 	               	MotorP96AheadToDarkArea( ps ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     if( ps->Scan.fRefreshState ) { | 
					
						
							|  |  |  |  |                         ps->Scan.fRefreshState = _FALSE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |           			if (!ps->fReshaded) { | 
					
						
							|  |  |  |  |                         ps->fReshaded = _TRUE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     	    		    if (ps->fColorMoreRedFlag || ps->fColorMoreBlueFlag) { | 
					
						
							|  |  |  |  |            					continue; | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  |     	            } | 
					
						
							|  |  |  |  | 	    	  	} | 
					
						
							|  |  |  |  | 	   		} | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	    } else { | 
					
						
							|  |  |  |  |         	ps->fScanningStatus = _FALSE; | 
					
						
							|  |  |  |  |         	ps->DataInf.dwAppLinesPerArea = 0; | 
					
						
							|  |  |  |  |         	return _E_TIMEOUT; | 
					
						
							|  |  |  |  | 	    } | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    	if((ps->sCaps.AsicID != _ASIC_IS_96001) && | 
					
						
							|  |  |  |  | 							       (ps->DataInf.wPhyDataType != COLOR_BW)) { | 
					
						
							|  |  |  |  | 		DacP96WriteBackToGammaShadingRAM(ps); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { | 
					
						
							|  |  |  |  |        	ps->bExtraMotorCtrl     = 0; | 
					
						
							|  |  |  |  |     	ps->Scan.fMotorBackward = _TRUE; | 
					
						
							|  |  |  |  |        	MotorP96ConstantMoveProc( ps, 4000 ); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * move sensor and setup scanner for grabbing the picture | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	_ASSERT(ps->WaitForPositionY); | 
					
						
							|  |  |  |  |    	ps->WaitForPositionY(ps); | 
					
						
							|  |  |  |  | 	return _OK; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /************************ exported functions *********************************/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*.............................................................................
 | 
					
						
							|  |  |  |  |  * initialize the register values and function calls for the 96001/3 asic | 
					
						
							|  |  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2003-09-24 14:08:01 +00:00
										 |  |  |  | _LOC int P48xxInitAsic( pScanData ps ) | 
					
						
							| 
									
										
										
										
											2003-09-23 07:10:53 +00:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	DBG( DBG_LOW, "P48xxInitAsic()\n" ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	ps->IO.bOpenCount = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	ps->RegSwitchBus			= 0; | 
					
						
							|  |  |  |  | 	ps->RegReadDataMode			= 1; | 
					
						
							|  |  |  |  | 	ps->RegWriteDataMode		= 2; | 
					
						
							|  |  |  |  | 	ps->RegEPPEnable			= 3; | 
					
						
							|  |  |  |  | 	ps->RegInitDataFifo			= 4; | 
					
						
							|  |  |  |  | 	ps->RegForceStep			= 5; | 
					
						
							|  |  |  |  | 	ps->RegInitScanState		= 6; | 
					
						
							|  |  |  |  | 	ps->RegRefreshScanState		= 7; | 
					
						
							|  |  |  |  | 	ps->RegStatus				= 0x10; | 
					
						
							|  |  |  |  | 	ps->RegFifoOffset			= 0x11; | 
					
						
							|  |  |  |  | 	ps->RegGetScanState			= 0x12; | 
					
						
							|  |  |  |  | 	ps->RegAsicID				= 0x13;	/* Determine the asic */ | 
					
						
							|  |  |  |  | 	ps->RegReadIOBufBus			= 0x17; | 
					
						
							|  |  |  |  | 	ps->RegModeControl			= 0x18; | 
					
						
							|  |  |  |  | 	ps->RegLineControl			= 0x19; | 
					
						
							|  |  |  |  | 	ps->RegScanControl			= 0x1a; | 
					
						
							|  |  |  |  | 	ps->RegMotorControl			= 0x1b; | 
					
						
							|  |  |  |  | 	ps->RegModelControl			= 0x1c; | 
					
						
							|  |  |  |  | 	ps->RegMemAccessControl		= 0x1d; | 
					
						
							|  |  |  |  | 	ps->RegDpiLow				= 0x1e; | 
					
						
							|  |  |  |  | 	ps->RegDpiHigh				= 0x1f; | 
					
						
							|  |  |  |  | 	ps->RegScanPosLow			= 0x20; | 
					
						
							|  |  |  |  | 	ps->RegScanPosHigh			= 0x21; | 
					
						
							|  |  |  |  | 	ps->RegWidthPixelsLow		= 0x22; | 
					
						
							|  |  |  |  | 	ps->RegWidthPixelsHigh		= 0x23; | 
					
						
							|  |  |  |  | 	ps->RegThresholdControl		= 0x24; | 
					
						
							|  |  |  |  | 	ps->RegWatchDogControl		= 0x25; | 
					
						
							|  |  |  |  | 	ps->RegModelControl2		= 0x26; | 
					
						
							|  |  |  |  | 	ps->RegThresholdGapControl	= 0x27; | 
					
						
							|  |  |  |  | 	ps->RegRedChShadingOffset   = 0x28; | 
					
						
							|  |  |  |  | 	ps->RegGreenChShadingOffset = 0x29; | 
					
						
							|  |  |  |  | 	ps->RegRedDCAdjust			= 0x27;  /* not sure why these are dup's */ | 
					
						
							|  |  |  |  | 	ps->RegGreenDCAdjust		= 0x28; | 
					
						
							|  |  |  |  | 	ps->RegBlueDCAdjust			= 0x29; | 
					
						
							|  |  |  |  | 	ps->RegBlueChShadingOffset	= 0x2a; | 
					
						
							|  |  |  |  | 	ps->RegRedChDarkOffset		= 0x2b; | 
					
						
							|  |  |  |  | 	ps->RegGreenChDarkOffset	= 0x2c; | 
					
						
							|  |  |  |  | 	ps->RegBlueChDarkOffset		= 0x2d; | 
					
						
							|  |  |  |  | 	ps->RegWriteIOBusDecode1	= 0x2e; | 
					
						
							|  |  |  |  | 	ps->RegWriteIOBusDecode2	= 0x2f; | 
					
						
							|  |  |  |  | 	ps->RegScanStateControl		= 0x30; | 
					
						
							|  |  |  |  | 	ps->RegRedChEvenOffset		= 0x31; | 
					
						
							|  |  |  |  | 	ps->RegGreenChEvenOffset	= 0x32; | 
					
						
							|  |  |  |  | 	ps->RegBlueChEvenOffset		= 0x33; | 
					
						
							|  |  |  |  | 	ps->RegRedChOddOffset		= 0x34; | 
					
						
							|  |  |  |  | 	ps->RegGreenChOddOffset		= 0x35; | 
					
						
							|  |  |  |  | 	ps->RegBlueChOddOffset		= 0x36; | 
					
						
							|  |  |  |  | 	ps->RegRedGainOutDirect		= 0x37; | 
					
						
							|  |  |  |  | 	ps->RegGreenGainOutDirect	= 0x38; | 
					
						
							|  |  |  |  | 	ps->RegBlueGainOutDirect	= 0x39; | 
					
						
							|  |  |  |  | 	ps->RegLedControl			= 0x3a; | 
					
						
							|  |  |  |  | 	ps->RegShadingCorrectCtrl	= 0x3b; | 
					
						
							|  |  |  |  | 	ps->RegScanStateBegin		= 0x40;	/* (0, 1)		*/ | 
					
						
							|  |  |  |  | 	ps->RegScanStateEnd			= 0x5f;	/* (62, 63)     */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * setup function calls | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	ps->ReadWriteTest		   = p48xxReadWriteTest; | 
					
						
							|  |  |  |  | 	ps->SetupScannerVariables  = p48xxSetupScannerVariables; | 
					
						
							|  |  |  |  | 	ps->SetupScanningCondition = p48xxSetupScanningCondition; | 
					
						
							|  |  |  |  |     ps->PutToIdleMode          = p48xxPutToIdleMode; | 
					
						
							|  |  |  |  |     ps->Calibration            = p48xxCalibration; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * setup misc | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF; | 
					
						
							|  |  |  |  | 	ps->CtrlReadLowNibble  = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	ps->MotorFreeRun = 0x80; | 
					
						
							|  |  |  |  | 	ps->bLampOn      = _SCAN_LAMP_ON; | 
					
						
							|  |  |  |  | 	ps->f97003 	     = _FALSE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * initialize the other modules | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	return p48xxInitAllModules( ps ); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* END PLUSTEK-PP_P48xx.C ...................................................*/ |