1/* @file plustekpp-io.c 2 * @brief as the name says, here we have all the I/O 3 * functions according to the parallel port hardware 4 * 5 * based on sources acquired from Plustek Inc. 6 * Copyright (C) 1998 Plustek Inc. 7 * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de> 8 * 9 * History: 10 * - 0.37 - initial version 11 * - added Kevins' suggestions 12 * - 0.38 - added Asic 98003 stuff and ioP98ReadWriteTest() 13 * - added IODataRegisterToDAC() 14 * - replaced function IOSPPWrite by IOMoveDataToScanner 15 * - modified ioP98OpenScanPath again and reuse V0.36 stuff again 16 * - added IO functions 17 * - 0.39 - added IO functions 18 * - added f97003 stuff from A3I code 19 * - 0.40 - no changes 20 * - 0.41 - no changes 21 * - 0.42 - changed include names 22 * - 0.43 - no changes 23 * - 0.44 - fix format string issues, as Long types default to int32_t 24 * now 25 * . 26 * <hr> 27 * This file is part of the SANE package. 28 * 29 * This program is free software; you can redistribute it and/or 30 * modify it under the terms of the GNU General Public License as 31 * published by the Free Software Foundation; either version 2 of the 32 * License, or (at your option) any later version. 33 * 34 * This program is distributed in the hope that it will be useful, but 35 * WITHOUT ANY WARRANTY; without even the implied warranty of 36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 37 * General Public License for more details. 38 * 39 * You should have received a copy of the GNU General Public License 40 * along with this program. If not, see <https://www.gnu.org/licenses/>. 41 * 42 * As a special exception, the authors of SANE give permission for 43 * additional uses of the libraries contained in this release of SANE. 44 * 45 * The exception is that, if you link a SANE library with other files 46 * to produce an executable, this does not by itself cause the 47 * resulting executable to be covered by the GNU General Public 48 * License. Your use of that executable is in no way restricted on 49 * account of linking the SANE library code into it. 50 * 51 * This exception does not, however, invalidate any other reasons why 52 * the executable file might be covered by the GNU General Public 53 * License. 54 * 55 * If you submit changes to SANE to the maintainers to be included in 56 * a subsequent release, you agree by submitting the changes that 57 * those changes may be distributed with this exception intact. 58 * 59 * If you write modifications of your own for SANE, it is your choice 60 * whether to permit this exception to apply to your modifications. 61 * If you do not wish that, delete this exception notice. 62 * <hr> 63 */ 64#include "plustek-pp_scan.h" 65 66/*************************** some prototypes *********************************/ 67 68static Bool fnEPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize ); 69static Bool fnSPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize ); 70static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize ); 71 72typedef struct { 73 pFnReadData func; 74 char *name; 75} ioReadFuncDef; 76 77static ioReadFuncDef ioReadFunc[3] = { 78 { fnEPPRead, "fnEPPRead" }, 79 { fnSPPRead, "fnSPPRead" }, 80 { fnBiDirRead, "fnBiDirRead" } 81}; 82 83/*************************** some definitions ********************************/ 84 85#define _MEMTEST_SIZE 1280 86 87/*************************** local functions *********************************/ 88 89/** we provide some functions to read data from SPP port according to 90 * the speed we have detected (ReadWriteTest!!) 91 */ 92static Byte ioDataFromSPPFast( pScanData ps ) 93{ 94 Byte bData, tmp; 95 96 /* notify asic we will read the high nibble data from status port */ 97 if( _FALSE == ps->f97003 ) { 98 _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); 99 _DO_UDELAY( 1 ); 100 } 101 102 /* read high nibble */ 103 bData = _INB_STATUS( ps ); 104 bData &= 0xf0; 105 106 _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); 107 _DO_UDELAY( 1 ); 108 109 /* read low nibble */ 110 tmp = _INB_STATUS( ps ); 111 112 /* combine with low nibble */ 113 bData |= (tmp >> 4); 114 115 _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); 116 _DO_UDELAY( 1 ); 117 118 return bData; 119} 120 121static Byte ioDataFromSPPMiddle( pScanData ps ) 122{ 123 Byte bData, tmp; 124 125 /* notify asic we will read the high nibble data from status port */ 126 if( _FALSE == ps->f97003 ) { 127 _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); 128 _DO_UDELAY( 1 ); 129 } 130 131 /* read high nibble */ 132 _INB_STATUS( ps ); 133 bData = _INB_STATUS( ps ); 134 bData &= 0xf0; 135 136 _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); 137 _DO_UDELAY( 1 ); 138 139 /* read low nibble */ 140 _INB_STATUS( ps ); 141 tmp = _INB_STATUS( ps ); 142 143 /* combine with low nibble */ 144 bData |= (tmp >> 4); 145 146 _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); 147 _DO_UDELAY( 1 ); 148 149 return bData; 150} 151 152static UChar ioDataFromSPPSlow( pScanData ps ) 153{ 154 Byte bData, tmp; 155 156 /* notify asic we will read the high nibble data from status port */ 157 if( _FALSE == ps->f97003 ) { 158 _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); 159 _DO_UDELAY( 2 ); 160 } 161 162 /* read high nibble */ 163 _INB_STATUS( ps ); 164 _INB_STATUS( ps ); 165 bData = _INB_STATUS( ps ); 166 bData &= 0xf0; 167 168 _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); 169 _DO_UDELAY( 2 ); 170 171 /* read low nibble */ 172 _INB_STATUS( ps ); 173 _INB_STATUS( ps ); 174 tmp = _INB_STATUS( ps ); 175 176 /* combine with low nibble */ 177 bData |= (tmp >> 4); 178 179 _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); 180 _DO_UDELAY( 2 ); 181 182 return bData; 183} 184 185static UChar ioDataFromSPPSlowest( pScanData ps ) 186{ 187 Byte bData, tmp; 188 189 /* notify asic we will read the high nibble data from status port */ 190 if( _FALSE == ps->f97003 ) { 191 _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); 192 _DO_UDELAY( 3 ); 193 } 194 195 /* read high nibble */ 196 _INB_STATUS( ps ); 197 _INB_STATUS( ps ); 198 _INB_STATUS( ps ); 199 bData = _INB_STATUS( ps ); 200 bData &= 0xf0; 201 202 _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); 203 _DO_UDELAY( 3 ); 204 205 /* read low nibble */ 206 _INB_STATUS( ps ); 207 _INB_STATUS( ps ); 208 _INB_STATUS( ps ); 209 tmp = _INB_STATUS( ps ); 210 211 /* combine with low nibble */ 212 bData |= (tmp >> 4); 213 214 _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); 215 _DO_UDELAY( 3 ); 216 217 return bData; 218} 219 220/** Read data from STATUS port. We have to read twice and combine two nibble 221 * data to one byte. 222 */ 223static Bool fnSPPRead( pScanData ps, pUChar pBuffer, ULong ulSize ) 224{ 225 switch( ps->IO.delay ) { 226 227 case 0: 228 for (; ulSize; ulSize--, pBuffer++) 229 *pBuffer = ioDataFromSPPFast( ps ); 230 break; 231 232 case 1: 233 for (; ulSize; ulSize--, pBuffer++) 234 *pBuffer = ioDataFromSPPMiddle( ps ); 235 break; 236 237 case 2: 238 for (; ulSize; ulSize--, pBuffer++) 239 *pBuffer = ioDataFromSPPSlow( ps ); 240 break; 241 242 default: 243 for (; ulSize; ulSize--, pBuffer++) 244 *pBuffer = ioDataFromSPPSlowest( ps ); 245 break; 246 } 247 248 return _TRUE; 249} 250 251 252/** Using buffered I/O to read data from EPP Data Port 253 */ 254static Bool fnEPPRead( pScanData ps, pUChar pBuffer, ULong ulSize ) 255{ 256 register ULong i; 257 258 if( _IS_ASIC98(ps->sCaps.AsicID)) { 259 260 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN ); 261 for( i = 0; i < ulSize; i++ ) 262 pBuffer[i] = _INB_EPPDATA( ps ); 263 264 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT ); 265 } else { 266 267 for( i = 0; i < ulSize; i++ ) 268 pBuffer[i] = _INB_EPPDATA( ps ); 269 } 270 271 return _TRUE; 272} 273 274/** 275 */ 276static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize ) 277{ 278 UChar start, end; 279 280 start = _CTRL_START_BIDIREAD; 281 end = _CTRL_END_BIDIREAD; 282 283 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN ); 284 285 if( !sanei_pp_uses_directio()) { 286 start &= ~_CTRL_DIRECTION; 287 end &= ~_CTRL_DIRECTION; 288 } 289 290 switch( ps->IO.delay ) { 291 292 case 0: 293 for( ; ulSize; ulSize--, pBuffer++ ) { 294 _OUTB_CTRL( ps, start ); 295 *pBuffer = _INB_DATA( ps ); 296 _OUTB_CTRL( ps, end ); 297 } 298 break; 299 300 case 1: 301 _DO_UDELAY( 1 ); 302 for(; ulSize; ulSize--, pBuffer++ ) { 303 _OUTB_CTRL( ps, start ); 304 _DO_UDELAY( 1 ); 305 306 *pBuffer = _INB_DATA( ps ); 307 308 _OUTB_CTRL( ps, end ); 309 _DO_UDELAY( 1 ); 310 } 311 break; 312 313 default: 314 _DO_UDELAY( 2 ); 315 for(; ulSize; ulSize--, pBuffer++ ) { 316 _OUTB_CTRL( ps, start ); 317 _DO_UDELAY( 2 ); 318 319 *pBuffer = _INB_DATA( ps ); 320 321 _OUTB_CTRL( ps, end ); 322 _DO_UDELAY( 2 ); 323 } 324 break; 325 326 } 327 328 sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT ); 329 return _TRUE; 330} 331 332/** as the name says, we switch to SPP mode 333 */ 334static void ioSwitchToSPPMode( pScanData ps ) 335{ 336 /* save the control and data port value 337 */ 338 ps->IO.bOldControlValue = _INB_CTRL( ps ); 339 ps->IO.bOldDataValue = _INB_DATA( ps ); 340 341 _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); /* 0xc4 */ 342 _DO_UDELAY( 2 ); 343} 344 345/** restore the port settings 346 */ 347static void ioRestoreParallelMode( pScanData ps ) 348{ 349 _OUTB_CTRL( ps, ps->IO.bOldControlValue & 0x3f ); 350 _DO_UDELAY( 1 ); 351 352 _OUTB_DATA( ps, ps->IO.bOldDataValue ); 353 _DO_UDELAY( 1 ); 354} 355 356/** try to connect to scanner (ASIC 9600x and 98001) 357 */ 358_LOC void ioP98001EstablishScannerConnection( pScanData ps, ULong delTime ) 359{ 360 _OUTB_DATA( ps, _ID_TO_PRINTER ); 361 _DO_UDELAY( delTime ); 362 363 _OUTB_DATA( ps, _ID1ST ); 364 _DO_UDELAY( delTime ); 365 366 _OUTB_DATA( ps, _ID2ND ); 367 _DO_UDELAY( delTime ); 368 369 _OUTB_DATA( ps, _ID3RD ); 370 _DO_UDELAY( delTime ); 371 372 _OUTB_DATA( ps, _ID4TH ); 373 _DO_UDELAY( delTime ); 374} 375 376/** try to connect to scanner (ASIC 98003) 377 */ 378static void ioP98003EstablishScannerConnection( pScanData ps, ULong delTime ) 379{ 380 _OUTB_DATA( ps, _ID1ST ); 381 _DO_UDELAY( delTime ); 382 383 _OUTB_DATA( ps, _ID2ND ); 384 _DO_UDELAY( delTime ); 385 386 _OUTB_DATA( ps, _ID3RD ); 387 _DO_UDELAY( delTime ); 388 389 _OUTB_DATA( ps, _ID4TH ); 390 _DO_UDELAY( delTime ); 391} 392 393/** switch the printer interface to scanner 394 */ 395static Bool ioP96OpenScanPath( pScanData ps ) 396{ 397 if( 0 == ps->IO.bOpenCount ) { 398 399 /* not established */ 400 ioSwitchToSPPMode( ps ); 401 402 /* Scanner command sequence to open scanner path */ 403 ioP98001EstablishScannerConnection( ps, 5 ); 404 } 405#ifdef DEBUG 406 else 407 DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount ); 408#endif 409 410 ps->IO.bOpenCount++; /* increment the opened count */ 411 412/* 413 * CHECK to we really need that !! 414 */ 415 ps->IO.useEPPCmdMode = _FALSE; 416 return _TRUE; 417} 418 419/** try to connect to scanner 420 */ 421static Bool ioP98OpenScanPath( pScanData ps ) 422{ 423 Byte tmp; 424 ULong dw; 425 ULong dwTime = 1; 426 427 if( 0 == ps->IO.bOpenCount ) { 428 429 /* not established */ 430 ioSwitchToSPPMode( ps ); 431 432 for( dw = 10; dw; dw-- ) { 433 434 /* 435 * this seems to be necessary... 436 */ 437 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { 438 ioP98001EstablishScannerConnection( ps, dw ); 439#if 0 440 ioP98001EstablishScannerConnection( ps, dw ); 441 ioP98001EstablishScannerConnection( ps, dw ); 442#endif 443 } else { 444 ioP98003EstablishScannerConnection( ps, dw ); 445 } 446 447 _INB_STATUS( ps ); 448 tmp = _INB_STATUS( ps ); 449 450 if( 0x50 == ( tmp & 0xf0 )) { 451 452 ps->IO.bOpenCount = 1; 453 454 if( ps->sCaps.AsicID == IODataFromRegister(ps, ps->RegAsicID)) { 455 return _TRUE; 456 } 457 ps->IO.bOpenCount = 0; 458 } 459 460 dwTime++; 461 } 462 DBG( DBG_IO, "ioP98OpenScanPath() failed!\n" ); 463 return _FALSE; 464 } 465#ifdef DEBUG 466 else 467 DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount ); 468#endif 469 470 ps->IO.bOpenCount++; /* increment the opened count */ 471 return _TRUE; 472} 473 474/** Switch back to printer mode. 475 * Restore the printer control/data port value. 476 */ 477static void ioCloseScanPath( pScanData ps ) 478{ 479 if( ps->IO.bOpenCount && !(--ps->IO.bOpenCount)) { 480 481#ifdef DEBUG 482 ps->IO.bOpenCount = 1; 483#endif 484 IORegisterToScanner( ps, 0xff ); 485 486 /* 487 * back to pass-through printer mode 488 */ 489 IORegisterToScanner( ps, ps->RegSwitchBus ); 490#ifdef DEBUG 491 ps->IO.bOpenCount = 0; 492#endif 493 ps->IO.useEPPCmdMode = _FALSE; 494 495 ioRestoreParallelMode( ps ); 496 } 497} 498 499/** check the memory to see that the data-transfers will work. 500 * (ASIC 9800x only) 501 */ 502static int ioP98ReadWriteTest( pScanData ps ) 503{ 504 UChar tmp; 505 ULong ul; 506 pUChar buffer; 507 int retval; 508 509 DBG( DBG_LOW, "ioP98ReadWriteTest()\n" ); 510 511 /* _MEMTEST_SIZE: Read, _MEMTEST_SIZE:Write */ 512 buffer = _KALLOC( sizeof(UChar) * _MEMTEST_SIZE*2, GFP_KERNEL ); 513 if( NULL == buffer ) 514 return _E_ALLOC; 515 516 /* prepare content */ 517 for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) 518 buffer[ul] = (UChar)ul; 519 520 ps->OpenScanPath(ps); 521 522 /* avoid switching to Lamp0, when previously scanned in transp./neg mode */ 523 tmp = ps->bLastLampStatus + _SCAN_BYTEMODE; 524 IODataToRegister( ps, ps->RegScanControl, tmp ); 525 526 IODataToRegister( ps, ps->RegModelControl, (_LED_ACTIVITY | _LED_CONTROL)); 527 528 IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem ); 529 IODataToRegister( ps, ps->RegMemoryLow, 0 ); 530 IODataToRegister( ps, ps->RegMemoryHigh, 0 ); 531 532 /* fill to buffer */ 533 IOMoveDataToScanner( ps, buffer, _MEMTEST_SIZE ); 534 535 IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem ); 536 IODataToRegister( ps, ps->RegMemoryLow, 0 ); 537 IODataToRegister( ps, ps->RegMemoryHigh, 0 ); 538 IODataToRegister( ps, ps->RegWidthPixelsLow, 0 ); 539 IODataToRegister( ps, ps->RegWidthPixelsHigh, 5 ); 540 541 ps->AsicReg.RD_ModeControl = _ModeReadMappingMem; 542 543 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) 544 ps->CloseScanPath( ps ); 545 546 IOReadScannerImageData( ps, buffer + _MEMTEST_SIZE, _MEMTEST_SIZE ); 547 548 if( _ASIC_IS_98003 == ps->sCaps.AsicID ) 549 ps->CloseScanPath( ps ); 550 551 /* check the result ! */ 552 retval = _OK; 553 554 for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) { 555 if( buffer[ul] != buffer[ul+_MEMTEST_SIZE] ) { 556 DBG( DBG_HIGH, "Error in memory test at pos %u (%u != %u)\n", 557 ul, buffer[ul], buffer[ul+_MEMTEST_SIZE] ); 558 retval = _E_NO_DEV; 559 break; 560 } 561 } 562 563 _KFREE(buffer); 564 return retval; 565} 566 567/** Put data to DATA port and trigger hardware through CONTROL port to read it. 568 */ 569static void ioSPPWrite( pScanData ps, pUChar pBuffer, ULong size ) 570{ 571 DBG( DBG_IO , "Moving %u bytes to scanner, IODELAY = %u...\n", 572 size, ps->IO.delay ); 573 switch( ps->IO.delay ) { 574 575 case 0: 576 for (; size; size--, pBuffer++) { 577 _OUTB_DATA( ps, *pBuffer ); 578 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 579 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 580 } 581 break; 582 583 case 1: 584 case 2: 585 for (; size; size--, pBuffer++) { 586 _OUTB_DATA( ps, *pBuffer ); 587 _DO_UDELAY( 1 ); 588 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 589 _DO_UDELAY( 1 ); 590 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 591 _DO_UDELAY( 2 ); 592 } 593 break; 594 595 default: 596 for (; size; size--, pBuffer++) { 597 _OUTB_DATA( ps, *pBuffer ); 598 _DO_UDELAY( 1 ); 599 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 600 _DO_UDELAY( 2 ); 601 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 602 _DO_UDELAY( 3 ); 603 } 604 break; 605 } 606 DBG( DBG_IO , "... done.\n" ); 607} 608 609/** set the scanner to "read" data mode 610 */ 611static void ioEnterReadMode( pScanData ps ) 612{ 613 if( ps->IO.portMode != _PORT_SPP ) { 614 615 _DO_UDELAY( 1 ); 616 IORegisterToScanner( ps, ps->RegEPPEnable ); 617 618 if( _IS_ASIC98( ps->sCaps.AsicID )) 619 ps->IO.useEPPCmdMode = _TRUE; 620 } 621 622 if( _ASIC_IS_98003 == ps->sCaps.AsicID ) 623 ps->IO.bOldControlValue = _INB_CTRL( ps ); 624 625 /* ask ASIC to enter read mode */ 626 IORegisterToScanner( ps, ps->RegReadDataMode ); 627} 628 629/************************ exported functions *********************************/ 630 631/** here we do some init work 632 */ 633_LOC int IOInitialize( pScanData ps ) 634{ 635 DBG( DBG_HIGH, "IOInitialize()\n" ); 636 637 if( NULL == ps ) 638 return _E_NULLPTR; 639 640 if( _IS_ASIC98(ps->sCaps.AsicID)) { 641 642 ps->OpenScanPath = ioP98OpenScanPath; 643 ps->ReadWriteTest = ioP98ReadWriteTest; 644 645 } else if( _IS_ASIC96(ps->sCaps.AsicID)) { 646 647 ps->OpenScanPath = ioP96OpenScanPath; 648 649 } else { 650 651 DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); 652 return _E_NOSUPP; 653 } 654 655 ps->CloseScanPath = ioCloseScanPath; 656 ps->Device.ReadData = ioReadFunc[ps->IO.portMode].func; 657 DBG( DBG_HIGH, "* using readfunction >%s<\n", 658 ioReadFunc[ps->IO.portMode].name ); 659 return _OK; 660} 661 662/** Write specific length buffer to scanner 663 * The scan path is already established 664 */ 665_LOC void IOMoveDataToScanner( pScanData ps, pUChar pBuffer, ULong size ) 666{ 667#ifdef DEBUG 668 if( 0 == ps->IO.bOpenCount ) 669 DBG( DBG_IO, "IOMoveDataToScanner - no connection!\n" ); 670#endif 671 672 IORegisterToScanner( ps, ps->RegInitDataFifo ); 673 IORegisterToScanner( ps, ps->RegWriteDataMode ); 674 675 ioSPPWrite( ps, pBuffer, size ); 676} 677 678/** Calling SITUATION: Scanner path is established. 679 * download a scanstate-table 680 */ 681_LOC void IODownloadScanStates( pScanData ps ) 682{ 683 TimerDef timer; 684#ifdef DEBUG 685 if( 0 == ps->IO.bOpenCount ) 686 DBG( DBG_IO, "IODownloadScanStates - no connection!\n" ); 687#endif 688 689 IORegisterToScanner( ps, ps->RegScanStateControl ); 690 691 ioSPPWrite( ps, ps->a_nbNewAdrPointer, _SCANSTATE_BYTES ); 692 693 if( ps->Scan.fRefreshState ) { 694 695 IORegisterToScanner( ps, ps->RegRefreshScanState ); 696 697 MiscStartTimer( &timer, (_SECOND/2)); 698 do { 699 700 if (!( IOGetScanState( ps, _TRUE) & _SCANSTATE_STOP)) 701 break; 702 } 703 while( !MiscCheckTimer(&timer)); 704 } 705} 706 707/** Calling SITUATION: Scanner path is established. 708 * Write a data to asic 709 */ 710_LOC void IODataToScanner( pScanData ps, Byte bValue ) 711{ 712 ULong deltime = 4; 713 714#ifdef DEBUG 715 if( 0 == ps->IO.bOpenCount ) 716 DBG( DBG_IO, "IODataToScanner - no connection!\n" ); 717#endif 718 719 if( ps->IO.delay < 2 ) 720 deltime = 2; 721 722 /* output data */ 723 _OUTB_DATA( ps, bValue ); 724 _DO_UDELAY( deltime ); 725 726 /* notify asic there is data */ 727 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 728 _DO_UDELAY( deltime ); 729 730 /* end write cycle */ 731 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 732 _DO_UDELAY( deltime-1 ); 733} 734 735/** Calling SITUATION: Scanner path is established. 736 * Write a data to specific asic's register 737 */ 738_LOC void IODataToRegister( pScanData ps, Byte bReg, Byte bData ) 739{ 740#ifdef DEBUG 741 if( 0 == ps->IO.bOpenCount ) 742 DBG( DBG_IO, "IODataToRegister - no connection!\n" ); 743#endif 744 745 /* specify register */ 746 IORegisterToScanner( ps, bReg ); 747 748 /* then write the content */ 749 IODataToScanner( ps, bData ); 750} 751 752/** Calling SITUATION: Scanner path is established. 753 * Read the content of specific asic's register 754 */ 755_LOC Byte IODataFromRegister( pScanData ps, Byte bReg ) 756{ 757 IORegisterToScanner( ps, bReg ); 758 759 if( 0 == ps->IO.delay ) 760 return ioDataFromSPPFast( ps ); 761 else if( 1 == ps->IO.delay ) 762 return ioDataFromSPPMiddle( ps ); 763 else if( 2 == ps->IO.delay ) 764 return ioDataFromSPPSlow( ps ); 765 else 766 return ioDataFromSPPSlowest( ps ); 767} 768 769/** Calling SITUATION: Scanner path is established. 770 * Write a register to asic (used for a command without parameter) 771 */ 772_LOC void IORegisterToScanner( pScanData ps, Byte bReg ) 773{ 774#ifdef DEBUG 775 if( 0 == ps->IO.bOpenCount ) 776 DBG( DBG_IO, "IORegisterToScanner - no connection!\n" ); 777#endif 778 779 /* 780 * write data to port 781 */ 782 _OUTB_DATA( ps, bReg ); 783 784 /* 785 * depending on the mode, generate the trigger signals 786 */ 787 if( ps->IO.useEPPCmdMode ) { 788 789 _DO_UDELAY( 5 ); 790 791 _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */ 792 _DO_UDELAY( 5 ); 793 794 _OUTB_CTRL( ps, _CTRL_EPPTRIG_REGWRITE);/* 0xcd */ 795 _DO_UDELAY( 5 ); 796 797 _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */ 798 _DO_UDELAY( 5 ); 799 800 _OUTB_CTRL( ps, _CTRL_END_REGWRITE); /* 0xc4 */ 801 802 } else { 803 if( ps->IO.delay < 2 ) { 804 805 _DO_UDELAY( 1 ); 806 _OUTB_CTRL( ps, _CTRL_START_REGWRITE); 807 _DO_UDELAY( 1 ); 808 _OUTB_CTRL( ps, _CTRL_END_REGWRITE); 809 } else { 810 811 _DO_UDELAY( 2 ); 812 _OUTB_CTRL( ps, _CTRL_START_REGWRITE); 813 _DO_UDELAY( 2 ); 814 _OUTB_CTRL( ps, _CTRL_END_REGWRITE); 815 _DO_UDELAY( 2 ); 816 } 817 } 818} 819 820/** write data to the DAC - ASIC 98001/3 only 821 */ 822_LOC void IODataRegisterToDAC( pScanData ps, Byte bReg, Byte bData ) 823{ 824 ULong i; 825 826 IODataToRegister( ps, ps->RegADCAddress, bReg ); 827 IODataToRegister( ps, ps->RegADCData, bData ); 828 IODataToRegister( ps, ps->RegADCSerialOutStr, bData ); 829 830 /* TEST: ORG was 1 ms for ASIC 98001 */ 831 _DO_UDELAY( 12 ); 832 833 for( i = 4; i; i-- ) { 834 835 _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); 836 _DO_UDELAY( 5 ); 837 _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); 838 _DO_UDELAY( 12 ); 839 } 840} 841 842/** Calling SITUATION: Scanner path was not established. 843 * Read the content of specific asics' register 844 */ 845_LOC Byte IODataRegisterFromScanner( pScanData ps, Byte bReg ) 846{ 847 Byte bData; 848 849 ps->OpenScanPath( ps ); 850 bData = IODataFromRegister( ps, bReg ); 851 ps->CloseScanPath( ps ); 852 853 return bData; 854} 855 856/** Calling SITUATION: Scanner path not established. 857 * Write a value of register to asic 858 */ 859_LOC void IOCmdRegisterToScanner( pScanData ps, Byte bReg, Byte bData ) 860{ 861 ps->OpenScanPath( ps ); 862 IODataToRegister( ps, bReg, bData ); 863 ps->CloseScanPath( ps ); 864} 865 866/** Calling SITUATION: Scanner path not established. 867 * Write a register to asic (used for a command without parameter) 868 */ 869_LOC void IORegisterDirectToScanner( pScanData ps, Byte bReg ) 870{ 871 ps->OpenScanPath( ps ); /* establish the connection */ 872 IORegisterToScanner( ps, bReg ); /* write register to asic */ 873 ps->CloseScanPath( ps ); /* disconnect */ 874} 875 876/** perform a SW reset of ASIC 98003 models 877 */ 878_LOC void IOSoftwareReset( pScanData ps ) 879{ 880 if( _ASIC_IS_98003 != ps->sCaps.AsicID ) 881 return; 882 883 ps->OpenScanPath( ps ); 884 885 IODataToRegister( ps, ps->RegTestMode, _SW_TESTMODE ); 886 887 ioSwitchToSPPMode( ps ); 888 889 _OUTB_DATA( ps, _RESET1ST ); 890 _DODELAY( 5 ); 891 892 _OUTB_DATA( ps, _RESET2ND ); 893 _DODELAY( 5 ); 894 895 _OUTB_DATA( ps, _RESET3RD ); 896 _DODELAY( 5 ); 897 898 _OUTB_DATA( ps, _RESET4TH ); 899 _DODELAY( 5 ); 900 901 ioRestoreParallelMode( ps ); 902 903 /* reset test mode register */ 904 IODataToRegister( ps, ps->RegTestMode, 0 ); 905 IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); 906 907 ps->CloseScanPath( ps ); 908} 909 910/** Read specific length data from scanner and the method depends on the 911 * mode defined in registry. 912 */ 913_LOC void IOReadScannerImageData( pScanData ps, pUChar pBuf, ULong size ) 914{ 915 if( _ASIC_IS_98003 != ps->sCaps.AsicID ) 916 ps->OpenScanPath( ps); 917 918 if( _IS_ASIC98( ps->sCaps.AsicID)) 919 IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); 920 921 /* enter read mode */ 922 ioEnterReadMode( ps ); 923 924 /* call corresponding read proc */ 925 ps->Device.ReadData( ps, pBuf, size ); 926 927 /* Clear EPP/ECP read mode by simply close scanner path and re-open it */ 928 ps->CloseScanPath( ps ); 929 930 if( _ASIC_IS_98003 == ps->sCaps.AsicID ) 931 ps->OpenScanPath( ps ); 932} 933 934/* END PLUSTEK-PP_IO.C ......................................................*/ 935