1141cc406Sopenharmony_ci/* @file plustekpp-io.c 2141cc406Sopenharmony_ci * @brief as the name says, here we have all the I/O 3141cc406Sopenharmony_ci * functions according to the parallel port hardware 4141cc406Sopenharmony_ci * 5141cc406Sopenharmony_ci * based on sources acquired from Plustek Inc. 6141cc406Sopenharmony_ci * Copyright (C) 1998 Plustek Inc. 7141cc406Sopenharmony_ci * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de> 8141cc406Sopenharmony_ci * 9141cc406Sopenharmony_ci * History: 10141cc406Sopenharmony_ci * - 0.37 - initial version 11141cc406Sopenharmony_ci * - added Kevins' suggestions 12141cc406Sopenharmony_ci * - 0.38 - added Asic 98003 stuff and ioP98ReadWriteTest() 13141cc406Sopenharmony_ci * - added IODataRegisterToDAC() 14141cc406Sopenharmony_ci * - replaced function IOSPPWrite by IOMoveDataToScanner 15141cc406Sopenharmony_ci * - modified ioP98OpenScanPath again and reuse V0.36 stuff again 16141cc406Sopenharmony_ci * - added IO functions 17141cc406Sopenharmony_ci * - 0.39 - added IO functions 18141cc406Sopenharmony_ci * - added f97003 stuff from A3I code 19141cc406Sopenharmony_ci * - 0.40 - no changes 20141cc406Sopenharmony_ci * - 0.41 - no changes 21141cc406Sopenharmony_ci * - 0.42 - changed include names 22141cc406Sopenharmony_ci * - 0.43 - no changes 23141cc406Sopenharmony_ci * - 0.44 - fix format string issues, as Long types default to int32_t 24141cc406Sopenharmony_ci * now 25141cc406Sopenharmony_ci * . 26141cc406Sopenharmony_ci * <hr> 27141cc406Sopenharmony_ci * This file is part of the SANE package. 28141cc406Sopenharmony_ci * 29141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 30141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 31141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the 32141cc406Sopenharmony_ci * License, or (at your option) any later version. 33141cc406Sopenharmony_ci * 34141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 35141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 36141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 37141cc406Sopenharmony_ci * General Public License for more details. 38141cc406Sopenharmony_ci * 39141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License 40141cc406Sopenharmony_ci * along with this program. If not, see <https://www.gnu.org/licenses/>. 41141cc406Sopenharmony_ci * 42141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for 43141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE. 44141cc406Sopenharmony_ci * 45141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files 46141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the 47141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public 48141cc406Sopenharmony_ci * License. Your use of that executable is in no way restricted on 49141cc406Sopenharmony_ci * account of linking the SANE library code into it. 50141cc406Sopenharmony_ci * 51141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why 52141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public 53141cc406Sopenharmony_ci * License. 54141cc406Sopenharmony_ci * 55141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in 56141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that 57141cc406Sopenharmony_ci * those changes may be distributed with this exception intact. 58141cc406Sopenharmony_ci * 59141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice 60141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications. 61141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice. 62141cc406Sopenharmony_ci * <hr> 63141cc406Sopenharmony_ci */ 64141cc406Sopenharmony_ci#include "plustek-pp_scan.h" 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci/*************************** some prototypes *********************************/ 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_cistatic Bool fnEPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize ); 69141cc406Sopenharmony_cistatic Bool fnSPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize ); 70141cc406Sopenharmony_cistatic Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize ); 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_citypedef struct { 73141cc406Sopenharmony_ci pFnReadData func; 74141cc406Sopenharmony_ci char *name; 75141cc406Sopenharmony_ci} ioReadFuncDef; 76141cc406Sopenharmony_ci 77141cc406Sopenharmony_cistatic ioReadFuncDef ioReadFunc[3] = { 78141cc406Sopenharmony_ci { fnEPPRead, "fnEPPRead" }, 79141cc406Sopenharmony_ci { fnSPPRead, "fnSPPRead" }, 80141cc406Sopenharmony_ci { fnBiDirRead, "fnBiDirRead" } 81141cc406Sopenharmony_ci}; 82141cc406Sopenharmony_ci 83141cc406Sopenharmony_ci/*************************** some definitions ********************************/ 84141cc406Sopenharmony_ci 85141cc406Sopenharmony_ci#define _MEMTEST_SIZE 1280 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci/*************************** local functions *********************************/ 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci/** we provide some functions to read data from SPP port according to 90141cc406Sopenharmony_ci * the speed we have detected (ReadWriteTest!!) 91141cc406Sopenharmony_ci */ 92141cc406Sopenharmony_cistatic Byte ioDataFromSPPFast( pScanData ps ) 93141cc406Sopenharmony_ci{ 94141cc406Sopenharmony_ci Byte bData, tmp; 95141cc406Sopenharmony_ci 96141cc406Sopenharmony_ci /* notify asic we will read the high nibble data from status port */ 97141cc406Sopenharmony_ci if( _FALSE == ps->f97003 ) { 98141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); 99141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 100141cc406Sopenharmony_ci } 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_ci /* read high nibble */ 103141cc406Sopenharmony_ci bData = _INB_STATUS( ps ); 104141cc406Sopenharmony_ci bData &= 0xf0; 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); 107141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci /* read low nibble */ 110141cc406Sopenharmony_ci tmp = _INB_STATUS( ps ); 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci /* combine with low nibble */ 113141cc406Sopenharmony_ci bData |= (tmp >> 4); 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); 116141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci return bData; 119141cc406Sopenharmony_ci} 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_cistatic Byte ioDataFromSPPMiddle( pScanData ps ) 122141cc406Sopenharmony_ci{ 123141cc406Sopenharmony_ci Byte bData, tmp; 124141cc406Sopenharmony_ci 125141cc406Sopenharmony_ci /* notify asic we will read the high nibble data from status port */ 126141cc406Sopenharmony_ci if( _FALSE == ps->f97003 ) { 127141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); 128141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 129141cc406Sopenharmony_ci } 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ci /* read high nibble */ 132141cc406Sopenharmony_ci _INB_STATUS( ps ); 133141cc406Sopenharmony_ci bData = _INB_STATUS( ps ); 134141cc406Sopenharmony_ci bData &= 0xf0; 135141cc406Sopenharmony_ci 136141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); 137141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_ci /* read low nibble */ 140141cc406Sopenharmony_ci _INB_STATUS( ps ); 141141cc406Sopenharmony_ci tmp = _INB_STATUS( ps ); 142141cc406Sopenharmony_ci 143141cc406Sopenharmony_ci /* combine with low nibble */ 144141cc406Sopenharmony_ci bData |= (tmp >> 4); 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); 147141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 148141cc406Sopenharmony_ci 149141cc406Sopenharmony_ci return bData; 150141cc406Sopenharmony_ci} 151141cc406Sopenharmony_ci 152141cc406Sopenharmony_cistatic UChar ioDataFromSPPSlow( pScanData ps ) 153141cc406Sopenharmony_ci{ 154141cc406Sopenharmony_ci Byte bData, tmp; 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci /* notify asic we will read the high nibble data from status port */ 157141cc406Sopenharmony_ci if( _FALSE == ps->f97003 ) { 158141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); 159141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 160141cc406Sopenharmony_ci } 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_ci /* read high nibble */ 163141cc406Sopenharmony_ci _INB_STATUS( ps ); 164141cc406Sopenharmony_ci _INB_STATUS( ps ); 165141cc406Sopenharmony_ci bData = _INB_STATUS( ps ); 166141cc406Sopenharmony_ci bData &= 0xf0; 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); 169141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci /* read low nibble */ 172141cc406Sopenharmony_ci _INB_STATUS( ps ); 173141cc406Sopenharmony_ci _INB_STATUS( ps ); 174141cc406Sopenharmony_ci tmp = _INB_STATUS( ps ); 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci /* combine with low nibble */ 177141cc406Sopenharmony_ci bData |= (tmp >> 4); 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); 180141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci return bData; 183141cc406Sopenharmony_ci} 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_cistatic UChar ioDataFromSPPSlowest( pScanData ps ) 186141cc406Sopenharmony_ci{ 187141cc406Sopenharmony_ci Byte bData, tmp; 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_ci /* notify asic we will read the high nibble data from status port */ 190141cc406Sopenharmony_ci if( _FALSE == ps->f97003 ) { 191141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); 192141cc406Sopenharmony_ci _DO_UDELAY( 3 ); 193141cc406Sopenharmony_ci } 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_ci /* read high nibble */ 196141cc406Sopenharmony_ci _INB_STATUS( ps ); 197141cc406Sopenharmony_ci _INB_STATUS( ps ); 198141cc406Sopenharmony_ci _INB_STATUS( ps ); 199141cc406Sopenharmony_ci bData = _INB_STATUS( ps ); 200141cc406Sopenharmony_ci bData &= 0xf0; 201141cc406Sopenharmony_ci 202141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); 203141cc406Sopenharmony_ci _DO_UDELAY( 3 ); 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci /* read low nibble */ 206141cc406Sopenharmony_ci _INB_STATUS( ps ); 207141cc406Sopenharmony_ci _INB_STATUS( ps ); 208141cc406Sopenharmony_ci _INB_STATUS( ps ); 209141cc406Sopenharmony_ci tmp = _INB_STATUS( ps ); 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci /* combine with low nibble */ 212141cc406Sopenharmony_ci bData |= (tmp >> 4); 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); 215141cc406Sopenharmony_ci _DO_UDELAY( 3 ); 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci return bData; 218141cc406Sopenharmony_ci} 219141cc406Sopenharmony_ci 220141cc406Sopenharmony_ci/** Read data from STATUS port. We have to read twice and combine two nibble 221141cc406Sopenharmony_ci * data to one byte. 222141cc406Sopenharmony_ci */ 223141cc406Sopenharmony_cistatic Bool fnSPPRead( pScanData ps, pUChar pBuffer, ULong ulSize ) 224141cc406Sopenharmony_ci{ 225141cc406Sopenharmony_ci switch( ps->IO.delay ) { 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ci case 0: 228141cc406Sopenharmony_ci for (; ulSize; ulSize--, pBuffer++) 229141cc406Sopenharmony_ci *pBuffer = ioDataFromSPPFast( ps ); 230141cc406Sopenharmony_ci break; 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci case 1: 233141cc406Sopenharmony_ci for (; ulSize; ulSize--, pBuffer++) 234141cc406Sopenharmony_ci *pBuffer = ioDataFromSPPMiddle( ps ); 235141cc406Sopenharmony_ci break; 236141cc406Sopenharmony_ci 237141cc406Sopenharmony_ci case 2: 238141cc406Sopenharmony_ci for (; ulSize; ulSize--, pBuffer++) 239141cc406Sopenharmony_ci *pBuffer = ioDataFromSPPSlow( ps ); 240141cc406Sopenharmony_ci break; 241141cc406Sopenharmony_ci 242141cc406Sopenharmony_ci default: 243141cc406Sopenharmony_ci for (; ulSize; ulSize--, pBuffer++) 244141cc406Sopenharmony_ci *pBuffer = ioDataFromSPPSlowest( ps ); 245141cc406Sopenharmony_ci break; 246141cc406Sopenharmony_ci } 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci return _TRUE; 249141cc406Sopenharmony_ci} 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_ci/** Using buffered I/O to read data from EPP Data Port 253141cc406Sopenharmony_ci */ 254141cc406Sopenharmony_cistatic Bool fnEPPRead( pScanData ps, pUChar pBuffer, ULong ulSize ) 255141cc406Sopenharmony_ci{ 256141cc406Sopenharmony_ci register ULong i; 257141cc406Sopenharmony_ci 258141cc406Sopenharmony_ci if( _IS_ASIC98(ps->sCaps.AsicID)) { 259141cc406Sopenharmony_ci 260141cc406Sopenharmony_ci sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN ); 261141cc406Sopenharmony_ci for( i = 0; i < ulSize; i++ ) 262141cc406Sopenharmony_ci pBuffer[i] = _INB_EPPDATA( ps ); 263141cc406Sopenharmony_ci 264141cc406Sopenharmony_ci sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT ); 265141cc406Sopenharmony_ci } else { 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci for( i = 0; i < ulSize; i++ ) 268141cc406Sopenharmony_ci pBuffer[i] = _INB_EPPDATA( ps ); 269141cc406Sopenharmony_ci } 270141cc406Sopenharmony_ci 271141cc406Sopenharmony_ci return _TRUE; 272141cc406Sopenharmony_ci} 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_ci/** 275141cc406Sopenharmony_ci */ 276141cc406Sopenharmony_cistatic Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize ) 277141cc406Sopenharmony_ci{ 278141cc406Sopenharmony_ci UChar start, end; 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci start = _CTRL_START_BIDIREAD; 281141cc406Sopenharmony_ci end = _CTRL_END_BIDIREAD; 282141cc406Sopenharmony_ci 283141cc406Sopenharmony_ci sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN ); 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ci if( !sanei_pp_uses_directio()) { 286141cc406Sopenharmony_ci start &= ~_CTRL_DIRECTION; 287141cc406Sopenharmony_ci end &= ~_CTRL_DIRECTION; 288141cc406Sopenharmony_ci } 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ci switch( ps->IO.delay ) { 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci case 0: 293141cc406Sopenharmony_ci for( ; ulSize; ulSize--, pBuffer++ ) { 294141cc406Sopenharmony_ci _OUTB_CTRL( ps, start ); 295141cc406Sopenharmony_ci *pBuffer = _INB_DATA( ps ); 296141cc406Sopenharmony_ci _OUTB_CTRL( ps, end ); 297141cc406Sopenharmony_ci } 298141cc406Sopenharmony_ci break; 299141cc406Sopenharmony_ci 300141cc406Sopenharmony_ci case 1: 301141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 302141cc406Sopenharmony_ci for(; ulSize; ulSize--, pBuffer++ ) { 303141cc406Sopenharmony_ci _OUTB_CTRL( ps, start ); 304141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci *pBuffer = _INB_DATA( ps ); 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci _OUTB_CTRL( ps, end ); 309141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 310141cc406Sopenharmony_ci } 311141cc406Sopenharmony_ci break; 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci default: 314141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 315141cc406Sopenharmony_ci for(; ulSize; ulSize--, pBuffer++ ) { 316141cc406Sopenharmony_ci _OUTB_CTRL( ps, start ); 317141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 318141cc406Sopenharmony_ci 319141cc406Sopenharmony_ci *pBuffer = _INB_DATA( ps ); 320141cc406Sopenharmony_ci 321141cc406Sopenharmony_ci _OUTB_CTRL( ps, end ); 322141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 323141cc406Sopenharmony_ci } 324141cc406Sopenharmony_ci break; 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci } 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT ); 329141cc406Sopenharmony_ci return _TRUE; 330141cc406Sopenharmony_ci} 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci/** as the name says, we switch to SPP mode 333141cc406Sopenharmony_ci */ 334141cc406Sopenharmony_cistatic void ioSwitchToSPPMode( pScanData ps ) 335141cc406Sopenharmony_ci{ 336141cc406Sopenharmony_ci /* save the control and data port value 337141cc406Sopenharmony_ci */ 338141cc406Sopenharmony_ci ps->IO.bOldControlValue = _INB_CTRL( ps ); 339141cc406Sopenharmony_ci ps->IO.bOldDataValue = _INB_DATA( ps ); 340141cc406Sopenharmony_ci 341141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); /* 0xc4 */ 342141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 343141cc406Sopenharmony_ci} 344141cc406Sopenharmony_ci 345141cc406Sopenharmony_ci/** restore the port settings 346141cc406Sopenharmony_ci */ 347141cc406Sopenharmony_cistatic void ioRestoreParallelMode( pScanData ps ) 348141cc406Sopenharmony_ci{ 349141cc406Sopenharmony_ci _OUTB_CTRL( ps, ps->IO.bOldControlValue & 0x3f ); 350141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci _OUTB_DATA( ps, ps->IO.bOldDataValue ); 353141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 354141cc406Sopenharmony_ci} 355141cc406Sopenharmony_ci 356141cc406Sopenharmony_ci/** try to connect to scanner (ASIC 9600x and 98001) 357141cc406Sopenharmony_ci */ 358141cc406Sopenharmony_ci_LOC void ioP98001EstablishScannerConnection( pScanData ps, ULong delTime ) 359141cc406Sopenharmony_ci{ 360141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID_TO_PRINTER ); 361141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID1ST ); 364141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID2ND ); 367141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID3RD ); 370141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID4TH ); 373141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 374141cc406Sopenharmony_ci} 375141cc406Sopenharmony_ci 376141cc406Sopenharmony_ci/** try to connect to scanner (ASIC 98003) 377141cc406Sopenharmony_ci */ 378141cc406Sopenharmony_cistatic void ioP98003EstablishScannerConnection( pScanData ps, ULong delTime ) 379141cc406Sopenharmony_ci{ 380141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID1ST ); 381141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID2ND ); 384141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID3RD ); 387141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 388141cc406Sopenharmony_ci 389141cc406Sopenharmony_ci _OUTB_DATA( ps, _ID4TH ); 390141cc406Sopenharmony_ci _DO_UDELAY( delTime ); 391141cc406Sopenharmony_ci} 392141cc406Sopenharmony_ci 393141cc406Sopenharmony_ci/** switch the printer interface to scanner 394141cc406Sopenharmony_ci */ 395141cc406Sopenharmony_cistatic Bool ioP96OpenScanPath( pScanData ps ) 396141cc406Sopenharmony_ci{ 397141cc406Sopenharmony_ci if( 0 == ps->IO.bOpenCount ) { 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci /* not established */ 400141cc406Sopenharmony_ci ioSwitchToSPPMode( ps ); 401141cc406Sopenharmony_ci 402141cc406Sopenharmony_ci /* Scanner command sequence to open scanner path */ 403141cc406Sopenharmony_ci ioP98001EstablishScannerConnection( ps, 5 ); 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci#ifdef DEBUG 406141cc406Sopenharmony_ci else 407141cc406Sopenharmony_ci DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount ); 408141cc406Sopenharmony_ci#endif 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_ci ps->IO.bOpenCount++; /* increment the opened count */ 411141cc406Sopenharmony_ci 412141cc406Sopenharmony_ci/* 413141cc406Sopenharmony_ci * CHECK to we really need that !! 414141cc406Sopenharmony_ci */ 415141cc406Sopenharmony_ci ps->IO.useEPPCmdMode = _FALSE; 416141cc406Sopenharmony_ci return _TRUE; 417141cc406Sopenharmony_ci} 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci/** try to connect to scanner 420141cc406Sopenharmony_ci */ 421141cc406Sopenharmony_cistatic Bool ioP98OpenScanPath( pScanData ps ) 422141cc406Sopenharmony_ci{ 423141cc406Sopenharmony_ci Byte tmp; 424141cc406Sopenharmony_ci ULong dw; 425141cc406Sopenharmony_ci ULong dwTime = 1; 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_ci if( 0 == ps->IO.bOpenCount ) { 428141cc406Sopenharmony_ci 429141cc406Sopenharmony_ci /* not established */ 430141cc406Sopenharmony_ci ioSwitchToSPPMode( ps ); 431141cc406Sopenharmony_ci 432141cc406Sopenharmony_ci for( dw = 10; dw; dw-- ) { 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci /* 435141cc406Sopenharmony_ci * this seems to be necessary... 436141cc406Sopenharmony_ci */ 437141cc406Sopenharmony_ci if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { 438141cc406Sopenharmony_ci ioP98001EstablishScannerConnection( ps, dw ); 439141cc406Sopenharmony_ci#if 0 440141cc406Sopenharmony_ci ioP98001EstablishScannerConnection( ps, dw ); 441141cc406Sopenharmony_ci ioP98001EstablishScannerConnection( ps, dw ); 442141cc406Sopenharmony_ci#endif 443141cc406Sopenharmony_ci } else { 444141cc406Sopenharmony_ci ioP98003EstablishScannerConnection( ps, dw ); 445141cc406Sopenharmony_ci } 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci _INB_STATUS( ps ); 448141cc406Sopenharmony_ci tmp = _INB_STATUS( ps ); 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci if( 0x50 == ( tmp & 0xf0 )) { 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci ps->IO.bOpenCount = 1; 453141cc406Sopenharmony_ci 454141cc406Sopenharmony_ci if( ps->sCaps.AsicID == IODataFromRegister(ps, ps->RegAsicID)) { 455141cc406Sopenharmony_ci return _TRUE; 456141cc406Sopenharmony_ci } 457141cc406Sopenharmony_ci ps->IO.bOpenCount = 0; 458141cc406Sopenharmony_ci } 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci dwTime++; 461141cc406Sopenharmony_ci } 462141cc406Sopenharmony_ci DBG( DBG_IO, "ioP98OpenScanPath() failed!\n" ); 463141cc406Sopenharmony_ci return _FALSE; 464141cc406Sopenharmony_ci } 465141cc406Sopenharmony_ci#ifdef DEBUG 466141cc406Sopenharmony_ci else 467141cc406Sopenharmony_ci DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount ); 468141cc406Sopenharmony_ci#endif 469141cc406Sopenharmony_ci 470141cc406Sopenharmony_ci ps->IO.bOpenCount++; /* increment the opened count */ 471141cc406Sopenharmony_ci return _TRUE; 472141cc406Sopenharmony_ci} 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci/** Switch back to printer mode. 475141cc406Sopenharmony_ci * Restore the printer control/data port value. 476141cc406Sopenharmony_ci */ 477141cc406Sopenharmony_cistatic void ioCloseScanPath( pScanData ps ) 478141cc406Sopenharmony_ci{ 479141cc406Sopenharmony_ci if( ps->IO.bOpenCount && !(--ps->IO.bOpenCount)) { 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_ci#ifdef DEBUG 482141cc406Sopenharmony_ci ps->IO.bOpenCount = 1; 483141cc406Sopenharmony_ci#endif 484141cc406Sopenharmony_ci IORegisterToScanner( ps, 0xff ); 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_ci /* 487141cc406Sopenharmony_ci * back to pass-through printer mode 488141cc406Sopenharmony_ci */ 489141cc406Sopenharmony_ci IORegisterToScanner( ps, ps->RegSwitchBus ); 490141cc406Sopenharmony_ci#ifdef DEBUG 491141cc406Sopenharmony_ci ps->IO.bOpenCount = 0; 492141cc406Sopenharmony_ci#endif 493141cc406Sopenharmony_ci ps->IO.useEPPCmdMode = _FALSE; 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci ioRestoreParallelMode( ps ); 496141cc406Sopenharmony_ci } 497141cc406Sopenharmony_ci} 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci/** check the memory to see that the data-transfers will work. 500141cc406Sopenharmony_ci * (ASIC 9800x only) 501141cc406Sopenharmony_ci */ 502141cc406Sopenharmony_cistatic int ioP98ReadWriteTest( pScanData ps ) 503141cc406Sopenharmony_ci{ 504141cc406Sopenharmony_ci UChar tmp; 505141cc406Sopenharmony_ci ULong ul; 506141cc406Sopenharmony_ci pUChar buffer; 507141cc406Sopenharmony_ci int retval; 508141cc406Sopenharmony_ci 509141cc406Sopenharmony_ci DBG( DBG_LOW, "ioP98ReadWriteTest()\n" ); 510141cc406Sopenharmony_ci 511141cc406Sopenharmony_ci /* _MEMTEST_SIZE: Read, _MEMTEST_SIZE:Write */ 512141cc406Sopenharmony_ci buffer = _KALLOC( sizeof(UChar) * _MEMTEST_SIZE*2, GFP_KERNEL ); 513141cc406Sopenharmony_ci if( NULL == buffer ) 514141cc406Sopenharmony_ci return _E_ALLOC; 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci /* prepare content */ 517141cc406Sopenharmony_ci for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) 518141cc406Sopenharmony_ci buffer[ul] = (UChar)ul; 519141cc406Sopenharmony_ci 520141cc406Sopenharmony_ci ps->OpenScanPath(ps); 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci /* avoid switching to Lamp0, when previously scanned in transp./neg mode */ 523141cc406Sopenharmony_ci tmp = ps->bLastLampStatus + _SCAN_BYTEMODE; 524141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegScanControl, tmp ); 525141cc406Sopenharmony_ci 526141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegModelControl, (_LED_ACTIVITY | _LED_CONTROL)); 527141cc406Sopenharmony_ci 528141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem ); 529141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegMemoryLow, 0 ); 530141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegMemoryHigh, 0 ); 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci /* fill to buffer */ 533141cc406Sopenharmony_ci IOMoveDataToScanner( ps, buffer, _MEMTEST_SIZE ); 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem ); 536141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegMemoryLow, 0 ); 537141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegMemoryHigh, 0 ); 538141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegWidthPixelsLow, 0 ); 539141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegWidthPixelsHigh, 5 ); 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_ci ps->AsicReg.RD_ModeControl = _ModeReadMappingMem; 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci if( _ASIC_IS_98001 == ps->sCaps.AsicID ) 544141cc406Sopenharmony_ci ps->CloseScanPath( ps ); 545141cc406Sopenharmony_ci 546141cc406Sopenharmony_ci IOReadScannerImageData( ps, buffer + _MEMTEST_SIZE, _MEMTEST_SIZE ); 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci if( _ASIC_IS_98003 == ps->sCaps.AsicID ) 549141cc406Sopenharmony_ci ps->CloseScanPath( ps ); 550141cc406Sopenharmony_ci 551141cc406Sopenharmony_ci /* check the result ! */ 552141cc406Sopenharmony_ci retval = _OK; 553141cc406Sopenharmony_ci 554141cc406Sopenharmony_ci for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) { 555141cc406Sopenharmony_ci if( buffer[ul] != buffer[ul+_MEMTEST_SIZE] ) { 556141cc406Sopenharmony_ci DBG( DBG_HIGH, "Error in memory test at pos %u (%u != %u)\n", 557141cc406Sopenharmony_ci ul, buffer[ul], buffer[ul+_MEMTEST_SIZE] ); 558141cc406Sopenharmony_ci retval = _E_NO_DEV; 559141cc406Sopenharmony_ci break; 560141cc406Sopenharmony_ci } 561141cc406Sopenharmony_ci } 562141cc406Sopenharmony_ci 563141cc406Sopenharmony_ci _KFREE(buffer); 564141cc406Sopenharmony_ci return retval; 565141cc406Sopenharmony_ci} 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci/** Put data to DATA port and trigger hardware through CONTROL port to read it. 568141cc406Sopenharmony_ci */ 569141cc406Sopenharmony_cistatic void ioSPPWrite( pScanData ps, pUChar pBuffer, ULong size ) 570141cc406Sopenharmony_ci{ 571141cc406Sopenharmony_ci DBG( DBG_IO , "Moving %u bytes to scanner, IODELAY = %u...\n", 572141cc406Sopenharmony_ci size, ps->IO.delay ); 573141cc406Sopenharmony_ci switch( ps->IO.delay ) { 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci case 0: 576141cc406Sopenharmony_ci for (; size; size--, pBuffer++) { 577141cc406Sopenharmony_ci _OUTB_DATA( ps, *pBuffer ); 578141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 579141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 580141cc406Sopenharmony_ci } 581141cc406Sopenharmony_ci break; 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci case 1: 584141cc406Sopenharmony_ci case 2: 585141cc406Sopenharmony_ci for (; size; size--, pBuffer++) { 586141cc406Sopenharmony_ci _OUTB_DATA( ps, *pBuffer ); 587141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 588141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 589141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 590141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 591141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 592141cc406Sopenharmony_ci } 593141cc406Sopenharmony_ci break; 594141cc406Sopenharmony_ci 595141cc406Sopenharmony_ci default: 596141cc406Sopenharmony_ci for (; size; size--, pBuffer++) { 597141cc406Sopenharmony_ci _OUTB_DATA( ps, *pBuffer ); 598141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 599141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 600141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 601141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 602141cc406Sopenharmony_ci _DO_UDELAY( 3 ); 603141cc406Sopenharmony_ci } 604141cc406Sopenharmony_ci break; 605141cc406Sopenharmony_ci } 606141cc406Sopenharmony_ci DBG( DBG_IO , "... done.\n" ); 607141cc406Sopenharmony_ci} 608141cc406Sopenharmony_ci 609141cc406Sopenharmony_ci/** set the scanner to "read" data mode 610141cc406Sopenharmony_ci */ 611141cc406Sopenharmony_cistatic void ioEnterReadMode( pScanData ps ) 612141cc406Sopenharmony_ci{ 613141cc406Sopenharmony_ci if( ps->IO.portMode != _PORT_SPP ) { 614141cc406Sopenharmony_ci 615141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 616141cc406Sopenharmony_ci IORegisterToScanner( ps, ps->RegEPPEnable ); 617141cc406Sopenharmony_ci 618141cc406Sopenharmony_ci if( _IS_ASIC98( ps->sCaps.AsicID )) 619141cc406Sopenharmony_ci ps->IO.useEPPCmdMode = _TRUE; 620141cc406Sopenharmony_ci } 621141cc406Sopenharmony_ci 622141cc406Sopenharmony_ci if( _ASIC_IS_98003 == ps->sCaps.AsicID ) 623141cc406Sopenharmony_ci ps->IO.bOldControlValue = _INB_CTRL( ps ); 624141cc406Sopenharmony_ci 625141cc406Sopenharmony_ci /* ask ASIC to enter read mode */ 626141cc406Sopenharmony_ci IORegisterToScanner( ps, ps->RegReadDataMode ); 627141cc406Sopenharmony_ci} 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci/************************ exported functions *********************************/ 630141cc406Sopenharmony_ci 631141cc406Sopenharmony_ci/** here we do some init work 632141cc406Sopenharmony_ci */ 633141cc406Sopenharmony_ci_LOC int IOInitialize( pScanData ps ) 634141cc406Sopenharmony_ci{ 635141cc406Sopenharmony_ci DBG( DBG_HIGH, "IOInitialize()\n" ); 636141cc406Sopenharmony_ci 637141cc406Sopenharmony_ci if( NULL == ps ) 638141cc406Sopenharmony_ci return _E_NULLPTR; 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci if( _IS_ASIC98(ps->sCaps.AsicID)) { 641141cc406Sopenharmony_ci 642141cc406Sopenharmony_ci ps->OpenScanPath = ioP98OpenScanPath; 643141cc406Sopenharmony_ci ps->ReadWriteTest = ioP98ReadWriteTest; 644141cc406Sopenharmony_ci 645141cc406Sopenharmony_ci } else if( _IS_ASIC96(ps->sCaps.AsicID)) { 646141cc406Sopenharmony_ci 647141cc406Sopenharmony_ci ps->OpenScanPath = ioP96OpenScanPath; 648141cc406Sopenharmony_ci 649141cc406Sopenharmony_ci } else { 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); 652141cc406Sopenharmony_ci return _E_NOSUPP; 653141cc406Sopenharmony_ci } 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci ps->CloseScanPath = ioCloseScanPath; 656141cc406Sopenharmony_ci ps->Device.ReadData = ioReadFunc[ps->IO.portMode].func; 657141cc406Sopenharmony_ci DBG( DBG_HIGH, "* using readfunction >%s<\n", 658141cc406Sopenharmony_ci ioReadFunc[ps->IO.portMode].name ); 659141cc406Sopenharmony_ci return _OK; 660141cc406Sopenharmony_ci} 661141cc406Sopenharmony_ci 662141cc406Sopenharmony_ci/** Write specific length buffer to scanner 663141cc406Sopenharmony_ci * The scan path is already established 664141cc406Sopenharmony_ci */ 665141cc406Sopenharmony_ci_LOC void IOMoveDataToScanner( pScanData ps, pUChar pBuffer, ULong size ) 666141cc406Sopenharmony_ci{ 667141cc406Sopenharmony_ci#ifdef DEBUG 668141cc406Sopenharmony_ci if( 0 == ps->IO.bOpenCount ) 669141cc406Sopenharmony_ci DBG( DBG_IO, "IOMoveDataToScanner - no connection!\n" ); 670141cc406Sopenharmony_ci#endif 671141cc406Sopenharmony_ci 672141cc406Sopenharmony_ci IORegisterToScanner( ps, ps->RegInitDataFifo ); 673141cc406Sopenharmony_ci IORegisterToScanner( ps, ps->RegWriteDataMode ); 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_ci ioSPPWrite( ps, pBuffer, size ); 676141cc406Sopenharmony_ci} 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci/** Calling SITUATION: Scanner path is established. 679141cc406Sopenharmony_ci * download a scanstate-table 680141cc406Sopenharmony_ci */ 681141cc406Sopenharmony_ci_LOC void IODownloadScanStates( pScanData ps ) 682141cc406Sopenharmony_ci{ 683141cc406Sopenharmony_ci TimerDef timer; 684141cc406Sopenharmony_ci#ifdef DEBUG 685141cc406Sopenharmony_ci if( 0 == ps->IO.bOpenCount ) 686141cc406Sopenharmony_ci DBG( DBG_IO, "IODownloadScanStates - no connection!\n" ); 687141cc406Sopenharmony_ci#endif 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci IORegisterToScanner( ps, ps->RegScanStateControl ); 690141cc406Sopenharmony_ci 691141cc406Sopenharmony_ci ioSPPWrite( ps, ps->a_nbNewAdrPointer, _SCANSTATE_BYTES ); 692141cc406Sopenharmony_ci 693141cc406Sopenharmony_ci if( ps->Scan.fRefreshState ) { 694141cc406Sopenharmony_ci 695141cc406Sopenharmony_ci IORegisterToScanner( ps, ps->RegRefreshScanState ); 696141cc406Sopenharmony_ci 697141cc406Sopenharmony_ci MiscStartTimer( &timer, (_SECOND/2)); 698141cc406Sopenharmony_ci do { 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci if (!( IOGetScanState( ps, _TRUE) & _SCANSTATE_STOP)) 701141cc406Sopenharmony_ci break; 702141cc406Sopenharmony_ci } 703141cc406Sopenharmony_ci while( !MiscCheckTimer(&timer)); 704141cc406Sopenharmony_ci } 705141cc406Sopenharmony_ci} 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci/** Calling SITUATION: Scanner path is established. 708141cc406Sopenharmony_ci * Write a data to asic 709141cc406Sopenharmony_ci */ 710141cc406Sopenharmony_ci_LOC void IODataToScanner( pScanData ps, Byte bValue ) 711141cc406Sopenharmony_ci{ 712141cc406Sopenharmony_ci ULong deltime = 4; 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci#ifdef DEBUG 715141cc406Sopenharmony_ci if( 0 == ps->IO.bOpenCount ) 716141cc406Sopenharmony_ci DBG( DBG_IO, "IODataToScanner - no connection!\n" ); 717141cc406Sopenharmony_ci#endif 718141cc406Sopenharmony_ci 719141cc406Sopenharmony_ci if( ps->IO.delay < 2 ) 720141cc406Sopenharmony_ci deltime = 2; 721141cc406Sopenharmony_ci 722141cc406Sopenharmony_ci /* output data */ 723141cc406Sopenharmony_ci _OUTB_DATA( ps, bValue ); 724141cc406Sopenharmony_ci _DO_UDELAY( deltime ); 725141cc406Sopenharmony_ci 726141cc406Sopenharmony_ci /* notify asic there is data */ 727141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 728141cc406Sopenharmony_ci _DO_UDELAY( deltime ); 729141cc406Sopenharmony_ci 730141cc406Sopenharmony_ci /* end write cycle */ 731141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 732141cc406Sopenharmony_ci _DO_UDELAY( deltime-1 ); 733141cc406Sopenharmony_ci} 734141cc406Sopenharmony_ci 735141cc406Sopenharmony_ci/** Calling SITUATION: Scanner path is established. 736141cc406Sopenharmony_ci * Write a data to specific asic's register 737141cc406Sopenharmony_ci */ 738141cc406Sopenharmony_ci_LOC void IODataToRegister( pScanData ps, Byte bReg, Byte bData ) 739141cc406Sopenharmony_ci{ 740141cc406Sopenharmony_ci#ifdef DEBUG 741141cc406Sopenharmony_ci if( 0 == ps->IO.bOpenCount ) 742141cc406Sopenharmony_ci DBG( DBG_IO, "IODataToRegister - no connection!\n" ); 743141cc406Sopenharmony_ci#endif 744141cc406Sopenharmony_ci 745141cc406Sopenharmony_ci /* specify register */ 746141cc406Sopenharmony_ci IORegisterToScanner( ps, bReg ); 747141cc406Sopenharmony_ci 748141cc406Sopenharmony_ci /* then write the content */ 749141cc406Sopenharmony_ci IODataToScanner( ps, bData ); 750141cc406Sopenharmony_ci} 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_ci/** Calling SITUATION: Scanner path is established. 753141cc406Sopenharmony_ci * Read the content of specific asic's register 754141cc406Sopenharmony_ci */ 755141cc406Sopenharmony_ci_LOC Byte IODataFromRegister( pScanData ps, Byte bReg ) 756141cc406Sopenharmony_ci{ 757141cc406Sopenharmony_ci IORegisterToScanner( ps, bReg ); 758141cc406Sopenharmony_ci 759141cc406Sopenharmony_ci if( 0 == ps->IO.delay ) 760141cc406Sopenharmony_ci return ioDataFromSPPFast( ps ); 761141cc406Sopenharmony_ci else if( 1 == ps->IO.delay ) 762141cc406Sopenharmony_ci return ioDataFromSPPMiddle( ps ); 763141cc406Sopenharmony_ci else if( 2 == ps->IO.delay ) 764141cc406Sopenharmony_ci return ioDataFromSPPSlow( ps ); 765141cc406Sopenharmony_ci else 766141cc406Sopenharmony_ci return ioDataFromSPPSlowest( ps ); 767141cc406Sopenharmony_ci} 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci/** Calling SITUATION: Scanner path is established. 770141cc406Sopenharmony_ci * Write a register to asic (used for a command without parameter) 771141cc406Sopenharmony_ci */ 772141cc406Sopenharmony_ci_LOC void IORegisterToScanner( pScanData ps, Byte bReg ) 773141cc406Sopenharmony_ci{ 774141cc406Sopenharmony_ci#ifdef DEBUG 775141cc406Sopenharmony_ci if( 0 == ps->IO.bOpenCount ) 776141cc406Sopenharmony_ci DBG( DBG_IO, "IORegisterToScanner - no connection!\n" ); 777141cc406Sopenharmony_ci#endif 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci /* 780141cc406Sopenharmony_ci * write data to port 781141cc406Sopenharmony_ci */ 782141cc406Sopenharmony_ci _OUTB_DATA( ps, bReg ); 783141cc406Sopenharmony_ci 784141cc406Sopenharmony_ci /* 785141cc406Sopenharmony_ci * depending on the mode, generate the trigger signals 786141cc406Sopenharmony_ci */ 787141cc406Sopenharmony_ci if( ps->IO.useEPPCmdMode ) { 788141cc406Sopenharmony_ci 789141cc406Sopenharmony_ci _DO_UDELAY( 5 ); 790141cc406Sopenharmony_ci 791141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */ 792141cc406Sopenharmony_ci _DO_UDELAY( 5 ); 793141cc406Sopenharmony_ci 794141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_EPPTRIG_REGWRITE);/* 0xcd */ 795141cc406Sopenharmony_ci _DO_UDELAY( 5 ); 796141cc406Sopenharmony_ci 797141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */ 798141cc406Sopenharmony_ci _DO_UDELAY( 5 ); 799141cc406Sopenharmony_ci 800141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_END_REGWRITE); /* 0xc4 */ 801141cc406Sopenharmony_ci 802141cc406Sopenharmony_ci } else { 803141cc406Sopenharmony_ci if( ps->IO.delay < 2 ) { 804141cc406Sopenharmony_ci 805141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 806141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_START_REGWRITE); 807141cc406Sopenharmony_ci _DO_UDELAY( 1 ); 808141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_END_REGWRITE); 809141cc406Sopenharmony_ci } else { 810141cc406Sopenharmony_ci 811141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 812141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_START_REGWRITE); 813141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 814141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_END_REGWRITE); 815141cc406Sopenharmony_ci _DO_UDELAY( 2 ); 816141cc406Sopenharmony_ci } 817141cc406Sopenharmony_ci } 818141cc406Sopenharmony_ci} 819141cc406Sopenharmony_ci 820141cc406Sopenharmony_ci/** write data to the DAC - ASIC 98001/3 only 821141cc406Sopenharmony_ci */ 822141cc406Sopenharmony_ci_LOC void IODataRegisterToDAC( pScanData ps, Byte bReg, Byte bData ) 823141cc406Sopenharmony_ci{ 824141cc406Sopenharmony_ci ULong i; 825141cc406Sopenharmony_ci 826141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegADCAddress, bReg ); 827141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegADCData, bData ); 828141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegADCSerialOutStr, bData ); 829141cc406Sopenharmony_ci 830141cc406Sopenharmony_ci /* TEST: ORG was 1 ms for ASIC 98001 */ 831141cc406Sopenharmony_ci _DO_UDELAY( 12 ); 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci for( i = 4; i; i-- ) { 834141cc406Sopenharmony_ci 835141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 836141cc406Sopenharmony_ci _DO_UDELAY( 5 ); 837141cc406Sopenharmony_ci _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 838141cc406Sopenharmony_ci _DO_UDELAY( 12 ); 839141cc406Sopenharmony_ci } 840141cc406Sopenharmony_ci} 841141cc406Sopenharmony_ci 842141cc406Sopenharmony_ci/** Calling SITUATION: Scanner path was not established. 843141cc406Sopenharmony_ci * Read the content of specific asics' register 844141cc406Sopenharmony_ci */ 845141cc406Sopenharmony_ci_LOC Byte IODataRegisterFromScanner( pScanData ps, Byte bReg ) 846141cc406Sopenharmony_ci{ 847141cc406Sopenharmony_ci Byte bData; 848141cc406Sopenharmony_ci 849141cc406Sopenharmony_ci ps->OpenScanPath( ps ); 850141cc406Sopenharmony_ci bData = IODataFromRegister( ps, bReg ); 851141cc406Sopenharmony_ci ps->CloseScanPath( ps ); 852141cc406Sopenharmony_ci 853141cc406Sopenharmony_ci return bData; 854141cc406Sopenharmony_ci} 855141cc406Sopenharmony_ci 856141cc406Sopenharmony_ci/** Calling SITUATION: Scanner path not established. 857141cc406Sopenharmony_ci * Write a value of register to asic 858141cc406Sopenharmony_ci */ 859141cc406Sopenharmony_ci_LOC void IOCmdRegisterToScanner( pScanData ps, Byte bReg, Byte bData ) 860141cc406Sopenharmony_ci{ 861141cc406Sopenharmony_ci ps->OpenScanPath( ps ); 862141cc406Sopenharmony_ci IODataToRegister( ps, bReg, bData ); 863141cc406Sopenharmony_ci ps->CloseScanPath( ps ); 864141cc406Sopenharmony_ci} 865141cc406Sopenharmony_ci 866141cc406Sopenharmony_ci/** Calling SITUATION: Scanner path not established. 867141cc406Sopenharmony_ci * Write a register to asic (used for a command without parameter) 868141cc406Sopenharmony_ci */ 869141cc406Sopenharmony_ci_LOC void IORegisterDirectToScanner( pScanData ps, Byte bReg ) 870141cc406Sopenharmony_ci{ 871141cc406Sopenharmony_ci ps->OpenScanPath( ps ); /* establish the connection */ 872141cc406Sopenharmony_ci IORegisterToScanner( ps, bReg ); /* write register to asic */ 873141cc406Sopenharmony_ci ps->CloseScanPath( ps ); /* disconnect */ 874141cc406Sopenharmony_ci} 875141cc406Sopenharmony_ci 876141cc406Sopenharmony_ci/** perform a SW reset of ASIC 98003 models 877141cc406Sopenharmony_ci */ 878141cc406Sopenharmony_ci_LOC void IOSoftwareReset( pScanData ps ) 879141cc406Sopenharmony_ci{ 880141cc406Sopenharmony_ci if( _ASIC_IS_98003 != ps->sCaps.AsicID ) 881141cc406Sopenharmony_ci return; 882141cc406Sopenharmony_ci 883141cc406Sopenharmony_ci ps->OpenScanPath( ps ); 884141cc406Sopenharmony_ci 885141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegTestMode, _SW_TESTMODE ); 886141cc406Sopenharmony_ci 887141cc406Sopenharmony_ci ioSwitchToSPPMode( ps ); 888141cc406Sopenharmony_ci 889141cc406Sopenharmony_ci _OUTB_DATA( ps, _RESET1ST ); 890141cc406Sopenharmony_ci _DODELAY( 5 ); 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci _OUTB_DATA( ps, _RESET2ND ); 893141cc406Sopenharmony_ci _DODELAY( 5 ); 894141cc406Sopenharmony_ci 895141cc406Sopenharmony_ci _OUTB_DATA( ps, _RESET3RD ); 896141cc406Sopenharmony_ci _DODELAY( 5 ); 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci _OUTB_DATA( ps, _RESET4TH ); 899141cc406Sopenharmony_ci _DODELAY( 5 ); 900141cc406Sopenharmony_ci 901141cc406Sopenharmony_ci ioRestoreParallelMode( ps ); 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci /* reset test mode register */ 904141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegTestMode, 0 ); 905141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); 906141cc406Sopenharmony_ci 907141cc406Sopenharmony_ci ps->CloseScanPath( ps ); 908141cc406Sopenharmony_ci} 909141cc406Sopenharmony_ci 910141cc406Sopenharmony_ci/** Read specific length data from scanner and the method depends on the 911141cc406Sopenharmony_ci * mode defined in registry. 912141cc406Sopenharmony_ci */ 913141cc406Sopenharmony_ci_LOC void IOReadScannerImageData( pScanData ps, pUChar pBuf, ULong size ) 914141cc406Sopenharmony_ci{ 915141cc406Sopenharmony_ci if( _ASIC_IS_98003 != ps->sCaps.AsicID ) 916141cc406Sopenharmony_ci ps->OpenScanPath( ps); 917141cc406Sopenharmony_ci 918141cc406Sopenharmony_ci if( _IS_ASIC98( ps->sCaps.AsicID)) 919141cc406Sopenharmony_ci IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci /* enter read mode */ 922141cc406Sopenharmony_ci ioEnterReadMode( ps ); 923141cc406Sopenharmony_ci 924141cc406Sopenharmony_ci /* call corresponding read proc */ 925141cc406Sopenharmony_ci ps->Device.ReadData( ps, pBuf, size ); 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci /* Clear EPP/ECP read mode by simply close scanner path and re-open it */ 928141cc406Sopenharmony_ci ps->CloseScanPath( ps ); 929141cc406Sopenharmony_ci 930141cc406Sopenharmony_ci if( _ASIC_IS_98003 == ps->sCaps.AsicID ) 931141cc406Sopenharmony_ci ps->OpenScanPath( ps ); 932141cc406Sopenharmony_ci} 933141cc406Sopenharmony_ci 934141cc406Sopenharmony_ci/* END PLUSTEK-PP_IO.C ......................................................*/ 935