root/drivers/scsi/advansys.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. advansys_proc_info
  2. advansys_detect
  3. advansys_release
  4. advansys_info
  5. advansys_command
  6. advansys_queuecommand
  7. advansys_abort
  8. advansys_reset
  9. advansys_biosparam
  10. advansys_setup
  11. asc_proc_copy
  12. advansys_interrupt
  13. advansys_command_done
  14. asc_execute_scsi_cmnd
  15. asc_isr_callback
  16. asc_execute_pending
  17. asc_init_dev
  18. asc_srch_pci_dev
  19. asc_scan_method
  20. asc_pci_find_dev
  21. asc_get_pci_cfg
  22. asc_get_cfg_word
  23. asc_get_cfg_byte
  24. asc_enqueue
  25. asc_dequeue
  26. asc_rmqueue
  27. DvcSleepMilliSecond
  28. DvcDisplayString
  29. DvcEnterCritical
  30. DvcLeaveCritical
  31. DvcGetPhyAddr
  32. DvcGetSGList
  33. DvcPutScsiQ
  34. DvcGetQinfo
  35. DvcOutPortWords
  36. DvcInPortWords
  37. DvcOutPortDWords
  38. asc_prt_stats
  39. asc_prt_stats_line
  40. asc_prt_scsi_host
  41. asc_prt_dvc_var
  42. asc_prt_dvc_cfg
  43. asc_prt_scsi_q
  44. asc_prt_qdone_info
  45. asc_prt_hex
  46. interrupts_enabled
  47. AscGetEisaChipCfg
  48. AscSetChipScsiID
  49. AscGetChipBiosAddress
  50. AscGetChipVersion
  51. AscGetChipBusType
  52. AscEnableIsaDma
  53. AscLoadMicroCode
  54. AscSearchIOPortAddr
  55. AscSearchIOPortAddr11
  56. AscFindSignature
  57. AscToggleIRQAct
  58. AscSetISAPNPWaitForKey
  59. AscGetChipIRQ
  60. AscSetChipIRQ
  61. AscGetChipScsiCtrl
  62. AscIsrChipHalted
  63. _AscCopyLramScsiDoneQ
  64. AscIsrQDone
  65. AscISR
  66. AscScsiSetupCmdQ
  67. AscExeScsiQueue
  68. AscSendScsiQueue
  69. AscSgListToQueue
  70. AscGetNumOfFreeQueue
  71. AscPutReadyQueue
  72. AscPutReadySgListQueue
  73. AscAbortSRB
  74. AscResetDevice
  75. AscResetSB
  76. AscSetRunChipSynRegAtID
  77. AscSetChipSynRegAtID
  78. AscReInitLram
  79. AscInitLram
  80. AscInitQLinkVar
  81. AscSetLibErrorCode
  82. _AscWaitQDone
  83. AscMsgOutSDTR
  84. AscCalSDTRData
  85. AscSetChipSDTR
  86. AscGetSynPeriodIndex
  87. AscAllocFreeQueue
  88. AscAllocMultipleFreeQueue
  89. AscRiscHaltedAbortSRB
  90. AscRiscHaltedAbortTIX
  91. AscHostReqRiscHalt
  92. AscStopQueueExe
  93. AscStartQueueExe
  94. AscCleanUpBusyQueue
  95. AscCleanUpDiscQueue
  96. AscWaitTixISRDone
  97. AscWaitISRDone
  98. AscGetOnePhyAddr
  99. AscGetEisaProductID
  100. AscSearchIOPortAddrEISA
  101. AscStartChip
  102. AscStopChip
  103. AscIsChipHalted
  104. AscSetChipIH
  105. AscAckInterrupt
  106. AscDisableInterrupt
  107. AscEnableInterrupt
  108. AscSetBank
  109. AscResetChipAndScsiBus
  110. AscGetIsaDmaChannel
  111. AscSetIsaDmaChannel
  112. AscSetIsaDmaSpeed
  113. AscGetIsaDmaSpeed
  114. AscGetMaxDmaCount
  115. AscInitGetConfig
  116. AscInitSetConfig
  117. AscInitAsc1000Driver
  118. AscInitAscDvcVar
  119. AscInitFromAscDvcVar
  120. AscInitFromEEP
  121. AscInitMicroCodeVar
  122. AscInitPollIsrCallBack
  123. AscTestExternalLram
  124. AscWriteEEPCmdReg
  125. AscWriteEEPDataReg
  126. AscWaitEEPRead
  127. AscWaitEEPWrite
  128. AscReadEEPWord
  129. AscWriteEEPWord
  130. AscGetEEPConfig
  131. AscSetEEPConfigOnce
  132. AscSetEEPConfig
  133. AscInitPollBegin
  134. AscInitPollEnd
  135. AscInitPollTarget
  136. PollQueueDone
  137. PollScsiInquiry
  138. PollScsiReadCapacity
  139. swapfarbuf4
  140. PollScsiTestUnitReady
  141. PollScsiStartUnit
  142. InitTestUnitReady
  143. AscPollQDone
  144. AscReadLramByte
  145. AscReadLramWord
  146. AscReadLramDWord
  147. AscWriteLramWord
  148. AscWriteLramDWord
  149. AscWriteLramByte
  150. AscVerWriteLramWord
  151. AscMemWordCopyToLram
  152. AscMemDWordCopyToLram
  153. AscMemWordCopyFromLram
  154. AscMemSumLramWord
  155. AscMemWordSetLram
  156. AscScsiInquiry
  157. AscScsiReadCapacity
  158. AscScsiTestUnitReady
  159. AscScsiStartStopUnit

   1 /* $Id: advansys.c,v 1.12 1996/02/23 20:48:27 bobf Exp bobf $ */
   2 /*
   3  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
   4  * 
   5  * Copyright (c) 1995-1996 Advanced System Products, Inc.
   6  * All Rights Reserved.
   7  *
   8  * This driver may be modified and freely distributed provided that
   9  * the above copyright message and this comment are included in the
  10  * distribution. The latest version of this driver is available at
  11  * the AdvanSys FTP and BBS sites listed below.
  12  *
  13  * Please send questions, comments, bug reports to:
  14  * bobf@advansys.com (Bob Frey)
  15  */
  16 
  17 /* The driver has been tested with Linux v1.2.1 and v1.3.57 kernels. */
  18 #define ASC_VERSION "1.3"       /* AdvanSys Driver Version */
  19 
  20 /*
  21 
  22   Documentation for the AdvanSys Driver
  23 
  24   A. Adapters Supported by this Driver
  25   B. Linux v1.2.X - Directions for Adding the AdvanSys Driver
  26   C. Linux v1.3.X - Directions for Adding the AdvanSys Driver
  27   D. Source Comments
  28   E. Driver Compile Time Options and Debugging
  29   F. Driver LILO Option
  30   G. Release History
  31   H. Known Problems or Issues
  32   I. Credits
  33   J. AdvanSys Contact Information
  34 
  35 
  36   A. Adapters Supported by this Driver
  37  
  38      AdvanSys (Advanced System Products, Inc.) manufactures the following
  39      Bus-Mastering SCSI-2 Host Adapters for the ISA, EISA, VL, and PCI
  40      buses. This Linux driver supports all of these adapters.
  41      
  42      The CDB counts below indicate the number of SCSI CDB (Command
  43      Descriptor Block) requests that can be stored in the RISC chip
  44      cache and board LRAM. The driver detect routine will display the
  45      number of CDBs available for each adapter detected. This value
  46      can be lowered in the BIOS by changing the 'Host Queue Size'
  47      adapter setting.
  48 
  49      Connectivity Products:
  50        ABP920 - Bus-Master PCI 16 CDB
  51        ABP930 - Bus-Master PCI 16 CDB
  52        ABP5140 - Bus-Master PnP ISA 16 CDB
  53    
  54      Single Channel Products:
  55        ABP542 - Bus-Master ISA 240 CDB
  56        ABP5150 - Bus-Master ISA 240 CDB *
  57        ABP742 - Bus-Master EISA 240 CDB
  58        ABP842 - Bus-Master VL 240 CDB
  59        ABP940 - Bus-Master PCI 240 CDB
  60    
  61      Dual Channel Products:
  62        ABP950 - Dual Channel Bus-Master PCI 240 CDB Per Channel
  63        ABP852 - Dual Channel Bus-Master VL 240 CDB Per Channel
  64        ABP752 - Dual Channel Bus-Master EISA 240 CDB Per Channel
  65 
  66      * This board is shipped by HP with the 4020i CD-R drive. It has
  67        no BIOS so it cannot control a boot device, but it can control
  68        any secondary devices.
  69  
  70   B. Linux v1.2.X - Directions for Adding the AdvanSys Driver
  71 
  72      These directions apply to v1.2.1. For versions that follow v1.2.1
  73      but precede v1.3.57 some of the changes for Linux v1.3.X listed
  74      below may need to be modified or included.
  75  
  76      There are two source files: advansys.h and advansys.c. Copy
  77      both of these files to the directory /usr/src/linux/drivers/scsi.
  78     
  79      1. Add the following line to /usr/src/linux/arch/i386/config.in
  80         after "comment 'SCSI low-level drivers'":
  81     
  82           bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
  83     
  84      2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
  85         after "#include "hosts.h"":
  86     
  87           #ifdef CONFIG_SCSI_ADVANSYS
  88           #include "advansys.h"
  89           #endif
  90     
  91         and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
  92     
  93           #ifdef CONFIG_SCSI_ADVANSYS
  94           ADVANSYS,
  95           #endif
  96     
  97      3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
  98     
  99           ifdef CONFIG_SCSI_ADVANSYS
 100           SCSI_SRCS := $(SCSI_SRCS) advansys.c
 101           SCSI_OBJS := $(SCSI_OBJS) advansys.o
 102           else
 103           SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o
 104           endif
 105 
 106      4. (Optional) If you would like to enable the LILO command line
 107         and /etc/lilo.conf 'advansys' option, make the following changes.
 108         This option can be used to disable I/O port scanning or to limit
 109         I/O port scanning to specific addresses. Refer to the 'Driver
 110         LILO Option' section below. Add the following lines to
 111         /usr/src/linux/init/main.c in the prototype section:
 112 
 113           extern void advansys_setup(char *str, int *ints);
 114 
 115         and add the following lines to the bootsetups[] array.
 116 
 117           #ifdef CONFIG_SCSI_ADVANSYS
 118              { "advansys=", advansys_setup },
 119           #endif
 120 
 121      5. If you have the HP 4020i CD-R driver and Linux v1.2.X you should
 122         add a fix to the CD-ROM target driver. This fix will allow
 123         you to mount CDs with the iso9660 file system. Linux v1.3.X
 124         already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c
 125         and function get_sectorsize() after the line:
 126 
 127         if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048;
 128 
 129         add the following line:
 130 
 131         if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048;
 132 
 133      6. In the directory /usr/src/linux run 'make config' to configure
 134         the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
 135         make the kernel. If the AdvanSys driver is not configured, then
 136         a loadable module can be built by running 'make modules' and
 137         'make modules_install'. Use 'insmod' and 'rmmod' to install
 138         and remove advansys.o.
 139  
 140   C. Linux v1.3.X - Directions for Adding the AdvanSys Driver
 141 
 142      These directions apply to v1.3.57. For versions that precede v1.3.57
 143      some of these changes may need to be modified or eliminated. Beginning
 144      with v1.3.58 this driver is included with the Linux distribution.
 145 
 146      There are two source files: advansys.h and advansys.c. Copy
 147      both of these files to the directory /usr/src/linux/drivers/scsi.
 148    
 149      1. Add the following line to /usr/src/linux/drivers/scsi/Config.in
 150         after "comment 'SCSI low-level drivers'":
 151    
 152           dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
 153    
 154      2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
 155         after "#include "hosts.h"":
 156    
 157           #ifdef CONFIG_SCSI_ADVANSYS
 158           #include "advansys.h"
 159           #endif
 160    
 161         and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
 162    
 163           #ifdef CONFIG_SCSI_ADVANSYS
 164           ADVANSYS,
 165           #endif
 166    
 167      3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
 168    
 169           ifeq ($(CONFIG_SCSI_ADVANSYS),y)
 170           L_OBJS += advansys.o
 171           else
 172             ifeq ($(CONFIG_SCSI_ADVANSYS),m)
 173             M_OBJS += advansys.o
 174             endif
 175           endif
 176    
 177      4. Add the following line to /usr/src/linux/include/linux/proc_fs.h
 178         in the enum scsi_directory_inos array:
 179    
 180           PROC_SCSI_ADVANSYS,
 181    
 182      5. (Optional) If you would like to enable the LILO command line
 183         and /etc/lilo.conf 'advansys' option, make the following changes.
 184         This option can be used to disable I/O port scanning or to limit
 185         I/O port scanning to specific addresses. Refer to the 'Driver
 186         LILO Option' section below. Add the following lines to
 187         /usr/src/linux/init/main.c in the prototype section:
 188    
 189           extern void advansys_setup(char *str, int *ints);
 190    
 191         and add the following lines to the bootsetups[] array.
 192    
 193           #ifdef CONFIG_SCSI_ADVANSYS
 194              { "advansys=", advansys_setup },
 195           #endif
 196    
 197      6. In the directory /usr/src/linux run 'make config' to configure
 198         the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
 199         make the kernel. If the AdvanSys driver is not configured, then
 200         a loadable module can be built by running 'make modules' and
 201         'make modules_install'. Use 'insmod' and 'rmmod' to install
 202         and remove advansys.o.
 203 
 204   D. Source Comments
 205  
 206      1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'.
 207  
 208      2. This driver should be maintained in multiple files. But to make
 209         it easier to include with Linux and to follow Linux conventions,
 210         the whole driver is maintained in the source files advansys.h and
 211         advansys.c. In this file logical sections of the driver begin with
 212         a comment that contains '---'. The following are the logical sections
 213         of the driver below.
 214  
 215            --- Linux Version
 216            --- Linux Include Files 
 217            --- Driver Options
 218            --- Asc Library Constants and Macros
 219            --- Debugging Header
 220            --- Driver Constants
 221            --- Driver Macros
 222            --- Driver Structures
 223            --- Driver Data
 224            --- Driver Function Prototypes
 225            --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
 226            --- Loadable Driver Support
 227            --- Miscellaneous Driver Functions
 228            --- Functions Required by the Asc Library
 229            --- Tracing and Debugging Functions
 230            --- Asc Library Functions
 231  
 232      3. The string 'XXX' is used to flag code that needs to be re-written
 233         or that contains a problem that needs to be addressed.
 234  
 235      4. I have stripped comments from and reformatted the source for the
 236         Asc Library which is included in this file. I haven't done this
 237         to obfuscate the code. Actually I have done this to deobfuscate
 238         the code. The Asc Library source can be found under the following
 239         headings.
 240  
 241            --- Asc Library Constants and Macros
 242            --- Asc Library Functions
 243  
 244   E. Driver Compile Time Options and Debugging
 245  
 246      In this source file the following constants can be defined. They are
 247      defined in the source below. Both of these options are enabled by
 248      default.
 249  
 250      1. ADVANSYS_DEBUG - enable for debugging and assertions
 251  
 252         The amount of debugging output can be controlled with the global
 253         variable 'asc_dbglvl'. The higher the number the more output. By
 254         default the debug level is 0.
 255         
 256         If the driver is loaded at boot time and the LILO Driver Option
 257         is included in the system, the debug level can be changed by
 258         specifying a 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port. The
 259         first three hex digits of the pseudo I/O Port must be set to
 260         'deb' and the fourth hex digit specifies the debug level: 0 - F.
 261         The following command line will look for an adapter at 0x330
 262         and set the debug level to 2.
 263 
 264            linux advansys=0x330,0,0,0,0xdeb2
 265 
 266         If the driver is built as a loadable module this variable can be
 267         defined when the driver is loaded. The following insmod command
 268         will set the debug level to one.
 269   
 270            insmod advansys.o asc_dbglvl=1
 271  
 272  
 273         Debugging Message Levels:
 274            0: Errors Only
 275            1: High-Level Tracing
 276            2-N: Verbose Tracing
 277  
 278         I don't know the approved way for turning on printk()s to the
 279         console. Here's a program I use to do this. Debug output is
 280         logged in /var/adm/messages.
 281  
 282           main()
 283           {
 284                   syscall(103, 7, 0, 0);
 285           }
 286  
 287         I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c
 288         prevents most level 1 debug messages from being lost.
 289  
 290      2. ADVANSYS_STATS - enable statistics and tracing
 291  
 292         For Linux v1.2.X if ADVANSYS_STATS_1_2_PRINT is defined every
 293         10,000 I/O operations the driver will print statistics to the
 294         console. This value can be changed by modifying the constant
 295         used in advansys_queuecommand(). ADVANSYS_STATS_1_2_PRINT is
 296         off by default.
 297 
 298         For Linux v1.3.X statistics can be accessed by reading the
 299         /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] files.
 300 
 301         Note: these statistics are currently maintained on a global driver
 302         basis and not per board.
 303 
 304   F. Driver LILO Option
 305  
 306      If init/main.c is modified as described in the 'Directions for Adding
 307      the AdvanSys Driver to Linux' section (B.4.) above, the driver will
 308      recognize the 'advansys' LILO command line and /etc/lilo.conf option.
 309      This option can be used to either disable I/O port scanning or to limit
 310      scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and
 311      PCI boards will still be searched for and detected. This option only
 312      affects searching for ISA and VL boards.
 313 
 314      Examples:
 315        1. Eliminate I/O port scanning:
 316             boot: linux advansys=
 317               or
 318             boot: linux advansys=0x0
 319        2. Limit I/O port scanning to one I/O port:
 320             boot: linux advansys=0x110
 321        3. Limit I/O port scanning to four I/O ports:
 322             boot: linux advansys=0x110,0x210,0x230,0x330
 323 
 324      For a loadable module the same effect can be achieved by setting
 325      the 'asc_iopflag' variable and 'asc_ioport' array when loading
 326      the driver, e.g.
 327 
 328            insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
 329 
 330      If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_BOARD_SUPPORTED + 1)
 331      I/O Port may be added to specify the driver debug level. Refer to
 332      the 'Driver Compile Time Options and Debugging' section above for
 333      more information.
 334 
 335   G. Release History
 336 
 337      12/23/95 BETA-1.0:
 338          First Release
 339 
 340      12/28/95 BETA-1.1:
 341          1. Prevent advansys_detect() from being called twice.
 342          2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
 343 
 344      1/12/96 1.2:
 345          1. Prevent re-entrancy in the interrupt handler which
 346             resulted in the driver hanging Linux.
 347          2. Fix problem that prevented ABP-940 cards from being
 348             recognized on some PCI motherboards.
 349          3. Add support for the ABP-5140 PnP ISA card.
 350          4. Fix check condition return status.
 351          5. Add conditionally compiled code for Linux v1.3.X.
 352 
 353      2/23/96 1.3:
 354          1. Fix problem in advansys_biosparam() that resulted in the
 355             wrong drive geometry being returned for drives > 1GB with
 356             extended translation enabled.
 357          2. Add additional tracing during device initialization.
 358          3. Change code that only applies to ISA PnP adapter.
 359          4. Eliminate 'make dep' warning.
 360          5. Try to fix problem with handling resets by increasing their
 361             timeout value.
 362         
 363   H. Known Problems or Issues
 364 
 365      1. The setting for 'cmd_per_lun' needs to be changed. It is currently
 366         less then what the AdvanSys boards can queue. Because the target and
 367         mid-level Linux drivers base memory allocation on 'cmd_per_lun' (as
 368         well as 'sg_tablesize') memory use gets out of hand with a large
 369         'cmd_per_lun'. 'cmd_per_lun' should be per device instead of per
 370         adapter. When the driver is compiled as a loadable module both
 371         'cmd_per_lun' and 'sg_tablesize' are tuned down to try to prevent
 372         memory allocation errors.
 373 
 374      2. For the first scsi command sent to a device the driver increases
 375         the timeout value. This gives the driver more time to perform
 376         its own initialization for the board and each device. The timeout
 377         value is only changed on the first scsi command for each device
 378         and never thereafter. The same change is made for reset commands.
 379 
 380      3. The driver occasionally enters a loop handling reset requests. It
 381         isn't clear yet whether this is a bug in the upper or mid-level
 382         scsi modules or in this driver.
 383 
 384   I. Credits
 385 
 386      Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and
 387      and basis for the Linux v1.3.X changes which were included in the
 388      1.2 release.
 389 
 390      Thomas E Zerucha <zerucha@shell.portal.com> pointed out the bug
 391      in advansys_biosparam() which was fixed the 1.3 release.
 392 
 393   J. AdvanSys Contact Information
 394  
 395      Mail:                   Advanced System Products, Inc.
 396                              1150 Ringwood Court
 397                              San Jose, CA 95131 USA
 398      Operator:               1-408-383-9400
 399      FAX:                    1-408-383-9612
 400      Tech Support:           1-800-525-7440
 401      BBS:                    1-408-383-9540 (9600,N,8,1)
 402      Interactive FAX:        1-408-383-9753
 403      Customer Direct Sales:  1-800-883-1099
 404      Tech Support E-Mail:    support@advansys.com
 405      Linux Support E-Mail:   bobf@advansys.com
 406      FTP Site:               ftp.advansys.com (login: anonymous)
 407      Web Site:               http://www.advansys.com
 408 
 409 */
 410 
 411 
 412 /*
 413  * --- Linux Version
 414  */
 415 
 416 /*
 417  * The driver can be used in Linux v1.2.X or v1.3.X.
 418  */
 419 #if !defined(LINUX_1_2) && !defined(LINUX_1_3)
 420 #ifndef LINUX_VERSION_CODE
 421 #include <linux/version.h>
 422 #endif /* LINUX_VERSION_CODE */
 423 #if LINUX_VERSION_CODE > 65536 + 3 * 256
 424 #define LINUX_1_3
 425 #else /* LINUX_VERSION_CODE */
 426 #define LINUX_1_2
 427 #endif /* LINUX_VERSION_CODE */
 428 #endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */
 429 
 430 
 431 /*
 432  * --- Linux Include Files 
 433  */
 434 
 435 #ifdef LINUX_1_3
 436 #ifdef MODULE
 437 #include <linux/module.h>
 438 #endif /* MODULE */
 439 #endif /* LINUX_1_3 */
 440 #include <linux/string.h>
 441 #include <linux/sched.h>
 442 #include <linux/kernel.h>
 443 #include <linux/head.h>
 444 #include <linux/types.h>
 445 #include <linux/ioport.h>
 446 #include <linux/delay.h>
 447 #include <linux/malloc.h>
 448 #ifdef LINUX_1_3
 449 #include <linux/proc_fs.h>
 450 #endif /* LINUX_1_3 */ 
 451 #include <asm/io.h>
 452 #include <asm/system.h>
 453 #include <asm/dma.h>
 454 #ifdef LINUX_1_2
 455 #include "../block/blk.h"
 456 #else /* LINUX_1_3 */ 
 457 #include <linux/blk.h>
 458 #include <linux/stat.h>
 459 #endif /* LINUX_1_3 */ 
 460 #include "scsi.h"
 461 #include "hosts.h"
 462 #include "sd.h"
 463 #include "advansys.h"
 464 
 465 
 466 /*
 467  * --- Driver Options
 468  */
 469 #define ADVANSYS_DEBUG /* Enable for debugging and assertions. */
 470 #define ADVANSYS_STATS /* Enable for statistics and tracing. */
 471 #ifdef LINUX_1_2
 472 #undef ADVANSYS_STATS_1_2_PRINT /* Enable to print statistics to console. */
 473 #endif /* LINUX_1_2 */
 474 
 475 
 476 /*
 477  * --- Asc Library Constants and Macros
 478  */
 479 
 480 #define ASC_LIB_VERSION_MAJOR  1
 481 #define ASC_LIB_VERSION_MINOR  16
 482 #define ASC_LIB_SERIAL_NUMBER  53
 483 
 484 typedef unsigned char uchar;
 485 typedef unsigned char BYTE;
 486 typedef unsigned short WORD;
 487 typedef unsigned long DWORD;
 488 
 489 typedef int         BOOL;
 490 
 491 #ifndef NULL
 492 #define NULL     (0)
 493 #endif
 494 
 495 #ifndef TRUE
 496 #define TRUE     (1)
 497 #endif
 498 
 499 #ifndef FALSE
 500 #define FALSE    (0)
 501 #endif
 502 
 503 #define  REG     register
 504 
 505 #define rchar    REG char
 506 #define rshort   REG short
 507 #define rint     REG int
 508 #define rlong    REG long
 509 
 510 #define ruchar   REG uchar
 511 #define rushort  REG ushort
 512 #define ruint    REG uint
 513 #define rulong   REG ulong
 514 
 515 #define NULLPTR   ( void *)0
 516 #define FNULLPTR  ( void dosfar *)0UL
 517 #define EOF      (-1)
 518 #define EOS      '\0'
 519 #define ERR      (-1)
 520 #define UB_ERR   (uchar)(0xFF)
 521 #define UW_ERR   (uint)(0xFFFF)
 522 #define UL_ERR   (ulong)(0xFFFFFFFFUL)
 523 
 524 #define iseven_word( val )  ( ( ( ( uint )val) & ( uint )0x0001 ) == 0 )
 525 #define isodd_word( val )   ( ( ( ( uint )val) & ( uint )0x0001 ) != 0 )
 526 #define toeven_word( val )  ( ( ( uint )val ) & ( uint )0xFFFE )
 527 
 528 #define biton( val, bits )   ((( uint )( val >> bits ) & (uint)0x0001 ) != 0 )
 529 #define bitoff( val, bits )  ((( uint )( val >> bits ) & (uint)0x0001 ) == 0 )
 530 #define lbiton( val, bits )  ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) != 0 )
 531 #define lbitoff( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) == 0 )
 532 
 533 #define  absh( val )    ( ( val ) < 0 ? -( val ) : ( val ) )
 534 
 535 #define  swapbyte( ch )  ( ( ( (ch) << 4 ) | ( (ch) >> 4 ) ) )
 536 
 537 #ifndef GBYTE
 538 #define GBYTE       (0x40000000UL)
 539 #endif
 540 
 541 #ifndef MBYTE
 542 #define MBYTE       (0x100000UL)
 543 #endif
 544 
 545 #ifndef KBYTE
 546 #define KBYTE       (0x400)
 547 #endif
 548 
 549 #define HI_BYTE(x) ( *( ( BYTE *)(&x)+1 ) )
 550 #define LO_BYTE(x) ( *( ( BYTE *)&x ) )
 551 
 552 #define HI_WORD(x) ( *( ( WORD *)(&x)+1 ) )
 553 #define LO_WORD(x) ( *( ( WORD *)&x ) )
 554 
 555 #ifndef MAKEWORD
 556 #define MAKEWORD(lo, hi)    ((WORD) (((WORD) lo) | ((WORD) hi << 8)))
 557 #endif
 558 
 559 #ifndef MAKELONG
 560 #define MAKELONG(lo, hi)    ((DWORD) (((DWORD) lo) | ((DWORD) hi << 16)))
 561 #endif
 562 
 563 #define SwapWords(dWord)        ((DWORD) ((dWord >> 16) | (dWord << 16)))
 564 #define SwapBytes(word)         ((WORD) ((word >> 8) | (word << 8)))
 565 
 566 #define BigToLittle(dWord) \
 567     ((DWORD) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
 568 #define LittleToBig(dWord)      BigToLittle(dWord)
 569 
 570 #define Lptr
 571 #define dosfar
 572 #define far
 573 #define PortAddr                        unsigned short
 574 #define Ptr2Func                ulong
 575 
 576 #define inp(port)               inb(port)
 577 #define inpw(port)              inw(port)
 578 #define outp(port, byte)    outb((byte), (port))
 579 #define outpw(port, word)   outw((word), (port))
 580 
 581 #define ASC_MAX_SG_QUEUE        5
 582 #define ASC_MAX_SG_LIST         (1 + ((ASC_SG_LIST_PER_Q) * (ASC_MAX_SG_QUEUE)))
 583 
 584 #define CC_INIT_INQ_DISPLAY     FALSE
 585 
 586 #define CC_CLEAR_LRAM_SRB_PTR   FALSE
 587 #define CC_VERIFY_LRAM_COPY     FALSE
 588 
 589 #define CC_DEBUG_SG_LIST        FALSE
 590 #define CC_FAST_STRING_IO       FALSE
 591 
 592 #define CC_WRITE_IO_COUNT       FALSE
 593 #define CC_CLEAR_DMA_REMAIN     FALSE
 594 
 595 #define CC_DISABLE_PCI_PARITY_INT TRUE
 596 
 597 #define CC_LINK_BUSY_Q         FALSE
 598 
 599 #define CC_TARGET_MODE         FALSE
 600 
 601 #define CC_SCAM                FALSE
 602 
 603 #define CC_LITTLE_ENDIAN_HOST  TRUE
 604 
 605 #ifndef CC_TEST_LRAM_ENDIAN
 606 
 607 #if CC_LITTLE_ENDIAN_HOST
 608 #define CC_TEST_LRAM_ENDIAN     FALSE
 609 #else
 610 #define CC_TEST_LRAM_ENDIAN     TRUE
 611 #endif
 612 
 613 #endif
 614 
 615 #define CC_STRUCT_ALIGNED      TRUE
 616 
 617 #define CC_MEMORY_MAPPED_IO    FALSE
 618 
 619 #ifndef CC_TARGET_MODE
 620 #define CC_TARGET_MODE         FALSE
 621 #endif
 622 
 623 #ifndef CC_STRUCT_ALIGNED
 624 #define CC_STRUCT_ALIGNED      FALSE
 625 #endif
 626 
 627 #ifndef CC_LITTLE_ENDIAN_HOST
 628 #define CC_LITTLE_ENDIAN_HOST  TRUE
 629 #endif
 630 
 631 #if !CC_LITTLE_ENDIAN_HOST
 632 
 633 #ifndef CC_TEST_LRAM_ENDIAN
 634 #define CC_TEST_LRAM_ENDIAN    TRUE
 635 #endif
 636 
 637 #endif
 638 
 639 #ifndef CC_MEMORY_MAPPED_IO
 640 #define CC_MEMORY_MAPPED_IO    FALSE
 641 #endif
 642 
 643 #ifndef CC_WRITE_IO_COUNT
 644 #define CC_WRITE_IO_COUNT      FALSE
 645 #endif
 646 
 647 #ifndef CC_CLEAR_DMA_REMAIN
 648 #define CC_CLEAR_DMA_REMAIN    FALSE
 649 #endif
 650 
 651 #define ASC_CS_TYPE  unsigned short
 652 
 653 #ifndef asc_ptr_type
 654 #define asc_ptr_type
 655 #endif
 656 
 657 #ifndef CC_SCAM
 658 #define CC_SCAM  FALSE
 659 #endif
 660 
 661 #ifndef ASC_GET_PTR2FUNC
 662 #define ASC_GET_PTR2FUNC( fun )  ( Ptr2Func )( fun )
 663 #endif
 664 
 665 #define FLIP_BYTE_NIBBLE( x )    ( ((x<<4)& 0xFF) | (x>>4) )
 666 
 667 #define ASC_IS_ISA          (0x0001)
 668 #define ASC_IS_ISAPNP       (0x0081)
 669 #define ASC_IS_EISA         (0x0002)
 670 #define ASC_IS_PCI          (0x0004)
 671 #define ASC_IS_PCMCIA       (0x0008)
 672 #define ASC_IS_PNP          (0x0010)
 673 #define ASC_IS_MCA          (0x0020)
 674 #define ASC_IS_VL           (0x0040)
 675 
 676 #define ASC_ISA_PNP_PORT_ADDR  (0x279)
 677 #define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
 678 
 679 #define ASC_IS_WIDESCSI_16  (0x0100)
 680 #define ASC_IS_WIDESCSI_32  (0x0200)
 681 
 682 #define ASC_IS_BIG_ENDIAN   (0x8000)
 683 
 684 #define ASC_CHIP_MIN_VER_VL      (0x01)
 685 #define ASC_CHIP_MAX_VER_VL      (0x07)
 686 
 687 #define ASC_CHIP_MIN_VER_PCI     (0x09)
 688 #define ASC_CHIP_MAX_VER_PCI     (0x0F)
 689 #define ASC_CHIP_VER_PCI_BIT     (0x08)
 690 
 691 #define ASC_CHIP_MIN_VER_ISA     (0x11)
 692 #define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
 693 #define ASC_CHIP_MAX_VER_ISA     (0x27)
 694 #define ASC_CHIP_VER_ISA_BIT     (0x30)
 695 #define ASC_CHIP_VER_ISAPNP_BIT  (0x20)
 696 
 697 #define ASC_CHIP_VER_ASYN_BUG    (0x21)
 698 
 699 #define ASC_CHIP_MIN_VER_EISA (0x41)
 700 #define ASC_CHIP_MAX_VER_EISA (0x47)
 701 #define ASC_CHIP_VER_EISA_BIT (0x40)
 702 
 703 #define ASC_MAX_VL_DMA_ADDR     (0x07FFFFFFL)
 704 #define ASC_MAX_VL_DMA_COUNT    (0x07FFFFFFL)
 705 
 706 #define ASC_MAX_PCI_DMA_ADDR    (0xFFFFFFFFL)
 707 #define ASC_MAX_PCI_DMA_COUNT   (0xFFFFFFFFL)
 708 
 709 #define ASC_MAX_ISA_DMA_ADDR    (0x00FFFFFFL)
 710 #define ASC_MAX_ISA_DMA_COUNT   (0x00FFFFFFL)
 711 
 712 #define ASC_MAX_EISA_DMA_ADDR   (0x07FFFFFFL)
 713 #define ASC_MAX_EISA_DMA_COUNT  (0x07FFFFFFL)
 714 
 715 #if !CC_STRUCT_ALIGNED
 716 
 717 #define DvcGetQinfo( iop_base, s_addr, outbuf, words)  \
 718         AscMemWordCopyFromLram( iop_base, s_addr, outbuf, words)
 719 
 720 #define DvcPutScsiQ( iop_base, s_addr, outbuf, words) \
 721         AscMemWordCopyToLram( iop_base, s_addr, outbuf, words)
 722 
 723 #endif
 724 
 725 #define ASC_SCSI_ID_BITS  3
 726 #define ASC_SCSI_TIX_TYPE     uchar
 727 #define ASC_ALL_DEVICE_BIT_SET  0xFF
 728 
 729 #ifdef ASC_WIDESCSI_16
 730 
 731 #undef  ASC_SCSI_ID_BITS
 732 #define ASC_SCSI_ID_BITS  4
 733 #define ASC_ALL_DEVICE_BIT_SET  0xFFFF
 734 
 735 #endif
 736 
 737 #ifdef ASC_WIDESCSI_32
 738 
 739 #undef  ASC_SCSI_ID_BITS
 740 #define ASC_SCSI_ID_BITS  5
 741 #define ASC_ALL_DEVICE_BIT_SET  0xFFFFFFFFL
 742 
 743 #endif
 744 
 745 #if ASC_SCSI_ID_BITS == 3
 746 
 747 #define ASC_SCSI_BIT_ID_TYPE  uchar
 748 #define ASC_MAX_TID       7
 749 #define ASC_MAX_LUN       7
 750 #define ASC_SCSI_WIDTH_BIT_SET  0xFF
 751 
 752 #elif ASC_SCSI_ID_BITS == 4
 753 
 754 #define ASC_SCSI_BIT_ID_TYPE   ushort
 755 #define ASC_MAX_TID         15
 756 #define ASC_MAX_LUN         7
 757 #define ASC_SCSI_WIDTH_BIT_SET  0xFFFF
 758 
 759 #elif ASC_SCSI_ID_BITS == 5
 760 
 761 #define ASC_SCSI_BIT_ID_TYPE    ulong
 762 #define ASC_MAX_TID         31
 763 #define ASC_MAX_LUN         7
 764 #define ASC_SCSI_WIDTH_BIT_SET  0xFFFFFFFF
 765 
 766 #else
 767 
 768 #error  ASC_SCSI_ID_BITS definition is wrong
 769 
 770 #endif
 771 
 772 #define ASC_MAX_SENSE_LEN   32
 773 #define ASC_MIN_SENSE_LEN   14
 774 
 775 #define ASC_MAX_CDB_LEN     12
 776 
 777 #define SCSICMD_TestUnitReady     0x00
 778 #define SCSICMD_Rewind            0x01
 779 #define SCSICMD_Rezero            0x01
 780 #define SCSICMD_RequestSense      0x03
 781 #define SCSICMD_Format            0x04
 782 #define SCSICMD_FormatUnit        0x04
 783 #define SCSICMD_Read6             0x08
 784 #define SCSICMD_Write6            0x0A
 785 #define SCSICMD_Seek6             0x0B
 786 #define SCSICMD_Inquiry           0x12
 787 #define SCSICMD_Verify6           0x13
 788 #define SCSICMD_ModeSelect6       0x15
 789 #define SCSICMD_ModeSense6        0x1A
 790 
 791 #define SCSICMD_StartStopUnit     0x1B
 792 #define SCSICMD_LoadUnloadTape    0x1B
 793 #define SCSICMD_ReadCapacity      0x25
 794 #define SCSICMD_Read10            0x28
 795 #define SCSICMD_Write10           0x2A
 796 #define SCSICMD_Seek10            0x2B
 797 #define SCSICMD_Erase10           0x2C
 798 #define SCSICMD_WriteAndVerify10  0x2E
 799 #define SCSICMD_Verify10          0x2F
 800 
 801 #define SCSICMD_ModeSelect10      0x55
 802 #define SCSICMD_ModeSense10       0x5A
 803 
 804 #define SCSI_TYPE_DASD     0x00
 805 #define SCSI_TYPE_SASD     0x01
 806 #define SCSI_TYPE_PRN      0x02
 807 #define SCSI_TYPE_PROC     0x03
 808 
 809 #define SCSI_TYPE_WORM     0x04
 810 #define SCSI_TYPE_CDROM    0x05
 811 #define SCSI_TYPE_SCANNER  0x06
 812 #define SCSI_TYPE_OPTMEM   0x07
 813 #define SCSI_TYPE_MED_CHG  0x08
 814 #define SCSI_TYPE_COMM     0x09
 815 #define SCSI_TYPE_UNKNOWN  0x1F
 816 #define SCSI_TYPE_NO_DVC   0xFF
 817 
 818 #define ASC_SCSIDIR_NOCHK    0x00
 819 
 820 #define ASC_SCSIDIR_T2H      0x08
 821 
 822 #define ASC_SCSIDIR_H2T      0x10
 823 
 824 #define ASC_SCSIDIR_NODATA   0x18
 825 
 826 #define SCSI_SENKEY_NO_SENSE      0x00
 827 #define SCSI_SENKEY_UNDEFINED     0x01
 828 #define SCSI_SENKEY_NOT_READY     0x02
 829 #define SCSI_SENKEY_MEDIUM_ERR    0x03
 830 #define SCSI_SENKEY_HW_ERR        0x04
 831 #define SCSI_SENKEY_ILLEGAL       0x05
 832 #define SCSI_SENKEY_ATTENSION     0x06
 833 #define SCSI_SENKEY_PROTECTED     0x07
 834 #define SCSI_SENKEY_BLANK         0x08
 835 #define SCSI_SENKEY_V_UNIQUE      0x09
 836 #define SCSI_SENKEY_CPY_ABORT     0x0A
 837 #define SCSI_SENKEY_ABORT         0x0B
 838 #define SCSI_SENKEY_EQUAL         0x0C
 839 #define SCSI_SENKEY_VOL_OVERFLOW  0x0D
 840 #define SCSI_SENKEY_MISCOMP       0x0E
 841 #define SCSI_SENKEY_RESERVED      0x0F
 842 
 843 #define ASC_SRB_HOST( x )  ( ( uchar )( ( uchar )( x ) >> 4 ) )
 844 #define ASC_SRB_TID( x )   ( ( uchar )( ( uchar )( x ) & ( uchar )0x0F ) )
 845 
 846 #define ASC_SRB_LUN( x )   ( ( uchar )( ( uint )( x ) >> 13 ) )
 847 
 848 #define PUT_CDB1( x )   ( ( uchar )( ( uint )( x ) >> 8 ) )
 849 
 850 #define SS_GOOD              0x00
 851 #define SS_CHK_CONDITION     0x02
 852 #define SS_CONDITION_MET     0x04
 853 #define SS_TARGET_BUSY       0x08
 854 #define SS_INTERMID          0x10
 855 #define SS_INTERMID_COND_MET 0x14
 856 
 857 #define SS_RSERV_CONFLICT    0x18
 858 #define SS_CMD_TERMINATED    0x22
 859 
 860 #define SS_QUEUE_FULL        0x28
 861 
 862 #define MS_CMD_DONE    0x00
 863 #define MS_EXTEND      0x01
 864 #define MS_SDTR_LEN    0x03
 865 #define MS_SDTR_CODE   0x01
 866 
 867 #define M1_SAVE_DATA_PTR        0x02
 868 #define M1_RESTORE_PTRS         0x03
 869 #define M1_DISCONNECT           0x04
 870 #define M1_INIT_DETECTED_ERR    0x05
 871 #define M1_ABORT                0x06
 872 #define M1_MSG_REJECT           0x07
 873 #define M1_NO_OP                0x08
 874 #define M1_MSG_PARITY_ERR       0x09
 875 #define M1_LINK_CMD_DONE        0x0A
 876 #define M1_LINK_CMD_DONE_WFLAG  0x0B
 877 #define M1_BUS_DVC_RESET        0x0C
 878 #define M1_ABORT_TAG            0x0D
 879 #define M1_CLR_QUEUE            0x0E
 880 #define M1_INIT_RECOVERY        0x0F
 881 #define M1_RELEASE_RECOVERY     0x10
 882 #define M1_KILL_IO_PROC         0x11
 883 
 884 #define M2_QTAG_MSG_SIMPLE      0x20
 885 #define M2_QTAG_MSG_HEAD        0x21
 886 #define M2_QTAG_MSG_ORDERED     0x22
 887 #define M2_IGNORE_WIDE_RESIDUE  0x23
 888 
 889 typedef struct {
 890         uchar               peri_dvc_type:5;
 891         uchar               peri_qualifier:3;
 892 } ASC_SCSI_INQ0;
 893 
 894 typedef struct {
 895         uchar               dvc_type_modifier:7;
 896         uchar               rmb:1;
 897 } ASC_SCSI_INQ1;
 898 
 899 typedef struct {
 900         uchar               ansi_apr_ver:3;
 901         uchar               ecma_ver:3;
 902         uchar               iso_ver:2;
 903 } ASC_SCSI_INQ2;
 904 
 905 typedef struct {
 906         uchar               rsp_data_fmt:4;
 907 
 908         uchar               res:2;
 909         uchar               TemIOP:1;
 910         uchar               aenc:1;
 911 } ASC_SCSI_INQ3;
 912 
 913 typedef struct {
 914         uchar               StfRe:1;
 915         uchar               CmdQue:1;
 916         uchar               Reserved:1;
 917         uchar               Linked:1;
 918         uchar               Sync:1;
 919         uchar               WBus16:1;
 920         uchar               WBus32:1;
 921         uchar               RelAdr:1;
 922 } ASC_SCSI_INQ7;
 923 
 924 typedef struct {
 925         ASC_SCSI_INQ0       byte0;
 926         ASC_SCSI_INQ1       byte1;
 927         ASC_SCSI_INQ2       byte2;
 928         ASC_SCSI_INQ3       byte3;
 929         uchar               add_len;
 930         uchar               res1;
 931         uchar               res2;
 932         ASC_SCSI_INQ7       byte7;
 933         uchar               vendor_id[8];
 934         uchar               product_id[16];
 935         uchar               product_rev_level[4];
 936 } ASC_SCSI_INQUIRY;
 937 
 938 typedef struct asc_req_sense {
 939         uchar               err_code:7;
 940         uchar               info_valid:1;
 941         uchar               segment_no;
 942         uchar               sense_key:4;
 943         uchar               reserved_bit:1;
 944         uchar               sense_ILI:1;
 945         uchar               sense_EOM:1;
 946         uchar               file_mark:1;
 947         uchar               info1[4];
 948         uchar               add_sense_len;
 949         uchar               cmd_sp_info[4];
 950         uchar               asc;
 951         uchar               ascq;
 952 
 953         uchar               fruc;
 954         uchar               sks_byte0:7;
 955         uchar               sks_valid:1;
 956         uchar               sks_bytes[2];
 957         uchar               notused[2];
 958         uchar               ex_sense_code;
 959         uchar               info2[4];
 960 } ASC_REQ_SENSE;
 961 
 962 #define ASC_SG_LIST_PER_Q   7
 963 
 964 #define QS_FREE        0x00
 965 #define QS_READY       0x01
 966 #define QS_DISC1       0x02
 967 #define QS_DISC2       0x04
 968 #define QS_BUSY        0x08
 969 
 970 #define QS_ABORTED     0x40
 971 #define QS_DONE        0x80
 972 
 973 #define QC_NO_CALLBACK   0x01
 974 
 975 #define QC_SG_SWAP_QUEUE 0x02
 976 #define QC_SG_HEAD       0x04
 977 #define QC_DATA_IN       0x08
 978 #define QC_DATA_OUT      0x10
 979 
 980 #define QC_URGENT        0x20
 981 #define QC_MSG_OUT       0x40
 982 #define QC_REQ_SENSE     0x80
 983 
 984 #define QCSG_SG_XFER_LIST  0x02
 985 #define QCSG_SG_XFER_MORE  0x04
 986 #define QCSG_SG_XFER_END   0x08
 987 
 988 #define QD_IN_PROGRESS       0x00
 989 #define QD_NO_ERROR          0x01
 990 #define QD_ABORTED_BY_HOST   0x02
 991 #define QD_WITH_ERROR        0x04
 992 #define QD_INVALID_REQUEST   0x80
 993 #define QD_INVALID_HOST_NUM  0x81
 994 #define QD_INVALID_DEVICE    0x82
 995 #define QD_ERR_INTERNAL      0xFF
 996 
 997 #define QHSTA_NO_ERROR               0x00
 998 #define QHSTA_M_SEL_TIMEOUT          0x11
 999 #define QHSTA_M_DATA_OVER_RUN        0x12
1000 #define QHSTA_M_DATA_UNDER_RUN       0x12
1001 #define QHSTA_M_UNEXPECTED_BUS_FREE  0x13
1002 #define QHSTA_M_BAD_BUS_PHASE_SEQ    0x14
1003 
1004 #define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
1005 #define QHSTA_D_ASC_DVC_ERROR_CODE_SET  0x22
1006 #define QHSTA_D_HOST_ABORT_FAILED       0x23
1007 #define QHSTA_D_EXE_SCSI_Q_FAILED       0x24
1008 #define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
1009 
1010 #define QHSTA_D_ASPI_NO_BUF_POOL        0x26
1011 
1012 #define QHSTA_M_WTM_TIMEOUT         0x41
1013 #define QHSTA_M_BAD_CMPL_STATUS_IN  0x42
1014 #define QHSTA_M_NO_AUTO_REQ_SENSE   0x43
1015 #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
1016 #define QHSTA_M_TARGET_STATUS_BUSY  0x45
1017 #define QHSTA_M_BAD_TAG_CODE        0x46
1018 
1019 #define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY  0x47
1020 
1021 #define QHSTA_D_LRAM_CMP_ERROR        0x81
1022 #define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
1023 
1024 #define ASC_FLAG_SCSIQ_REQ        0x01
1025 #define ASC_FLAG_BIOS_SCSIQ_REQ   0x02
1026 #define ASC_FLAG_BIOS_ASYNC_IO    0x04
1027 #define ASC_FLAG_SRB_LINEAR_ADDR  0x08
1028 
1029 #define ASC_FLAG_WIN16            0x10
1030 #define ASC_FLAG_WIN32            0x20
1031 
1032 #define ASC_FLAG_DOS_VM_CALLBACK  0x80
1033 
1034 #define ASC_TAG_FLAG_ADD_ONE_BYTE     0x10
1035 #define ASC_TAG_FLAG_ISAPNP_ADD_BYTES 0x40
1036 
1037 #define ASC_SCSIQ_CPY_BEG              4
1038 #define ASC_SCSIQ_SGHD_CPY_BEG         2
1039 
1040 #define ASC_SCSIQ_B_FWD                0
1041 #define ASC_SCSIQ_B_BWD                1
1042 
1043 #define ASC_SCSIQ_B_STATUS             2
1044 #define ASC_SCSIQ_B_QNO                3
1045 
1046 #define ASC_SCSIQ_B_CNTL               4
1047 #define ASC_SCSIQ_B_SG_QUEUE_CNT       5
1048 
1049 #define ASC_SCSIQ_D_DATA_ADDR          8
1050 #define ASC_SCSIQ_D_DATA_CNT          12
1051 #define ASC_SCSIQ_B_SENSE_LEN         20
1052 #define ASC_SCSIQ_DONE_INFO_BEG       22
1053 #define ASC_SCSIQ_D_SRBPTR            22
1054 #define ASC_SCSIQ_B_TARGET_IX         26
1055 #define ASC_SCSIQ_B_CDB_LEN           28
1056 #define ASC_SCSIQ_B_TAG_CODE          29
1057 #define ASC_SCSIQ_W_VM_ID             30
1058 #define ASC_SCSIQ_DONE_STATUS         32
1059 #define ASC_SCSIQ_HOST_STATUS         33
1060 #define ASC_SCSIQ_SCSI_STATUS         34
1061 #define ASC_SCSIQ_CDB_BEG             36
1062 #define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
1063 #define ASC_SCSIQ_DW_REMAIN_XFER_CNT  60
1064 #define ASC_SCSIQ_B_SG_WK_QP          49
1065 #define ASC_SCSIQ_B_SG_WK_IX          50
1066 #define ASC_SCSIQ_W_REQ_COUNT         52
1067 #define ASC_SCSIQ_B_LIST_CNT          6
1068 #define ASC_SCSIQ_B_CUR_LIST_CNT      7
1069 
1070 #define ASC_SGQ_B_SG_CNTL             4
1071 #define ASC_SGQ_B_SG_HEAD_QP          5
1072 #define ASC_SGQ_B_SG_LIST_CNT         6
1073 #define ASC_SGQ_B_SG_CUR_LIST_CNT     7
1074 #define ASC_SGQ_LIST_BEG              8
1075 
1076 #define ASC_DEF_SCSI1_QNG    2
1077 #define ASC_MAX_SCSI1_QNG    2
1078 #define ASC_DEF_SCSI2_QNG    16
1079 #define ASC_MAX_SCSI2_QNG    32
1080 
1081 #define ASC_TAG_CODE_MASK    0x23
1082 
1083 #define ASC_STOP_REQ_RISC_STOP      0x01
1084 
1085 #define ASC_STOP_ACK_RISC_STOP      0x03
1086 
1087 #define ASC_STOP_CLEAN_UP_BUSY_Q    0x10
1088 #define ASC_STOP_CLEAN_UP_DISC_Q    0x20
1089 #define ASC_STOP_HOST_REQ_RISC_HALT 0x40
1090 #define ASC_STOP_SEND_INT_TO_HOST   0x80
1091 
1092 #define ASC_TIDLUN_TO_IX( tid, lun )  ( ASC_SCSI_TIX_TYPE )( (tid) + ((lun)<<ASC_SCSI_ID_BITS) )
1093 
1094 #define ASC_TID_TO_TARGET_ID( tid )   ( ASC_SCSI_BIT_ID_TYPE )( 0x01 << (tid) )
1095 #define ASC_TIX_TO_TARGET_ID( tix )   ( 0x01 << ( (tix) & ASC_MAX_TID ) )
1096 #define ASC_TIX_TO_TID( tix )  ( (tix) & ASC_MAX_TID )
1097 #define ASC_TID_TO_TIX( tid )  ( (tid) & ASC_MAX_TID )
1098 #define ASC_TIX_TO_LUN( tix )  ( ( (tix) >> ASC_SCSI_ID_BITS ) & ASC_MAX_LUN )
1099 
1100 #define ASC_QNO_TO_QADDR( q_no )      ( (ASC_QADR_BEG)+( ( int )(q_no) << 6 ) )
1101 
1102 typedef struct asc_scisq_1 {
1103         uchar               status;
1104         uchar               q_no;
1105         uchar               cntl;
1106         uchar               sg_queue_cnt;
1107 
1108         uchar               target_id;
1109         uchar               target_lun;
1110 
1111         ulong               data_addr;
1112         ulong               data_cnt;
1113         ulong               sense_addr;
1114         uchar               sense_len;
1115         uchar               user_def;
1116 } ASC_SCSIQ_1;
1117 
1118 typedef struct asc_scisq_2 {
1119         ulong               srb_ptr;
1120         uchar               target_ix;
1121 
1122         uchar               flag;
1123         uchar               cdb_len;
1124         uchar               tag_code;
1125 
1126         ushort              vm_id;
1127 } ASC_SCSIQ_2;
1128 
1129 typedef struct asc_scsiq_3 {
1130         uchar               done_stat;
1131         uchar               host_stat;
1132         uchar               scsi_stat;
1133         uchar               scsi_msg;
1134 } ASC_SCSIQ_3;
1135 
1136 typedef struct asc_scsiq_4 {
1137         uchar               cdb[ASC_MAX_CDB_LEN];
1138         uchar               y_first_sg_list_qp;
1139         uchar               y_working_sg_qp;
1140         uchar               y_working_sg_ix;
1141         uchar               y_cntl;
1142         ushort              x_req_count;
1143         ushort              x_reconnect_rtn;
1144         ulong               x_saved_data_addr;
1145         ulong               x_saved_data_cnt;
1146 } ASC_SCSIQ_4;
1147 
1148 typedef struct asc_q_done_info {
1149         ASC_SCSIQ_2         d2;
1150         ASC_SCSIQ_3         d3;
1151         uchar               q_status;
1152         uchar               q_no;
1153         uchar               cntl;
1154         uchar               sense_len;
1155         uchar               user_def;
1156         uchar               res;
1157         ulong               remain_bytes;
1158 } ASC_QDONE_INFO;
1159 
1160 typedef struct asc_sg_list {
1161         ulong               addr;
1162         ulong               bytes;
1163 } ASC_SG_LIST;
1164 
1165 typedef struct asc_sg_head {
1166         uchar               entry_cnt;
1167 
1168         uchar               queue_cnt;
1169 
1170         uchar               entry_to_copy;
1171         uchar               res;
1172         ASC_SG_LIST         sg_list[ASC_MAX_SG_LIST];
1173 } ASC_SG_HEAD;
1174 
1175 #define ASC_MIN_SG_LIST   2
1176 
1177 typedef struct asc_min_sg_head {
1178         uchar               entry_cnt;
1179 
1180         uchar               queue_cnt;
1181 
1182         uchar               entry_to_copy;
1183         uchar               res;
1184         ASC_SG_LIST         sg_list[ASC_MIN_SG_LIST];
1185 } ASC_MIN_SG_HEAD;
1186 
1187 #define QCX_SORT        (0x0001)
1188 #define QCX_COALEASE    (0x0002)
1189 
1190 #if CC_LINK_BUSY_Q
1191 typedef struct asc_ext_scsi_q {
1192         ulong               lba;
1193         ushort              lba_len;
1194         struct asc_scsi_q dosfar *next;
1195         struct asc_scsi_q dosfar *join;
1196         ushort              cntl;
1197         ushort              buffer_id;
1198         uchar               q_required;
1199         uchar               res;
1200 } ASC_EXT_SCSI_Q;
1201 
1202 #endif
1203 
1204 typedef struct asc_scsi_q {
1205         ASC_SCSIQ_1         q1;
1206         ASC_SCSIQ_2         q2;
1207         uchar dosfar       *cdbptr;
1208 
1209         ASC_SG_HEAD dosfar *sg_head;
1210 
1211 #if CC_LINK_BUSY_Q
1212         ASC_EXT_SCSI_Q      ext;
1213 #endif
1214 
1215 } ASC_SCSI_Q;
1216 
1217 typedef struct asc_scsi_req_q {
1218         ASC_SCSIQ_1         r1;
1219         ASC_SCSIQ_2         r2;
1220         uchar dosfar       *cdbptr;
1221         ASC_SG_HEAD dosfar *sg_head;
1222 
1223 #if CC_LINK_BUSY_Q
1224         ASC_EXT_SCSI_Q      ext;
1225 #endif
1226 
1227         uchar dosfar       *sense_ptr;
1228 
1229         ASC_SCSIQ_3         r3;
1230         uchar               cdb[ASC_MAX_CDB_LEN];
1231         uchar               sense[ASC_MIN_SENSE_LEN];
1232 } ASC_SCSI_REQ_Q;
1233 
1234 typedef struct asc_risc_q {
1235         uchar               fwd;
1236         uchar               bwd;
1237         ASC_SCSIQ_1         i1;
1238         ASC_SCSIQ_2         i2;
1239         ASC_SCSIQ_3         i3;
1240         ASC_SCSIQ_4         i4;
1241 } ASC_RISC_Q;
1242 
1243 typedef struct asc_sg_list_q {
1244 
1245         uchar               seq_no;
1246         uchar               q_no;
1247         uchar               cntl;
1248         uchar               sg_head_qp;
1249         uchar               sg_list_cnt;
1250         uchar               sg_cur_list_cnt;
1251 
1252 } ASC_SG_LIST_Q;
1253 
1254 typedef struct asc_risc_sg_list_q {
1255         uchar               fwd;
1256         uchar               bwd;
1257         ASC_SG_LIST_Q       sg;
1258         ASC_SG_LIST         sg_list[7];
1259 } ASC_RISC_SG_LIST_Q;
1260 
1261 #define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP  0x1000000UL
1262 #define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP  1024
1263 
1264 #define ASCQ_ERR_NO_ERROR             0
1265 #define ASCQ_ERR_IO_NOT_FOUND         1
1266 #define ASCQ_ERR_LOCAL_MEM            2
1267 #define ASCQ_ERR_CHKSUM               3
1268 #define ASCQ_ERR_START_CHIP           4
1269 #define ASCQ_ERR_INT_TARGET_ID        5
1270 #define ASCQ_ERR_INT_LOCAL_MEM        6
1271 #define ASCQ_ERR_HALT_RISC            7
1272 #define ASCQ_ERR_GET_ASPI_ENTRY       8
1273 #define ASCQ_ERR_CLOSE_ASPI           9
1274 #define ASCQ_ERR_HOST_INQUIRY         0x0A
1275 #define ASCQ_ERR_SAVED_SRB_BAD        0x0B
1276 #define ASCQ_ERR_QCNTL_SG_LIST        0x0C
1277 #define ASCQ_ERR_Q_STATUS             0x0D
1278 #define ASCQ_ERR_WR_SCSIQ             0x0E
1279 #define ASCQ_ERR_PC_ADDR              0x0F
1280 #define ASCQ_ERR_SYN_OFFSET           0x10
1281 #define ASCQ_ERR_SYN_XFER_TIME        0x11
1282 #define ASCQ_ERR_LOCK_DMA             0x12
1283 #define ASCQ_ERR_UNLOCK_DMA           0x13
1284 #define ASCQ_ERR_VDS_CHK_INSTALL      0x14
1285 #define ASCQ_ERR_MICRO_CODE_HALT      0x15
1286 #define ASCQ_ERR_SET_LRAM_ADDR        0x16
1287 #define ASCQ_ERR_CUR_QNG              0x17
1288 #define ASCQ_ERR_SG_Q_LINKS           0x18
1289 #define ASCQ_ERR_SCSIQ_PTR            0x19
1290 #define ASCQ_ERR_ISR_RE_ENTRY         0x1A
1291 #define ASCQ_ERR_CRITICAL_RE_ENTRY    0x1B
1292 #define ASCQ_ERR_ISR_ON_CRITICAL      0x1C
1293 #define ASCQ_ERR_SG_LIST_ODD_ADDRESS  0x1D
1294 #define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
1295 #define ASCQ_ERR_SCSIQ_NULL_PTR       0x1F
1296 #define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR   0x20
1297 #define ASCQ_ERR_GET_NUM_OF_FREE_Q    0x21
1298 #define ASCQ_ERR_SEND_SCSI_Q          0x22
1299 #define ASCQ_ERR_HOST_REQ_RISC_HALT   0x23
1300 #define ASCQ_ERR_RESET_SDTR           0x24
1301 
1302 #define ASC_WARN_NO_ERROR             0x0000
1303 #define ASC_WARN_IO_PORT_ROTATE       0x0001
1304 #define ASC_WARN_EEPROM_CHKSUM        0x0002
1305 #define ASC_WARN_IRQ_MODIFIED         0x0004
1306 #define ASC_WARN_AUTO_CONFIG          0x0008
1307 #define ASC_WARN_CMD_QNG_CONFLICT     0x0010
1308 
1309 #define ASC_WARN_EEPROM_RECOVER       0x0020
1310 #define ASC_WARN_CFG_MSW_RECOVER      0x0040
1311 
1312 #define ASC_IERR_WRITE_EEPROM         0x0001
1313 #define ASC_IERR_MCODE_CHKSUM         0x0002
1314 #define ASC_IERR_SET_PC_ADDR          0x0004
1315 #define ASC_IERR_START_STOP_CHIP      0x0008
1316 
1317 #define ASC_IERR_IRQ_NO               0x0010
1318 
1319 #define ASC_IERR_SET_IRQ_NO           0x0020
1320 #define ASC_IERR_CHIP_VERSION         0x0040
1321 #define ASC_IERR_SET_SCSI_ID          0x0080
1322 #define ASC_IERR_GET_PHY_ADDR         0x0100
1323 #define ASC_IERR_BAD_SIGNATURE        0x0200
1324 #define ASC_IERR_NO_BUS_TYPE          0x0400
1325 #define ASC_IERR_SCAM                 0x0800
1326 #define ASC_IERR_SET_SDTR             0x1000
1327 #define ASC_IERR_RW_LRAM              0x8000
1328 
1329 #define ASC_DEF_IRQ_NO  10
1330 #define ASC_MAX_IRQ_NO  15
1331 #define ASC_MIN_IRQ_NO  10
1332 
1333 #define ASC_MIN_REMAIN_Q        (0x02)
1334 #define ASC_DEF_MAX_TOTAL_QNG   (0x40)
1335 
1336 #define ASC_MIN_TAG_Q_PER_DVC   (0x04)
1337 #define ASC_DEF_TAG_Q_PER_DVC   (0x04)
1338 
1339 #define ASC_MIN_FREE_Q        ASC_MIN_REMAIN_Q
1340 
1341 #define ASC_MIN_TOTAL_QNG     (( ASC_MAX_SG_QUEUE )+( ASC_MIN_FREE_Q ))
1342 
1343 #define ASC_MAX_TOTAL_QNG 240
1344 #define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
1345 
1346 #define ASC_MAX_INRAM_TAG_QNG   16
1347 
1348 typedef struct asc_dvc_cfg {
1349         ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
1350 
1351         ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
1352         ASC_SCSI_BIT_ID_TYPE disc_enable;
1353         uchar               res;
1354         uchar               chip_scsi_id:4;
1355 
1356         uchar               isa_dma_speed:4;
1357 
1358         uchar               isa_dma_channel;
1359         uchar               chip_version;
1360         ushort              pci_device_id;
1361         ushort              lib_serial_no;
1362         ushort              lib_version;
1363         ushort              mcode_date;
1364         ushort              mcode_version;
1365         uchar               sdtr_data[ASC_MAX_TID + 1];
1366         uchar               max_tag_qng[ASC_MAX_TID + 1];
1367         uchar dosfar       *overrun_buf;
1368 
1369 } ASC_DVC_CFG;
1370 
1371 #define ASC_DEF_DVC_CNTL       0xFFFF
1372 #define ASC_DEF_CHIP_SCSI_ID   7
1373 #define ASC_DEF_ISA_DMA_SPEED  4
1374 
1375 #define ASC_INIT_STATE_NULL          0x0000
1376 #define ASC_INIT_STATE_BEG_GET_CFG   0x0001
1377 #define ASC_INIT_STATE_END_GET_CFG   0x0002
1378 #define ASC_INIT_STATE_BEG_SET_CFG   0x0004
1379 #define ASC_INIT_STATE_END_SET_CFG   0x0008
1380 #define ASC_INIT_STATE_BEG_LOAD_MC   0x0010
1381 #define ASC_INIT_STATE_END_LOAD_MC   0x0020
1382 #define ASC_INIT_STATE_BEG_INQUIRY   0x0040
1383 #define ASC_INIT_STATE_END_INQUIRY   0x0080
1384 #define ASC_INIT_RESET_SCSI_DONE     0x0100
1385 
1386 #define ASC_PCI_DEVICE_ID_REV_A      0x1100
1387 #define ASC_PCI_DEVICE_ID_REV_B      0x1200
1388 
1389 #define ASC_BUG_FIX_ADD_ONE_BYTE     0x0001
1390 
1391 #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
1392 
1393 #define ASC_MIN_TAGGED_CMD  7
1394 
1395 typedef struct asc_dvc_var {
1396         PortAddr            iop_base;
1397         ushort              err_code;
1398         ushort              dvc_cntl;
1399         ushort              bug_fix_cntl;
1400         ushort              bus_type;
1401         Ptr2Func            isr_callback;
1402         Ptr2Func            exe_callback;
1403 
1404         ASC_SCSI_BIT_ID_TYPE init_sdtr;
1405 
1406         ASC_SCSI_BIT_ID_TYPE sdtr_done;
1407 
1408         ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
1409 
1410         ASC_SCSI_BIT_ID_TYPE unit_not_ready;
1411 
1412         ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
1413 
1414         ASC_SCSI_BIT_ID_TYPE start_motor;
1415         uchar               scsi_reset_wait;
1416         uchar               chip_no;
1417 
1418         char                is_in_int;
1419         uchar               max_total_qng;
1420 
1421         uchar               cur_total_qng;
1422 
1423         uchar               in_critical_cnt;
1424 
1425         uchar               irq_no;
1426         uchar               last_q_shortage;
1427 
1428         ushort              init_state;
1429         uchar               cur_dvc_qng[ASC_MAX_TID + 1];
1430         uchar               max_dvc_qng[ASC_MAX_TID + 1];
1431 
1432         ASC_SCSI_Q dosfar  *scsiq_busy_head[ASC_MAX_TID + 1];
1433         ASC_SCSI_Q dosfar  *scsiq_busy_tail[ASC_MAX_TID + 1];
1434 
1435         ulong               int_count;
1436         ulong               req_count;
1437         ulong               busy_count;
1438 
1439         ASC_DVC_CFG dosfar *cfg;
1440         Ptr2Func            saved_ptr2func;
1441         ulong               reserved2;
1442         ulong               reserved3;
1443         ulong               max_dma_count;
1444         ASC_SCSI_BIT_ID_TYPE no_scam;
1445         ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
1446 } ASC_DVC_VAR;
1447 
1448 typedef int         (dosfar * ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO dosfar *);
1449 typedef int         (dosfar * ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
1450 
1451 typedef struct asc_dvc_inq_info {
1452         uchar               type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1453 } ASC_DVC_INQ_INFO;
1454 
1455 typedef struct asc_cap_info {
1456         ulong               lba;
1457         ulong               blk_size;
1458 } ASC_CAP_INFO;
1459 
1460 typedef struct asc_cap_info_array {
1461         ASC_CAP_INFO        cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1462 } ASC_CAP_INFO_ARRAY;
1463 
1464 #define ASC_IOADR_TABLE_MAX_IX  11
1465 #define ASC_IOADR_GAP   0x10
1466 #define ASC_SEARCH_IOP_GAP 0x10
1467 #define ASC_MIN_IOP_ADDR   ( PortAddr )0x0100
1468 #define ASC_MAX_IOP_ADDR   ( PortAddr )0x3F0
1469 
1470 #define ASC_IOADR_1     ( PortAddr )0x0110
1471 #define ASC_IOADR_2     ( PortAddr )0x0130
1472 #define ASC_IOADR_3     ( PortAddr )0x0150
1473 #define ASC_IOADR_4     ( PortAddr )0x0190
1474 #define ASC_IOADR_5     ( PortAddr )0x0210
1475 #define ASC_IOADR_6     ( PortAddr )0x0230
1476 #define ASC_IOADR_7     ( PortAddr )0x0250
1477 #define ASC_IOADR_8     ( PortAddr )0x0330
1478 #define ASC_IOADR_DEF   ASC_IOADR_8
1479 
1480 #define ASC_SYN_XFER_NO   8
1481 #define ASC_MAX_SDTR_PERIOD_INDEX  7
1482 #define ASC_SYN_MAX_OFFSET   0x0F
1483 #define ASC_DEF_SDTR_OFFSET  0x0F
1484 #define ASC_DEF_SDTR_INDEX   0x00
1485 
1486 #define SYN_XFER_NS_0  25
1487 #define SYN_XFER_NS_1  30
1488 #define SYN_XFER_NS_2  35
1489 #define SYN_XFER_NS_3  40
1490 #define SYN_XFER_NS_4  50
1491 #define SYN_XFER_NS_5  60
1492 #define SYN_XFER_NS_6  70
1493 #define SYN_XFER_NS_7  85
1494 
1495 #define ASC_SDTR_PERIOD_IX_MIN  7
1496 
1497 #define SYN_XMSG_WLEN  3
1498 
1499 typedef struct sdtr_xmsg {
1500         uchar               msg_type;
1501         uchar               msg_len;
1502         uchar               msg_req;
1503         uchar               xfer_period;
1504         uchar               req_ack_offset;
1505         uchar               res;
1506 } SDTR_XMSG;
1507 
1508 #define ASC_MCNTL_NO_SEL_TIMEOUT  ( ushort )0x0001
1509 #define ASC_MCNTL_NULL_TARGET     ( ushort )0x0002
1510 
1511 #define ASC_CNTL_INITIATOR         ( ushort )0x0001
1512 #define ASC_CNTL_BIOS_GT_1GB       ( ushort )0x0002
1513 #define ASC_CNTL_BIOS_GT_2_DISK    ( ushort )0x0004
1514 #define ASC_CNTL_BIOS_REMOVABLE    ( ushort )0x0008
1515 #define ASC_CNTL_NO_SCAM           ( ushort )0x0010
1516 #define ASC_CNTL_NO_PCI_FIX_ASYN_XFER ( ushort )0x0020
1517 
1518 #define ASC_CNTL_INT_MULTI_Q       ( ushort )0x0080
1519 
1520 #define ASC_CNTL_NO_LUN_SUPPORT    ( ushort )0x0040
1521 
1522 #define ASC_CNTL_NO_VERIFY_COPY    ( ushort )0x0100
1523 #define ASC_CNTL_RESET_SCSI        ( ushort )0x0200
1524 #define ASC_CNTL_INIT_INQUIRY      ( ushort )0x0400
1525 #define ASC_CNTL_INIT_VERBOSE      ( ushort )0x0800
1526 
1527 #define ASC_CNTL_SCSI_PARITY       ( ushort )0x1000
1528 #define ASC_CNTL_BURST_MODE        ( ushort )0x2000
1529 
1530 #define ASC_CNTL_USE_8_IOP_BASE    ( ushort )0x4000
1531 
1532 #define ASC_EEP_DVC_CFG_BEG_VL    2
1533 #define ASC_EEP_MAX_DVC_ADDR_VL   15
1534 
1535 #define ASC_EEP_DVC_CFG_BEG      32
1536 #define ASC_EEP_MAX_DVC_ADDR     45
1537 
1538 #define ASC_EEP_DEFINED_WORDS    10
1539 #define ASC_EEP_MAX_ADDR         63
1540 #define ASC_EEP_RES_WORDS         0
1541 #define ASC_EEP_MAX_RETRY        20
1542 #define ASC_MAX_INIT_BUSY_RETRY   8
1543 
1544 #define ASC_EEP_ISA_PNP_WSIZE    16
1545 
1546 typedef struct asceep_config {
1547         ushort              cfg_lsw;
1548         ushort              cfg_msw;
1549 
1550         uchar               init_sdtr;
1551         uchar               disc_enable;
1552 
1553         uchar               use_cmd_qng;
1554 
1555         uchar               start_motor;
1556         uchar               max_total_qng;
1557         uchar               max_tag_qng;
1558         uchar               bios_scan;
1559 
1560         uchar               power_up_wait;
1561 
1562         uchar               no_scam;
1563         uchar               chip_scsi_id:4;
1564 
1565         uchar               isa_dma_speed:4;
1566 
1567         uchar               sdtr_data[ASC_MAX_TID + 1];
1568 
1569         uchar               adapter_info[6];
1570 
1571         ushort              cntl;
1572 
1573         ushort              chksum;
1574 } ASCEEP_CONFIG;
1575 
1576 #define ASC_EEP_CMD_READ          0x80
1577 #define ASC_EEP_CMD_WRITE         0x40
1578 #define ASC_EEP_CMD_WRITE_ABLE    0x30
1579 #define ASC_EEP_CMD_WRITE_DISABLE 0x00
1580 
1581 #define ASC_OVERRUN_BSIZE  0x00000048UL
1582 
1583 #define ASCV_MSGOUT_BEG         0x0000
1584 #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
1585 #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
1586 
1587 #define ASCV_MSGIN_BEG          (ASCV_MSGOUT_BEG+8)
1588 #define ASCV_MSGIN_SDTR_PERIOD  (ASCV_MSGIN_BEG+3)
1589 #define ASCV_MSGIN_SDTR_OFFSET  (ASCV_MSGIN_BEG+4)
1590 
1591 #define ASCV_SDTR_DATA_BEG      (ASCV_MSGIN_BEG+8)
1592 #define ASCV_SDTR_DONE_BEG      (ASCV_SDTR_DATA_BEG+8)
1593 #define ASCV_MAX_DVC_QNG_BEG    ( ushort )0x0020
1594 
1595 #define ASCV_ASCDVC_ERR_CODE_W  ( ushort )0x0030
1596 #define ASCV_MCODE_CHKSUM_W   ( ushort )0x0032
1597 #define ASCV_MCODE_SIZE_W     ( ushort )0x0034
1598 #define ASCV_STOP_CODE_B      ( ushort )0x0036
1599 #define ASCV_DVC_ERR_CODE_B   ( ushort )0x0037
1600 
1601 #define ASCV_OVERRUN_PADDR_D  ( ushort )0x0038
1602 #define ASCV_OVERRUN_BSIZE_D  ( ushort )0x003C
1603 
1604 #define ASCV_HALTCODE_W       ( ushort )0x0040
1605 #define ASCV_CHKSUM_W         ( ushort )0x0042
1606 #define ASCV_MC_DATE_W        ( ushort )0x0044
1607 #define ASCV_MC_VER_W         ( ushort )0x0046
1608 #define ASCV_NEXTRDY_B        ( ushort )0x0048
1609 #define ASCV_DONENEXT_B       ( ushort )0x0049
1610 #define ASCV_USE_TAGGED_QNG_B ( ushort )0x004A
1611 #define ASCV_SCSIBUSY_B       ( ushort )0x004B
1612 #define ASCV_CDBCNT_B         ( ushort )0x004C
1613 #define ASCV_CURCDB_B         ( ushort )0x004D
1614 #define ASCV_RCLUN_B          ( ushort )0x004E
1615 #define ASCV_BUSY_QHEAD_B     ( ushort )0x004F
1616 #define ASCV_DISC1_QHEAD_B    ( ushort )0x0050
1617 
1618 #define ASCV_DISC_ENABLE_B    ( ushort )0x0052
1619 #define ASCV_CAN_TAGGED_QNG_B ( ushort )0x0053
1620 #define ASCV_HOSTSCSI_ID_B    ( ushort )0x0055
1621 #define ASCV_MCODE_CNTL_B     ( ushort )0x0056
1622 #define ASCV_NULL_TARGET_B    ( ushort )0x0057
1623 
1624 #define ASCV_FREE_Q_HEAD_W    ( ushort )0x0058
1625 #define ASCV_DONE_Q_TAIL_W    ( ushort )0x005A
1626 #define ASCV_FREE_Q_HEAD_B    ( ushort )(ASCV_FREE_Q_HEAD_W+1)
1627 #define ASCV_DONE_Q_TAIL_B    ( ushort )(ASCV_DONE_Q_TAIL_W+1)
1628 
1629 #define ASCV_HOST_FLAG_B      ( ushort )0x005D
1630 
1631 #define ASCV_TOTAL_READY_Q_B  ( ushort )0x0064
1632 #define ASCV_VER_SERIAL_B     ( ushort )0x0065
1633 #define ASCV_HALTCODE_SAVED_W ( ushort )0x0066
1634 #define ASCV_WTM_FLAG_B       ( ushort )0x0068
1635 #define ASCV_RISC_FLAG_B      ( ushort )0x006A
1636 #define ASCV_REQ_SG_LIST_QP   ( ushort )0x006B
1637 
1638 #define ASC_HOST_FLAG_IN_ISR        0x01
1639 #define ASC_HOST_FLAG_ACK_INT       0x02
1640 
1641 #define ASC_RISC_FLAG_GEN_INT      0x01
1642 #define ASC_RISC_FLAG_REQ_SG_LIST  0x02
1643 
1644 #define IOP_CTRL         (0x0F)
1645 #define IOP_STATUS       (0x0E)
1646 #define IOP_INT_ACK      IOP_STATUS
1647 
1648 #define IOP_REG_IFC      (0x0D)
1649 
1650 #define IOP_SYN_OFFSET   (0x0B)
1651 #define IOP_REG_PC       (0x0C)
1652 #define IOP_RAM_ADDR     (0x0A)
1653 #define IOP_RAM_DATA     (0x08)
1654 #define IOP_EEP_DATA     (0x06)
1655 #define IOP_EEP_CMD      (0x07)
1656 
1657 #define IOP_VERSION      (0x03)
1658 #define IOP_CONFIG_HIGH  (0x04)
1659 #define IOP_CONFIG_LOW   (0x02)
1660 #define IOP_ASPI_ID_LOW  (0x01)
1661 #define IOP_ASPI_ID_HIGH (0x00)
1662 
1663 #define IOP_REG_DC1      (0x0E)
1664 #define IOP_REG_DC0      (0x0C)
1665 #define IOP_REG_SB       (0x0B)
1666 #define IOP_REG_DA1      (0x0A)
1667 #define IOP_REG_DA0      (0x08)
1668 #define IOP_REG_SC       (0x09)
1669 #define IOP_DMA_SPEED    (0x07)
1670 #define IOP_REG_FLAG     (0x07)
1671 #define IOP_FIFO_H       (0x06)
1672 #define IOP_FIFO_L       (0x04)
1673 #define IOP_REG_ID       (0x05)
1674 #define IOP_REG_QP       (0x03)
1675 #define IOP_REG_IH       (0x02)
1676 #define IOP_REG_IX       (0x01)
1677 #define IOP_REG_AX       (0x00)
1678 
1679 #define IFC_REG_LOCK      (0x00)
1680 #define IFC_REG_UNLOCK    (0x09)
1681 
1682 #define IFC_WR_EN_FILTER  (0x10)
1683 #define IFC_RD_NO_EEPROM  (0x10)
1684 #define IFC_SLEW_RATE     (0x20)
1685 #define IFC_ACT_NEG       (0x40)
1686 #define IFC_INP_FILTER    (0x80)
1687 
1688 #define IFC_INIT_DEFAULT  ( IFC_ACT_NEG | IFC_REG_UNLOCK )
1689 
1690 #define SC_SEL   (0x80)
1691 #define SC_BSY   (0x40)
1692 #define SC_ACK   (0x20)
1693 #define SC_REQ   (0x10)
1694 #define SC_ATN   (0x08)
1695 #define SC_IO    (0x04)
1696 #define SC_CD    (0x02)
1697 #define SC_MSG   (0x01)
1698 
1699 #define AscGetVarFreeQHead( port )       AscReadLramWord( port, ASCV_FREE_Q_HEAD_W )
1700 #define AscGetVarDoneQTail( port )       AscReadLramWord( port, ASCV_DONE_Q_TAIL_W )
1701 #define AscPutVarFreeQHead( port, val )  AscWriteLramWord( port, ASCV_FREE_Q_HEAD_W, val )
1702 #define AscPutVarDoneQTail( port, val )  AscWriteLramWord( port, ASCV_DONE_Q_TAIL_W, val )
1703 
1704 #define AscGetRiscVarFreeQHead( port )        AscReadLramByte( port, ASCV_NEXTRDY_B )
1705 #define AscGetRiscVarDoneQTail( port )        AscReadLramByte( port, ASCV_DONENEXT_B )
1706 #define AscPutRiscVarFreeQHead( port, val )   AscWriteLramByte( port, ASCV_NEXTRDY_B, val )
1707 #define AscPutRiscVarDoneQTail( port, val )   AscWriteLramByte( port, ASCV_DONENEXT_B, val )
1708 
1709 #define AscGetChipIFC( port )               inp( (port)+IOP_REG_IFC )
1710 #define AscPutChipIFC( port, data )         outp( (port)+IOP_REG_IFC, data )
1711 
1712 #define AscGetChipLramAddr( port )          ( ushort )inpw( ( PortAddr )((port)+IOP_RAM_ADDR) )
1713 #define AscSetChipLramAddr( port, addr )    outpw( ( PortAddr )( (port)+IOP_RAM_ADDR ), addr )
1714 #define AscPutChipLramData( port, data )    outpw( (port)+IOP_RAM_DATA, data )
1715 #define AscGetChipLramData( port )          inpw( (port)+IOP_RAM_DATA )
1716 
1717 #define AscWriteChipSyn( port, data )       outp( (port)+IOP_SYN_OFFSET, data )
1718 #define AscReadChipSyn( port )              inp( (port)+IOP_SYN_OFFSET )
1719 
1720 #define AscWriteChipIH( port, data )        outpw( (port)+IOP_REG_IH, data )
1721 #define AscReadChipIH( port )               inpw( (port)+IOP_REG_IH )
1722 
1723 #define AscWriteChipScsiID( port, data )    outp( (port)+IOP_REG_ID, data )
1724 #define AscReadChipScsiID( port )           inp( (port)+IOP_REG_ID )
1725 
1726 #define AscGetChipDmaSpeed( port )         ( uchar )inp( (port)+IOP_DMA_SPEED )
1727 #define AscSetChipDmaSpeed( port, data )   outp( (port)+IOP_DMA_SPEED, data )
1728 #define AscGetChipQP( port )               ( uchar )inp( (port)+IOP_REG_QP )
1729 #define AscSetPCAddr( port, data )         outpw( (port)+IOP_REG_PC, data )
1730 #define AscGetPCAddr( port )               inpw( (port)+IOP_REG_PC )
1731 #define AscGetChipVerNo( port )            ( uchar )inp( (port)+IOP_VERSION )
1732 
1733 #define AscGetChipEEPCmd( port )           ( uchar )inp( (port)+IOP_EEP_CMD )
1734 #define AscSetChipEEPCmd( port, data )     outp( (port)+IOP_EEP_CMD, data )
1735 #define AscGetChipEEPData( port )          inpw( (port)+IOP_EEP_DATA )
1736 #define AscSetChipEEPData( port, data )    outpw( (port)+IOP_EEP_DATA, data )
1737 
1738 #define AscGetChipControl( port )          ( uchar )inp( (port)+IOP_CTRL )
1739 #define AscSetChipControl( port, cc_val )  outp( (port)+IOP_CTRL, cc_val )
1740 
1741 #define AscGetChipStatus( port )           ( ASC_CS_TYPE )inpw( (port)+IOP_STATUS )
1742 #define AscSetChipStatus( port, cs_val )   outpw( (port)+IOP_STATUS, cs_val )
1743 
1744 #define AscGetChipCfgLsw( port )           ( ushort )inpw( (port)+IOP_CONFIG_LOW )
1745 #define AscGetChipCfgMsw( port )           ( ushort )inpw( (port)+IOP_CONFIG_HIGH )
1746 #define AscSetChipCfgLsw( port, data )     outpw( (port)+IOP_CONFIG_LOW, data )
1747 #define AscSetChipCfgMsw( port, data )     outpw( (port)+IOP_CONFIG_HIGH, data )
1748 
1749 #define AscIsIntPending( port )           ( AscGetChipStatus( port ) & CSW_INT_PENDING )
1750 #define AscGetChipScsiID( port )          ( ( AscGetChipCfgLsw( port ) >> 8 ) & ASC_MAX_TID )
1751 
1752 #define ASC_HALT_EXTMSG_IN     ( ushort )0x8000
1753 #define ASC_HALT_CHK_CONDITION ( ushort )0x8100
1754 #define ASC_HALT_SS_QUEUE_FULL ( ushort )0x8200
1755 #define ASC_HALT_SDTR_REJECTED ( ushort )0x4000
1756 
1757 #define ASC_MAX_QNO        0xF8
1758 #define ASC_DATA_SEC_BEG   ( ushort )0x0080
1759 #define ASC_DATA_SEC_END   ( ushort )0x0080
1760 #define ASC_CODE_SEC_BEG   ( ushort )0x0080
1761 #define ASC_CODE_SEC_END   ( ushort )0x0080
1762 #define ASC_QADR_BEG       (0x4000)
1763 #define ASC_QADR_USED      ( ushort )( ASC_MAX_QNO * 64 )
1764 #define ASC_QADR_END       ( ushort )0x7FFF
1765 #define ASC_QLAST_ADR      ( ushort )0x7FC0
1766 #define ASC_QBLK_SIZE      0x40
1767 #define ASC_BIOS_DATA_QBEG 0xF8
1768 
1769 #define ASC_MIN_ACTIVE_QNO 0x01
1770 
1771 #define ASC_QLINK_END      0xFF
1772 #define ASC_EEPROM_WORDS   0x10
1773 #define ASC_MAX_MGS_LEN    0x10
1774 
1775 #define ASC_BIOS_ADDR_DEF  0xDC00
1776 #define ASC_BIOS_SIZE      0x3800
1777 #define ASC_BIOS_RAM_OFF   0x3800
1778 #define ASC_BIOS_RAM_SIZE  0x800
1779 #define ASC_BIOS_MIN_ADDR  0xC000
1780 #define ASC_BIOS_MAX_ADDR  0xEC00
1781 #define ASC_BIOS_BANK_SIZE 0x0400
1782 
1783 #define ASC_MCODE_START_ADDR  0x0080
1784 
1785 #define ASC_CFG0_HOST_INT_ON    0x0020
1786 #define ASC_CFG0_BIOS_ON        0x0040
1787 #define ASC_CFG0_VERA_BURST_ON  0x0080
1788 #define ASC_CFG0_SCSI_PARITY_ON 0x0800
1789 
1790 #define ASC_CFG1_SCSI_TARGET_ON 0x0080
1791 #define ASC_CFG1_LRAM_8BITS_ON  0x0800
1792 
1793 #define ASC_CFG_MSW_CLR_MASK    0xF0C0
1794 
1795 #define CSW_TEST1             ( ASC_CS_TYPE )0x8000
1796 #define CSW_AUTO_CONFIG       ( ASC_CS_TYPE )0x4000
1797 #define CSW_RESERVED1         ( ASC_CS_TYPE )0x2000
1798 #define CSW_IRQ_WRITTEN       ( ASC_CS_TYPE )0x1000
1799 #define CSW_33MHZ_SELECTED    ( ASC_CS_TYPE )0x0800
1800 #define CSW_TEST2             ( ASC_CS_TYPE )0x0400
1801 #define CSW_TEST3             ( ASC_CS_TYPE )0x0200
1802 #define CSW_RESERVED2         ( ASC_CS_TYPE )0x0100
1803 #define CSW_DMA_DONE          ( ASC_CS_TYPE )0x0080
1804 #define CSW_FIFO_RDY          ( ASC_CS_TYPE )0x0040
1805 
1806 #define CSW_EEP_READ_DONE     ( ASC_CS_TYPE )0x0020
1807 
1808 #define CSW_HALTED            ( ASC_CS_TYPE )0x0010
1809 #define CSW_SCSI_RESET_ACTIVE ( ASC_CS_TYPE )0x0008
1810 
1811 #define CSW_PARITY_ERR        ( ASC_CS_TYPE )0x0004
1812 #define CSW_SCSI_RESET_LATCH  ( ASC_CS_TYPE )0x0002
1813 
1814 #define CSW_INT_PENDING       ( ASC_CS_TYPE )0x0001
1815 
1816 #define CIW_INT_ACK      ( ASC_CS_TYPE )0x0100
1817 #define CIW_TEST1        ( ASC_CS_TYPE )0x0200
1818 #define CIW_TEST2        ( ASC_CS_TYPE )0x0400
1819 #define CIW_SEL_33MHZ    ( ASC_CS_TYPE )0x0800
1820 
1821 #define CIW_IRQ_ACT      ( ASC_CS_TYPE )0x1000
1822 
1823 #define CC_CHIP_RESET   ( uchar )0x80
1824 #define CC_SCSI_RESET   ( uchar )0x40
1825 #define CC_HALT         ( uchar )0x20
1826 #define CC_SINGLE_STEP  ( uchar )0x10
1827 #define CC_DMA_ABLE     ( uchar )0x08
1828 #define CC_TEST         ( uchar )0x04
1829 #define CC_BANK_ONE     ( uchar )0x02
1830 #define CC_DIAG         ( uchar )0x01
1831 
1832 #define ASC_1000_ID0W      0x04C1
1833 #define ASC_1000_ID0W_FIX  0x00C1
1834 #define ASC_1000_ID1B      0x25
1835 
1836 #define ASC_EISA_BIG_IOP_GAP   (0x1C30-0x0C50)
1837 #define ASC_EISA_SMALL_IOP_GAP (0x0020)
1838 #define ASC_EISA_MIN_IOP_ADDR  (0x0C30)
1839 #define ASC_EISA_MAX_IOP_ADDR  (0xFC50)
1840 #define ASC_EISA_REV_IOP_MASK  (0x0C83)
1841 #define ASC_EISA_PID_IOP_MASK  (0x0C80)
1842 #define ASC_EISA_CFG_IOP_MASK  (0x0C86)
1843 
1844 #define ASC_GET_EISA_SLOT( iop )  ( PortAddr )( (iop) & 0xF000 )
1845 
1846 #define ASC_EISA_ID_740    0x01745004UL
1847 #define ASC_EISA_ID_750    0x01755004UL
1848 
1849 #define INS_HALTINT        ( ushort )0x6281
1850 #define INS_HALT           ( ushort )0x6280
1851 #define INS_SINT           ( ushort )0x6200
1852 #define INS_RFLAG_WTM      ( ushort )0x7380
1853 
1854 #define ASC_MC_SAVE_CODE_WSIZE  0x500
1855 #define ASC_MC_SAVE_DATA_WSIZE  0x40
1856 
1857 typedef struct asc_mc_saved {
1858         ushort              data[ASC_MC_SAVE_DATA_WSIZE];
1859         ushort              code[ASC_MC_SAVE_CODE_WSIZE];
1860 } ASC_MC_SAVED;
1861 
1862 int                 AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1863 int                 AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1864 void                AscWaitEEPRead(void);
1865 void                AscWaitEEPWrite(void);
1866 ushort              AscReadEEPWord(PortAddr, uchar);
1867 ushort              AscWriteEEPWord(PortAddr, uchar, ushort);
1868 ushort              AscGetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
1869 int                 AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
1870 int                 AscSetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
1871 ushort              AscEEPSum(PortAddr, uchar, uchar);
1872 
1873 int                 AscStartChip(PortAddr);
1874 int                 AscStopChip(PortAddr);
1875 void                AscSetChipIH(PortAddr, ushort);
1876 int                 AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1877 
1878 int                 AscIsChipHalted(PortAddr);
1879 
1880 void                AscSetChipCfgDword(PortAddr, ulong);
1881 ulong               AscGetChipCfgDword(PortAddr);
1882 
1883 void                AscAckInterrupt(PortAddr);
1884 void                AscDisableInterrupt(PortAddr);
1885 void                AscEnableInterrupt(PortAddr);
1886 void                AscSetBank(PortAddr, uchar);
1887 uchar               AscGetBank(PortAddr);
1888 int                 AscResetChipAndScsiBus(PortAddr);
1889 ushort              AscGetIsaDmaChannel(PortAddr);
1890 ushort              AscSetIsaDmaChannel(PortAddr, ushort);
1891 uchar               AscSetIsaDmaSpeed(PortAddr, uchar);
1892 uchar               AscGetIsaDmaSpeed(PortAddr);
1893 
1894 uchar               AscReadLramByte(PortAddr, ushort);
1895 ushort              AscReadLramWord(PortAddr, ushort);
1896 ulong               AscReadLramDWord(PortAddr, ushort);
1897 void                AscWriteLramWord(PortAddr, ushort, ushort);
1898 void                AscWriteLramDWord(PortAddr, ushort, ulong);
1899 void                AscWriteLramByte(PortAddr, ushort, uchar);
1900 int                 AscVerWriteLramDWord(PortAddr, ushort, ulong);
1901 int                 AscVerWriteLramWord(PortAddr, ushort, ushort);
1902 int                 AscVerWriteLramByte(PortAddr, ushort, uchar);
1903 
1904 ulong               AscMemSumLramWord(PortAddr, ushort, int);
1905 void                AscMemWordSetLram(PortAddr, ushort, ushort, int);
1906 void                AscMemWordCopyToLram(PortAddr, ushort, ushort dosfar *, int);
1907 void                AscMemDWordCopyToLram(PortAddr, ushort, ulong dosfar *, int);
1908 void                AscMemWordCopyFromLram(PortAddr, ushort, ushort dosfar *, int);
1909 int                 AscMemWordCmpToLram(PortAddr, ushort, ushort dosfar *, int);
1910 
1911 ushort              AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
1912 ulong               AscLoadMicroCode(PortAddr, ushort,
1913                                                                          ushort dosfar *, ushort);
1914 ushort              AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *);
1915 ushort              AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
1916 ushort              AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc);
1917 
1918 void dosfar         AscInitPollIsrCallBack(ASC_DVC_VAR asc_ptr_type *,
1919                                                                                    ASC_QDONE_INFO dosfar *);
1920 int                 AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *);
1921 ushort              AscTestLramEndian(PortAddr);
1922 
1923 uchar               AscMsgOutSDTR(PortAddr, uchar, uchar);
1924 
1925 uchar               AscCalSDTRData(uchar, uchar);
1926 void                AscSetChipSDTR(PortAddr, uchar, uchar);
1927 int                 AscInitChipAllSynReg(ASC_DVC_VAR asc_ptr_type *, uchar);
1928 uchar               AscGetSynPeriodIndex(uchar);
1929 uchar               AscSynIndexToPeriod(uchar);
1930 uchar               AscAllocFreeQueue(PortAddr, uchar);
1931 uchar               AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1932 int                 AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
1933 int                 AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar);
1934 int                 AscRiscHaltedAbortALL(ASC_DVC_VAR asc_ptr_type *);
1935 int                 AscHostReqRiscHalt(PortAddr);
1936 int                 AscStopQueueExe(PortAddr);
1937 int                 AscStartQueueExe(PortAddr);
1938 int                 AscCleanUpDiscQueue(PortAddr);
1939 int                 AscCleanUpBusyQueue(PortAddr);
1940 int                 _AscAbortTidBusyQueue(ASC_DVC_VAR asc_ptr_type *,
1941                                                                                   ASC_QDONE_INFO dosfar *, uchar);
1942 int                 _AscAbortSrbBusyQueue(ASC_DVC_VAR asc_ptr_type *,
1943                                                                                   ASC_QDONE_INFO dosfar *, ulong);
1944 int                 AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar);
1945 int                 AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *);
1946 ulong               AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong);
1947 
1948 int                 AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc,
1949                                                                          ASC_SCSI_Q dosfar * scsiq,
1950                                                                          uchar n_q_required);
1951 int                 AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *, uchar);
1952 int                 AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *,
1953                                                                                    ASC_SCSI_Q dosfar *, uchar);
1954 int                 AscAbortScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
1955 void                AscExeScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
1956 int                 AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1957 int                 AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1958 ushort              AscInitLram(ASC_DVC_VAR asc_ptr_type *);
1959 int                 AscReInitLram(ASC_DVC_VAR asc_ptr_type *);
1960 ushort              AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *);
1961 int                 AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort);
1962 int                 _AscWaitQDone(PortAddr, ASC_SCSI_Q dosfar *);
1963 
1964 int                 AscEnterCritical(void);
1965 void                AscLeaveCritical(int);
1966 
1967 int                 AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *);
1968 uchar               _AscCopyLramScsiDoneQ(PortAddr, ushort,
1969                                                                                   ASC_QDONE_INFO dosfar *, ulong);
1970 int                 AscIsrQDone(ASC_DVC_VAR asc_ptr_type *);
1971 ushort              AscIsrExeBusyQueue(ASC_DVC_VAR asc_ptr_type *, uchar);
1972 int                 AscScsiSetupCmdQ(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
1973                                                                          uchar dosfar *, ulong);
1974 
1975 int                 AscScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
1976                                                                    uchar dosfar *, int);
1977 int                 AscScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *);
1978 int                 AscScsiStartStopUnit(ASC_DVC_VAR asc_ptr_type *,
1979                                                                                  ASC_SCSI_REQ_Q dosfar *, uchar);
1980 int                 AscScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
1981                                                                                 ASC_SCSI_REQ_Q dosfar *,
1982                                                                                 uchar dosfar *);
1983 
1984 ulong dosfar       *swapfarbuf4(uchar dosfar *);
1985 int                 PollQueueDone(ASC_DVC_VAR asc_ptr_type *,
1986                                                                   ASC_SCSI_REQ_Q dosfar *,
1987                                                                   int);
1988 int                 PollScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
1989                                                                                  ASC_SCSI_REQ_Q dosfar *,
1990                                                                                  ASC_CAP_INFO dosfar *);
1991 int                 PollScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
1992                                                                         uchar dosfar *, int);
1993 int                 PollScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
1994                                                                                   ASC_SCSI_REQ_Q dosfar *);
1995 int                 PollScsiStartUnit(ASC_DVC_VAR asc_ptr_type *,
1996                                                                           ASC_SCSI_REQ_Q dosfar *);
1997 int                 InitTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
1998                                                                           ASC_SCSI_REQ_Q dosfar *);
1999 void                AscDispInquiry(uchar, uchar, ASC_SCSI_INQUIRY dosfar *);
2000 int                 AscPollQDone(ASC_DVC_VAR asc_ptr_type *,
2001                                                                  ASC_SCSI_REQ_Q dosfar *, int);
2002 
2003 int                 AscSetBIOSBank(PortAddr, int, ushort);
2004 int                 AscSetVlBIOSBank(PortAddr, int);
2005 int                 AscSetEisaBIOSBank(PortAddr, int);
2006 int                 AscSetIsaBIOSBank(PortAddr, int);
2007 
2008 int                 AscIsBiosEnabled(PortAddr, ushort);
2009 void                AscResetScsiBus(PortAddr);
2010 void                AscClrResetScsiBus(PortAddr);
2011 
2012 void                AscSingleStepChip(PortAddr);
2013 uchar               AscSetChipScsiID(PortAddr, uchar);
2014 ushort              AscGetChipBiosAddress(PortAddr, ushort);
2015 ushort              AscSetChipBiosAddress(PortAddr, ushort, ushort);
2016 uchar               AscGetChipVersion(PortAddr, ushort);
2017 ushort              AscGetChipBusType(PortAddr);
2018 
2019 PortAddr            AscSearchIOPortAddr11(PortAddr);
2020 PortAddr            AscSearchIOPortAddr100(PortAddr);
2021 int                 AscFindSignature(PortAddr);
2022 void                AscToggleIRQAct(PortAddr);
2023 int                 AscResetChip(PortAddr);
2024 void                AscClrResetChip(PortAddr);
2025 
2026 short               itos(ushort, uchar dosfar *, short, short);
2027 int                 insnchar(uchar dosfar *, short, short, ruchar, short);
2028 void                itoh(ushort, ruchar dosfar *);
2029 void                btoh(uchar, ruchar dosfar *);
2030 void                ltoh(ulong, ruchar dosfar *);
2031 uchar dosfar       *todstr(ushort, uchar dosfar *);
2032 uchar dosfar       *tohstr(ushort, uchar dosfar *);
2033 uchar dosfar       *tobhstr(uchar, uchar dosfar *);
2034 uchar dosfar       *tolhstr(ulong, uchar dosfar *);
2035 
2036 void                AscSetISAPNPWaitForKey(void);
2037 uchar               AscGetChipIRQ(PortAddr, ushort);
2038 uchar               AscSetChipIRQ(PortAddr, uchar, ushort);
2039 uchar               AscGetChipScsiCtrl(PortAddr);
2040 
2041 ushort              AscGetEisaChipCfg(PortAddr);
2042 ushort              AscGetEisaChipGpReg(PortAddr);
2043 ushort              AscSetEisaChipCfg(PortAddr, ushort);
2044 ushort              AscSetEisaChipGpReg(PortAddr, ushort);
2045 
2046 ulong               AscGetEisaProductID(PortAddr);
2047 PortAddr            AscSearchIOPortAddrEISA(PortAddr);
2048 
2049 int                 AscPollQTailSync(PortAddr);
2050 int                 AscPollQHeadSync(PortAddr);
2051 int                 AscWaitQTailSync(PortAddr);
2052 
2053 int                 _AscRestoreMicroCode(PortAddr, ASC_MC_SAVED dosfar *);
2054 
2055 int                 AscSCAM(ASC_DVC_VAR asc_ptr_type *);
2056 
2057 ushort              SwapByteOfWord(ushort word_val);
2058 ulong               SwapWordOfDWord(ulong dword_val);
2059 ulong               AdjEndianDword(ulong dword_val);
2060 
2061 int                 AscAdjEndianScsiQ(ASC_SCSI_Q dosfar *);
2062 int                 AscAdjEndianQDoneInfo(ASC_QDONE_INFO dosfar *);
2063 
2064 extern int          DvcEnterCritical(void);
2065 extern void         DvcLeaveCritical(int);
2066 
2067 extern void         DvcInPortWords(PortAddr, ushort dosfar *, int);
2068 extern void         DvcOutPortWords(PortAddr, ushort dosfar *, int);
2069 extern void         DvcOutPortDWords(PortAddr, ulong dosfar *, int);
2070 
2071 extern void         DvcSleepMilliSecond(ulong);
2072 extern void         DvcDisplayString(uchar dosfar *);
2073 extern ulong        DvcGetPhyAddr(uchar dosfar * buf_addr, ulong buf_len);
2074 extern ulong        DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong,
2075                                                                  ASC_SG_HEAD dosfar *);
2076 
2077 extern void         DvcSCAMDelayMS(ulong);
2078 extern int          DvcDisableCPUInterrupt(void);
2079 extern void         DvcRestoreCPUInterrupt(int);
2080 
2081 void                DvcPutScsiQ(PortAddr, ushort, ushort dosfar *, int);
2082 void                DvcGetQinfo(PortAddr, ushort, ushort dosfar *, int);
2083 
2084 PortAddr            AscSearchIOPortAddr(PortAddr, ushort);
2085 ushort              AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *);
2086 ushort              AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *);
2087 ushort              AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *);
2088 int                 AscInitScsiTarget(ASC_DVC_VAR asc_ptr_type *,
2089                                                                           ASC_DVC_INQ_INFO dosfar *,
2090                                                                           uchar dosfar *,
2091                                                                           ASC_CAP_INFO_ARRAY dosfar *,
2092                                                                           ushort);
2093 int                 AscInitPollBegin(ASC_DVC_VAR asc_ptr_type *);
2094 int                 AscInitPollEnd(ASC_DVC_VAR asc_ptr_type *);
2095 int                 AscInitPollTarget(ASC_DVC_VAR asc_ptr_type *,
2096                                                                           ASC_SCSI_REQ_Q dosfar *,
2097                                                                           ASC_SCSI_INQUIRY dosfar *,
2098                                                                           ASC_CAP_INFO dosfar *);
2099 int                 AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
2100 
2101 int                 AscISR(ASC_DVC_VAR asc_ptr_type *);
2102 void                AscISR_AckInterrupt(ASC_DVC_VAR asc_ptr_type *);
2103 int                 AscISR_CheckQDone(ASC_DVC_VAR asc_ptr_type *,
2104                                                                           ASC_QDONE_INFO dosfar *,
2105                                                                           uchar dosfar *);
2106 
2107 int                 AscStartUnit(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_TIX_TYPE);
2108 int                 AscStopUnit(
2109                                                                    ASC_DVC_VAR asc_ptr_type * asc_dvc,
2110                                                                    ASC_SCSI_TIX_TYPE target_ix
2111 );
2112 
2113 uint                AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
2114 int                 AscSgListToQueue(int);
2115 int                 AscQueueToSgList(int);
2116 int                 AscSetDvcErrorCode(ASC_DVC_VAR asc_ptr_type *, uchar);
2117 
2118 int                 AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
2119 int                 AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar);
2120 int                 AscResetSB(ASC_DVC_VAR asc_ptr_type *);
2121 
2122 void                AscEnableIsaDma(uchar);
2123 void                AscDisableIsaDma(uchar);
2124 
2125 ulong               AscGetMaxDmaAddress(ushort);
2126 ulong               AscGetMaxDmaCount(ushort);
2127 
2128 int                 AscSaveMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
2129 int                 AscRestoreOldMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
2130 int                 AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
2131 
2132 /*
2133  * --- Debugging Header
2134  */
2135 
2136 #ifdef ADVANSYS_DEBUG
2137 #define STATIC
2138 #else /* ADVANSYS_DEBUG */
2139 #define STATIC static
2140 #endif /* ADVANSYS_DEBUG */
2141 
2142 
2143 /*
2144  * --- Driver Constants and Macros
2145  */
2146 
2147 #define ASC_NUM_BOARD_SUPPORTED 4
2148 #define ASC_NUM_BUS                             4
2149 
2150 /* Reference Scsi_Host hostdata */
2151 #define ASC_BOARD(host) ((struct asc_board *) &(host)->hostdata)
2152 
2153 #define NO_ISA_DMA      0xff            /* No ISA DMA Channel Used */
2154 
2155 #ifndef min
2156 #define min(a, b) (((a) < (b)) ? (a) : (b))
2157 #endif /* min */
2158 
2159 /* Asc Library return codes */
2160 #define ASC_TRUE                1
2161 #define ASC_FALSE               0
2162 #define ASC_NOERROR             1
2163 #define ASC_BUSY                0
2164 #define ASC_ERROR               (-1)
2165 
2166 /* Scsi_Cmnd function return codes */
2167 #define STATUS_BYTE(byte)       (byte)
2168 #define MSG_BYTE(byte)          ((byte) << 8)
2169 #define HOST_BYTE(byte)         ((byte) << 16)
2170 #define DRIVER_BYTE(byte)       ((byte) << 24)
2171 
2172 /* asc_enqueue() flags */
2173 #define ASC_FRONT               1
2174 #define ASC_BACK                2
2175 
2176 /* PCI configuration declarations */
2177 
2178 #define ASC_PCI_REV_A_INIT              0x01
2179 #define ASC_PCI_REV_A_DONE              0x02
2180 #define ASC_PCI_REV_B_INIT              0x04
2181 #define ASC_PCI_REV_B_DONE              0x08
2182 
2183 #define PCI_BASE_CLASS_PREDEFINED                       0x00
2184 #define PCI_BASE_CLASS_MASS_STORAGE                     0x01
2185 #define PCI_BASE_CLASS_NETWORK                          0x02
2186 #define PCI_BASE_CLASS_DISPLAY                          0x03
2187 #define PCI_BASE_CLASS_MULTIMEDIA                       0x04
2188 #define PCI_BASE_CLASS_MEMORY_CONTROLLER        0x05
2189 #define PCI_BASE_CLASS_BRIDGE_DEVICE            0x06
2190 
2191 /* MASS STORAGE */
2192 #define PCI_SUB_CLASS_SCSI_CONTROLLER                   0x00
2193 #define PCI_SUB_CLASS_IDE_CONTROLLER                    0x01
2194 #define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER    0x02
2195 #define PCI_SUB_CLASS_IPI_BUS_CONTROLLER                0x03
2196 #define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER             0x80
2197 
2198 /* NETWORK CONTROLLER */
2199 #define PCI_SUB_CLASS_ETHERNET_CONTROLLER               0x00
2200 #define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER             0x01
2201 #define PCI_SUB_CLASS_FDDI_CONTROLLER                   0x02
2202 #define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER  0x80
2203 
2204 /* DISPLAY CONTROLLER */
2205 #define PCI_SUB_CLASS_VGA_CONTROLLER                    0x00
2206 #define PCI_SUB_CLASS_XGA_CONTROLLER                    0x01
2207 #define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER  0x80
2208 
2209 /* MULTIMEDIA CONTROLLER */
2210 #define PCI_SUB_CLASS_VIDEO_DEVICE                              0x00
2211 #define PCI_SUB_CLASS_AUDIO_DEVICE                              0x01
2212 #define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE   0x80
2213 
2214 /* MEMORY CONTROLLER */
2215 #define PCI_SUB_CLASS_RAM_CONTROLLER                    0x00
2216 #define PCI_SUB_CLASS_FLASH_CONTROLLER                  0x01
2217 #define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER   0x80
2218 
2219 /* BRIDGE CONTROLLER */
2220 #define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER            0x00
2221 #define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER                     0x01
2222 #define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER            0x02
2223 #define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER                      0x03
2224 #define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER      0x04
2225 #define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER          0x05
2226 #define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER           0x80
2227 
2228 #define PCI_MAX_SLOT                    0x1F
2229 #define PCI_MAX_BUS                             0xFF
2230 #define ASC_PCI_VENDORID                0x10CD
2231 #define PCI_IOADDRESS_MASK              0xFFFE
2232 
2233 /* PCI IO Port Addresses to generate special cycle */
2234 
2235 #define PCI_CONFIG_ADDRESS_MECH1                0x0CF8
2236 #define PCI_CONFIG_DATA_MECH1                   0x0CFC
2237 
2238 #define PCI_CONFIG_FORWARD_REGISTER             0x0CFA  /* 0=type 0; 1=type 1; */
2239 
2240 #define PCI_CONFIG_BUS_NUMBER_MASK              0x00FF0000
2241 #define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00
2242 #define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8
2243 
2244 #define PCI_DEVICE_FOUND                                0x0000
2245 #define PCI_DEVICE_NOT_FOUND                    0xffff
2246 
2247 #define SUBCLASS_OFFSET         0x0A
2248 #define CLASSCODE_OFFSET        0x0B
2249 #define VENDORID_OFFSET         0x00
2250 #define DEVICEID_OFFSET         0x02
2251 
2252 /*
2253  * --- Driver Macros
2254  */
2255 
2256 #ifndef ADVANSYS_STATS
2257 #define ASC_STATS(counter)
2258 #define ASC_STATS_ADD(counter, count)
2259 #else /* ADVANSYS_STATS */
2260 #define ASC_STATS(counter)                              asc_stats.counter++
2261 #define ASC_STATS_ADD(counter, count)   asc_stats.counter += (count)
2262 #endif /* ADVANSYS_STATS */
2263 
2264 #ifndef ADVANSYS_DEBUG
2265 
2266 #define ASC_DBG(lvl, s)
2267 #define ASC_DBG1(lvl, s, a1)
2268 #define ASC_DBG2(lvl, s, a1, a2)
2269 #define ASC_DBG3(lvl, s, a1, a2, a3)
2270 #define ASC_DBG4(lvl, s, a1, a2, a3, a4)
2271 #define ASC_DBG_PRT_SCSI_HOST(lvl, s)
2272 #define ASC_DBG_PRT_DVC_VAR(lvl, v)
2273 #define ASC_DBG_PRT_DVC_CFG(lvl, c)
2274 #define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp)
2275 #define ASC_DBG_PRT_QDONE_INFO(lvl, qdone)
2276 #define ASC_DBG_PRT_HEX(lvl, name, start, length)
2277 #define ASC_DBG_PRT_CDB(lvl, cdb, len)
2278 #define ASC_DBG_PRT_SENSE(lvl, sense, len)
2279 #define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2280 #define ASC_ASSERT(a)
2281 
2282 #else /* ADVANSYS_DEBUG */
2283 
2284 /*
2285  * Debugging Message Levels:
2286  * 0: Errors Only
2287  * 1: High-Level Tracing
2288  * 2-N: Verbose Tracing
2289  */
2290 
2291 #define ASC_DBG(lvl, s) \
2292         { \
2293                 if (asc_dbglvl >= (lvl)) { \
2294                         printk(s); \
2295                 } \
2296         }
2297 
2298 #define ASC_DBG1(lvl, s, a1) \
2299         { \
2300                 if (asc_dbglvl >= (lvl)) { \
2301                         printk((s), (a1)); \
2302                 } \
2303         }
2304 
2305 #define ASC_DBG2(lvl, s, a1, a2) \
2306         { \
2307                 if (asc_dbglvl >= (lvl)) { \
2308                         printk((s), (a1), (a2)); \
2309                 } \
2310         }
2311 
2312 #define ASC_DBG3(lvl, s, a1, a2, a3) \
2313         { \
2314                 if (asc_dbglvl >= (lvl)) { \
2315                         printk((s), (a1), (a2), (a3)); \
2316                 } \
2317         }
2318 
2319 #define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
2320         { \
2321                 if (asc_dbglvl >= (lvl)) { \
2322                         printk((s), (a1), (a2), (a3), (a4)); \
2323                 } \
2324         }
2325 
2326 #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2327         { \
2328                 if (asc_dbglvl >= (lvl)) { \
2329                         asc_prt_scsi_host(s); \
2330                 } \
2331         }
2332 
2333 #define ASC_DBG_PRT_DVC_VAR(lvl, v) \
2334         { \
2335                 if (asc_dbglvl >= (lvl)) { \
2336                         asc_prt_dvc_var(v); \
2337                 } \
2338         }
2339 
2340 #define ASC_DBG_PRT_DVC_CFG(lvl, c) \
2341         { \
2342                 if (asc_dbglvl >= (lvl)) { \
2343                         asc_prt_dvc_cfg(c); \
2344                 } \
2345         }
2346 
2347 #define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) \
2348         { \
2349                 if (asc_dbglvl >= (lvl)) { \
2350                         asc_prt_scsi_q(scsiqp); \
2351                 } \
2352         }
2353 
2354 #define ASC_DBG_PRT_QDONE_INFO(lvl, qdone) \
2355         { \
2356                 if (asc_dbglvl >= (lvl)) { \
2357                         asc_prt_qdone_info(qdone); \
2358                 } \
2359         }
2360 
2361 #define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2362         { \
2363                 if (asc_dbglvl >= (lvl)) { \
2364                         asc_prt_hex((name), (start), (length)); \
2365                 } \
2366         }
2367 
2368 #define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2369                 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2370 
2371 #define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2372                 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2373 
2374 #define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2375                 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2376 
2377 #define ASC_ASSERT(a) \
2378         { \
2379                 if (!(a)) { \
2380                         printk("ASC_ASSERT() Failure: file %s, line %d\n", \
2381                                 __FILE__, __LINE__); \
2382                 } \
2383         }
2384 #endif /* ADVANSYS_DEBUG */
2385 
2386 
2387 /*
2388  * --- Driver Structures
2389  */
2390 
2391 /*
2392  * Structure allocated for each board.
2393  *
2394  * This structure is allocated by scsi_register() at the end
2395  * of the 'Scsi_Host' structure starting at the 'hostdata'
2396  * field. It is guaranteed to be allocated from DMA-able memory.
2397  */
2398 struct asc_board {
2399         /* Asc Library */
2400         ASC_DVC_VAR                      board;                                 /* Board configuration */
2401         ASC_DVC_CFG                      cfg;                                   /* Device configuration */
2402         uchar                            overrun_buf[ASC_OVERRUN_BSIZE];
2403         /* Queued Commands */
2404         ASC_SCSI_BIT_ID_TYPE pending_tidmask;           /* Pending command mask */
2405         Scsi_Cmnd                        *pending[ASC_MAX_TID];
2406         /* Target Initialization */
2407         ASC_SCSI_BIT_ID_TYPE init_tidmask;                      /* Target initialized mask */
2408         ASC_SCSI_REQ_Q           scsireqq;
2409         ASC_CAP_INFO             cap_info;
2410         ASC_SCSI_INQUIRY         inquiry;
2411 };
2412 
2413 /*
2414  * PCI configuration structures
2415  */
2416 typedef struct _PCI_DATA_
2417 {
2418         uchar   type;
2419         uchar   bus;
2420         uchar   slot;
2421         uchar   func;
2422         uchar   offset;
2423 } PCI_DATA;
2424 
2425 typedef struct _PCI_DEVICE_
2426 {
2427         ushort  vendorID;
2428         ushort  deviceID;
2429         ushort  slotNumber;
2430         ushort  slotFound;
2431         uchar   busNumber;
2432         uchar   maxBusNumber;
2433         uchar   devFunc;
2434         ushort  startSlot;
2435         ushort  endSlot;
2436         uchar   bridge;
2437         uchar   type;
2438 } PCI_DEVICE;
2439 
2440 typedef struct _PCI_CONFIG_SPACE_
2441 {
2442         ushort  vendorID;
2443         ushort  deviceID;
2444         ushort  command;
2445         ushort  status;
2446         uchar   revision;
2447         uchar   classCode[3];
2448         uchar   cacheSize;
2449         uchar   latencyTimer;
2450         uchar   headerType;
2451         uchar   bist;
2452         ulong   baseAddress[6];
2453         ushort  reserved[4];
2454         ulong   optionRomAddr;
2455         ushort  reserved2[4];
2456         uchar   irqLine;
2457         uchar   irqPin;
2458         uchar   minGnt;
2459         uchar   maxLatency;
2460 } PCI_CONFIG_SPACE;
2461 
2462 #ifdef ADVANSYS_STATS
2463 struct asc_stats {
2464         ulong   command;                /* # calls to advansys_command() */
2465         ulong   queuecommand;   /* # calls to advansys_queuecommand() */
2466         ulong   abort;                  /* # calls to advansys_abort() */
2467         ulong   reset;                  /* # calls to advansys_reset() */
2468         ulong   biosparam;              /* # calls to advansys_biosparam() */
2469         ulong   interrupt;              /* # calls to advansys_interrupt() */
2470         ulong   callback;               /* # calls asc_isr_callback() */
2471         ulong   cont_cnt;               /* # non-scatter-gather I/O requests received */
2472         ulong   cont_xfer;              /* contiguous transfer total (512 byte units) */
2473         ulong   sg_cnt;                 /* # scatter-gather I/O requests received */
2474         ulong   sg_elem;                /* scatter-gather element total */
2475         ulong   sg_xfer;                /* scatter-gather tranfer total (512 byte units) */
2476         ulong   error;                  /* # AscExeScsiQueue() ASC_ERROR returns. */
2477         /*
2478          * Number of times interrupts disabled in advansys_queuecommand() and
2479          * asc_isr_callback(), respectively. For the former indicates how many
2480          * times commands were pending when a new command was received.
2481          */
2482         ulong   cmd_disable;
2483         ulong   intr_disable;
2484         /*
2485          * Number of times asc_enqueue() called. Indicates how many ASC_BUSY
2486          * returns have occurred.
2487          */
2488         ulong   enqueue;
2489         ulong   dequeue;                /* # calls to asc_dequeue(). */
2490         /*
2491          * Number of times asc_rmqueue() called and the specified command
2492          * was found and removed.
2493          */
2494         ulong   rmqueue;
2495 } asc_stats;
2496 #endif /* ADVANSYS_STATS */
2497 
2498 
2499 /*
2500  * --- Driver Data
2501  */
2502 
2503 #ifdef LINUX_1_3
2504 struct proc_dir_entry proc_scsi_advansys =
2505 {
2506         PROC_SCSI_ADVANSYS,                             /* unsigned short low_ino */
2507         8,                                                              /* unsigned short namelen */
2508         "advansys",                                             /* const char *name */
2509         S_IFDIR | S_IRUGO | S_IXUGO,    /* mode_t mode */
2510         2                                                               /* nlink_t nlink */
2511 };
2512 #endif /* LINUX_1_3 */
2513 
2514 STATIC int asc_board_count; /* Number of boards detected in system. */
2515 STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED];
2516 STATIC Scsi_Cmnd *asc_scsi_done; /* Commands needing done function call. */
2517 
2518 STATIC ushort asc_bus[ASC_NUM_BUS] = {
2519         ASC_IS_ISA,
2520         ASC_IS_VL,
2521         ASC_IS_EISA,
2522         ASC_IS_PCI,
2523 };
2524 
2525 /*
2526  * Used with the LILO 'advansys' option to eliminate or
2527  * limit I/O port probing at boot time, cf. advansys_setup().
2528  */
2529 int asc_iopflag = ASC_FALSE;
2530 int asc_ioport[ASC_NUM_BOARD_SUPPORTED] = { 0, 0, 0, 0 };
2531 
2532 #ifdef ADVANSYS_DEBUG
2533 char *
2534 asc_bus_name[ASC_NUM_BUS] = {
2535         "ASC_IS_ISA",
2536         "ASC_IS_VL",
2537         "ASC_IS_EISA",
2538         "ASC_IS_PCI",
2539 };
2540 
2541 int             asc_dbglvl = 0;
2542 #endif /* ADVANSYS_DEBUG */
2543 
2544 
2545 /*
2546  * --- Driver Function Prototypes
2547  *
2548  * advansys.h contains function prototypes for functions global to Linux.
2549  */
2550 
2551 #ifdef LINUX_1_3
2552 STATIC int                      asc_proc_copy(off_t, off_t, char *, int , char *, int);
2553 #endif /* LINUX_1_3 */
2554 STATIC void             advansys_interrupt(int, void *, struct pt_regs *);
2555 STATIC void             advansys_command_done(Scsi_Cmnd *);
2556 STATIC int                      asc_execute_scsi_cmnd(Scsi_Cmnd *);
2557 STATIC void             asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
2558 STATIC void                     asc_execute_pending(struct Scsi_Host *);
2559 STATIC int                      asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *);
2560 STATIC int                      asc_srch_pci_dev(PCI_DEVICE *);
2561 STATIC uchar            asc_scan_method(PCI_DEVICE *);
2562 STATIC int                      asc_pci_find_dev(PCI_DEVICE *);
2563 STATIC void             asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *);
2564 STATIC ushort           asc_get_cfg_word(PCI_DATA *);
2565 STATIC uchar            asc_get_cfg_byte(PCI_DATA *);
2566 STATIC void                     asc_enqueue(struct Scsi_Host *, Scsi_Cmnd *, int, int);
2567 STATIC Scsi_Cmnd        *asc_dequeue(struct Scsi_Host *, int);
2568 STATIC int                      asc_rmqueue(struct Scsi_Host *, Scsi_Cmnd *, int);
2569 
2570 /* XXX - Asc Library Routines not supposed to be used directly */
2571 ushort                  AscGetChipBiosAddress(PortAddr, ushort);
2572 int             AscFindSignature(PortAddr);
2573 
2574 #ifdef ADVANSYS_STATS
2575 STATIC int              asc_prt_stats(char *, int);
2576 STATIC int              asc_prt_stats_line(char *, int, char *fmt, ...);
2577 #endif /* ADVANSYS_STATS */
2578 #ifdef ADVANSYS_DEBUG
2579 STATIC void     asc_prt_scsi_host(struct Scsi_Host *);
2580 STATIC void     asc_prt_dvc_cfg(ASC_DVC_CFG *);
2581 STATIC void     asc_prt_dvc_var(ASC_DVC_VAR *);
2582 STATIC void     asc_prt_scsi_q(ASC_SCSI_Q *);
2583 STATIC void     asc_prt_qdone_info(ASC_QDONE_INFO *);
2584 STATIC void     asc_prt_hex(char *f, uchar *, int);
2585 STATIC int              interrupts_enabled(void);
2586 #endif /* ADVANSYS_DEBUG */
2587 
2588 
2589 /*
2590  * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
2591  */
2592 
2593 #ifdef LINUX_1_3
2594 /*
2595  * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
2596  *
2597  * *buffer: I/O buffer
2598  * **start: if inout == FALSE pointer into buffer where user read should start
2599  * offset: current offset into /proc/scsi/advansys file
2600  * length: length of buffer
2601  * hostno: Scsi_Host host_no
2602  * inout: TRUE - user is writing; FALSE - user is reading
2603  *
2604  * Return the number of bytes read from or written to
2605  * /proc/scsi/advansys file.
2606  */
2607 int
2608 advansys_proc_info(char *buffer, char **start, off_t offset, int length, 
     /* [previous][next][first][last][top][bottom][index][help] */
2609                                    int hostno, int inout)
2610 {
2611         struct Scsi_Host        *shp;
2612         int                                     i;
2613         char                            *cp;
2614         int                                     cplen;
2615         int                                     cnt;
2616         int                                     totcnt;
2617         int                                     leftlen;
2618         char                            *curbuf;
2619         off_t                           advoffset;
2620     Scsi_Device                 *scd;
2621         char                            prtbuf[480];    /* 6 lines */
2622 
2623         ASC_DBG(1, "advansys_proc_info: begin\n");
2624 
2625         /*
2626          * User write not supported.
2627          */
2628         if (inout == TRUE) {
2629                 return(-ENOSYS);
2630         }
2631 
2632         /*
2633          * User read of /proc/scsi/advansys file.
2634          */
2635 
2636         /* Find the specified board. */
2637         for (i = 0; i < asc_board_count; i++) {
2638                 if (asc_host[i]->host_no == hostno) {
2639                         break;
2640                 }
2641         }
2642         if (i == asc_board_count) {
2643                 return(-ENOENT);
2644         }
2645         shp = asc_host[i];
2646 
2647         /* Always copy read data to the beginning of the buffer. */
2648         *start = buffer;
2649 
2650         curbuf = buffer;
2651         advoffset = 0;
2652         totcnt = 0;
2653         leftlen = length;
2654 
2655         /* Get board information. */
2656         cp = (char *) advansys_info(shp);
2657         strcat(cp, "\n");
2658         cplen = strlen(cp);
2659 
2660         /* Copy board information. */
2661         cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2662         totcnt += cnt;
2663         leftlen -= cnt;
2664         if (leftlen == 0) {
2665                 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2666                 return totcnt;
2667         }
2668         advoffset += cplen;
2669         curbuf += cnt;
2670 
2671         /*
2672          * Get and copy information for each device attached to the board.
2673          */
2674         cp = &prtbuf[0];
2675         sprintf(cp, "\nDevices attached to SCSI Host %d:\n", shp->host_no);
2676         cplen = strlen(cp);
2677         cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2678         totcnt += cnt;
2679         leftlen -= cnt;
2680         if (leftlen == 0) {
2681                 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2682                 return totcnt;
2683         }
2684         advoffset += cplen;
2685         curbuf += cnt;
2686 
2687         cp = &prtbuf[0];
2688     for (scd = scsi_devices; scd; scd = scd->next) {
2689                 if (scd->host == shp) {
2690                 proc_print_scsidevice(scd, cp, &cplen, 0);
2691                         cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2692                         totcnt += cnt;
2693                         leftlen -= cnt;
2694                         if (leftlen == 0) {
2695                                 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2696                                 return totcnt;
2697                         }
2698                         advoffset += cplen;
2699                         curbuf += cnt;
2700                 }
2701     }
2702     
2703 #ifdef ADVANSYS_STATS
2704         /*
2705          * prtbuf[] has about 6 lines worth of space. If the statistics ever
2706          * get longer than 6 lines, prtbuf[] should be increased in size. If
2707          * prtbuf[] is too small it will not be overwritten. Instead the user
2708          * just won't get all of the available statistics.
2709          */
2710         cp = &prtbuf[0];
2711         cplen = asc_prt_stats(cp, sizeof(prtbuf));
2712         cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2713         totcnt += cnt;
2714         leftlen -= cnt;
2715         if (leftlen == 0) {
2716                 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2717                 return totcnt;
2718         }
2719         advoffset += cplen;
2720         curbuf += cnt;
2721 #endif /* ADVANSYS_STATS */
2722 
2723         ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2724 
2725         return totcnt;
2726 }
2727 #endif /* LINUX_1_3 */
2728 
2729 
2730 /*
2731  * advansys_detect()
2732  *
2733  * Detect function for AdvanSys adapters.
2734  *
2735  * Argument is a pointer to the host driver's scsi_hosts entry.
2736  *
2737  * Return number of adapters found.
2738  *
2739  * Note: Because this function is called during system initialization
2740  * it must not call SCSI mid-level functions including scsi_malloc()
2741  * and scsi_free().
2742  */
2743 int
2744 advansys_detect(Scsi_Host_Template *tpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
2745 {
2746         static int                      detect_called = ASC_FALSE;
2747         int                                     iop;
2748         int                                     bus;
2749         struct Scsi_Host        *shp;
2750         ASC_DVC_VAR                     *boardp;
2751         int                                     ioport = 0;
2752         PCI_DEVICE                      pciDevice;
2753         PCI_CONFIG_SPACE        pciConfig;
2754         int                                     ret;
2755         extern PortAddr         _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX];
2756 
2757 
2758         if (detect_called == ASC_FALSE) {
2759                 detect_called = ASC_TRUE;
2760         } else {
2761                 printk("AdvanSys SCSI: advansys_detect() mulitple calls ignored\n");
2762                 return 0;
2763         }
2764 
2765         ASC_DBG(1, "advansys_detect: begin\n");
2766 
2767 #ifdef LINUX_1_3
2768         tpnt->proc_dir = &proc_scsi_advansys;
2769 #endif /* LINUX_1_3 */
2770 
2771 #ifdef ADVANSYS_STATS
2772         memset(&asc_stats, 0, sizeof(asc_stats));
2773 #endif /* ADVANSYS_STATS */
2774 
2775         asc_board_count = 0;
2776 
2777         /*
2778          * If I/O port probing has been modified, then verify and
2779          * clean-up the 'asc_ioport' list.
2780          */
2781         if (asc_iopflag == ASC_TRUE) {
2782                 for (ioport = 0; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) {
2783                         ASC_DBG2(1, "asdvansys_detect: asc_ioport[%d] %x\n",
2784                                 ioport, asc_ioport[ioport]);
2785                         if (asc_ioport[ioport] != 0) {
2786                                 for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
2787                                         if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
2788                                                 break;
2789                                         }
2790                                 }
2791                                 if (iop == ASC_IOADR_TABLE_MAX_IX) {
2792                                         printk("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
2793                                                 asc_ioport[ioport]);
2794                                         asc_ioport[ioport] = 0;
2795                                 }
2796                         }
2797                 }
2798                 ioport = 0;
2799         }
2800 
2801         memset(&pciDevice, 0, sizeof(PCI_DEVICE));
2802         memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
2803         pciDevice.maxBusNumber = PCI_MAX_BUS;
2804         pciDevice.endSlot = PCI_MAX_SLOT;
2805 
2806         for (bus = 0; bus < ASC_NUM_BUS; bus++) {
2807 
2808                 ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
2809                         bus, asc_bus_name[bus]);
2810                 iop = 0;
2811 
2812                 while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
2813 
2814                         ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
2815                                 asc_board_count);
2816 
2817                         switch (asc_bus[bus]) {
2818                         case ASC_IS_ISA:
2819                         case ASC_IS_VL:
2820                                 if (asc_iopflag == ASC_FALSE) {
2821                                         iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
2822                                 } else {
2823                                         /*
2824                                          * ISA and VL I/O port scanning has either been
2825                                          * eliminated or limited to selected ports on
2826                                          * the LILO command line, /etc/lilo.conf, or
2827                                          * by setting variables when the module was loaded.
2828                                          */
2829                                         ASC_DBG(1, "advansys_detect: I/O port scanning modified\n");
2830                                 ioport_try_again:
2831                                         iop = 0;
2832                                         for (; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) {
2833                                                 if ((iop = asc_ioport[ioport]) != 0) {
2834                                                         break;
2835                                                 }
2836                                         }
2837                                         if (iop) {
2838                                                 ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n",
2839                                                         iop);
2840                                                 if (check_region(iop, ASC_IOADR_GAP) != 0) {
2841                                                         printk("AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
2842                                                         /* Don't try this I/O port twice. */
2843                                                         asc_ioport[ioport] = 0;
2844                                                         goto ioport_try_again;
2845                                                 } else if (AscFindSignature(iop) == ASC_FALSE) {
2846                                                         printk("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
2847                                                         /* Don't try this I/O port twice. */
2848                                                         asc_ioport[ioport] = 0;
2849                                                         goto ioport_try_again;
2850                                                 } else {
2851                                                         /*
2852                                                          * If this isn't an ISA board, then it must be
2853                                                          * a VL board. If currently looking an ISA
2854                                                          * board is being looked for then try for
2855                                                          * another ISA board in 'asc_ioport'.
2856                                                          */
2857                                                         if (asc_bus[bus] == ASC_IS_ISA &&
2858                                                             (AscGetChipVersion(iop, ASC_IS_ISA) &
2859                                                                  ASC_CHIP_VER_ISA_BIT) == 0) {
2860                                                                 /*
2861                                                                  * Don't clear 'asc_ioport[ioport]'. Try
2862                                                                  * this board again for VL. Increment
2863                                                                  * 'ioport' past this board.
2864                                                                  */
2865                                                                  ioport++;
2866                                                                  goto ioport_try_again;
2867                                                         }
2868                                                 }
2869                                                 /*
2870                                                  * This board appears good, don't try the I/O port
2871                                                  * again by clearing its value. Increment 'ioport'
2872                                                  * for the next iteration.
2873                                                  */
2874                                                 asc_ioport[ioport++] = 0;
2875                                         }
2876                                 }
2877                                 break;
2878 
2879                         case ASC_IS_EISA:
2880                                 iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
2881                                 break;
2882 
2883                         case ASC_IS_PCI:
2884                                         if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
2885                                                 iop = 0;
2886                                         } else {
2887                                                 ASC_DBG2(2,
2888                                                         "advansys_detect: slotFound %d, busNumber %d\n",
2889                                                         pciDevice.slotFound, pciDevice.busNumber);
2890                                                 asc_get_pci_cfg(&pciDevice, &pciConfig);
2891                                                 iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
2892                                                 ASC_DBG2(2, "advansys_detect: iop %x, irqLine %d\n",
2893                                                         iop, pciConfig.irqLine);
2894                                         }
2895                                 break;
2896 
2897                         default:
2898                                 ASC_DBG(0, "advansys_detect: unknown bus type\n");
2899                                 break;
2900                         }
2901                         ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
2902 
2903                         /*
2904                          * Adapter not found, try next bus type.
2905                          */
2906                         if (iop == 0) {
2907                                 break;
2908                         }
2909 
2910                         /*
2911                          * Adapter found.
2912                          *
2913                          * Register the adapter, get its configuration, and
2914                          * initialize it.
2915                          */
2916                         ASC_DBG(2, "advansys_detect: scsi_register()\n");
2917                         shp = scsi_register(tpnt, sizeof(struct asc_board));
2918 
2919                         /* Save a pointer to the Scsi_host of each found board. */
2920                         asc_host[asc_board_count++] = shp;
2921 
2922                         /* Initialize private per board data */
2923                         memset(ASC_BOARD(shp), 0, sizeof(struct asc_board));
2924                         boardp = &ASC_BOARD(shp)->board;
2925                         boardp->cfg = &ASC_BOARD(shp)->cfg;
2926                         boardp->cfg->overrun_buf = &ASC_BOARD(shp)->overrun_buf[0];
2927                         boardp->iop_base = iop;
2928 
2929                         /*
2930                          * Set the board bus type and PCI IRQ for AscInitGetConfig().
2931                          */
2932                         boardp->bus_type = asc_bus[bus];
2933                         switch (boardp->bus_type) {
2934                         case ASC_IS_ISA:
2935                                 shp->unchecked_isa_dma = TRUE;
2936                                 break;
2937                         case ASC_IS_EISA:
2938                                 shp->unchecked_isa_dma = FALSE;
2939                                 break;
2940                         case ASC_IS_VL:
2941                                 shp->unchecked_isa_dma = FALSE;
2942                                 break;
2943                         case ASC_IS_PCI:
2944                                 shp->irq = boardp->irq_no = pciConfig.irqLine;
2945                                 boardp->cfg->pci_device_id = pciConfig.deviceID;
2946                                 shp->unchecked_isa_dma = FALSE;
2947                                 break;
2948                         default:
2949                                 ASC_DBG(0, "advansys_detect: unknown adapter type");
2950                                 shp->unchecked_isa_dma = TRUE;
2951                                 break;
2952                         }
2953 
2954                         /*
2955                          * Get the board configuration.  AscInitGetConfig() may change
2956                          * the board's bus_type value. The asc_bus[bus] value should no
2957                          * longer be used.
2958                          */
2959                         ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
2960                         switch(ret = AscInitGetConfig(boardp)) {
2961                         case 0: /* No error */
2962                                 break;
2963                         case ASC_WARN_IO_PORT_ROTATE:
2964                                 ASC_DBG(0, "AscInitGetConfig: I/O port address modified\n");
2965                                 break;
2966                         case ASC_WARN_EEPROM_CHKSUM:
2967                                 ASC_DBG(0, "AscInitGetConfig: EEPROM checksum error\n");
2968                                 break;
2969                         case ASC_WARN_IRQ_MODIFIED:
2970                                 ASC_DBG(0, "AscInitGetConfig: IRQ modified\n");
2971                                 break;
2972                         case ASC_WARN_CMD_QNG_CONFLICT:
2973                                 ASC_DBG(0,
2974                                         "AscInitGetConfig: Tag queuing enabled w/o disconnects\n");
2975                                 break;
2976                         default:
2977                                 ASC_DBG1(0, "AscInitGetConfig: Unknown warning: %x\n", ret);
2978                                 break;
2979                         }
2980                         if (boardp->err_code != 0) {
2981                                 ASC_DBG2(0,
2982                                         "AscInitGetConfig: error: init_state %x, err_code %x\n",
2983                                         boardp->init_state, boardp->err_code);
2984                                 scsi_unregister(shp);
2985                                 asc_board_count--;
2986                                 continue;
2987                         }
2988 
2989                         /*
2990                          * Modify board configuration.
2991                          */
2992                         boardp->isr_callback = (Ptr2Func) asc_isr_callback;
2993                         boardp->exe_callback = (Ptr2Func) NULL;
2994 
2995                         ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
2996                         switch (ret = AscInitSetConfig(boardp)) {
2997                         case 0: /* No error. */
2998                                 break;
2999                         case ASC_WARN_IO_PORT_ROTATE:
3000                                 ASC_DBG(0, "AscInitSetConfig: I/O port address modified\n");
3001                                 break;
3002                         case ASC_WARN_EEPROM_CHKSUM:
3003                                 ASC_DBG(0, "AscInitSetConfig: EEPROM checksum error\n");
3004                                 break;
3005                         case ASC_WARN_IRQ_MODIFIED:
3006                                 ASC_DBG(0, "AscInitSetConfig: IRQ modified\n");
3007                                 break;
3008                         case ASC_WARN_CMD_QNG_CONFLICT:
3009                                 ASC_DBG(0, "AscInitSetConfig: Tag queuing w/o disconnects\n");
3010                                 break;
3011                         default:
3012                                 ASC_DBG1(0, "AscInitSetConfig: Unknown warning: %x\n", ret);
3013                                 break;
3014                         }
3015                         if (boardp->err_code != 0) {
3016                                 ASC_DBG2(0,
3017                                         "AscInitSetConfig: error: init_state %x, err_code %x\n",
3018                                         boardp->init_state, boardp->err_code);
3019                                 scsi_unregister(shp);
3020                                 asc_board_count--;
3021                                 continue;
3022                         }
3023 
3024                         /*
3025                          * Finish initializing the 'Scsi_Host' structure.
3026                          */
3027 
3028                         /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
3029                         if (boardp->bus_type != ASC_IS_PCI) {
3030                                 shp->irq = boardp->irq_no;
3031                         }
3032 
3033                         shp->io_port = boardp->iop_base;
3034                         shp->n_io_port = ASC_IOADR_GAP;
3035                         shp->this_id = boardp->cfg->chip_scsi_id;
3036 
3037                         /* Maximum number of queues this adapter can handle. */
3038                         shp->can_queue = boardp->max_total_qng;
3039 
3040                         /*
3041                          * XXX - Command queuing limits are maintained per target
3042                          * by AdvanSys adapters. Set 'cmd_per_lun' to the minimum
3043                          * value of the all the target settings for the adapter.
3044                          *
3045                          * For now set 'cmd_per_lun' to 'max_total_qng'. This
3046                          * value should be adjusted every time a new device is
3047                          * found in asc_init_dev().
3048                          *
3049                          * XXX - memory allocation is done by the mid-level scsi
3050                          * driver based on 'cmd_per_lun'. If 'sg_tablesize' is too large
3051                          * allocation failures can occur in scsi_register_host().
3052                          * A 'Scsi_Cmnd' structure is pre-allocated for each command
3053                          * also DMA memory is reserved. Set it artificially low for now.
3054                          *
3055                          * shp->cmd_per_lun = boardp->max_total_qng;
3056                          */
3057 #ifdef MODULE
3058                         shp->cmd_per_lun = 1;
3059 #else /* MODULE */
3060                         shp->cmd_per_lun = 4;
3061 #endif /* MODULE */
3062                         ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
3063                         
3064                         /* Maximum number of scatter-gather elements adapter can handle. */
3065                         /*
3066                          * XXX - memory allocation is done by the mid-level scsi
3067                          * driver based on sg_tablesize. If 'sg_tablesize' is too large
3068                          * allocation failures can occur in scsi_register_host().
3069                          */
3070 #ifdef MODULE
3071                         shp->sg_tablesize = 8;
3072 #else /* MODULE */
3073                         shp->sg_tablesize = ASC_MAX_SG_LIST;
3074 #endif /* MODULE */
3075                         ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
3076                                 shp->sg_tablesize);
3077 
3078                         /* BIOS start address. */
3079                         shp->base = (char *) ((ulong) AscGetChipBiosAddress(
3080                                                                                                 boardp->iop_base,
3081                                                                                                 boardp->bus_type));
3082 
3083                         /*
3084                          * Register Board Resources - I/O Port, DMA, IRQ
3085                          */
3086 
3087                         /* Register I/O port range */
3088                         ASC_DBG(2, "advansys_detect: request_region()\n");
3089                         request_region(shp->io_port, shp->n_io_port, "advansys");
3090 
3091                         /* Register DMA channel for ISA bus. */
3092                         if ((boardp->bus_type & ASC_IS_ISA) == 0) {
3093                                 shp->dma_channel = NO_ISA_DMA;
3094                         } else {
3095                                 shp->dma_channel = boardp->cfg->isa_dma_channel;
3096                                 if ((ret = request_dma(shp->dma_channel, "advansys")) != 0) {
3097                                         ASC_DBG2(0, "advansys_detect: request_dma() %d failed %d\n",
3098                                                 shp->dma_channel, ret);
3099                                         release_region(shp->io_port, shp->n_io_port);
3100                                         scsi_unregister(shp);
3101                                         asc_board_count--;
3102                                         continue;
3103                                 }
3104                                 AscEnableIsaDma(shp->dma_channel);
3105                         }
3106 
3107                         /* Register IRQ Number. */
3108                         ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
3109                         if ((ret = request_irq(shp->irq, advansys_interrupt,
3110                                                                 SA_INTERRUPT, "advansys", NULL)) != 0) {
3111                                 ASC_DBG1(0, "advansys_detect: request_irq() failed %d\n", ret);
3112                                 release_region(shp->io_port, shp->n_io_port);
3113                                 if (shp->dma_channel != NO_ISA_DMA) {
3114                                         free_dma(shp->dma_channel);
3115                                 }
3116                                 scsi_unregister(shp);
3117                                 asc_board_count--;
3118                                 continue;
3119                         }
3120 
3121                         /*
3122                          * Initialize board RISC chip and enable interrupts.
3123                          */
3124                         ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
3125                         if (AscInitAsc1000Driver(boardp)) {
3126                                 ASC_DBG2(0,
3127                                         "AscInitAsc1000Driver: error: init_state %x, err_code %x\n",
3128                                         boardp->init_state, boardp->err_code);
3129                                 release_region(shp->io_port, shp->n_io_port);
3130                                 if (shp->dma_channel != NO_ISA_DMA) {
3131                                         free_dma(shp->dma_channel);
3132                                 }
3133                                 free_irq(shp->irq, NULL);
3134                                 scsi_unregister(shp);
3135                                 asc_board_count--;
3136                                 continue;
3137                         }
3138                         ASC_DBG_PRT_SCSI_HOST(2, shp);
3139                 }
3140         }
3141 
3142         ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
3143         return asc_board_count;
3144 }
3145 
3146 /*
3147  * advansys_release()
3148  *
3149  * Release resources allocated for a single AdvanSys adapter.
3150  */
3151 int
3152 advansys_release(struct Scsi_Host *shp)
     /* [previous][next][first][last][top][bottom][index][help] */
3153 {
3154         ASC_DBG(1, "advansys_release: begin\n");
3155         free_irq(shp->irq, NULL);
3156         if (shp->dma_channel != NO_ISA_DMA) {
3157                 ASC_DBG(1, "advansys_release: free_dma()\n");
3158                 free_dma(shp->dma_channel);
3159         }
3160         release_region(shp->io_port, shp->n_io_port);
3161         scsi_unregister(shp);
3162         ASC_DBG(1, "advansys_release: end\n");
3163         return 0;
3164 }
3165 
3166 /*
3167  * advansys_info()
3168  *
3169  * Return suitable for printing on the console with the argument
3170  * adapter's configuration information.
3171  */
3172 const char *
3173 advansys_info(struct Scsi_Host *shp)
     /* [previous][next][first][last][top][bottom][index][help] */
3174 {
3175         static char     info[128];
3176         ASC_DVC_VAR             *boardp;
3177         char                    *busname;
3178 
3179         boardp = &ASC_BOARD(shp)->board;
3180         ASC_DBG(1, "advansys_info: begin\n");
3181         if (boardp->bus_type & ASC_IS_ISA) {
3182                 sprintf(info,
3183                         "AdvanSys SCSI %s: ISA (%u CDB): BIOS %X, IO %X-%X, IRQ %u, DMA %u",
3184                         ASC_VERSION, ASC_BOARD(shp)->board.max_total_qng,
3185                         (unsigned) shp->base, shp->io_port,
3186                         shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel);
3187         } else {
3188                 switch (boardp->bus_type) {
3189                 case ASC_IS_EISA:
3190                         busname = "EISA";
3191                         break;
3192                 case ASC_IS_VL:
3193                         busname = "VL";
3194                         break;
3195                 case ASC_IS_PCI:
3196                         busname = "PCI";
3197                         break;
3198                 default:
3199                         busname = "?";
3200                         ASC_DBG1(0, "advansys_info: unknown bus type %d\n",
3201                                 boardp->bus_type);
3202                         break;
3203                 }
3204                 /* No DMA channel for non-ISA busses. */
3205                 sprintf(info,
3206                         "AdvanSys SCSI %s: %s (%u CDB): BIOS %X, IO %X-%X, IRQ %u",
3207                         ASC_VERSION, busname, ASC_BOARD(shp)->board.max_total_qng,
3208                         (unsigned) shp->base, shp->io_port,
3209                         shp->io_port + (shp->n_io_port - 1), shp->irq);
3210         }
3211         ASC_DBG(1, "advansys_info: end\n");
3212         return info;
3213 }
3214 
3215 /*
3216  * advansys_command()
3217  *
3218  * Polled-I/O. Apparently host drivers shouldn't return until
3219  * command is finished.
3220  *
3221  * XXX - Can host drivers block here instead of spinning on command status?
3222  */
3223 int
3224 advansys_command(Scsi_Cmnd *scp)
     /* [previous][next][first][last][top][bottom][index][help] */
3225 {
3226         ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
3227         ASC_STATS(command);
3228         scp->SCp.Status = 0; /* Set to a known state */
3229         advansys_queuecommand(scp, advansys_command_done);
3230         while (scp->SCp.Status == 0) {
3231                 continue;
3232         }
3233         ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
3234         return scp->result;
3235 }
3236 
3237 /*
3238  * advansys_queuecommand()
3239  *
3240  * This function always returns 0. Command return status is saved
3241  * in the 'scp' result field.
3242  */
3243 int
3244 advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
3245 {
3246         struct Scsi_Host                *shp;
3247         int                                             flags = 0;
3248         int                                             interrupts_disabled;
3249 
3250         ASC_STATS(queuecommand);
3251         shp = scp->host;
3252 
3253 #ifdef LINUX_1_2
3254         /*
3255          * For LINUX_1_3, if statistics are enabled they can be accessed
3256          * by reading /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)].
3257          */
3258 #ifdef ADVANSYS_STATS_1_2_PRINT
3259         /* Display statistics every 10000 commands. */
3260         if ((asc_stats.queuecommand % 10000) == 0) {
3261                 printk("\n");
3262                 (void) asc_prt_stats(NULL, 0);
3263                 printk("\n");
3264         }
3265 #endif /* ADVANSYS_STATS_1_2_PRINT */
3266 #endif /* LINUX_1_2 */
3267 
3268         /*
3269          * If there are any pending commands for this board before trying
3270          * to execute them, disable interrupts to preserve request ordering.
3271          *
3272          * The typical case will be no pending commands and interrupts
3273          * not disabled.
3274          */
3275         if (ASC_BOARD(shp)->pending_tidmask == 0) {
3276                 interrupts_disabled = ASC_FALSE;
3277         } else {
3278                 ASC_STATS(cmd_disable);
3279                 /* Disable interrupts */
3280                 interrupts_disabled = ASC_TRUE;
3281                 save_flags(flags);
3282                 cli();
3283                 ASC_DBG1(1, "advansys_queuecommand: asc_execute_pending() %x\n",
3284                         ASC_BOARD(shp)->pending_tidmask);
3285                 asc_execute_pending(shp);
3286         }
3287 
3288         /*
3289          * Save the function pointer to Linux mid-level 'done' function and
3290          * execute the command.
3291          */
3292         scp->scsi_done = done;
3293         if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) {
3294                 if (interrupts_disabled == ASC_FALSE) {
3295                         save_flags(flags);
3296                         cli();
3297                         interrupts_disabled = ASC_TRUE;
3298                 }
3299                 asc_enqueue(shp, scp, scp->target, ASC_BACK);
3300         }
3301 
3302         if (interrupts_disabled == ASC_TRUE) {
3303                 restore_flags(flags);
3304         }
3305 
3306         return 0;
3307 }
3308 
3309 /*
3310  * advansys_abort()
3311  *
3312  * Abort the specified command and reset the device
3313  * associated with the command 'scp'.
3314  */
3315 int
3316 advansys_abort(Scsi_Cmnd *scp)
     /* [previous][next][first][last][top][bottom][index][help] */
3317 {
3318         ASC_DVC_VAR             *boardp;
3319         int                             flags;
3320         int                             ret;
3321 
3322         ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
3323         save_flags(flags);
3324         cli();
3325         ASC_STATS(abort);
3326         if (scp->host == NULL) {
3327                 scp->result = HOST_BYTE(DID_ERROR);
3328                 ret = SCSI_ABORT_ERROR;
3329         } else if (asc_rmqueue(scp->host, scp, scp->target) == ASC_TRUE) {
3330                 scp->result = HOST_BYTE(DID_ABORT);
3331                 ret = SCSI_ABORT_SUCCESS;
3332                 (void) AscResetDevice(&ASC_BOARD(scp->host)->board, scp->target);
3333         } else {
3334                 /* Must enable interrupts for AscAbortSRB() */
3335                 sti();
3336                 boardp = &ASC_BOARD(scp->host)->board;
3337                 scp->result = HOST_BYTE(DID_ABORT);
3338                 switch (AscAbortSRB(boardp, (ulong) scp)) {
3339                 case ASC_TRUE:
3340                         /* asc_isr_callback() will be called */
3341                         ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
3342                         ret = SCSI_ABORT_PENDING;
3343                         break;
3344                 case ASC_FALSE:
3345                         /* Request has apparently already completed. */
3346                         ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
3347                         ret = SCSI_ABORT_NOT_RUNNING;
3348                         break;
3349                 case ASC_ERROR:
3350                 default:
3351                         ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
3352                         ret = SCSI_ABORT_ERROR;
3353                         break;
3354                 }
3355                 (void) AscResetDevice(boardp, scp->target);
3356         }
3357         restore_flags(flags);
3358         ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
3359         return ret;
3360 }
3361 
3362 /*
3363  * advansys_reset()
3364  *
3365  * Reset all devices and the SCSI bus for the board
3366  * associated with 'scp'.
3367  */
3368 int
3369 advansys_reset(Scsi_Cmnd *scp)
     /* [previous][next][first][last][top][bottom][index][help] */
3370 {
3371         ASC_DVC_VAR             *boardp;
3372         int                             flags;
3373         Scsi_Cmnd               *tscp;
3374         int                             i;
3375         int                             ret;
3376 
3377         ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
3378         save_flags(flags);
3379         cli();
3380         ASC_STATS(reset);
3381         if (scp->host == NULL) {
3382                 scp->result = HOST_BYTE(DID_ERROR);
3383                 ret = SCSI_RESET_ERROR;
3384         } else {
3385                 /* Remove any pending commands, set DID_RESET, and done them.  */
3386                 for (i = 0; i < ASC_MAX_TID; i++) {
3387                         while ((tscp = asc_dequeue(scp->host, i)) != NULL) {
3388                                 tscp->result = HOST_BYTE(DID_RESET);
3389                                 tscp->scsi_done(tscp);
3390                         }
3391                 }
3392                 /*
3393                  * XXX - Host drivers should not modify the timeout field.
3394                  * Allow the SCSI bus reset more time to complete.
3395                  */
3396                 scp->timeout += 2000;   /* Add 5 seconds to the request timeout. */
3397 
3398                 /* Must enable interrupts for AscResetSB() */
3399                 sti();
3400                 boardp = &ASC_BOARD(scp->host)->board;
3401                 scp->result = HOST_BYTE(DID_RESET);
3402                 switch (AscResetSB(boardp)) {
3403                 case ASC_TRUE:
3404                         ASC_DBG(1, "advansys_reset: AscResetSB() TRUE\n");
3405                         ret = SCSI_RESET_SUCCESS;
3406                         break;
3407                 case ASC_ERROR:
3408                 default:
3409                         ASC_DBG(1, "advansys_reset: AscResetSB() ERROR\n");
3410                         ret = SCSI_RESET_ERROR;
3411                         break;
3412                 }
3413         }
3414         restore_flags(flags);
3415         ASC_DBG1(1, "advansys_reset: ret %d", ret);
3416         return ret;
3417 }
3418 
3419 /*
3420  * advansys_biosparam()
3421  *
3422  * Translate disk drive geometry if the "BIOS greater than 1 GB"
3423  * support is enabled for a drive.
3424  *
3425  * ip (information pointer) is an int array with the following definition:
3426  * ip[0]: heads
3427  * ip[1]: sectors
3428  * ip[2]: cylinders
3429  */
3430 int
3431 #ifdef LINUX_1_2
3432 advansys_biosparam(Disk *dp, int dep, int ip[])
     /* [previous][next][first][last][top][bottom][index][help] */
3433 #else /* LINUX_1_3 */
3434 advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
3435 #endif /* LINUX_1_3 */
3436 {
3437         ASC_DBG(1, "advansys_biosparam: begin\n");
3438         ASC_STATS(biosparam);
3439         if ((ASC_BOARD(dp->device->host)->board.dvc_cntl & ASC_CNTL_BIOS_GT_1GB) &&
3440                 dp->capacity > 0x200000) {
3441                         ip[0] = 255;
3442                         ip[1] = 63;
3443         } else {
3444                         ip[0] = 64;
3445                         ip[1] = 32;
3446         }
3447         ip[2] = dp->capacity / (ip[0] * ip[1]);
3448         ASC_DBG(1, "advansys_biosparam: end\n");
3449         return 0;
3450 }
3451 
3452 /*
3453  * advansys_setup()
3454  *
3455  * This function is called from init/main.c at boot time.
3456  * It it passed LILO parameters that can be set from the
3457  * LILO command line or in /etc/lilo.conf.
3458  *
3459  * It is used by the AdvanSys driver to either disable I/O
3460  * port scanning or to limit scanning to 1 - 4 I/O ports.
3461  * Regardless of the option setting EISA and PCI boards
3462  * will still be searched for and detected. This option
3463  * only affects searching for ISA and VL boards.
3464  *
3465  * If ADVANSYS_DEBUG is defined the driver debug level may
3466  * be set using the 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port.
3467  *
3468  * Examples:
3469  * 1. Eliminate I/O port scanning:
3470  *              boot: linux advansys=
3471  *       or
3472  *              boot: linux advansys=0x0
3473  * 2. Limit I/O port scanning to one I/O port:
3474  *              boot: linux advansys=0x110
3475  * 3. Limit I/O port scanning to four I/O ports:
3476  *              boot: linux advansys=0x110,0x210,0x230,0x330
3477  * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
3478  *    set the driver debug level to 2.
3479  *              boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
3480  *
3481  * ints[0] - number of arguments
3482  * ints[1] - first argument
3483  * ints[2] - second argument
3484  * ...
3485  */
3486 void
3487 advansys_setup(char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
3488 {
3489         int     i;
3490 
3491         if (asc_iopflag == ASC_TRUE) {
3492                 printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
3493                 return;
3494         }
3495 
3496         asc_iopflag = ASC_TRUE;
3497 
3498         if (ints[0] > ASC_NUM_BOARD_SUPPORTED) {
3499 #ifdef ADVANSYS_DEBUG
3500                 if ((ints[0] == ASC_NUM_BOARD_SUPPORTED + 1) &&
3501                     (ints[ASC_NUM_BOARD_SUPPORTED + 1] >> 4 == 0xdeb)) {
3502                         asc_dbglvl = ints[ASC_NUM_BOARD_SUPPORTED + 1] & 0xf;
3503                 } else {
3504 #endif /* ADVANSYS_DEBUG */
3505                         printk("AdvanSys SCSI: only %d I/O ports accepted\n",
3506                                 ASC_NUM_BOARD_SUPPORTED);
3507 #ifdef ADVANSYS_DEBUG
3508                 }
3509 #endif /* ADVANSYS_DEBUG */
3510         }
3511 
3512 #ifdef ADVANSYS_DEBUG
3513         ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
3514         for (i = 1; i < ints[0]; i++) {
3515                 ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
3516         }
3517         ASC_DBG(1, "\n");
3518 #endif /* ADVANSYS_DEBUG */
3519 
3520         for (i = 1; i <= ints[0] && i <= ASC_NUM_BOARD_SUPPORTED; i++) {
3521                 asc_ioport[i-1] = ints[i];
3522                 ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
3523                         i - 1, asc_ioport[i-1]);
3524         }
3525 }
3526 
3527 
3528 /*
3529  * --- Loadable Driver Support
3530  */
3531 
3532 #ifdef MODULE
3533 Scsi_Host_Template driver_template = ADVANSYS;
3534 # include "scsi_module.c"
3535 #endif /* MODULE */
3536 
3537 
3538 /*
3539  * --- Miscellaneous Driver Functions
3540  */
3541 
3542 #ifdef LINUX_1_3
3543 /*
3544  * asc_proc_copy() 
3545  *
3546  * Copy proc information to a read buffer considering the current read
3547  * offset in the file and the remaining space in the read buffer.
3548  */
3549 STATIC int
3550 asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
     /* [previous][next][first][last][top][bottom][index][help] */
3551                           char *cp, int cplen)
3552 {
3553         int cnt = 0;
3554         
3555         ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
3556                         (unsigned) offset, (unsigned) advoffset, cplen);
3557         if (offset <= advoffset) {
3558                 /* Read offset below current offset, copy everything. */
3559                 cnt = min(cplen, leftlen);
3560                 ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
3561                                 (unsigned) curbuf, (unsigned) cp, cnt);
3562                 memcpy(curbuf, cp, cnt);
3563         } else if (offset < advoffset + cplen) {
3564                 /* Read offset within current range, partial copy. */
3565                 cnt = (advoffset + cplen) - offset;
3566                 cp = (cp + cplen) - cnt;
3567                 cnt = min(cnt, leftlen);
3568                 ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
3569                                 (unsigned) curbuf, (unsigned) cp, cnt);
3570                 memcpy(curbuf, cp, cnt);
3571         }
3572         return cnt;
3573 }
3574 #endif /* LINUX_1_3 */
3575 
3576 /*
3577  * First-level interrupt handler.
3578  */
3579 STATIC void
3580 advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
3581 {
3582         int                     i;
3583         int                     flags;
3584         Scsi_Cmnd       *scp;
3585         Scsi_Cmnd       *tscp;
3586 
3587         /* Disable interrupts, if the aren't already disabled. */
3588         save_flags(flags);
3589         cli();
3590 
3591         ASC_DBG(1, "advansys_interrupt: begin\n");
3592         ASC_STATS(interrupt);
3593         /*
3594          * Check for interrupts on all boards.
3595          * AscISR() will call asc_isr_callback().
3596          */
3597         for (i = 0; i < asc_board_count; i++) {
3598                 while (AscIsIntPending(asc_host[i]->io_port)) {
3599                         ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
3600                         AscISR(&ASC_BOARD(asc_host[i])->board);
3601                 }
3602         }
3603         ASC_DBG(1, "advansys_interrupt: end\n");
3604 
3605         /*
3606          * While interrupts are still disabled save the list of requests that
3607          * need their done function called. After re-enabling interrupts call
3608          * the done function which may re-enable interrupts anyway.
3609          */
3610         if ((scp = asc_scsi_done) != NULL) {
3611                 asc_scsi_done = NULL;
3612         }
3613 
3614         /* Re-enable interrupts, if they were enabled on entry. */
3615         restore_flags(flags);
3616 
3617         while (scp) {
3618                 tscp = (Scsi_Cmnd *) scp->host_scribble;
3619                 scp->scsi_done(scp);
3620                 scp = tscp;
3621         }
3622 
3623         return;
3624 }
3625 
3626 /*
3627  * Function used only with polled I/O requests that are initiated by
3628  * advansys_command().
3629  */
3630 STATIC void
3631 advansys_command_done(Scsi_Cmnd *scp)
     /* [previous][next][first][last][top][bottom][index][help] */
3632 {
3633         ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
3634         scp->SCp.Status = 1;
3635 }
3636 
3637 /*
3638  * Execute a single 'Scsi_Cmnd'.
3639  *
3640  * The function 'done' is called when the request has been completed.
3641  *
3642  * Scsi_Cmnd:
3643  *
3644  *  host - board controlling device
3645  *  device - device to send command
3646  *  target - target of device
3647  *  lun - lun of device
3648  *  cmd_len - length of SCSI CDB
3649  *      cmnd - buffer for SCSI 8, 10, or 12 byte CDB
3650  *  use_sg - if non-zero indicates scatter-gather request with use_sg elements
3651  *
3652  *  if (use_sg == 0)
3653  *              request_buffer - buffer address for request
3654  *              request_bufflen - length of request buffer
3655  *  else
3656  *              request_buffer - pointer to scatterlist structure
3657  *
3658  *  sense_buffer - sense command buffer
3659  *
3660  *  result (4 bytes of an int):
3661  *   Byte Meaning
3662  *   0    SCSI Status Byte Code
3663  *   1    SCSI One Byte Message Code
3664  *   2    Host Error Code
3665  *   3    Mid-Level Error Code
3666  *
3667  *  host driver fields:
3668  *  SCp - Scsi_Pointer used for command processing status
3669  *  scsi_done - used to save caller's done function
3670  *      host_scribble - used for pointer to another Scsi_Cmnd
3671  *
3672  * If this function returns ASC_NOERROR or ASC_ERROR the done
3673  * function has been called. If ASC_BUSY is returned the request
3674  * must be enqueued by the caller and re-tried later.
3675  */
3676 STATIC int
3677 asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
     /* [previous][next][first][last][top][bottom][index][help] */
3678 {
3679         ASC_DVC_VAR             *boardp;
3680         ASC_SCSI_Q              scsiq;
3681         ASC_SG_HEAD             sghead;
3682         int                             ret;
3683 
3684         ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
3685                 (unsigned) scp, (unsigned) scp->scsi_done);
3686 
3687         boardp = &ASC_BOARD(scp->host)->board;
3688 
3689         /*
3690          * If this is the first command, then initialize the device. If
3691          * no device is found set 'DID_BAD_TARGET' and return.
3692          */
3693         if ((ASC_BOARD(scp->host)->init_tidmask &
3694                  ASC_TIX_TO_TARGET_ID(scp->target)) == 0) {
3695                 if (asc_init_dev(boardp, scp) == ASC_FALSE) {
3696                         scp->result = HOST_BYTE(DID_BAD_TARGET);
3697                         scp->scsi_done(scp);
3698                         return ASC_ERROR;
3699                 }
3700                 ASC_BOARD(scp->host)->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target);
3701         }
3702 
3703         memset(&scsiq, 0, sizeof(ASC_SCSI_Q));
3704 
3705         /*
3706          * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
3707          */
3708         scsiq.q2.srb_ptr = (ulong) scp;
3709 
3710         /*
3711          * Build the ASC_SCSI_Q request.
3712          */
3713         scsiq.cdbptr = &scp->cmnd[0];
3714         scsiq.q2.cdb_len = scp->cmd_len;
3715         scsiq.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
3716         scsiq.q1.target_lun = scp->lun;
3717         scsiq.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
3718         scsiq.q1.sense_addr = (ulong) &scp->sense_buffer[0];
3719         scsiq.q1.sense_len = sizeof(scp->sense_buffer);
3720         scsiq.q2.tag_code = M2_QTAG_MSG_SIMPLE;
3721 
3722         /*
3723          * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
3724          * buffer command.
3725          */
3726         if (scp->use_sg == 0) {
3727                 /*
3728                  * CDB request of single contiguous buffer.
3729                  */
3730                 ASC_STATS(cont_cnt);
3731                 /* request_buffer is already a real address. */
3732                 scsiq.q1.data_addr = (ulong) scp->request_buffer;
3733                 scsiq.q1.data_cnt = scp->request_bufflen;
3734                 ASC_STATS_ADD(cont_xfer, (scp->request_bufflen + 511) >> 9);
3735                 scsiq.q1.sg_queue_cnt = 0;
3736                 scsiq.sg_head = NULL;
3737         } else {
3738                 /*
3739                  * CDB scatter-gather request list.
3740                  */
3741                 int                                     sgcnt;
3742                 struct scatterlist      *slp;
3743 
3744                 if (scp->use_sg > ASC_MAX_SG_LIST) {
3745                         ASC_DBG2(0, "asc_execute_scsi_cmnd: use_sg %d > %d\n",
3746                                 scp->use_sg, ASC_MAX_SG_LIST);
3747                         scp->result = HOST_BYTE(DID_ERROR);
3748                         scp->scsi_done(scp);
3749                         return ASC_ERROR;
3750                 }
3751 
3752                 ASC_STATS(sg_cnt);
3753 
3754                 /*
3755                  * Allocate a ASC_SG_HEAD structure and set the ASC_SCSI_Q
3756                  * to point to it.
3757                  */
3758                 memset(&sghead, 0, sizeof(ASC_SG_HEAD));
3759 
3760                 scsiq.q1.cntl |= QC_SG_HEAD;
3761                 scsiq.sg_head = &sghead;
3762                 scsiq.q1.data_cnt = 0;
3763                 scsiq.q1.data_addr = 0;
3764                 sghead.entry_cnt = scsiq.q1.sg_queue_cnt = scp->use_sg;
3765                 ASC_STATS_ADD(sg_elem, sghead.entry_cnt);
3766 
3767                 /*
3768                  * Convert scatter-gather list into ASC_SG_HEAD list.
3769                  */
3770                 slp = (struct scatterlist *) scp->request_buffer;
3771                 for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
3772                         sghead.sg_list[sgcnt].addr = (ulong) slp->address;
3773                         sghead.sg_list[sgcnt].bytes = slp->length;
3774                         ASC_STATS_ADD(sg_xfer, (slp->length + 511) >> 9);
3775                 }
3776         }
3777 
3778         ASC_DBG_PRT_SCSI_Q(2, &scsiq);
3779         ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
3780 
3781         switch (ret = AscExeScsiQueue(boardp, &scsiq)) {
3782         case ASC_NOERROR:
3783                 ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_NOERROR\n");
3784                 break;
3785         case ASC_BUSY:
3786                 /* Caller must enqueue request and retry later. */
3787                 break;
3788         case ASC_ERROR:
3789                 ASC_DBG1(0,
3790                         "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_ERROR err_code %x\n",
3791                         boardp->err_code);
3792                 ASC_STATS(error);
3793                 scp->result = HOST_BYTE(DID_ERROR);
3794                 scp->scsi_done(scp);
3795                 break;
3796         }
3797 
3798         ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
3799         return ret;
3800 }
3801 
3802 /*
3803  * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
3804  */
3805 void
3806 asc_isr_callback(ASC_DVC_VAR *boardp, ASC_QDONE_INFO *qdonep)
     /* [previous][next][first][last][top][bottom][index][help] */
3807 {
3808         Scsi_Cmnd                       *scp;
3809         struct Scsi_Host        *shp;
3810         int                                     flags;
3811         Scsi_Cmnd                       **scpp;
3812 
3813         ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
3814         ASC_DBG2(1, "asc_isr_callback: boardp %x, qdonep %x\n",
3815                 (unsigned) boardp, (unsigned) qdonep);
3816         ASC_STATS(callback);
3817         ASC_DBG_PRT_QDONE_INFO(2, qdonep);
3818 
3819         /*
3820          * Get the Scsi_Cmnd structure and Scsi_Host structure for the
3821          * command that has been completed.
3822          */
3823         scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
3824         ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
3825         ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
3826 
3827         shp = scp->host;
3828         ASC_ASSERT(shp);
3829         ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
3830 
3831         /*
3832          * 'qdonep' contains the command's ending status.
3833          */
3834         switch (qdonep->d3.done_stat) {
3835         case QD_NO_ERROR:
3836                 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
3837                 switch (qdonep->d3.host_stat) {
3838                 case QHSTA_NO_ERROR:
3839                         scp->result = 0;
3840                         break;
3841                 default:
3842                         /* QHSTA error occurred */
3843                         scp->result = HOST_BYTE(DID_ERROR);
3844                         break;
3845                 }
3846                 break;
3847 
3848         case QD_WITH_ERROR:
3849                 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
3850                 switch (qdonep->d3.host_stat) {
3851                 case QHSTA_NO_ERROR:
3852                         if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
3853                                 ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
3854                                 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
3855                                         sizeof(scp->sense_buffer));
3856                                 /*
3857                                  * Note: The status_byte() macro used by target drivers
3858                                  * defined in scsi.h shifts the status byte returned by
3859                                  * host drivers right by 1 bit. This is why target drivers
3860                                  * also use left shifted status byte definitions. For instance
3861                                  * target drivers use CHECK_CONDITION, defined to 0x1, instead
3862                                  * of the SCSI defined check condition value of 0x2.
3863                                  */
3864                                 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
3865                                         STATUS_BYTE(qdonep->d3.scsi_stat); 
3866                         } else {
3867                                 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); 
3868                         }
3869                         break;
3870 
3871                 default:
3872                         /* QHSTA error occurred */
3873                         ASC_DBG1(2, "asc_isr_callback: host_stat %x\n",
3874                                 qdonep->d3.host_stat);
3875                         scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
3876                                 STATUS_BYTE(qdonep->d3.scsi_stat);
3877                         break;
3878                 }
3879                 break;
3880 
3881         case QD_ABORTED_BY_HOST:
3882                 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
3883                 scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
3884                                 STATUS_BYTE(qdonep->d3.scsi_stat);
3885                 break;
3886 
3887         default:
3888                 ASC_DBG1(0, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat );
3889                 scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
3890                                 STATUS_BYTE(qdonep->d3.scsi_stat);
3891                 break;
3892         }
3893 
3894         /*
3895          * Before calling 'scsi_done' for the current 'Scsi_Cmnd' and possibly
3896          * triggering more commands to be issued, try to start any pending
3897          * commands.
3898          */
3899         if (ASC_BOARD(shp)->pending_tidmask != 0) {
3900                 /*
3901                  * If there are any pending commands for this board before trying
3902                  * to execute them, disable interrupts to preserve request ordering.
3903                  */
3904                 ASC_STATS(intr_disable);
3905                 save_flags(flags);
3906                 cli();
3907                 ASC_DBG1(1, "asc_isr_callback: asc_execute_pending() %x\n",
3908                         ASC_BOARD(shp)->pending_tidmask);
3909                 asc_execute_pending(shp);
3910                 restore_flags(flags);
3911         }
3912 
3913         /* 
3914          * Because interrupts may be enabled by the 'Scsi_Cmnd' done function,
3915          * add the command to the end of the global done list. The done function
3916          * for the command will be called in advansys_interrupt().
3917          */
3918         for (scpp = &asc_scsi_done; *scpp;
3919              scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
3920                 ;
3921         }
3922         *scpp = scp;
3923         scp->host_scribble = NULL;
3924         return;
3925 }
3926 
3927 /*
3928  * Execute as many pending requests as possible for the
3929  * board specified by 'Scsi_Host'.
3930  */
3931 STATIC void
3932 asc_execute_pending(struct Scsi_Host *shp)
     /* [previous][next][first][last][top][bottom][index][help] */
3933 {
3934         ASC_SCSI_BIT_ID_TYPE    scan_tidmask;
3935         Scsi_Cmnd                               *scp;
3936         int                                             i;
3937 
3938         ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
3939         /*
3940          * Execute pending commands for devices attached to
3941          * the current board in round-robin fashion.
3942          */
3943         scan_tidmask = ASC_BOARD(shp)->pending_tidmask;
3944         do {
3945                 for (i = 0; i < ASC_MAX_TID; i++) {
3946                         if (scan_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
3947                                 if ((scp = asc_dequeue(shp, i)) == NULL) {
3948                                         scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
3949                                 } else if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) {
3950                                         scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
3951                                         /* Put the request back at front of the list. */
3952                                         asc_enqueue(shp, scp, i, ASC_FRONT);
3953                                 }
3954                         }
3955                 }
3956         } while (scan_tidmask);
3957         return;
3958 }
3959 
3960 /*
3961  * asc_init_dev()
3962  *
3963  * Perform one-time initialization of a device.
3964  */
3965 STATIC int
3966 asc_init_dev(ASC_DVC_VAR *boardp, Scsi_Cmnd *scp)
     /* [previous][next][first][last][top][bottom][index][help] */
3967 {
3968         ASC_SCSI_REQ_Q                  *scsireqq;
3969         ASC_CAP_INFO                    *cap_info;
3970         ASC_SCSI_INQUIRY                *inquiry;
3971         int                                             found;
3972         ASC_SCSI_BIT_ID_TYPE    save_use_tagged_qng;
3973         ASC_SCSI_BIT_ID_TYPE    save_can_tagged_qng;
3974         int                                             ret;
3975 #ifdef ADVANSYS_DEBUG
3976         ASC_SCSI_BIT_ID_TYPE    tidmask; /* target id bit mask: 1 - 128 */
3977 #endif /* ADVANSYS_DEBUG */
3978 
3979         ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target);
3980 
3981         /* Return true for the board's target id. */
3982         if (boardp->cfg->chip_scsi_id == scp->target) {
3983                 return ASC_TRUE;
3984         }
3985 
3986         /*
3987          * XXX - Host drivers should not modify the timeout field.
3988          * But on the first command only add some extra time to
3989          * allow the driver to complete its initialization for the
3990          * device.
3991          */
3992         scp->timeout += 2000;   /* Add 5 seconds to the request timeout. */
3993 
3994         /* Set-up AscInitPollTarget() arguments. */
3995         scsireqq = &ASC_BOARD(scp->host)->scsireqq;
3996         memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
3997         cap_info = &ASC_BOARD(scp->host)->cap_info;
3998         memset(cap_info, 0, sizeof(ASC_CAP_INFO));
3999         inquiry = &ASC_BOARD(scp->host)->inquiry;
4000         memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
4001 
4002         /*
4003          * XXX - AscInitPollBegin() re-initializes these fields to
4004          * zero. 'Or' in the new values and restore them before calling 
4005          * AscInitPollEnd(). Normally all targets are initialized within
4006          * a call to AscInitPollBegin() and AscInitPollEnd().
4007          */
4008         save_use_tagged_qng = boardp->use_tagged_qng;
4009     save_can_tagged_qng = boardp->cfg->can_tagged_qng;
4010 
4011         ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n");
4012         if (AscInitPollBegin(boardp)) {
4013                 ASC_DBG(0, "asc_init_dev: AscInitPollBegin() failed\n");
4014                 return ASC_FALSE;
4015         }
4016 
4017         scsireqq->sense_ptr = &scsireqq->sense[0];
4018         scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN;
4019         scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
4020         scsireqq->r1.target_lun = 0;
4021         scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
4022 
4023         found = ASC_FALSE;
4024         ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n");
4025         switch (ret = AscInitPollTarget(boardp, scsireqq, inquiry, cap_info)) {
4026         case ASC_TRUE:
4027                 found = ASC_TRUE;
4028 #ifdef ADVANSYS_DEBUG
4029                 tidmask = ASC_TIX_TO_TARGET_ID(scp->target);
4030                 ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n",
4031                         cap_info->lba, cap_info->blk_size);
4032                 ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n",
4033                         inquiry->byte0.peri_dvc_type);
4034                 if (boardp->use_tagged_qng & tidmask) {
4035                         ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
4036                                 boardp->max_dvc_qng[scp->target]);
4037                 } else {
4038                         ASC_DBG(1, "asc_init_dev: command queuing disabled\n");
4039                 }
4040                 if (boardp->init_sdtr & tidmask) {
4041                         ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n");
4042                 } else {
4043                         ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n");
4044                 }
4045                 /* Set bit means fix disabled. */
4046                 if (boardp->pci_fix_asyn_xfer & tidmask) {
4047                         ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n");
4048                 } else {
4049                         ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n");
4050                 }
4051 #endif /* ADVANSYS_DEBUG */
4052                 break;
4053         case ASC_FALSE:
4054                 ASC_DBG(1, "asc_init_dev: no device found\n");
4055                 break;
4056         case ASC_ERROR:
4057                 ASC_DBG(0, "asc_init_dev: AscInitPollTarget() ASC_ERROR\n");
4058                 break;
4059         default:
4060                 ASC_DBG1(0, "asc_init_dev: AscInitPollTarget() unknown ret %d\n", ret);
4061                 break;
4062         }
4063 
4064         /* XXX - 'Or' in original tag bits. */
4065         boardp->use_tagged_qng |= save_use_tagged_qng;
4066         boardp->cfg->can_tagged_qng |= save_can_tagged_qng;
4067 
4068         ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n");
4069         AscInitPollEnd(boardp);
4070 
4071 #ifdef ASC_SET_CMD_PER_LUN
4072         /*
4073          * XXX - Refer to the comment in advansys_detect()
4074          * regarding cmd_per_lun.
4075          */
4076         for (i = 0; i <= ASC_MAX_TID; i++) {
4077                 if (boardp->max_dvc_qng[i] < scp->host->cmd_per_lun) {
4078                         scp->host->cmd_per_lun = boardp->max_dvc_qng[i];
4079                 }
4080         }
4081 #endif /* ASC_SET_CMD_PER_LUN */
4082 
4083         return found;
4084 }
4085 
4086 /*
4087  * Search for an AdvanSys PCI device in the PCI configuration space.
4088  */
4089 STATIC int
4090 asc_srch_pci_dev(PCI_DEVICE *pciDevice)
     /* [previous][next][first][last][top][bottom][index][help] */
4091 {
4092         int ret;
4093         static int scan = 1;
4094 
4095         ASC_DBG(2, "asc_srch_pci_dev: begin\n");
4096 
4097         if (scan) {
4098                 pciDevice->type = asc_scan_method(pciDevice);
4099                 scan = 0;
4100                 ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
4101         }
4102         ret = asc_pci_find_dev(pciDevice);
4103         ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
4104         if (ret == PCI_DEVICE_FOUND) {
4105                 pciDevice->slotNumber = pciDevice->slotFound + 1;
4106                 pciDevice->startSlot = pciDevice->slotFound + 1;
4107         } else {
4108                 if (pciDevice->bridge > pciDevice->busNumber) {
4109                         ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
4110                                 pciDevice->bridge, pciDevice->busNumber);
4111                         pciDevice->busNumber++;
4112                         pciDevice->slotNumber = 0;
4113                         pciDevice->startSlot = 0;
4114                         pciDevice->endSlot = 0x0f;
4115                         ret = asc_srch_pci_dev(pciDevice);
4116                         ASC_DBG1(2, "asc_srch_pci_dev recursive call return %d\n", ret);
4117                 }
4118         }
4119         ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
4120         return ret;
4121 }
4122 
4123 /*
4124  * Determine the access method to be used for 'pciDevice'.
4125  */
4126 STATIC uchar
4127 asc_scan_method(PCI_DEVICE *pciDevice)
     /* [previous][next][first][last][top][bottom][index][help] */
4128 {
4129         ushort data;
4130         PCI_DATA pciData;
4131         uchar type;
4132         uchar slot;
4133 
4134         ASC_DBG(2, "asc_scan_method: begin\n");
4135         memset(&pciData, 0, sizeof(pciData));
4136         for (type = 1; type < 3; type++) {
4137                 pciData.type = type;
4138                 for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
4139                         pciData.slot = slot;
4140                         data = asc_get_cfg_word(&pciData);
4141                         if ((data != 0xFFFF) && (data != 0x0000)) {
4142                                 ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
4143                                 return (type);
4144                         }
4145                 }
4146         }
4147         ASC_DBG1(4, "asc_scan_method: type %d\n", type);
4148         return (type);
4149 }
4150 
4151 /*
4152  * Check for an AdvanSys PCI device in 'pciDevice'.
4153  *
4154  * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
4155  */
4156 STATIC int
4157 asc_pci_find_dev(PCI_DEVICE *pciDevice)
     /* [previous][next][first][last][top][bottom][index][help] */
4158 {
4159         PCI_DATA pciData;
4160         ushort vendorid, deviceid;
4161         uchar classcode, subclass;
4162         uchar lslot;
4163 
4164         ASC_DBG(3, "asc_pci_find_dev: begin\n");
4165         pciData.type = pciDevice->type;
4166         pciData.bus = pciDevice->busNumber;
4167         pciData.func = pciDevice->devFunc;
4168         lslot = pciDevice->startSlot;
4169         for (; lslot < pciDevice->endSlot; lslot++) {
4170                 pciData.slot = lslot;
4171                 pciData.offset = VENDORID_OFFSET;
4172                 vendorid = asc_get_cfg_word(&pciData);
4173                 ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
4174                 if (vendorid != 0xffff) {
4175                         pciData.offset = DEVICEID_OFFSET;
4176                         deviceid = asc_get_cfg_word(&pciData);
4177                         ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
4178                         if ((vendorid == ASC_PCI_VENDORID) &&
4179                                 ((deviceid == ASC_PCI_DEVICE_ID_REV_A) ||
4180                                 (deviceid == ASC_PCI_DEVICE_ID_REV_B))) {
4181                                 pciDevice->slotFound = lslot;
4182                                 ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
4183                                 return PCI_DEVICE_FOUND;
4184                         } else {
4185                                 pciData.offset = SUBCLASS_OFFSET;
4186                                 subclass = asc_get_cfg_byte(&pciData);
4187                                 pciData.offset = CLASSCODE_OFFSET;
4188                                 classcode = asc_get_cfg_byte(&pciData);
4189                                 if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
4190                                         (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
4191                                         pciDevice->bridge++;
4192                                 }
4193                                 ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
4194                                         subclass, classcode);
4195                         }
4196                 }
4197         }
4198         return PCI_DEVICE_NOT_FOUND;
4199 }
4200 
4201 /*
4202  * Read PCI configuration data into 'pciConfig'.
4203  */
4204 STATIC void
4205 asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
     /* [previous][next][first][last][top][bottom][index][help] */
4206 {
4207         PCI_DATA pciData;
4208         uchar counter;
4209         uchar *localConfig;
4210 
4211         ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ",
4212                 pciDevice->slotFound);
4213 
4214         pciData.type = pciDevice->type;
4215         pciData.bus = pciDevice->busNumber;
4216         pciData.slot = pciDevice->slotFound;
4217         pciData.func = pciDevice->devFunc;
4218         localConfig = (uchar *) pciConfig;
4219 
4220         for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
4221                 pciData.offset = counter;
4222                 *localConfig = asc_get_cfg_byte(&pciData);
4223                 ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
4224                 localConfig++;
4225         }
4226         ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
4227 }
4228 
4229 /*
4230  * Read a word (16 bits) from the PCI configuration space.
4231  *
4232  * The configuration mechanism is checked for the correct access method.
4233  */
4234 STATIC ushort
4235 asc_get_cfg_word(PCI_DATA *pciData)
     /* [previous][next][first][last][top][bottom][index][help] */
4236 {
4237         ushort tmp;
4238         ulong address;
4239         ulong lbus = pciData->bus;
4240         ulong lslot = pciData->slot;
4241         ulong lfunc = pciData->func;
4242         uchar t2CFA, t2CF8;
4243         ushort t1CF8, t1CFA, t1CFC, t1CFE;
4244 
4245         ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
4246                 pciData->type, lbus, lslot, lfunc);
4247 
4248         /*
4249          * check type of configuration mechanism
4250          */
4251         if (pciData->type == 2) {
4252                 /*
4253                  * save these registers so we can restore them after we are done
4254                  */
4255                 t2CFA = inp(0xCFA);     /* save PCI bus register */
4256                 t2CF8 = inp(0xCF8);     /* save config space enable register */
4257 
4258                 /*
4259                  * go out and write the bus and enable registers
4260                  */
4261                 /* set for type 1 cycle, if needed */
4262                 outp(0xCFA, pciData->bus);
4263                 /* set the function number */
4264                 outp(0xCF8, 0x10 | (pciData->func << 1)) ;
4265 
4266                 /*
4267                  * read the configuration space type 2 locations
4268                  */
4269                 tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
4270         } else {
4271                 /*
4272                  * type 1 configuration mechanism
4273                  *
4274                  * save the CONFIG_ADDRESS and CONFIG_DATA register values
4275                  */
4276                 t1CFC = inpw(0xCFC);
4277                 t1CFE = inpw(0xCFE);
4278                 t1CF8 = inpw(0xCF8);
4279                 t1CFA = inpw(0xCFA);
4280 
4281                 /*
4282                  * enable <31>, bus = <23:16>, slot = <15:11>,
4283                  * func = <10:8>, reg = <7:2>
4284                  */
4285                 address = (ulong) ((lbus << 16) | (lslot << 11) |
4286                         (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
4287 
4288                 /*
4289                  * write out the address to CONFIG_ADDRESS
4290                  */
4291                 outl(address, 0xCF8);
4292 
4293                 /*
4294                  * read in the word from CONFIG_DATA
4295                  */
4296                 tmp = (ushort) ((inl(0xCFC) >>
4297                                  ((pciData->offset & 2) * 8)) & 0xFFFF);
4298         }
4299         ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
4300         return tmp;
4301 }
4302 
4303 /*
4304  * Reads a byte from the PCI configuration space.
4305  *
4306  * The configuration mechanism is checked for the correct access method.
4307  */
4308 STATIC uchar
4309 asc_get_cfg_byte(PCI_DATA *pciData)
     /* [previous][next][first][last][top][bottom][index][help] */
4310 {
4311         uchar tmp;
4312         ulong address;
4313         ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
4314         uchar t2CFA, t2CF8;
4315         ushort t1CF8, t1CFA, t1CFC, t1CFE;
4316 
4317         ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
4318 
4319         /*
4320          * check type of configuration mechanism
4321          */
4322         if (pciData->type == 2) {
4323                 /*
4324                  * save these registers so we can restore them after we are done
4325                  */
4326                 t2CFA = inp(0xCFA);     /* save PCI bus register */
4327                 t2CF8 = inp(0xCF8);     /* save config space enable register */
4328 
4329                 /*
4330                  * go out and write the bus and enable registers
4331                  */
4332                 /* set for type 1 cycle, if needed */
4333                 outp(0xCFA, pciData->bus);
4334                 /* set the function number */
4335                 outp(0xCF8, 0x10 | (pciData->func << 1));
4336 
4337                 /*
4338                  * read the configuration space type 2 locations
4339                  */
4340                 tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
4341 
4342                 /*
4343                  * restore the registers used for our transaction
4344                  */
4345                 outp(0xCF8, t2CF8);     /* restore the enable register */
4346                 outp(0xCFA, t2CFA);     /* restore PCI bus register */
4347         } else {
4348                 /*
4349                  * type 1 configuration mechanism
4350                  *
4351                  * save the CONFIG_ADDRESS and CONFIG_DATA register values
4352                  */
4353                 t1CFC = inpw(0xCFC);
4354                 t1CFE = inpw(0xCFE);
4355                 t1CF8 = inpw(0xCF8);
4356                 t1CFA = inpw(0xCFA);
4357 
4358                 /*
4359                  * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
4360                  * reg = <7:2>
4361                  */
4362                 address = (ulong) ((lbus << 16) | (lslot << 11) |
4363                         (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
4364 
4365                 /*
4366                  * write out the address to CONFIG_ADDRESS
4367                  */
4368                 outl(address, 0xCF8);
4369 
4370                 /*
4371                  * read in the word from CONFIG_DATA
4372                  */
4373                 tmp = (uchar) ((inl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
4374         }
4375         ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
4376         return tmp;
4377 }
4378 
4379 /*
4380  * Add a 'Scsi_Cmnd' to the end of specified 'Scsi_Host' 
4381  * target device pending command list. Set 'pending_tidmask'
4382  * to indicate a command is queued for the device.
4383  *
4384  * 'flag' may be either ASC_FRONT or ASC_BACK.
4385  *
4386  * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
4387  */
4388 STATIC void
4389 asc_enqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid, int flag)
     /* [previous][next][first][last][top][bottom][index][help] */
4390 {
4391         Scsi_Cmnd       **scpp;
4392 
4393         ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
4394         ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
4395         ASC_STATS(enqueue);
4396         if (flag == ASC_FRONT) {
4397                 scp->host_scribble = (unsigned char *) ASC_BOARD(shp)->pending[tid];
4398                 ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp;
4399         } else { /* ASC_BACK */
4400                 for (scpp = &ASC_BOARD(shp)->pending[tid]; *scpp;
4401                          scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
4402                         ;
4403                 }
4404                 *scpp = scp;
4405                 scp->host_scribble = NULL;
4406         }
4407         ASC_BOARD(shp)->pending_tidmask |= ASC_TIX_TO_TARGET_ID(tid);
4408 }
4409 
4410 /*
4411  * Return first pending 'Scsi_Cmnd' on the specified 'Scsi_Host'
4412  * for the specified target device. Clear the 'pending_tidmask'
4413  * bit for the device if no more commands are left queued for it.
4414  *
4415  * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
4416  */
4417 STATIC Scsi_Cmnd *
4418 asc_dequeue(struct Scsi_Host *shp, int tid)
     /* [previous][next][first][last][top][bottom][index][help] */
4419 {
4420         Scsi_Cmnd       *scp;
4421 
4422         ASC_STATS(dequeue);
4423         ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
4424         if ((scp = ASC_BOARD(shp)->pending[tid]) != NULL) {
4425                 ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp->host_scribble;
4426         }
4427         if (ASC_BOARD(shp)->pending[tid] == NULL) {
4428                 ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
4429         }
4430         return scp;
4431 }
4432 
4433 /*
4434  * Remove the specified 'Scsi_Cmnd' from the specified 'Scsi_Host'
4435  * for the specified target device. Clear the 'pending_tidmask'
4436  * bit for the device if no more commands are left queued for it.
4437  *
4438  * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
4439  *
4440  * Return ASC_TRUE if the command was found and removed, otherwise
4441  * return ASC_FALSE if the command was not found.
4442  */
4443 STATIC int
4444 asc_rmqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid)
     /* [previous][next][first][last][top][bottom][index][help] */
4445 {
4446         Scsi_Cmnd       **scpp;
4447         int                     ret;
4448 
4449         ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
4450         ret = ASC_FALSE;
4451         for (scpp = &ASC_BOARD(shp)->pending[tid];
4452              *scpp; scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
4453                 if (*scpp == scp) {
4454                         *scpp = (Scsi_Cmnd *) scp->host_scribble;       
4455                         scp->host_scribble = NULL;
4456                         ASC_STATS(rmqueue);
4457                         ret = ASC_TRUE;
4458                 }
4459         }
4460         if (ASC_BOARD(shp)->pending[tid] == NULL) {
4461                 ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
4462         }
4463         return ret;
4464 }
4465 
4466 
4467 /*
4468  * --- Functions Required by the Asc Library
4469  */
4470 
4471 /*
4472  * Delay for 'n' milliseconds. Don't use the 'jiffies'
4473  * global variable which is incremented once every 5 ms
4474  * from a timer interrupt, because this function may be
4475  * called when interrupts are disabled.
4476  */
4477 void
4478 DvcSleepMilliSecond(ulong n)
     /* [previous][next][first][last][top][bottom][index][help] */
4479 {
4480         ulong i;
4481 
4482         ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
4483         for (i = 0; i < n; i++) {
4484                 udelay(1000);
4485         }
4486 }
4487 
4488 void
4489 DvcDisplayString(uchar *s)
     /* [previous][next][first][last][top][bottom][index][help] */
4490 {
4491         printk(s);
4492 }
4493 
4494 int
4495 DvcEnterCritical(void)
     /* [previous][next][first][last][top][bottom][index][help] */
4496 {
4497         int     flags;
4498 
4499         save_flags(flags);
4500         cli();
4501         return flags;
4502 }
4503 
4504 void
4505 DvcLeaveCritical(int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
4506 {
4507         restore_flags(flags);
4508 }
4509 
4510 /*
4511  * Convert a virtual address to a virtual address.
4512  *
4513  * Apparently Linux is loaded V=R (virtual equals real). Just return
4514  * the virtual address.
4515  */
4516 ulong
4517 DvcGetPhyAddr(uchar *buf_addr, ulong buf_len)
     /* [previous][next][first][last][top][bottom][index][help] */
4518 {
4519         ulong phys_addr;
4520 
4521         phys_addr = (ulong) buf_addr;
4522         return phys_addr;
4523 }
4524 
4525 ulong
4526 DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
     /* [previous][next][first][last][top][bottom][index][help] */
4527                          ASC_SG_HEAD *asc_sg_head_ptr)
4528 {
4529         ulong buf_size;
4530 
4531         buf_size = buf_len;
4532         asc_sg_head_ptr->entry_cnt = 1;
4533         asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
4534         asc_sg_head_ptr->sg_list[0].bytes = buf_size;
4535         return buf_size;
4536 }
4537 
4538 /*
4539  * void
4540  * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
4541  *
4542  * Calling/Exit State:
4543  *      none
4544  *
4545  * Description:
4546  *      Output an ASC_SCSI_Q structure to the chip
4547  */
4548 void
4549 DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
     /* [previous][next][first][last][top][bottom][index][help] */
4550 {
4551         int     i;
4552 
4553         ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
4554         AscSetChipLramAddr(iop_base, s_addr);
4555         for (i = 0; i < words; i++, outbuf++) {
4556                 if (i == 2 || i == 10) {
4557                         continue;
4558                 }
4559                 AscPutChipLramData(iop_base, *outbuf);
4560         }
4561 }
4562 
4563 /*
4564  * void
4565  * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
4566  *
4567  * Calling/Exit State:
4568  *      none
4569  *
4570  * Description:
4571  *      Input an ASC_QDONE_INFO structure from the chip
4572  */
4573 void
4574 DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
     /* [previous][next][first][last][top][bottom][index][help] */
4575 {
4576         int     i;
4577 
4578         AscSetChipLramAddr(iop_base, s_addr);
4579         for (i = 0; i < words; i++, inbuf++) {
4580                 if (i == 5) {
4581                         continue;
4582                 }
4583                 *inbuf = AscGetChipLramData(iop_base);
4584         }
4585         ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
4586 }
4587 
4588 /*
4589  * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
4590  *
4591  * Calling/Exit State:
4592  *      none
4593  *
4594  * Description:
4595  *      output a buffer to an i/o port address
4596  */
4597 void
4598 DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
     /* [previous][next][first][last][top][bottom][index][help] */
4599 {
4600         int     i;
4601 
4602         for (i = 0; i < words; i++, outbuf++)
4603                 outpw(iop_base, *outbuf);
4604 }
4605 
4606 /*
4607  * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
4608  *
4609  * Calling/Exit State:
4610  *      none
4611  *
4612  * Description:
4613  *      input a buffer from an i/o port address
4614  */
4615 void
4616 DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
     /* [previous][next][first][last][top][bottom][index][help] */
4617 {
4618         int     i;
4619 
4620         for (i = 0; i < words; i++, inbuf++)
4621                 *inbuf = inpw(iop_base);
4622 }
4623 
4624 
4625 /*
4626  * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
4627  *
4628  * Calling/Exit State:
4629  *      none
4630  *
4631  * Description:
4632  *      output a buffer of 32-bit integers to an i/o port address in
4633  *  16 bit integer units
4634  */
4635 void  
4636 DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
     /* [previous][next][first][last][top][bottom][index][help] */
4637 {
4638         int             i;
4639         int             words;
4640         ushort  *pw;
4641 
4642         pw = (ushort *) pdw;
4643         words = dwords << 1;
4644         for(i = 0; i < words; i++, pw++) {
4645                 outpw(port, *pw);
4646         }
4647         return;
4648 }
4649 
4650 
4651 /*
4652  * --- Tracing and Debugging Functions
4653  */
4654 
4655 #ifdef ADVANSYS_STATS
4656 
4657 #define ASC_PRT_STATS_NEXT() \
4658         if (cp) { \
4659                 totlen += len; \
4660                 leftlen -= len; \
4661                 if (leftlen == 0) { \
4662                         return totlen; \
4663                 } \
4664                 cp += len; \
4665         }
4666 
4667 /*
4668  * asc_prt_stats()
4669  *
4670  * Note: no single line should be greater than 160 characters, cf.
4671  * asc_prt_stats_line().
4672  *
4673  * Return the number of characters copied into 'cp'. No more than
4674  * 'cplen' characters will be copied to 'cp'.
4675  */
4676 STATIC int
4677 asc_prt_stats(char *cp, int cplen)
     /* [previous][next][first][last][top][bottom][index][help] */
4678 {
4679         struct asc_stats        *s;
4680         int                                     leftlen;
4681         int                                     totlen;
4682         int                                     len;
4683 
4684         s = &asc_stats;
4685         leftlen = cplen;
4686         totlen = len = 0;
4687 
4688         len = asc_prt_stats_line(cp, leftlen,
4689 "\nAdvanSys SCSI Host Driver Statistics:\n");
4690         ASC_PRT_STATS_NEXT();
4691         
4692         len = asc_prt_stats_line(cp, leftlen,
4693 " command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu,\n",
4694                 s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
4695         ASC_PRT_STATS_NEXT();
4696 
4697         len = asc_prt_stats_line(cp, leftlen,
4698 " interrupt %lu, callback %lu, cmd_disable %lu, intr_disable %lu,\n",
4699                 s->interrupt, s->callback, s->cmd_disable, s->intr_disable);
4700         ASC_PRT_STATS_NEXT();
4701 
4702         len = asc_prt_stats_line(cp, leftlen,
4703 " error %lu, enqueue %lu, dequeue %lu, rmqueue %lu,\n",
4704                 s->error, s->enqueue, s->dequeue, s->rmqueue);
4705         ASC_PRT_STATS_NEXT();
4706 
4707         if (s->cont_cnt > 0) {
4708                 len = asc_prt_stats_line(cp, leftlen,
4709 " cont_cnt %lu, cont_xfer %lu: avg_xfer=%lu kb\n",
4710                         s->cont_cnt, s->cont_xfer, (s->cont_xfer/2)/s->cont_cnt);
4711                 ASC_PRT_STATS_NEXT();
4712         }
4713 
4714         if (s->sg_cnt > 0) {
4715                 len = asc_prt_stats_line(cp, leftlen,
4716 " sg_cnt %lu, sg_elem %lu, sg_xfer %lu: avg_elem=%lu, avg_size=%lu kb\n",
4717                         s->sg_cnt, s->sg_elem, s->sg_xfer,
4718                         s->sg_elem/s->sg_cnt, (s->sg_xfer/2)/s->sg_cnt);
4719                 ASC_PRT_STATS_NEXT();
4720         }
4721 
4722         return totlen;
4723 }
4724 
4725 /*
4726  * asc_prt_stats_line()
4727  *
4728  * If 'cp' is NULL print to the console, otherwise print to a buffer.
4729  *
4730  * Return 0 if printing to the console, otherwise return the number of
4731  * bytes written to the buffer.
4732  *
4733  * Note: If any single line is greater than 160 bytes the stack
4734  * will be corrupted. 's[]' is defined to be 160 bytes.
4735  */
4736 int
4737 asc_prt_stats_line(char *buf, int buflen, char *fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
4738 {
4739         va_list         args;
4740         int                     ret;
4741         char            s[160];         /* 2 lines */
4742 
4743         va_start(args, fmt);
4744         ret = vsprintf(s, fmt, args);
4745         if (buf == NULL) {
4746                 (void) printk(s);
4747                 ret = 0;
4748         } else {
4749                 ret = min(buflen, ret);
4750                 memcpy(buf, s, ret);
4751         }
4752         va_end(args);
4753         return ret;
4754 }
4755 #endif /* ADVANSYS_STATS */
4756 
4757 #ifdef ADVANSYS_DEBUG
4758 /*
4759  * asc_prt_scsi_host()
4760  */
4761 STATIC void 
4762 asc_prt_scsi_host(struct Scsi_Host *s)
     /* [previous][next][first][last][top][bottom][index][help] */
4763 {
4764         printk("Scsi_Host at addr %x\n", (unsigned) s);
4765         printk(
4766 " next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
4767                 (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
4768                 s->last_reset);
4769 
4770         printk(
4771 " host_wait %x, host_queue %x, hostt %x, block %x,\n",
4772                 (unsigned) s->host_wait, (unsigned) s->host_queue,
4773                 (unsigned) s->hostt, (unsigned) s->block);
4774 
4775         printk(
4776 " wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n",
4777                 s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port,
4778                 s->irq, s->dma_channel);
4779 
4780         printk(
4781 " this_id %d, can_queue %d,\n", s->this_id, s->can_queue);
4782 
4783         printk(
4784 " cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
4785                 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
4786                 s->loaded_as_module);
4787 
4788         printk("hostdata (struct asc_board)\n");
4789         asc_prt_dvc_var(&ASC_BOARD(s)->board);
4790         asc_prt_dvc_cfg(&ASC_BOARD(s)->cfg);
4791         printk(" overrun_buf %x\n", (unsigned) &ASC_BOARD(s)->overrun_buf[0]);
4792 }
4793 
4794 /*
4795  * asc_prt_dvc_var()
4796  */
4797 STATIC void 
4798 asc_prt_dvc_var(ASC_DVC_VAR *h)
     /* [previous][next][first][last][top][bottom][index][help] */
4799 {
4800         printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
4801 
4802         printk(
4803 " iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
4804                 h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
4805 
4806         printk(
4807 " bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
4808                 h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
4809                 (unsigned) h->init_sdtr);
4810 
4811         printk(
4812 " sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
4813                 (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
4814                 (unsigned) h->unit_not_ready, (unsigned) h->chip_no);
4815                 
4816         printk(
4817 " queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
4818                 (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
4819                 (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
4820 
4821         printk(
4822 " is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
4823                 (unsigned) h->is_in_int, (unsigned) h->max_total_qng,
4824                 (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
4825 
4826         printk(
4827 " last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
4828                 (unsigned) h->last_q_shortage, (unsigned) h->init_state,
4829                 (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
4830 
4831         printk(
4832 " int_count %ld, req_count %ld, busy_count %ld, cfg %x, saved_ptr2func %x\n",
4833                 h->int_count, h->req_count, h->busy_count, (unsigned) h->cfg,
4834                 (unsigned) h->saved_ptr2func);
4835 }
4836 
4837 /*
4838  * asc_prt_dvc_cfg()
4839  */
4840 STATIC void 
4841 asc_prt_dvc_cfg(ASC_DVC_CFG *h)
     /* [previous][next][first][last][top][bottom][index][help] */
4842 {
4843         printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
4844 
4845         printk(
4846 " can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n",
4847                         h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res);
4848 
4849         printk(
4850 " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
4851                          h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
4852                          h->chip_version);
4853 
4854         printk(
4855 " pci_device_id %d, lib_serial_no %d, lib_version %d, mcode_date %d,\n",
4856                   h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
4857 
4858         printk(
4859 " mcode_version %d, overrun_buf %x\n",
4860                         h->mcode_version, (unsigned) h->overrun_buf);
4861 }
4862 
4863 /*
4864  * asc_prt_scsi_q()
4865  */
4866 STATIC void 
4867 asc_prt_scsi_q(ASC_SCSI_Q *q)
     /* [previous][next][first][last][top][bottom][index][help] */
4868 {
4869         ASC_SG_HEAD     *sgp;
4870         int i;
4871 
4872         printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
4873 
4874         printk(
4875 " target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
4876                         q->q2.target_ix, q->q1.target_lun,
4877                         (unsigned) q->q2.srb_ptr, q->q2.tag_code);
4878 
4879         printk(
4880 " data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
4881                         (unsigned) q->q1.data_addr, q->q1.data_cnt,
4882                         (unsigned) q->q1.sense_addr, q->q1.sense_len);
4883 
4884         printk(
4885 " cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
4886                         (unsigned) q->cdbptr, q->q2.cdb_len,
4887                         (unsigned) q->sg_head, q->q1.sg_queue_cnt);
4888 
4889         if (q->sg_head) {
4890                 sgp = q->sg_head;
4891                 printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
4892                 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
4893                 for (i = 0; i < sgp->entry_cnt; i++) {
4894                         printk(" [%u]: addr %x, bytes %lu\n",
4895                                 i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
4896                 }
4897 
4898         }
4899 }
4900 
4901 /*
4902  * asc_prt_qdone_info()
4903  */
4904 STATIC void 
4905 asc_prt_qdone_info(ASC_QDONE_INFO *q)
     /* [previous][next][first][last][top][bottom][index][help] */
4906 {
4907         printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
4908         printk(
4909 " srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
4910                         (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
4911                         q->d2.tag_code, q->d3.done_stat);
4912         printk(
4913 " host_stat %x, scsi_stat %x, scsi_msg %x\n",
4914                         q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
4915 }
4916 
4917 /*
4918  * asc_prt_hex()
4919  *
4920  * Print hexadecimal output in 4 byte groupings 32 bytes 
4921  * or 8 double-words per line.
4922  */
4923 STATIC void 
4924 asc_prt_hex(char *f, uchar *s, int l)
     /* [previous][next][first][last][top][bottom][index][help] */
4925 {
4926         int                     i;
4927         int                     j;
4928         int                     k;
4929         int                     m;
4930 
4931         printk("%s: (%d bytes)\n", f, l);
4932 
4933         for (i = 0; i < l; i += 32) {
4934                 
4935                 /* Display a maximum of 8 double-words per line. */
4936                 if ((k = (l - i) / 4) >= 8) {
4937                         k = 8;
4938                         m = 0;
4939                 } else {
4940                         m = (l - i) % 4 ;
4941                 }
4942 
4943                 for (j = 0; j < k; j++) {
4944                         printk(" %2.2X%2.2X%2.2X%2.2X",
4945                                 (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
4946                                 (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
4947                 }
4948 
4949                 switch (m) {
4950                 case 0:
4951                 default:
4952                         break;
4953                 case 1:
4954                         printk(" %2.2X",
4955                                 (unsigned) s[i+(j*4)+4]);
4956                         break;
4957                 case 2:
4958                         printk(" %2.2X%2.2X",
4959                                 (unsigned) s[i+(j*4)+4],
4960                                 (unsigned) s[i+(j*4)+5]);
4961                         break;
4962                 case 3:
4963                         printk(" %2.2X%2.2X%2.2X",
4964                                 (unsigned) s[i+(j*4)+4],
4965                                 (unsigned) s[i+(j*4)+5],
4966                                 (unsigned) s[i+(j*4)+6]);
4967                         break;
4968                 }
4969 
4970                 printk("\n");
4971         }
4972 }
4973 
4974 /*
4975  * interrupts_enabled()
4976  *
4977  * Return 1 if interrupts are enabled, otherwise return 0.
4978  */
4979 STATIC int
4980 interrupts_enabled(void)
     /* [previous][next][first][last][top][bottom][index][help] */
4981 {
4982         int flags;
4983 
4984         save_flags(flags);
4985         if (flags & 0x0200) {
4986                 return ASC_TRUE;
4987         } else {
4988                 return ASC_FALSE;
4989         }
4990 }
4991 
4992 #endif /* ADVANSYS_DEBUG */
4993 
4994 
4995 /*
4996  * --- Asc Library Functions
4997  */
4998 
4999 ushort
5000 AscGetEisaChipCfg(
     /* [previous][next][first][last][top][bottom][index][help] */
5001                                          PortAddr iop_base
5002 )
5003 {
5004         PortAddr            eisa_cfg_iop;
5005 
5006         eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
5007           (PortAddr) (ASC_EISA_CFG_IOP_MASK);
5008         return (inpw(eisa_cfg_iop));
5009 }
5010 
5011 uchar
5012 AscSetChipScsiID(
     /* [previous][next][first][last][top][bottom][index][help] */
5013                                         PortAddr iop_base,
5014                                         uchar new_host_id
5015 )
5016 {
5017         ushort              cfg_lsw;
5018 
5019         if (AscGetChipScsiID(iop_base) == new_host_id) {
5020                 return (new_host_id);
5021         }
5022         cfg_lsw = AscGetChipCfgLsw(iop_base);
5023         cfg_lsw &= 0xF8FF;
5024         cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
5025         AscSetChipCfgLsw(iop_base, cfg_lsw);
5026         return (AscGetChipScsiID(iop_base));
5027 }
5028 
5029 ushort
5030 AscGetChipBiosAddress(
     /* [previous][next][first][last][top][bottom][index][help] */
5031                                                  PortAddr iop_base,
5032                                                  ushort bus_type
5033 )
5034 {
5035         ushort              cfg_lsw;
5036         ushort              bios_addr;
5037 
5038         if ((bus_type & ASC_IS_EISA) != 0) {
5039                 cfg_lsw = AscGetEisaChipCfg(iop_base);
5040                 cfg_lsw &= 0x000F;
5041                 bios_addr = (ushort) (ASC_BIOS_MIN_ADDR +
5042                                                           (cfg_lsw * ASC_BIOS_BANK_SIZE));
5043                 return (bios_addr);
5044         }
5045         cfg_lsw = AscGetChipCfgLsw(iop_base);
5046         bios_addr = (ushort) (((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + ASC_BIOS_MIN_ADDR);
5047         return (bios_addr);
5048 }
5049 
5050 uchar
5051 AscGetChipVersion(
     /* [previous][next][first][last][top][bottom][index][help] */
5052                                          PortAddr iop_base,
5053                                          ushort bus_type
5054 )
5055 {
5056         if ((bus_type & ASC_IS_EISA) != 0) {
5057 
5058                 PortAddr            eisa_iop;
5059                 uchar               revision;
5060 
5061                 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
5062                   (PortAddr) ASC_EISA_REV_IOP_MASK;
5063                 revision = inp(eisa_iop);
5064                 return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
5065         }
5066         return (AscGetChipVerNo(iop_base));
5067 }
5068 
5069 ushort
5070 AscGetChipBusType(
     /* [previous][next][first][last][top][bottom][index][help] */
5071                                          PortAddr iop_base
5072 )
5073 {
5074         ushort              chip_ver;
5075 
5076         chip_ver = AscGetChipVerNo(iop_base);
5077         if ((chip_ver >= ASC_CHIP_MIN_VER_VL) &&
5078                 (chip_ver <= ASC_CHIP_MAX_VER_VL)) {
5079                 if (((iop_base & 0x0C30) == 0x0C30) ||
5080                         ((iop_base & 0x0C50) == 0x0C50)) {
5081                         return (ASC_IS_EISA);
5082                 }
5083                 return (ASC_IS_VL);
5084         } else if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
5085                            (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
5086                 if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
5087                         return (ASC_IS_ISAPNP);
5088                 }
5089                 return (ASC_IS_ISA);
5090         } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
5091                            (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
5092                 return (ASC_IS_PCI);
5093         } else {
5094                 return (0);
5095         }
5096 }
5097 
5098 void
5099 AscEnableIsaDma(
     /* [previous][next][first][last][top][bottom][index][help] */
5100                                    uchar dma_channel
5101 )
5102 {
5103         if (dma_channel < 4) {
5104                 outp(0x000B, (ushort) (0xC0 | dma_channel));
5105                 outp(0x000A, dma_channel);
5106         } else if (dma_channel < 8) {
5107 
5108                 outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
5109                 outp(0x00D4, (ushort) (dma_channel - 4));
5110         }
5111         return;
5112 }
5113 
5114 ulong
5115 AscLoadMicroCode(
     /* [previous][next][first][last][top][bottom][index][help] */
5116                                         PortAddr iop_base,
5117                                         ushort s_addr,
5118                                         ushort dosfar * mcode_buf,
5119                                         ushort mcode_size
5120 )
5121 {
5122         ulong               chksum;
5123         ushort              mcode_word_size;
5124         ushort              mcode_chksum;
5125 
5126         mcode_word_size = (ushort) (mcode_size >> 1);
5127         AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
5128         AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
5129 
5130         chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
5131         mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
5132                                                                                           (ushort) ASC_CODE_SEC_BEG,
5133                   (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
5134         AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
5135         AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
5136         return (chksum);
5137 }
5138 
5139 uchar               _hextbl_[16] =
5140 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
5141  'A', 'B', 'C', 'D', 'E', 'F'};
5142 
5143 uchar               _isa_pnp_inited = 0;
5144 
5145 PortAddr            _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] =
5146 {
5147         0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
5148         ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
5149 };
5150 
5151 PortAddr
5152 AscSearchIOPortAddr(
     /* [previous][next][first][last][top][bottom][index][help] */
5153                                            PortAddr iop_beg,
5154                                            ushort bus_type
5155 )
5156 {
5157         if (bus_type & ASC_IS_VL) {
5158                 while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
5159                         if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
5160                                 return (iop_beg);
5161                         }
5162                 }
5163                 return (0);
5164         }
5165         if (bus_type & ASC_IS_ISA) {
5166                 if (_isa_pnp_inited == 0) {
5167                         AscSetISAPNPWaitForKey();
5168                         _isa_pnp_inited++;
5169                 }
5170                 while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
5171                         if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
5172                                 return (iop_beg);
5173                         }
5174                 }
5175                 return (0);
5176         }
5177         if (bus_type & ASC_IS_EISA) {
5178                 if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
5179                         return (iop_beg);
5180                 }
5181                 return (0);
5182         }
5183         return (0);
5184 }
5185 
5186 PortAddr
5187 AscSearchIOPortAddr11(
     /* [previous][next][first][last][top][bottom][index][help] */
5188                                                  PortAddr s_addr
5189 )
5190 {
5191 
5192         int                 i;
5193         PortAddr            iop_base;
5194 
5195         for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
5196                 if (_asc_def_iop_base[i] > s_addr) {
5197                         break;
5198                 }
5199         }
5200         for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
5201                 iop_base = _asc_def_iop_base[i];
5202                 if (AscFindSignature(iop_base)) {
5203                         return (iop_base);
5204                 }
5205         }
5206         return (0);
5207 }
5208 
5209 int
5210 AscFindSignature(
     /* [previous][next][first][last][top][bottom][index][help] */
5211                                         PortAddr iop_base
5212 )
5213 {
5214         ushort              sig_word;
5215 
5216         if ((inp((PortAddr) (iop_base + 1)) & 0xFF) == (uchar) ASC_1000_ID1B) {
5217                 sig_word = inpw(iop_base);
5218                 if ((sig_word == (ushort) ASC_1000_ID0W) ||
5219                         (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
5220                         return (1);
5221                 }
5222         }
5223         return (0);
5224 }
5225 
5226 void
5227 AscToggleIRQAct(
     /* [previous][next][first][last][top][bottom][index][help] */
5228                                    PortAddr iop_base
5229 )
5230 {
5231         AscSetChipStatus(iop_base, CIW_IRQ_ACT);
5232         AscSetChipStatus(iop_base, 0);
5233         return;
5234 }
5235 
5236 #if CC_INIT_INQ_DISPLAY
5237 
5238 #endif
5239 
5240 void
5241 AscSetISAPNPWaitForKey(
     /* [previous][next][first][last][top][bottom][index][help] */
5242                                                   void)
5243 {
5244 
5245         outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
5246         outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
5247         return;
5248 }
5249 
5250 uchar
5251 AscGetChipIRQ(
     /* [previous][next][first][last][top][bottom][index][help] */
5252                                  PortAddr iop_base,
5253                                  ushort bus_type
5254 )
5255 {
5256         ushort              cfg_lsw;
5257         uchar               chip_irq;
5258 
5259         if ((bus_type & ASC_IS_EISA) != 0) {
5260 
5261                 cfg_lsw = AscGetEisaChipCfg(iop_base);
5262                 chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
5263                 if ((chip_irq == 13) || (chip_irq > 15)) {
5264 
5265                         return (0);
5266                 }
5267                 return (chip_irq);
5268         } else {
5269 
5270                 cfg_lsw = AscGetChipCfgLsw(iop_base);
5271 
5272                 if ((bus_type & ASC_IS_VL) != 0) {
5273 
5274                         chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
5275                         if ((chip_irq == 0) ||
5276                                 (chip_irq == 4) ||
5277                                 (chip_irq == 7)) {
5278                                 return (0);
5279                         }
5280                         return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
5281                 }
5282                 chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
5283                 if (chip_irq == 3)
5284                         chip_irq += (uchar) 2;
5285                 return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
5286         }
5287 }
5288 
5289 uchar
5290 AscSetChipIRQ(
     /* [previous][next][first][last][top][bottom][index][help] */
5291                                  PortAddr iop_base,
5292                                  uchar irq_no,
5293                                  ushort bus_type
5294 )
5295 {
5296         ushort              cfg_lsw;
5297 
5298         if ((bus_type & ASC_IS_VL) != 0) {
5299 
5300                 if (irq_no != 0) {
5301                         if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
5302                                 irq_no = 0;
5303                         } else {
5304                                 irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
5305                         }
5306                 }
5307                 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
5308                 cfg_lsw |= (ushort) 0x0010;
5309                 AscSetChipCfgLsw(iop_base, cfg_lsw);
5310                 AscToggleIRQAct(iop_base);
5311 
5312                 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
5313                 cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
5314                 AscSetChipCfgLsw(iop_base, cfg_lsw);
5315                 AscToggleIRQAct(iop_base);
5316 
5317                 return (AscGetChipIRQ(iop_base, bus_type));
5318 
5319         } else if ((bus_type & (ASC_IS_ISA)) != 0) {
5320 
5321                 if (irq_no == 15)
5322                         irq_no -= (uchar) 2;
5323                 irq_no -= (uchar) ASC_MIN_IRQ_NO;
5324                 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
5325                 cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
5326                 AscSetChipCfgLsw(iop_base, cfg_lsw);
5327                 return (AscGetChipIRQ(iop_base, bus_type));
5328         } else {
5329 
5330                 return (0);
5331         }
5332 }
5333 
5334 uchar
5335 AscGetChipScsiCtrl(
     /* [previous][next][first][last][top][bottom][index][help] */
5336                                           PortAddr iop_base
5337 )
5338 {
5339         uchar               sc;
5340 
5341         AscSetBank(iop_base, 1);
5342         sc = inp(iop_base + IOP_REG_SC);
5343         AscSetBank(iop_base, 0);
5344         return (sc);
5345 }
5346 
5347 extern uchar        _sdtr_period_tbl_[];
5348 
5349 int
5350 AscIsrChipHalted(
     /* [previous][next][first][last][top][bottom][index][help] */
5351                                         ASC_DVC_VAR asc_ptr_type * asc_dvc
5352 )
5353 {
5354         SDTR_XMSG           sdtr_xmsg;
5355         SDTR_XMSG           out_msg;
5356         ushort              halt_q_addr;
5357         int                 sdtr_accept;
5358         ushort              int_halt_code;
5359         ASC_SCSI_BIT_ID_TYPE scsi_busy;
5360         ASC_SCSI_BIT_ID_TYPE target_id;
5361         PortAddr            iop_base;
5362         uchar               tag_code;
5363         uchar               q_status;
5364         uchar               halt_qp;
5365         uchar               sdtr_data;
5366         uchar               target_ix;
5367         uchar               q_cntl, tid_no;
5368         uchar               cur_dvc_qng;
5369         uchar               asyn_sdtr;
5370         uchar               scsi_status;
5371 
5372         iop_base = asc_dvc->iop_base;
5373         int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
5374 
5375         halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
5376         halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
5377         target_ix = AscReadLramByte(iop_base,
5378                                    (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
5379         q_cntl = AscReadLramByte(iop_base,
5380                                                 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
5381         tid_no = ASC_TIX_TO_TID(target_ix);
5382         target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
5383         if (asc_dvc->pci_fix_asyn_xfer & target_id) {
5384 
5385                 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
5386         } else {
5387                 asyn_sdtr = 0;
5388         }
5389         if (int_halt_code == ASC_HALT_EXTMSG_IN) {
5390 
5391                 AscMemWordCopyFromLram(iop_base,
5392                                                            ASCV_MSGIN_BEG,
5393                                                            (ushort dosfar *) & sdtr_xmsg,
5394                                                            (ushort) (sizeof (SDTR_XMSG) >> 1));
5395                 if ((sdtr_xmsg.msg_type == MS_EXTEND) &&
5396                         (sdtr_xmsg.msg_len == MS_SDTR_LEN)) {
5397                         sdtr_accept = TRUE;
5398                         if (sdtr_xmsg.msg_req == MS_SDTR_CODE) {
5399                                 if (sdtr_xmsg.req_ack_offset > ASC_SYN_MAX_OFFSET) {
5400 
5401                                         sdtr_accept = FALSE;
5402                                         sdtr_xmsg.req_ack_offset = ASC_SYN_MAX_OFFSET;
5403                                 }
5404                                 sdtr_data = AscCalSDTRData(sdtr_xmsg.xfer_period,
5405                                                                                    sdtr_xmsg.req_ack_offset);
5406                                 if (sdtr_xmsg.req_ack_offset == 0) {
5407 
5408                                         q_cntl &= ~QC_MSG_OUT;
5409                                         asc_dvc->init_sdtr &= ~target_id;
5410                                         asc_dvc->sdtr_done &= ~target_id;
5411                                         AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
5412                                 } else if ((sdtr_data == 0xFF)) {
5413 
5414                                         q_cntl |= QC_MSG_OUT;
5415                                         asc_dvc->init_sdtr &= ~target_id;
5416                                         asc_dvc->sdtr_done &= ~target_id;
5417                                         AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
5418                                 } else {
5419                                         if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
5420 
5421                                                 q_cntl &= ~QC_MSG_OUT;
5422                                                 asc_dvc->sdtr_done |= target_id;
5423                                                 asc_dvc->init_sdtr |= target_id;
5424                                                 asc_dvc->pci_fix_asyn_xfer &= ~target_id;
5425                                                 AscSetChipSDTR(iop_base, sdtr_data, tid_no);
5426                                         } else {
5427 
5428                                                 q_cntl |= QC_MSG_OUT;
5429 
5430                                                 AscMsgOutSDTR(iop_base,
5431                                                                           sdtr_xmsg.xfer_period,
5432                                                                           sdtr_xmsg.req_ack_offset);
5433                                                 asc_dvc->pci_fix_asyn_xfer &= ~target_id;
5434                                                 AscSetChipSDTR(iop_base, sdtr_data, tid_no);
5435                                                 asc_dvc->sdtr_done |= target_id;
5436                                                 asc_dvc->init_sdtr |= target_id;
5437                                         }
5438                                 }
5439 
5440                                 AscWriteLramByte(iop_base,
5441                                                  (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
5442                                                                  q_cntl);
5443                                 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
5444                                 return (0);
5445                         }
5446                 }
5447         } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
5448 
5449                 q_cntl |= QC_REQ_SENSE;
5450                 if (((asc_dvc->init_sdtr & target_id) != 0) &&
5451                         ((asc_dvc->sdtr_done & target_id) != 0)) {
5452 
5453                         sdtr_data = AscReadLramByte(iop_base,
5454                                   (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
5455                         AscMsgOutSDTR(iop_base,
5456                                                   _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)],
5457                                                   (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
5458                         q_cntl |= QC_MSG_OUT;
5459                 }
5460                 AscWriteLramByte(iop_base,
5461                                                  (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
5462                                                  q_cntl);
5463 
5464                 tag_code = AscReadLramByte(iop_base,
5465                                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
5466                 tag_code &= 0xDC;
5467                 AscWriteLramByte(iop_base,
5468                                          (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
5469                                                  tag_code);
5470 
5471                 q_status = AscReadLramByte(iop_base,
5472                                           (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
5473                 q_status |= (QS_READY | QS_BUSY);
5474                 AscWriteLramByte(iop_base,
5475                                            (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
5476                                                  q_status);
5477 
5478                 scsi_busy = AscReadLramByte(iop_base,
5479                                                                         (ushort) ASCV_SCSIBUSY_B);
5480                 scsi_busy &= ~target_id;
5481                 AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
5482 
5483                 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
5484                 return (0);
5485         } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
5486 
5487                 AscMemWordCopyFromLram(iop_base,
5488                                                            ASCV_MSGOUT_BEG,
5489                                                            (ushort dosfar *) & out_msg,
5490                                                            (ushort) (sizeof (SDTR_XMSG) >> 1));
5491 
5492                 if ((out_msg.msg_type == MS_EXTEND) &&
5493                         (out_msg.msg_len == MS_SDTR_LEN) &&
5494                         (out_msg.msg_req == MS_SDTR_CODE)) {
5495 
5496                         asc_dvc->init_sdtr &= ~target_id;
5497                         asc_dvc->sdtr_done &= ~target_id;
5498                         AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
5499 
5500                 } else {
5501 
5502                 }
5503 
5504                 q_cntl &= ~QC_MSG_OUT;
5505                 AscWriteLramByte(iop_base,
5506                                                  (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
5507                                                  q_cntl);
5508                 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
5509                 return (0);
5510         } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
5511 
5512                 scsi_status = AscReadLramByte(iop_base,
5513                   (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
5514                 cur_dvc_qng = AscReadLramByte(iop_base,
5515                                          (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
5516                 if ((cur_dvc_qng > 0) &&
5517                         (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
5518 
5519                         scsi_busy = AscReadLramByte(iop_base,
5520                                                                                 (ushort) ASCV_SCSIBUSY_B);
5521                         scsi_busy |= target_id;
5522                         AscWriteLramByte(iop_base,
5523                                                          (ushort) ASCV_SCSIBUSY_B, scsi_busy);
5524                         asc_dvc->queue_full_or_busy |= target_id;
5525 
5526                         if (scsi_status == SS_QUEUE_FULL) {
5527                                 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
5528                                         cur_dvc_qng -= 1;
5529                                         asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
5530 
5531                                         AscWriteLramByte(iop_base,
5532                                                                          (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) tid_no),
5533                                                                          cur_dvc_qng);
5534                                 }
5535                         }
5536                 }
5537                 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
5538                 return (0);
5539         }
5540         return (0);
5541 }
5542 
5543 uchar
5544 _AscCopyLramScsiDoneQ(
     /* [previous][next][first][last][top][bottom][index][help] */
5545                                                  PortAddr iop_base,
5546                                                  ushort q_addr,
5547                                                  ASC_QDONE_INFO dosfar * scsiq,
5548                                                  ulong max_dma_count
5549 )
5550 {
5551         ushort              _val;
5552         uchar               sg_queue_cnt;
5553 
5554         DvcGetQinfo(iop_base,
5555                                 (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
5556                                 (ushort dosfar *) scsiq,
5557                           (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
5558 
5559 #if !CC_LITTLE_ENDIAN_HOST
5560         AscAdjEndianQDoneInfo(scsiq);
5561 #endif
5562 
5563         _val = AscReadLramWord(iop_base,
5564                                                    (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
5565         scsiq->q_status = (uchar) _val;
5566         scsiq->q_no = (uchar) (_val >> 8);
5567 
5568         _val = AscReadLramWord(iop_base,
5569                                                    (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
5570         scsiq->cntl = (uchar) _val;
5571         sg_queue_cnt = (uchar) (_val >> 8);
5572 
5573         _val = AscReadLramWord(iop_base,
5574                                                 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
5575         scsiq->sense_len = (uchar) _val;
5576         scsiq->user_def = (uchar) (_val >> 8);
5577 
5578         scsiq->remain_bytes = AscReadLramDWord(iop_base,
5579                                  (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
5580         scsiq->remain_bytes &= max_dma_count;
5581 
5582         return (sg_queue_cnt);
5583 }
5584 
5585 int
5586 AscIsrQDone(
     /* [previous][next][first][last][top][bottom][index][help] */
5587                            ASC_DVC_VAR asc_ptr_type * asc_dvc
5588 )
5589 {
5590         uchar               next_qp;
5591         uchar               i;
5592         uchar               n_q_used;
5593         uchar               sg_list_qp;
5594         uchar               sg_queue_cnt;
5595         uchar               done_q_tail;
5596 
5597         uchar               tid_no;
5598         ASC_SCSI_BIT_ID_TYPE scsi_busy;
5599         ASC_SCSI_BIT_ID_TYPE target_id;
5600         PortAddr            iop_base;
5601         ushort              q_addr;
5602         ushort              sg_q_addr;
5603         uchar               cur_target_qng;
5604         ASC_QDONE_INFO      scsiq_buf;
5605         ASC_QDONE_INFO dosfar *scsiq;
5606         int                 false_overrun;
5607         ASC_ISR_CALLBACK    asc_isr_callback;
5608 
5609         uchar               tag_code;
5610 
5611 #if CC_LINK_BUSY_Q
5612         ushort              n_busy_q_done;
5613 
5614 #endif
5615 
5616         iop_base = asc_dvc->iop_base;
5617         asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
5618 
5619         n_q_used = 1;
5620         scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
5621         done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
5622         q_addr = ASC_QNO_TO_QADDR(done_q_tail);
5623         next_qp = AscReadLramByte(iop_base,
5624                                                           (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
5625         if (next_qp != ASC_QLINK_END) {
5626 
5627                 AscPutVarDoneQTail(iop_base, next_qp);
5628                 q_addr = ASC_QNO_TO_QADDR(next_qp);
5629 
5630                 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
5631 
5632                 AscWriteLramByte(iop_base,
5633                                                  (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
5634                          (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
5635                 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
5636                 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
5637                 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
5638                         sg_q_addr = q_addr;
5639                         sg_list_qp = next_qp;
5640                         for (i = 0; i < sg_queue_cnt; i++) {
5641                                 sg_list_qp = AscReadLramByte(iop_base,
5642                                                    (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
5643                                 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
5644                                 if (sg_list_qp == ASC_QLINK_END) {
5645                                         AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
5646                                         scsiq->d3.done_stat = QD_WITH_ERROR;
5647                                         scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
5648                                         goto FATAL_ERR_QDONE;
5649                                 }
5650                                 AscWriteLramByte(iop_base,
5651                                                  (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
5652                                                                  QS_FREE);
5653                         }
5654 
5655                         n_q_used = sg_queue_cnt + 1;
5656                         AscPutVarDoneQTail(iop_base, sg_list_qp);
5657                 }
5658                 if (asc_dvc->queue_full_or_busy & target_id) {
5659 
5660                         cur_target_qng = AscReadLramByte(iop_base,
5661                         (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
5662                         if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
5663                                 scsi_busy = AscReadLramByte(iop_base,
5664                                                                                         (ushort) ASCV_SCSIBUSY_B);
5665                                 scsi_busy &= ~target_id;
5666                                 AscWriteLramByte(iop_base,
5667                                                                  (ushort) ASCV_SCSIBUSY_B, scsi_busy);
5668                                 asc_dvc->queue_full_or_busy &= ~target_id;
5669                         }
5670                 }
5671                 if (asc_dvc->cur_total_qng >= n_q_used) {
5672                         asc_dvc->cur_total_qng -= n_q_used;
5673                         if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
5674                                 asc_dvc->cur_dvc_qng[tid_no]--;
5675                         }
5676                 } else {
5677                         AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
5678                         scsiq->d3.done_stat = QD_WITH_ERROR;
5679                         goto FATAL_ERR_QDONE;
5680                 }
5681 
5682                 if ((scsiq->d2.srb_ptr == 0UL) ||
5683                         ((scsiq->q_status & QS_ABORTED) != 0)) {
5684 
5685                         return (0x11);
5686                 } else if (scsiq->q_status == QS_DONE) {
5687 
5688                         false_overrun = FALSE;
5689 
5690                         if (asc_dvc->bug_fix_cntl) {
5691                                 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
5692                                         tag_code = AscReadLramByte(iop_base,
5693                                                  (ushort) (q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
5694                                         if (tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) {
5695                                                 if (scsiq->remain_bytes != 0UL) {
5696                                                         scsiq->remain_bytes--;
5697                                                         if (scsiq->remain_bytes == 0UL) {
5698                                                                 false_overrun = TRUE;
5699                                                         }
5700                                                 }
5701                                         }
5702                                 }
5703                         }
5704                         if ((scsiq->d3.done_stat == QD_WITH_ERROR) &&
5705                                 (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN)) {
5706                                 if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
5707                                         scsiq->d3.done_stat = QD_NO_ERROR;
5708                                         scsiq->d3.host_stat = QHSTA_NO_ERROR;
5709                                 } else if (false_overrun) {
5710                                         scsiq->d3.done_stat = QD_NO_ERROR;
5711                                         scsiq->d3.host_stat = QHSTA_NO_ERROR;
5712                                 }
5713                         }
5714 #if CC_CLEAR_LRAM_SRB_PTR
5715                         AscWriteLramDWord(iop_base,
5716                                                         (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
5717                                                           asc_dvc->int_count);
5718 #endif
5719 
5720                         if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
5721                                 (*asc_isr_callback) (asc_dvc, scsiq);
5722                         } else {
5723                                 if ((AscReadLramByte(iop_base,
5724                                                   (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
5725                                          SCSICMD_StartStopUnit)) {
5726 
5727                                         asc_dvc->unit_not_ready &= ~target_id;
5728                                         if (scsiq->d3.done_stat != QD_NO_ERROR) {
5729                                                 asc_dvc->start_motor &= ~target_id;
5730                                         }
5731                                 }
5732                         }
5733 
5734 #if CC_LINK_BUSY_Q
5735                         n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, tid_no);
5736                         if (n_busy_q_done == 0) {
5737 
5738                                 i = tid_no + 1;
5739                                 while (TRUE) {
5740                                         if (i > ASC_MAX_TID)
5741                                                 i = 0;
5742                                         if (i == tid_no)
5743                                                 break;
5744                                         n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, i);
5745                                         if (n_busy_q_done != 0)
5746                                                 break;
5747                                         i++;
5748                                 }
5749                         }
5750                         if (n_busy_q_done == 0xFFFF)
5751                                 return (0x80);
5752 #endif
5753 
5754                         return (1);
5755                 } else {
5756 
5757                         AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
5758 
5759                   FATAL_ERR_QDONE:
5760                         if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
5761                                 (*asc_isr_callback) (asc_dvc, scsiq);
5762                         }
5763                         return (0x80);
5764                 }
5765         }
5766         return (0);
5767 }
5768 
5769 int
5770 AscISR(
     /* [previous][next][first][last][top][bottom][index][help] */
5771                   ASC_DVC_VAR asc_ptr_type * asc_dvc
5772 )
5773 {
5774         ASC_CS_TYPE         chipstat;
5775         PortAddr            iop_base;
5776         ushort              saved_ram_addr;
5777         uchar               ctrl_reg;
5778         uchar               saved_ctrl_reg;
5779         int                 int_pending;
5780         int                 status;
5781         uchar               host_flag;
5782 
5783         iop_base = asc_dvc->iop_base;
5784         int_pending = FALSE;
5785 
5786         asc_dvc->int_count++;
5787 
5788         if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) ||
5789                 (asc_dvc->isr_callback == 0)) {
5790 
5791                 return (ERR);
5792         }
5793         if (asc_dvc->in_critical_cnt != 0) {
5794                 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
5795                 return (ERR);
5796         }
5797         if (asc_dvc->is_in_int) {
5798                 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
5799                 asc_dvc->busy_count++;
5800                 return (ERR);
5801         }
5802         asc_dvc->is_in_int = TRUE;
5803         ctrl_reg = AscGetChipControl(iop_base);
5804         saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
5805                                                                    CC_SINGLE_STEP | CC_DIAG | CC_TEST));
5806 
5807         if ((chipstat = AscGetChipStatus(iop_base)) & CSW_INT_PENDING) {
5808                 int_pending = TRUE;
5809                 AscAckInterrupt(iop_base);
5810 
5811                 host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B);
5812                 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
5813                                                  (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
5814                 saved_ram_addr = AscGetChipLramAddr(iop_base);
5815 
5816                 if ((chipstat & CSW_HALTED) &&
5817                         (ctrl_reg & CC_SINGLE_STEP)) {
5818                         if (AscIsrChipHalted(asc_dvc) == ERR) {
5819 
5820                                 goto ISR_REPORT_QDONE_FATAL_ERROR;
5821 
5822                         } else {
5823                                 saved_ctrl_reg &= ~CC_HALT;
5824                         }
5825                 } else {
5826                   ISR_REPORT_QDONE_FATAL_ERROR:
5827                         if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
5828                                 while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
5829 
5830                                 }
5831                         } else {
5832                                 do {
5833                                         if ((status = AscIsrQDone(asc_dvc)) == 1) {
5834 
5835                                                 break;
5836                                         }
5837                                 } while (status == 0x11);
5838                         }
5839                         if ((status & 0x80) != 0)
5840                                 int_pending = ERR;
5841                 }
5842                 AscSetChipLramAddr(iop_base, saved_ram_addr);
5843                 if (AscGetChipLramAddr(iop_base) != saved_ram_addr) {
5844                         AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SET_LRAM_ADDR);
5845                 }
5846                 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
5847         }
5848         AscSetChipControl(iop_base, saved_ctrl_reg);
5849         asc_dvc->is_in_int = FALSE;
5850         return (int_pending);
5851 }
5852 
5853 int
5854 AscScsiSetupCmdQ(
     /* [previous][next][first][last][top][bottom][index][help] */
5855                                         ASC_DVC_VAR asc_ptr_type * asc_dvc,
5856                                         ASC_SCSI_REQ_Q dosfar * scsiq,
5857                                         uchar dosfar * buf_addr,
5858                                         ulong buf_len
5859 )
5860 {
5861         ulong               phy_addr;
5862 
5863         scsiq->r1.cntl = 0;
5864         scsiq->r1.sg_queue_cnt = 0;
5865         scsiq->r1.q_no = 0;
5866         scsiq->r1.user_def = 0;
5867         scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
5868         scsiq->r3.scsi_stat = 0;
5869         scsiq->r3.scsi_msg = 0;
5870         scsiq->r3.host_stat = 0;
5871         scsiq->r3.done_stat = 0;
5872         scsiq->r2.vm_id = 0;
5873         scsiq->r1.data_cnt = buf_len;
5874 
5875         scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE;
5876         scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ;
5877         scsiq->r2.srb_ptr = (ulong) scsiq;
5878         scsiq->r1.status = (uchar) QS_READY;
5879         scsiq->r1.data_addr = 0L;
5880 
5881         if (buf_len != 0L) {
5882                 if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
5883                                         (uchar dosfar *) buf_addr, scsiq->r1.data_cnt)) == 0L) {
5884                         return (ERR);
5885                 }
5886                 scsiq->r1.data_addr = phy_addr;
5887         }
5888         return (0);
5889 }
5890 
5891 uchar               _mcode_buf[] =
5892 {
5893         0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5894         0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5895         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5896         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5897         0x00, 0x00, 0x00, 0x00, 0xDD, 0x0A, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
5898         0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5899         0x00, 0x00, 0x00, 0x23, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
5900         0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x88, 0x00, 0x00, 0x00, 0x00,
5901         0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC8, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
5902         0xB6, 0x00, 0x36, 0x00, 0x06, 0xD6, 0x0D, 0xD2, 0x15, 0xDE, 0x12, 0xDA, 0x00, 0xA2, 0xC8, 0x00,
5903         0x92, 0x80, 0xE0, 0x97, 0x50, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00,
5904         0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
5905         0x80, 0x62, 0x92, 0x80, 0x00, 0x62, 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01,
5906         0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDC, 0x00, 0x68, 0x97, 0x7F, 0x23, 0x04, 0x61,
5907         0x84, 0x01, 0xB2, 0x84, 0xCF, 0xC1, 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE8, 0x01,
5908         0x68, 0x97, 0xD4, 0x81, 0x00, 0x33, 0x02, 0x00, 0x82, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01,
5909         0x01, 0xA1, 0x08, 0x01, 0x4F, 0x00, 0x46, 0x97, 0x07, 0xA6, 0x12, 0x01, 0x00, 0x33, 0x03, 0x00,
5910         0x82, 0x88, 0x03, 0x03, 0x03, 0xDE, 0x00, 0x33, 0x05, 0x00, 0x82, 0x88, 0xCE, 0x00, 0x69, 0x60,
5911         0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x86, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x32, 0x01,
5912         0x86, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x42, 0x01, 0x00, 0x33, 0x04, 0x00,
5913         0x82, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x2A, 0x98, 0x4D, 0x04, 0xD0, 0x84,
5914         0x05, 0xD8, 0x0D, 0x23, 0x2A, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xB8, 0x88, 0xFB, 0x23, 0x02, 0x61,
5915         0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x70, 0x01, 0x00, 0x33, 0x0A, 0x00, 0x82, 0x88,
5916         0x4E, 0x00, 0x07, 0xA3, 0x7C, 0x01, 0x00, 0x33, 0x0B, 0x00, 0x82, 0x88, 0xCD, 0x04, 0x36, 0x2D,
5917         0x00, 0x33, 0x1A, 0x00, 0x82, 0x88, 0x50, 0x04, 0x96, 0x81, 0x06, 0xAB, 0x90, 0x01, 0x96, 0x81,
5918         0x4E, 0x00, 0x07, 0xA3, 0xA0, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x4A, 0x01, 0x00, 0x05, 0x8A, 0x81,
5919         0x08, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xCC, 0x81,
5920         0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xC2, 0x01,
5921         0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0x82, 0x88, 0x06, 0x23, 0x2A, 0x98,
5922         0xCD, 0x04, 0xB2, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xE2, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE8, 0x01,
5923         0xB2, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xB2, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2,
5924         0x10, 0x02, 0x04, 0x01, 0x0D, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x46, 0x97, 0x0A, 0x82,
5925         0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x24, 0x97, 0x48, 0x04, 0xFF, 0x23, 0x84, 0x80,
5926         0xB2, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
5927         0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x66, 0xEB, 0x11, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0xFA, 0x80,
5928         0x80, 0x73, 0x80, 0x77, 0x06, 0xA6, 0x3E, 0x02, 0x00, 0x33, 0x31, 0x00, 0x82, 0x88, 0x04, 0x01,
5929         0x03, 0xD8, 0x74, 0x98, 0x02, 0x96, 0x50, 0x82, 0xA2, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
5930         0xB6, 0x2D, 0x02, 0xA6, 0x7A, 0x02, 0x07, 0xA6, 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x03, 0xA6,
5931         0x70, 0x02, 0x00, 0x33, 0x10, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x52, 0x82, 0xF8, 0x95, 0x52, 0x82,
5932         0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x16, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23,
5933         0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23,
5934         0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAC, 0x02, 0x07, 0xA6,
5935         0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x12, 0x00, 0x82, 0x88, 0x00, 0x0E, 0x80, 0x63,
5936         0x00, 0x43, 0x00, 0xA0, 0x9A, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61,
5937         0x84, 0x01, 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
5938         0xEC, 0x82, 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE4, 0x02, 0x04, 0x01, 0x8E, 0xC8, 0x00, 0x33,
5939         0x1F, 0x00, 0x82, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x40, 0x98, 0xB6, 0x2D,
5940         0x01, 0xA6, 0x0E, 0x03, 0x00, 0xA6, 0x1C, 0x03, 0x07, 0xA6, 0x2A, 0x03, 0x06, 0xA6, 0x2E, 0x03,
5941         0x03, 0xA6, 0xFA, 0x03, 0x02, 0xA6, 0x7A, 0x02, 0x00, 0x33, 0x33, 0x00, 0x82, 0x88, 0x08, 0x23,
5942         0xB3, 0x01, 0x04, 0x01, 0x0E, 0xD0, 0x00, 0x33, 0x14, 0x00, 0x82, 0x88, 0x10, 0x23, 0xB3, 0x01,
5943         0x04, 0x01, 0x07, 0xCC, 0x00, 0x33, 0x15, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xF0, 0x82, 0xF8, 0x95,
5944         0xF0, 0x82, 0x44, 0x98, 0x80, 0x42, 0x40, 0x98, 0x48, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05,
5945         0x07, 0x01, 0x00, 0xA2, 0x72, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x48, 0x98, 0x40, 0x98,
5946         0x00, 0xA6, 0x34, 0x03, 0x07, 0xA6, 0x6A, 0x03, 0x03, 0xA6, 0x16, 0x04, 0x06, 0xA6, 0x6E, 0x03,
5947         0x01, 0xA6, 0x34, 0x03, 0x00, 0x33, 0x25, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x50, 0x83, 0xF8, 0x95,
5948         0x50, 0x83, 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0x82, 0x88, 0x00, 0x01,
5949         0x05, 0x05, 0xFF, 0xA2, 0x90, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x4C, 0x83, 0x05, 0x05,
5950         0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0xAA, 0x03, 0xF0, 0x83, 0x68, 0x98, 0x80, 0x42, 0x01, 0xA6,
5951         0x9A, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x2F, 0x00, 0x82, 0x88, 0x68, 0x98, 0x80, 0x42, 0x00, 0xA6,
5952         0xAA, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x26, 0x00, 0x82, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36,
5953         0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0xF0, 0x83, 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33,
5954         0x20, 0x00, 0x82, 0x88, 0x03, 0xA6, 0xEE, 0x03, 0x07, 0xA6, 0xE6, 0x03, 0x06, 0xA6, 0xEA, 0x03,
5955         0x00, 0x33, 0x17, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xD4, 0x83, 0xF8, 0x95, 0xD4, 0x83, 0xFA, 0x83,
5956         0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, 0x20, 0x00, 0x82, 0x88, 0xB6, 0x2D, 0x03, 0xA6, 0x16, 0x04,
5957         0x07, 0xA6, 0x0E, 0x04, 0x06, 0xA6, 0x12, 0x04, 0x00, 0x33, 0x30, 0x00, 0x82, 0x88, 0x4A, 0x95,
5958         0xFA, 0x83, 0xF8, 0x95, 0xFA, 0x83, 0xA2, 0x0D, 0x80, 0x63, 0x07, 0xA6, 0x24, 0x04, 0x00, 0x33,
5959         0x18, 0x00, 0x82, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x2E, 0x04, 0x23, 0x01,
5960         0x00, 0xA2, 0x50, 0x04, 0x0A, 0xA0, 0x40, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00, 0x82, 0x88,
5961         0x0B, 0xA0, 0x4C, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, 0x82, 0x88, 0x42, 0x23, 0xB8, 0x88,
5962         0x00, 0x23, 0x22, 0xA3, 0xB2, 0x04, 0x08, 0x23, 0x22, 0xA3, 0x6C, 0x04, 0x28, 0x23, 0x22, 0xA3,
5963         0x78, 0x04, 0x02, 0x23, 0x22, 0xA3, 0x8E, 0x04, 0x42, 0x23, 0xB8, 0x88, 0x4A, 0x00, 0x06, 0x61,
5964         0x00, 0xA0, 0x78, 0x04, 0x45, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0x00, 0xA2, 0x8A, 0x04, 0x74, 0x98,
5965         0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF6, 0x81, 0x47, 0x23, 0xB8, 0x88, 0x04, 0x01,
5966         0x0C, 0xDE, 0x14, 0x01, 0x00, 0xA2, 0xA6, 0x04, 0xC6, 0x97, 0x74, 0x98, 0x00, 0x33, 0x00, 0x81,
5967         0xC0, 0x20, 0x81, 0x62, 0x10, 0x82, 0x43, 0x23, 0xB8, 0x88, 0x04, 0x23, 0xA0, 0x01, 0x44, 0x23,
5968         0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xC0, 0x04, 0x00, 0x33, 0x27, 0x00, 0x82, 0x88,
5969         0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xC6, 0x97, 0xF4, 0x94,
5970         0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0xEE, 0x04, 0x00, 0x05, 0x76, 0x00,
5971         0x06, 0x61, 0x00, 0xA2, 0xE8, 0x04, 0xD6, 0x84, 0x08, 0x97, 0xCD, 0x04, 0xF2, 0x84, 0x48, 0x04,
5972         0xFF, 0x23, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x02, 0x85, 0x02, 0x23,
5973         0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x0E, 0x05, 0x1D, 0x01, 0x04, 0xD6, 0xFF, 0x23,
5974         0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, 0x04, 0x01,
5975         0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00,
5976         0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x2E, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, 0x5D, 0x00,
5977         0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xA0, 0x05, 0x03, 0x03,
5978         0x02, 0xA0, 0x5C, 0x05, 0x9C, 0x85, 0x00, 0x33, 0x2D, 0x00, 0x82, 0x88, 0x04, 0xA0, 0x82, 0x05,
5979         0x80, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x6E, 0x05, 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23,
5980         0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x24, 0x97, 0xD0, 0x84, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01,
5981         0xD0, 0x84, 0x08, 0xA0, 0x88, 0x05, 0x9C, 0x85, 0x03, 0xA0, 0x8E, 0x05, 0x9C, 0x85, 0x01, 0xA0,
5982         0x9A, 0x05, 0x88, 0x00, 0x80, 0x63, 0x78, 0x96, 0x4A, 0x85, 0x88, 0x86, 0x80, 0x63, 0x4A, 0x85,
5983         0x00, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xDE, 0x05, 0x1D, 0x01, 0x18, 0xD4, 0xC0, 0x23,
5984         0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0xC0, 0x05, 0x00, 0x33, 0x37, 0x00, 0x82, 0x88,
5985         0x1D, 0x01, 0x02, 0xD6, 0x46, 0x23, 0xB8, 0x88, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
5986         0xD8, 0x05, 0x00, 0x33, 0x38, 0x00, 0x82, 0x88, 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00,
5987         0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xF2, 0x05, 0xC0, 0x23, 0x07, 0x41,
5988         0x00, 0x63, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63,
5989         0x00, 0x63, 0x06, 0xA6, 0x14, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x02, 0xA6, 0xBC, 0x06, 0x00, 0x33,
5990         0x39, 0x00, 0x82, 0x88, 0x00, 0x00, 0x01, 0xA0, 0xD6, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63,
5991         0x06, 0xA6, 0x28, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63,
5992         0x01, 0x00, 0x06, 0xA6, 0x40, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3A, 0x00, 0x82, 0x88,
5993         0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x32, 0x06, 0x06, 0xA6, 0x58, 0x06, 0x07, 0xA6,
5994         0x64, 0x06, 0x00, 0x33, 0x3B, 0x00, 0x82, 0x88, 0x80, 0x67, 0x40, 0x0E, 0x80, 0x63, 0x07, 0xA6,
5995         0x64, 0x06, 0x00, 0x63, 0x03, 0x03, 0x80, 0x63, 0x88, 0x00, 0x01, 0xA2, 0x78, 0x06, 0x07, 0xA2,
5996         0xBC, 0x06, 0x00, 0x33, 0x35, 0x00, 0x82, 0x88, 0x07, 0xA6, 0x82, 0x06, 0x00, 0x33, 0x2A, 0x00,
5997         0x82, 0x88, 0x03, 0x03, 0x03, 0xA2, 0x8E, 0x06, 0x07, 0x23, 0x80, 0x00, 0xC8, 0x86, 0x80, 0x63,
5998         0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0x9E, 0x06, 0x00, 0x33, 0x29, 0x00, 0x82, 0x88, 0x00, 0x43,
5999         0x00, 0xA2, 0xAA, 0x06, 0xC0, 0x0E, 0x80, 0x63, 0x94, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80,
6000         0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, 0x08, 0xDA, 0x80, 0x63, 0x00, 0x63, 0x80, 0x67, 0x00, 0x33,
6001         0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x20, 0x06,
6002         0x00, 0x33, 0x2C, 0x00, 0x82, 0x88, 0x0C, 0xA2, 0xF0, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63,
6003         0x06, 0xA6, 0xEE, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3D, 0x00, 0x82, 0x88, 0x00, 0x00,
6004         0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x06, 0x07, 0x07, 0xA6, 0x64, 0x06, 0xBF, 0x23,
6005         0x04, 0x61, 0x84, 0x01, 0xB2, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01,
6006         0xF2, 0x00, 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05,
6007         0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00,
6008         0x81, 0x01, 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00,
6009         0x80, 0x01, 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00,
6010         0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04,
6011         0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01,
6012         0xA2, 0x01, 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0x86, 0x07,
6013         0x00, 0x33, 0x07, 0x00, 0x82, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00,
6014         0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2,
6015         0xA6, 0x07, 0x00, 0x05, 0x9C, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05,
6016         0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08,
6017         0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02,
6018         0x00, 0xA0, 0xD6, 0x07, 0xD8, 0x87, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
6019         0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2,
6020         0x06, 0x08, 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0xE6, 0x07,
6021         0xC6, 0x97, 0xF4, 0x94, 0xE6, 0x87, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x1C, 0x88,
6022         0x02, 0x01, 0x04, 0xD8, 0x08, 0x97, 0xC6, 0x97, 0xF4, 0x94, 0x0C, 0x88, 0x75, 0x00, 0x00, 0xA3,
6023         0x26, 0x08, 0x00, 0x05, 0x10, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6,
6024         0x38, 0x08, 0x00, 0x33, 0x3E, 0x00, 0x82, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63,
6025         0x38, 0x2B, 0x5E, 0x88, 0x38, 0x2B, 0x54, 0x88, 0x32, 0x09, 0x31, 0x05, 0x54, 0x98, 0x05, 0x05,
6026         0xB2, 0x09, 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32,
6027         0x80, 0x36, 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A,
6028         0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0x74, 0x08, 0x5D, 0x00, 0xFE, 0xC3,
6029         0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
6030         0x13, 0x23, 0xB8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01,
6031         0x81, 0x62, 0xA2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2,
6032         0xF1, 0xC7, 0x41, 0x23, 0xB8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xB2, 0x84,
6033 
6034 };
6035 
6036 ushort              _mcode_size = sizeof (_mcode_buf);
6037 ulong               _mcode_chksum = 0x012258FBUL;
6038 
6039 extern uchar        _sdtr_period_tbl_[];
6040 
6041 int
6042 AscExeScsiQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
6043                                    ASC_DVC_VAR asc_ptr_type * asc_dvc,
6044                                    ASC_SCSI_Q dosfar * scsiq
6045 )
6046 {
6047         PortAddr            iop_base;
6048         int                 last_int_level;
6049         int                 sta;
6050         ulong               addr;
6051         uchar               sg_entry_cnt;
6052         uchar               target_ix;
6053         int                 n_q_required;
6054         uchar               sg_entry_cnt_minus_one;
6055         uchar               tid_no;
6056         uchar               sdtr_data;
6057         ASC_EXE_CALLBACK    asc_exe_callback;
6058 
6059 #if CC_DEBUG_SG_LIST
6060         int                 i;
6061 
6062 #endif
6063 #if CC_LINK_BUSY_Q
6064         ASC_SCSI_Q dosfar  *scsiq_tail;
6065         ASC_SCSI_Q dosfar  *scsiq_next;
6066         ASC_SCSI_Q dosfar  *scsiq_prev;
6067 
6068 #endif
6069 
6070         iop_base = asc_dvc->iop_base;
6071         asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
6072         if (asc_dvc->err_code != 0)
6073                 return (ERR);
6074         if (scsiq == (ASC_SCSI_Q dosfar *) 0L) {
6075                 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
6076                 return (ERR);
6077         }
6078         scsiq->q1.q_no = 0;
6079         sta = 0;
6080         target_ix = scsiq->q2.target_ix;
6081         tid_no = ASC_TIX_TO_TID(target_ix);
6082 
6083         n_q_required = 1;
6084 
6085         if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
6086 
6087                 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
6088                         ((asc_dvc->sdtr_done & scsiq->q1.target_id) != 0)) {
6089                         sdtr_data = AscReadLramByte(iop_base,
6090                                   (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
6091                         AscMsgOutSDTR(iop_base,
6092                                                   _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)],
6093                                                   (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
6094                         scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
6095                 }
6096         }
6097         last_int_level = DvcEnterCritical();
6098         if (asc_dvc->in_critical_cnt != 0) {
6099                 DvcLeaveCritical(last_int_level);
6100                 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
6101                 return (ERR);
6102         }
6103         asc_dvc->in_critical_cnt++;
6104 
6105         if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
6106 
6107                 if ((sg_entry_cnt = scsiq->sg_head->entry_cnt) == 0) {
6108                         asc_dvc->in_critical_cnt--;
6109                         DvcLeaveCritical(last_int_level);
6110                         return (ERR);
6111                 }
6112                 if (sg_entry_cnt == 1) {
6113                         scsiq->q1.data_addr = scsiq->sg_head->sg_list[0].addr;
6114                         scsiq->q1.data_cnt = scsiq->sg_head->sg_list[0].bytes;
6115                         scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
6116                         goto NON_SG_LIST_REQ;
6117                 }
6118                 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
6119 
6120                         return (ERR);
6121                 }
6122                 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
6123 
6124 #if CC_DEBUG_SG_LIST
6125                 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
6126                         for (i = 0; i < sg_entry_cnt_minus_one; i++) {
6127 
6128                                 addr = scsiq->sg_head->sg_list[i].addr +
6129                                   scsiq->sg_head->sg_list[i].bytes;
6130 
6131                                 if (((ushort) addr & 0x0003) != 0) {
6132                                         asc_dvc->in_critical_cnt--;
6133                                         DvcLeaveCritical(last_int_level);
6134                                         AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_LIST_ODD_ADDRESS);
6135                                         return (ERR);
6136                                 }
6137                         }
6138                 }
6139 #endif
6140 
6141                 if (asc_dvc->bug_fix_cntl) {
6142                         if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
6143 
6144                                 addr = scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].addr +
6145                                   scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
6146                                 if (((ushort) addr & 0x0003) != 0) {
6147                                         if ((scsiq->cdbptr[0] == SCSICMD_Read6) ||
6148                                                 (scsiq->cdbptr[0] == SCSICMD_Read10)) {
6149                                                 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) {
6150 
6151                                                         scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes++;
6152                                                         scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE;
6153                                                 }
6154                                         }
6155                                 }
6156                         }
6157                 }
6158                 scsiq->sg_head->entry_to_copy = scsiq->sg_head->entry_cnt;
6159                 n_q_required = AscSgListToQueue(sg_entry_cnt);
6160 
6161 #if CC_LINK_BUSY_Q
6162                 scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no];
6163                 if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) {
6164                         goto link_scisq_to_busy_list;
6165                 }
6166 #endif
6167 
6168                 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required)
6169                          >= (uint) n_q_required) ||
6170                         ((scsiq->q1.cntl & QC_URGENT) != 0)) {
6171                         if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
6172                                                                                 n_q_required)) == 1) {
6173 
6174                                 asc_dvc->in_critical_cnt--;
6175                                 if (asc_exe_callback != 0) {
6176                                         (*asc_exe_callback) (asc_dvc, scsiq);
6177                                 }
6178                                 DvcLeaveCritical(last_int_level);
6179                                 return (sta);
6180                         }
6181                 }
6182         } else {
6183 
6184           NON_SG_LIST_REQ:
6185 
6186                 if (asc_dvc->bug_fix_cntl) {
6187                         if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
6188 
6189                                 addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
6190                                 if ((scsiq->cdbptr[0] == SCSICMD_Read6) ||
6191                                         (scsiq->cdbptr[0] == SCSICMD_Read10)) {
6192                                         if (((ushort) addr & 0x0003) != 0) {
6193                                                 if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
6194 
6195                                                         if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) {
6196 
6197                                                                 scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE;
6198                                                                 scsiq->q1.data_cnt++;
6199                                                         }
6200                                                 }
6201                                         }
6202                                 }
6203                         }
6204                 }
6205                 n_q_required = 1;
6206 
6207 #if CC_LINK_BUSY_Q
6208                 scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no];
6209                 if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) {
6210                         goto link_scisq_to_busy_list;
6211                 }
6212 #endif
6213                 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
6214                         ((scsiq->q1.cntl & QC_URGENT) != 0)) {
6215                         if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
6216                                                                                 n_q_required)) == 1) {
6217 
6218                                 asc_dvc->in_critical_cnt--;
6219                                 if (asc_exe_callback != 0) {
6220                                         (*asc_exe_callback) (asc_dvc, scsiq);
6221                                 }
6222                                 DvcLeaveCritical(last_int_level);
6223                                 return (sta);
6224                         }
6225                 }
6226         }
6227 
6228 #if CC_LINK_BUSY_Q
6229         if (sta == 0) {
6230 
6231           link_scisq_to_busy_list:
6232                 scsiq->ext.q_required = n_q_required;
6233                 if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) {
6234                         asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6235                         asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6236                         scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L;
6237                         scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
6238                         scsiq->q1.status = QS_BUSY;
6239                         sta = 1;
6240                 } else {
6241                         scsiq_tail = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_tail[tid_no];
6242                         if (scsiq_tail->ext.next == (ASC_SCSI_Q dosfar *) 0L) {
6243                                 if ((scsiq->q1.cntl & QC_URGENT) != 0) {
6244 
6245                                         asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6246                                         scsiq->ext.next = scsiq_next;
6247                                         scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
6248                                 } else {
6249                                         if (scsiq->ext.cntl & QCX_SORT) {
6250                                                 do {
6251                                                         scsiq_prev = scsiq_next;
6252                                                         scsiq_next = scsiq_next->ext.next;
6253                                                         if (scsiq->ext.lba < scsiq_prev->ext.lba)
6254                                                                 break;
6255                                                 } while (scsiq_next != (ASC_SCSI_Q dosfar *) 0L);
6256 
6257                                                 scsiq_prev->ext.next = scsiq;
6258                                                 scsiq->ext.next = scsiq_next;
6259                                                 if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) {
6260                                                         asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6261                                                 }
6262                                                 scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
6263                                         } else {
6264 
6265                                                 scsiq_tail->ext.next = (ASC_SCSI_Q dosfar *) scsiq;
6266                                                 asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6267                                                 scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L;
6268                                                 scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
6269                                         }
6270                                 }
6271                                 scsiq->q1.status = QS_BUSY;
6272                                 sta = 1;
6273                         } else {
6274 
6275                                 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_BAD_NEXT_PTR);
6276                                 sta = ERR;
6277                         }
6278                 }
6279         }
6280 #endif
6281         asc_dvc->in_critical_cnt--;
6282         DvcLeaveCritical(last_int_level);
6283         return (sta);
6284 }
6285 
6286 int
6287 AscSendScsiQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
6288                                         ASC_DVC_VAR asc_ptr_type * asc_dvc,
6289                                         ASC_SCSI_Q dosfar * scsiq,
6290                                         uchar n_q_required
6291 )
6292 {
6293         PortAddr            iop_base;
6294         uchar               free_q_head;
6295         uchar               next_qp;
6296         uchar               tid_no;
6297         uchar               target_ix;
6298         int                 sta;
6299 
6300         iop_base = asc_dvc->iop_base;
6301         target_ix = scsiq->q2.target_ix;
6302         tid_no = ASC_TIX_TO_TID(target_ix);
6303         sta = 0;
6304         free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
6305         if (n_q_required > 1) {
6306                 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
6307                                                                            free_q_head, (uchar) (n_q_required)))
6308                         != (uchar) ASC_QLINK_END) {
6309                         asc_dvc->last_q_shortage = 0;
6310                         scsiq->sg_head->queue_cnt = n_q_required - 1;
6311                         scsiq->q1.q_no = free_q_head;
6312 
6313                         if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
6314                                                                                           free_q_head)) == 1) {
6315 
6316 #if CC_WRITE_IO_COUNT
6317                                 asc_dvc->req_count++;
6318 #endif
6319 
6320                                 AscPutVarFreeQHead(iop_base, next_qp);
6321                                 asc_dvc->cur_total_qng += (uchar) (n_q_required);
6322                                 asc_dvc->cur_dvc_qng[tid_no]++;
6323                         }
6324                         return (sta);
6325                 }
6326         } else if (n_q_required == 1) {
6327 
6328                 if ((next_qp = AscAllocFreeQueue(iop_base,
6329                                                                                  free_q_head)) != ASC_QLINK_END) {
6330 
6331                         scsiq->q1.q_no = free_q_head;
6332                         if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
6333                                                                                 free_q_head)) == 1) {
6334 
6335 #if CC_WRITE_IO_COUNT
6336                                 asc_dvc->req_count++;
6337 #endif
6338 
6339                                 AscPutVarFreeQHead(iop_base, next_qp);
6340                                 asc_dvc->cur_total_qng++;
6341                                 asc_dvc->cur_dvc_qng[tid_no]++;
6342                         }
6343                         return (sta);
6344                 }
6345         }
6346         return (sta);
6347 }
6348 
6349 int
6350 AscSgListToQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
6351                                         int sg_list
6352 )
6353 {
6354         int                 n_sg_list_qs;
6355 
6356         n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
6357         if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
6358                 n_sg_list_qs++;
6359         return (n_sg_list_qs + 1);
6360 }
6361 
6362 uint
6363 AscGetNumOfFreeQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
6364                                                 ASC_DVC_VAR asc_ptr_type * asc_dvc,
6365                                                 uchar target_ix, uchar n_qs
6366 )
6367 {
6368         uint                cur_used_qs;
6369         uint                cur_free_qs;
6370         ASC_SCSI_BIT_ID_TYPE target_id;
6371         uchar               tid_no;
6372 
6373         target_id = ASC_TIX_TO_TARGET_ID(target_ix);
6374         tid_no = ASC_TIX_TO_TID(target_ix);
6375         if ((asc_dvc->unit_not_ready & target_id) ||
6376                 (asc_dvc->queue_full_or_busy & target_id)) {
6377                 return (0);
6378         }
6379         if (n_qs == 1) {
6380                 cur_used_qs = (uint) asc_dvc->cur_total_qng +
6381                   (uint) asc_dvc->last_q_shortage +
6382                   (uint) ASC_MIN_FREE_Q;
6383         } else {
6384                 cur_used_qs = (uint) asc_dvc->cur_total_qng +
6385                   (uint) ASC_MIN_FREE_Q;
6386         }
6387 
6388         if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
6389                 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
6390                 if (asc_dvc->cur_dvc_qng[tid_no] >=
6391                         asc_dvc->max_dvc_qng[tid_no]) {
6392                         return (0);
6393                 }
6394                 return (cur_free_qs);
6395         }
6396         if (n_qs > 1) {
6397                 if (n_qs > asc_dvc->last_q_shortage) {
6398                         asc_dvc->last_q_shortage = n_qs;
6399                 }
6400         }
6401         return (0);
6402 }
6403 
6404 int
6405 AscPutReadyQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
6406                                         ASC_DVC_VAR asc_ptr_type * asc_dvc,
6407                                         ASC_SCSI_Q dosfar * scsiq,
6408                                         uchar q_no
6409 )
6410 {
6411         ushort              q_addr;
6412         uchar               tid_no;
6413         uchar               sdtr_data;
6414         uchar               syn_period_ix;
6415         uchar               syn_offset;
6416         PortAddr            iop_base;
6417 
6418         iop_base = asc_dvc->iop_base;
6419 
6420         if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
6421                 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
6422 
6423                 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
6424 
6425                 sdtr_data = AscReadLramByte(iop_base,
6426                                   (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
6427                 syn_period_ix = (sdtr_data >> 4) & (ASC_SYN_XFER_NO - 1);
6428                 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
6429                 AscMsgOutSDTR(iop_base,
6430                                           _sdtr_period_tbl_[syn_period_ix],
6431                                           syn_offset);
6432 
6433                 scsiq->q1.cntl |= QC_MSG_OUT;
6434         }
6435         q_addr = ASC_QNO_TO_QADDR(q_no);
6436 
6437         if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
6438                 scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
6439         }
6440         scsiq->q1.status = QS_FREE;
6441 
6442         AscMemWordCopyToLram(iop_base,
6443                                                  (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
6444                                                  (ushort dosfar *) scsiq->cdbptr,
6445                                                  (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
6446 
6447 #if !CC_LITTLE_ENDIAN_HOST
6448         AscAdjEndianScsiQ(scsiq);
6449 #endif
6450 
6451         DvcPutScsiQ(iop_base,
6452                                 (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
6453                                 (ushort dosfar *) & scsiq->q1.cntl,
6454           (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
6455 
6456 #if CC_WRITE_IO_COUNT
6457         AscWriteLramWord(iop_base,
6458                                          (ushort) (q_addr + (ushort) ASC_SCSIQ_W_REQ_COUNT),
6459                                          (ushort) asc_dvc->req_count);
6460 
6461 #endif
6462 
6463 #if CC_VERIFY_LRAM_COPY
6464         if ((asc_dvc->dvc_cntl & ASC_CNTL_NO_VERIFY_COPY) == 0) {
6465 
6466                 if (AscMemWordCmpToLram(iop_base,
6467                                                          (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
6468                                                                 (ushort dosfar *) scsiq->cdbptr,
6469                                                                 (ushort) (scsiq->q2.cdb_len >> 1)) != 0) {
6470                         AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
6471                         return (ERR);
6472                 }
6473                 if (AscMemWordCmpToLram(iop_base,
6474                                                          (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
6475                                                                 (ushort dosfar *) & scsiq->q1.cntl,
6476                  (ushort) (((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1))
6477                         != 0) {
6478                         AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
6479                         return (ERR);
6480                 }
6481         }
6482 #endif
6483 
6484 #if CC_CLEAR_DMA_REMAIN
6485 
6486         AscWriteLramDWord(iop_base,
6487                    (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_ADDR), 0UL);
6488         AscWriteLramDWord(iop_base,
6489                         (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT), 0UL);
6490 
6491 #endif
6492 
6493         AscWriteLramWord(iop_base,
6494                                          (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
6495                          (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
6496         return (1);
6497 }
6498 
6499 int
6500 AscPutReadySgListQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
6501                                                   ASC_DVC_VAR asc_ptr_type * asc_dvc,
6502                                                   ASC_SCSI_Q dosfar * scsiq,
6503                                                   uchar q_no
6504 )
6505 {
6506         uchar               sg_list_dwords;
6507         uchar               sg_index, i;
6508         uchar               sg_entry_cnt;
6509         uchar               next_qp;
6510         ushort              q_addr;
6511         int                 sta;
6512         ASC_SG_HEAD dosfar *sg_head;
6513         ASC_SG_LIST_Q       scsi_sg_q;
6514         ulong               saved_data_addr;
6515         ulong               saved_data_cnt;
6516         PortAddr            iop_base;
6517 
6518         iop_base = asc_dvc->iop_base;
6519 
6520         sg_head = scsiq->sg_head;
6521 
6522         saved_data_addr = scsiq->q1.data_addr;
6523         saved_data_cnt = scsiq->q1.data_cnt;
6524         scsiq->q1.data_addr = sg_head->sg_list[0].addr;
6525         scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
6526         sg_entry_cnt = sg_head->entry_cnt - 1;
6527         if (sg_entry_cnt != 0) {
6528                 scsiq->q1.cntl |= QC_SG_HEAD;
6529                 q_addr = ASC_QNO_TO_QADDR(q_no);
6530                 sg_index = 1;
6531                 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
6532                 scsi_sg_q.sg_head_qp = q_no;
6533                 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
6534                 for (i = 0; i < sg_head->queue_cnt; i++) {
6535                         scsi_sg_q.seq_no = i + 1;
6536                         if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
6537                                 sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
6538                                 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
6539                                 if (i == 0) {
6540                                         scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
6541                                         scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
6542                                 } else {
6543                                         scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
6544                                         scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
6545                                 }
6546                         } else {
6547 
6548                                 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
6549                                 sg_list_dwords = sg_entry_cnt << 1;
6550                                 if (i == 0) {
6551                                         scsi_sg_q.sg_list_cnt = sg_entry_cnt;
6552                                         scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
6553                                 } else {
6554                                         scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
6555                                         scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
6556                                 }
6557                                 sg_entry_cnt = 0;
6558                         }
6559                         next_qp = AscReadLramByte(iop_base,
6560                                                                           (ushort) (q_addr + ASC_SCSIQ_B_FWD));
6561                         scsi_sg_q.q_no = next_qp;
6562                         q_addr = ASC_QNO_TO_QADDR(next_qp);
6563 
6564                         AscMemWordCopyToLram(iop_base,
6565                                                                  (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
6566                                                                  (ushort dosfar *) & scsi_sg_q,
6567                                                                  (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
6568 
6569                         AscMemDWordCopyToLram(iop_base,
6570                                                                   (ushort) (q_addr + ASC_SGQ_LIST_BEG),
6571                                                           (ulong dosfar *) & sg_head->sg_list[sg_index],
6572                                                                   (ushort) sg_list_dwords);
6573 
6574                         sg_index += ASC_SG_LIST_PER_Q;
6575                 }
6576         } else {
6577 
6578                 scsiq->q1.cntl &= ~QC_SG_HEAD;
6579         }
6580         sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
6581 
6582         scsiq->q1.data_addr = saved_data_addr;
6583         scsiq->q1.data_cnt = saved_data_cnt;
6584         return (sta);
6585 }
6586 
6587 int
6588 AscAbortSRB(
     /* [previous][next][first][last][top][bottom][index][help] */
6589                            ASC_DVC_VAR asc_ptr_type * asc_dvc,
6590                            ulong srb_ptr
6591 )
6592 {
6593         int                 sta;
6594         ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
6595         PortAddr            iop_base;
6596 
6597         iop_base = asc_dvc->iop_base;
6598         sta = ERR;
6599         saved_unit_not_ready = asc_dvc->unit_not_ready;
6600         asc_dvc->unit_not_ready = 0xFF;
6601         AscWaitISRDone(asc_dvc);
6602         if (AscStopQueueExe(iop_base) == 1) {
6603                 if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
6604                         sta = 1;
6605                         AscCleanUpBusyQueue(iop_base);
6606                         AscStartQueueExe(iop_base);
6607 
6608                 } else {
6609                         sta = 0;
6610                         AscStartQueueExe(iop_base);
6611                 }
6612         }
6613         asc_dvc->unit_not_ready = saved_unit_not_ready;
6614         return (sta);
6615 }
6616 
6617 int
6618 AscResetDevice(
     /* [previous][next][first][last][top][bottom][index][help] */
6619                                   ASC_DVC_VAR asc_ptr_type * asc_dvc,
6620                                   uchar target_ix
6621 )
6622 {
6623         PortAddr            iop_base;
6624         int                 sta;
6625         uchar               tid_no;
6626         ASC_SCSI_BIT_ID_TYPE target_id;
6627         int                 i;
6628         ASC_SCSI_REQ_Q      scsiq_buf;
6629         ASC_SCSI_REQ_Q dosfar *scsiq;
6630         uchar dosfar       *buf;
6631         ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
6632 
6633         iop_base = asc_dvc->iop_base;
6634         tid_no = ASC_TIX_TO_TID(target_ix);
6635         target_id = ASC_TID_TO_TARGET_ID(tid_no);
6636         saved_unit_not_ready = asc_dvc->unit_not_ready;
6637         asc_dvc->unit_not_ready = target_id;
6638         sta = ERR;
6639         AscWaitTixISRDone(asc_dvc, target_ix);
6640         if (AscStopQueueExe(iop_base) == 1) {
6641                 if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
6642 
6643                         AscCleanUpBusyQueue(iop_base);
6644                         AscStartQueueExe(iop_base);
6645 
6646                         AscWaitTixISRDone(asc_dvc, target_ix);
6647 
6648                         sta = TRUE;
6649                         scsiq = (ASC_SCSI_REQ_Q dosfar *) & scsiq_buf;
6650                         buf = (uchar dosfar *) & scsiq_buf;
6651                         for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
6652                                 *buf++ = 0x00;
6653                         }
6654 
6655                         scsiq->r1.status = (uchar) QS_READY;
6656                         scsiq->r2.cdb_len = 6;
6657                         scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
6658                         scsiq->r1.target_id = target_id;
6659 
6660                         scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
6661                         scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
6662 
6663                         scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
6664                         AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
6665                                                          M1_BUS_DVC_RESET);
6666 
6667                         asc_dvc->unit_not_ready &= ~target_id;
6668 
6669                         asc_dvc->sdtr_done |= target_id;
6670 
6671                         if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q dosfar *) scsiq)
6672                                 == 1) {
6673                                 asc_dvc->unit_not_ready = target_id;
6674                                 DvcSleepMilliSecond(1000);
6675                                 _AscWaitQDone(iop_base, (ASC_SCSI_Q dosfar *) scsiq);
6676                                 if (AscStopQueueExe(iop_base) == 1) {
6677 
6678                                         AscCleanUpDiscQueue(iop_base);
6679                                         AscStartQueueExe(iop_base);
6680                                         if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6681 
6682                                                 AscSetRunChipSynRegAtID(iop_base, tid_no,
6683                                                                                          ASYN_SDTR_DATA_FIX_PCI_REV_AB);
6684                                         }
6685                                         AscWaitTixISRDone(asc_dvc, target_ix);
6686                                 }
6687                         } else {
6688 
6689                                 sta = 0;
6690                         }
6691 
6692                         asc_dvc->sdtr_done &= ~target_id;
6693                 } else {
6694                         sta = ERR;
6695                         AscStartQueueExe(iop_base);
6696                 }
6697         }
6698         asc_dvc->unit_not_ready = saved_unit_not_ready;
6699         return (sta);
6700 }
6701 
6702 int
6703 AscResetSB(
     /* [previous][next][first][last][top][bottom][index][help] */
6704                           ASC_DVC_VAR asc_ptr_type * asc_dvc
6705 )
6706 {
6707         int                 sta;
6708         int                 i;
6709         PortAddr            iop_base;
6710 
6711         iop_base = asc_dvc->iop_base;
6712         asc_dvc->unit_not_ready = 0xFF;
6713         sta = TRUE;
6714         AscWaitISRDone(asc_dvc);
6715         AscStopQueueExe(iop_base);
6716 
6717         asc_dvc->sdtr_done = 0;
6718         AscResetChipAndScsiBus(iop_base);
6719 
6720         DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
6721 
6722 #if CC_SCAM
6723         if (!(asc_dvc->dvc_cntl & ASC_CNTL_NO_SCAM)) {
6724                 AscSCAM(asc_dvc);
6725         }
6726 #endif
6727         AscReInitLram(asc_dvc);
6728 
6729         for (i = 0; i <= ASC_MAX_TID; i++) {
6730                 asc_dvc->cur_dvc_qng[i] = 0;
6731                 if (asc_dvc->pci_fix_asyn_xfer & (0x01 << i)) {
6732 
6733                         AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
6734                 }
6735         }
6736 
6737         asc_dvc->err_code = 0;
6738 
6739         AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
6740         if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
6741                 sta = ERR;
6742         }
6743         if (AscStartChip(iop_base) == 0) {
6744                 sta = ERR;
6745         }
6746         AscStartQueueExe(iop_base);
6747         asc_dvc->unit_not_ready = 0;
6748         asc_dvc->queue_full_or_busy = 0;
6749         return (sta);
6750 }
6751 
6752 int
6753 AscSetRunChipSynRegAtID(
     /* [previous][next][first][last][top][bottom][index][help] */
6754                                                    PortAddr iop_base,
6755                                                    uchar tid_no,
6756                                                    uchar sdtr_data
6757 )
6758 {
6759         int                 sta = FALSE;
6760 
6761         if (AscHostReqRiscHalt(iop_base)) {
6762                 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
6763 
6764                 AscStartChip(iop_base);
6765                 return (sta);
6766         }
6767         return (sta);
6768 }
6769 
6770 int
6771 AscSetChipSynRegAtID(
     /* [previous][next][first][last][top][bottom][index][help] */
6772                                                 PortAddr iop_base,
6773                                                 uchar id,
6774                                                 uchar sdtr_data
6775 )
6776 {
6777         AscSetBank(iop_base, 1);
6778         AscWriteChipScsiID(iop_base, id);
6779         if (AscReadChipScsiID(iop_base) != (0x01 << id)) {
6780                 return (FALSE);
6781         }
6782         AscSetBank(iop_base, 0);
6783         AscWriteChipSyn(iop_base, sdtr_data);
6784         if (AscReadChipSyn(iop_base) != sdtr_data) {
6785                 return (FALSE);
6786         }
6787         return (TRUE);
6788 }
6789 
6790 int
6791 AscReInitLram(
     /* [previous][next][first][last][top][bottom][index][help] */
6792                                  ASC_DVC_VAR asc_ptr_type * asc_dvc
6793 )
6794 {
6795         AscInitLram(asc_dvc);
6796         AscInitQLinkVar(asc_dvc);
6797         return (0);
6798 }
6799 
6800 ushort
6801 AscInitLram(
     /* [previous][next][first][last][top][bottom][index][help] */
6802                            ASC_DVC_VAR asc_ptr_type * asc_dvc)
6803 {
6804         uchar               i;
6805         ushort              s_addr;
6806         PortAddr            iop_base;
6807         ushort              warn_code;
6808 
6809         iop_base = asc_dvc->iop_base;
6810         warn_code = 0;
6811 
6812         AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
6813                            (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
6814           );
6815 
6816         i = ASC_MIN_ACTIVE_QNO;
6817         s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
6818 
6819         AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
6820                                          (uchar) (i + 1));
6821         AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
6822                                          (uchar) (asc_dvc->max_total_qng));
6823         AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
6824                                          (uchar) i);
6825         i++;
6826         s_addr += ASC_QBLK_SIZE;
6827         for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
6828                 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
6829                                                  (uchar) (i + 1));
6830                 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
6831                                                  (uchar) (i - 1));
6832                 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
6833                                                  (uchar) i);
6834         }
6835 
6836         AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
6837                                          (uchar) ASC_QLINK_END);
6838         AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
6839                                          (uchar) (asc_dvc->max_total_qng - 1));
6840         AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
6841                                          (uchar) asc_dvc->max_total_qng);
6842         i++;
6843         s_addr += ASC_QBLK_SIZE;
6844 
6845         for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
6846                  i++, s_addr += ASC_QBLK_SIZE) {
6847 
6848                 AscWriteLramByte(iop_base,
6849                                                  (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
6850                 AscWriteLramByte(iop_base,
6851                                                  (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
6852                 AscWriteLramByte(iop_base,
6853                                                  (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
6854         }
6855 
6856         return (warn_code);
6857 }
6858 
6859 ushort
6860 AscInitQLinkVar(
     /* [previous][next][first][last][top][bottom][index][help] */
6861                                    ASC_DVC_VAR asc_ptr_type * asc_dvc
6862 )
6863 {
6864         PortAddr            iop_base;
6865         int                 i;
6866         ushort              lram_addr;
6867 
6868         iop_base = asc_dvc->iop_base;
6869         AscPutRiscVarFreeQHead(iop_base, 1);
6870         AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6871 
6872         AscPutVarFreeQHead(iop_base, 1);
6873         AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6874 
6875         AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
6876                                          (uchar) ((int) asc_dvc->max_total_qng + 1));
6877         AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
6878                                          (uchar) ((int) asc_dvc->max_total_qng + 2));
6879 
6880         AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
6881                                          asc_dvc->max_total_qng);
6882 
6883         AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
6884         AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6885         AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
6886         AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
6887         AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
6888 
6889         AscWriteLramByte(iop_base, (ushort) ASCV_CDBCNT_B, 0);
6890 
6891         lram_addr = ASC_QADR_BEG;
6892         for (i = 0; i < 32; i++, lram_addr += 2) {
6893                 AscWriteLramWord(iop_base, lram_addr, 0);
6894         }
6895 
6896         return (0);
6897 }
6898 
6899 int
6900 AscSetLibErrorCode(
     /* [previous][next][first][last][top][bottom][index][help] */
6901                                           ASC_DVC_VAR asc_ptr_type * asc_dvc,
6902                                           ushort err_code
6903 )
6904 {
6905         if (asc_dvc->err_code == 0) {
6906 
6907                 asc_dvc->err_code = err_code;
6908                 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
6909                                                  err_code);
6910         }
6911         return (err_code);
6912 }
6913 
6914 int
6915 _AscWaitQDone(
     /* [previous][next][first][last][top][bottom][index][help] */
6916                                  PortAddr iop_base,
6917                                  ASC_SCSI_Q dosfar * scsiq
6918 )
6919 {
6920         ushort              q_addr;
6921         uchar               q_status;
6922         int                 count = 0;
6923 
6924         while (scsiq->q1.q_no == 0) ;
6925         q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
6926 
6927         do {
6928                 q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
6929                 DvcSleepMilliSecond(100L);
6930                 if (count++ > 30) {
6931                         return (0);
6932                 }
6933         } while ((q_status & QS_READY) != 0);
6934         return (1);
6935 }
6936 
6937 uchar               _sdtr_period_tbl_[ASC_SYN_XFER_NO] =
6938 {
6939         SYN_XFER_NS_0,
6940         SYN_XFER_NS_1,
6941         SYN_XFER_NS_2,
6942         SYN_XFER_NS_3,
6943         SYN_XFER_NS_4,
6944         SYN_XFER_NS_5,
6945         SYN_XFER_NS_6,
6946         SYN_XFER_NS_7};
6947 
6948 uchar
6949 AscMsgOutSDTR(
     /* [previous][next][first][last][top][bottom][index][help] */
6950                                  PortAddr iop_base,
6951                                  uchar sdtr_period,
6952                                  uchar sdtr_offset
6953 )
6954 {
6955         SDTR_XMSG           sdtr_buf;
6956         uchar               sdtr_period_index;
6957 
6958         sdtr_buf.msg_type = MS_EXTEND;
6959         sdtr_buf.msg_len = MS_SDTR_LEN;
6960         sdtr_buf.msg_req = MS_SDTR_CODE;
6961         sdtr_buf.xfer_period = sdtr_period;
6962         sdtr_offset &= ASC_SYN_MAX_OFFSET;
6963         sdtr_buf.req_ack_offset = sdtr_offset;
6964         AscMemWordCopyToLram(iop_base, ASCV_MSGOUT_BEG,
6965                                                  (ushort dosfar *) & sdtr_buf, SYN_XMSG_WLEN);
6966         if ((sdtr_period_index = AscGetSynPeriodIndex(sdtr_period)) <=
6967                 ASC_MAX_SDTR_PERIOD_INDEX) {
6968                 return ((sdtr_period_index << 4) | sdtr_offset);
6969         } else {
6970 
6971                 return (0);
6972         }
6973 }
6974 
6975 uchar
6976 AscCalSDTRData(
     /* [previous][next][first][last][top][bottom][index][help] */
6977                                   uchar sdtr_period,
6978                                   uchar syn_offset
6979 )
6980 {
6981         uchar               byte;
6982         uchar               sdtr_period_ix;
6983 
6984         sdtr_period_ix = AscGetSynPeriodIndex(sdtr_period);
6985         if ((sdtr_period_ix > ASC_MAX_SDTR_PERIOD_INDEX) ||
6986                 (sdtr_period_ix > ASC_SDTR_PERIOD_IX_MIN)) {
6987                 return (0xFF);
6988         }
6989         byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
6990         return (byte);
6991 }
6992 
6993 void
6994 AscSetChipSDTR(
     /* [previous][next][first][last][top][bottom][index][help] */
6995                                   PortAddr iop_base,
6996                                   uchar sdtr_data,
6997                                   uchar tid_no
6998 )
6999 {
7000 
7001         AscWriteChipSyn(iop_base, sdtr_data);
7002         AscWriteLramByte(iop_base,
7003                                    (ushort) ((ushort) ASCV_SDTR_DONE_BEG + (ushort) tid_no),
7004                                          sdtr_data);
7005         return;
7006 }
7007 
7008 uchar
7009 AscGetSynPeriodIndex(
     /* [previous][next][first][last][top][bottom][index][help] */
7010                                                 uchar syn_time
7011 )
7012 {
7013         if ((syn_time >= SYN_XFER_NS_0) && (syn_time <= SYN_XFER_NS_7)) {
7014                 if (syn_time <= SYN_XFER_NS_6) {
7015                         if (syn_time <= SYN_XFER_NS_5) {
7016                                 if (syn_time <= SYN_XFER_NS_4) {
7017                                         if (syn_time <= SYN_XFER_NS_3) {
7018                                                 if (syn_time <= SYN_XFER_NS_2) {
7019                                                         if (syn_time <= SYN_XFER_NS_1) {
7020                                                                 if (syn_time <= SYN_XFER_NS_0) {
7021                                                                         return (0);
7022                                                                 } else
7023                                                                         return (1);
7024                                                         } else {
7025                                                                 return (2);
7026                                                         }
7027                                                 } else {
7028                                                         return (3);
7029                                                 }
7030                                         } else {
7031                                                 return (4);
7032                                         }
7033                                 } else {
7034                                         return (5);
7035                                 }
7036                         } else {
7037                                 return (6);
7038                         }
7039                 } else {
7040                         return (7);
7041                 }
7042         } else {
7043 
7044                 return (8);
7045         }
7046 }
7047 
7048 uchar
7049 AscAllocFreeQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
7050                                          PortAddr iop_base,
7051                                          uchar free_q_head
7052 )
7053 {
7054         ushort              q_addr;
7055         uchar               next_qp;
7056         uchar               q_status;
7057 
7058         q_addr = ASC_QNO_TO_QADDR(free_q_head);
7059         q_status = (uchar) AscReadLramByte(iop_base,
7060                                                                         (ushort) (q_addr + ASC_SCSIQ_B_STATUS));
7061         next_qp = AscReadLramByte(iop_base,
7062                                                           (ushort) (q_addr + ASC_SCSIQ_B_FWD));
7063         if (((q_status & QS_READY) == 0) &&
7064                 (next_qp != ASC_QLINK_END)) {
7065                 return (next_qp);
7066         }
7067         return (ASC_QLINK_END);
7068 }
7069 
7070 uchar
7071 AscAllocMultipleFreeQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
7072                                                          PortAddr iop_base,
7073                                                          uchar free_q_head,
7074                                                          uchar n_free_q
7075 )
7076 {
7077         uchar               i;
7078 
7079         for (i = 0; i < n_free_q; i++) {
7080                 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
7081                         == ASC_QLINK_END) {
7082                         return (ASC_QLINK_END);
7083                 }
7084         }
7085         return (free_q_head);
7086 }
7087 
7088 int
7089 AscRiscHaltedAbortSRB(
     /* [previous][next][first][last][top][bottom][index][help] */
7090                                                  ASC_DVC_VAR asc_ptr_type * asc_dvc,
7091                                                  ulong srb_ptr
7092 )
7093 {
7094         PortAddr            iop_base;
7095         ushort              q_addr;
7096         uchar               q_no;
7097         ASC_QDONE_INFO      scsiq_buf;
7098         ASC_QDONE_INFO dosfar *scsiq;
7099         ASC_ISR_CALLBACK    asc_isr_callback;
7100         int                 last_int_level;
7101 
7102         iop_base = asc_dvc->iop_base;
7103         asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
7104         last_int_level = DvcEnterCritical();
7105         scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
7106 
7107 #if CC_LINK_BUSY_Q
7108         _AscAbortSrbBusyQueue(asc_dvc, scsiq, srb_ptr);
7109 #endif
7110 
7111         for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
7112                  q_no++) {
7113                 q_addr = ASC_QNO_TO_QADDR(q_no);
7114                 scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
7115                                                    (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
7116                 if (scsiq->d2.srb_ptr == srb_ptr) {
7117                         _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
7118                         if (((scsiq->q_status & QS_READY) != 0) &&
7119                                 ((scsiq->q_status & QS_ABORTED) == 0) &&
7120                                 ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
7121 
7122                                 scsiq->q_status |= QS_ABORTED;
7123                                 scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
7124                                 AscWriteLramDWord(iop_base,
7125                                                         (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
7126                                                                   0L);
7127                                 AscWriteLramByte(iop_base,
7128                                                         (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
7129                                                                  scsiq->q_status);
7130                                 (*asc_isr_callback) (asc_dvc, scsiq);
7131                                 return (1);
7132                         }
7133                 }
7134         }
7135         DvcLeaveCritical(last_int_level);
7136         return (0);
7137 }
7138 
7139 int
7140 AscRiscHaltedAbortTIX(
     /* [previous][next][first][last][top][bottom][index][help] */
7141                                                  ASC_DVC_VAR asc_ptr_type * asc_dvc,
7142                                                  uchar target_ix
7143 )
7144 {
7145         PortAddr            iop_base;
7146         ushort              q_addr;
7147         uchar               q_no;
7148         ASC_QDONE_INFO      scsiq_buf;
7149         ASC_QDONE_INFO dosfar *scsiq;
7150         ASC_ISR_CALLBACK    asc_isr_callback;
7151         int                 last_int_level;
7152 
7153 #if CC_LINK_BUSY_Q
7154         uchar               tid_no;
7155 
7156 #endif
7157 
7158         iop_base = asc_dvc->iop_base;
7159         asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
7160         last_int_level = DvcEnterCritical();
7161         scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
7162 
7163 #if CC_LINK_BUSY_Q
7164 
7165         tid_no = ASC_TIX_TO_TID(target_ix);
7166         _AscAbortTidBusyQueue(asc_dvc, scsiq, tid_no);
7167 
7168 #endif
7169 
7170         for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
7171                  q_no++) {
7172                 q_addr = ASC_QNO_TO_QADDR(q_no);
7173                 _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
7174                 if (((scsiq->q_status & QS_READY) != 0) &&
7175                         ((scsiq->q_status & QS_ABORTED) == 0) &&
7176                         ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
7177                         if (scsiq->d2.target_ix == target_ix) {
7178                                 scsiq->q_status |= QS_ABORTED;
7179                                 scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
7180 
7181                                 AscWriteLramDWord(iop_base,
7182                                                         (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
7183                                                                   0L);
7184 
7185                                 AscWriteLramByte(iop_base,
7186                                                         (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
7187                                                                  scsiq->q_status);
7188                                 (*asc_isr_callback) (asc_dvc, scsiq);
7189                         }
7190                 }
7191         }
7192         DvcLeaveCritical(last_int_level);
7193         return (1);
7194 }
7195 
7196 #if CC_LINK_BUSY_Q
7197 
7198 #endif
7199 
7200 int
7201 AscHostReqRiscHalt(
     /* [previous][next][first][last][top][bottom][index][help] */
7202                                           PortAddr iop_base
7203 )
7204 {
7205         int                 count = 0;
7206         int                 sta = 0;
7207         uchar               saved_stop_code;
7208 
7209         if (AscIsChipHalted(iop_base))
7210                 return (1);
7211         saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
7212 
7213         AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
7214                                          ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
7215           );
7216         do {
7217                 if (AscIsChipHalted(iop_base)) {
7218                         sta = 1;
7219                         break;
7220                 }
7221                 DvcSleepMilliSecond(100);
7222         } while (count++ < 20);
7223 
7224         AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
7225         return (sta);
7226 }
7227 
7228 int
7229 AscStopQueueExe(
     /* [previous][next][first][last][top][bottom][index][help] */
7230                                    PortAddr iop_base
7231 )
7232 {
7233         int                 count;
7234 
7235         count = 0;
7236         if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
7237                 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
7238                                                  ASC_STOP_REQ_RISC_STOP);
7239                 do {
7240                         if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
7241                                 ASC_STOP_ACK_RISC_STOP) {
7242                                 return (1);
7243                         }
7244                         DvcSleepMilliSecond(100);
7245                 } while (count++ < 20);
7246         }
7247         return (0);
7248 }
7249 
7250 int
7251 AscStartQueueExe(
     /* [previous][next][first][last][top][bottom][index][help] */
7252                                         PortAddr iop_base
7253 )
7254 {
7255         if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
7256                 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
7257         }
7258         return (1);
7259 }
7260 
7261 int
7262 AscCleanUpBusyQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
7263                                            PortAddr iop_base
7264 )
7265 {
7266         int                 count;
7267         uchar               stop_code;
7268 
7269         count = 0;
7270         if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
7271                 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
7272                                                  ASC_STOP_CLEAN_UP_BUSY_Q);
7273                 do {
7274                         stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
7275                         if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
7276                                 break;
7277                         DvcSleepMilliSecond(100);
7278                 } while (count++ < 20);
7279         }
7280         return (1);
7281 }
7282 
7283 int
7284 AscCleanUpDiscQueue(
     /* [previous][next][first][last][top][bottom][index][help] */
7285                                            PortAddr iop_base
7286 )
7287 {
7288         int                 count;
7289         uchar               stop_code;
7290 
7291         count = 0;
7292         if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
7293                 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
7294                                                  ASC_STOP_CLEAN_UP_DISC_Q);
7295                 do {
7296                         stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
7297                         if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
7298                                 break;
7299                         DvcSleepMilliSecond(100);
7300                 } while (count++ < 20);
7301         }
7302         return (1);
7303 }
7304 
7305 int
7306 AscWaitTixISRDone(
     /* [previous][next][first][last][top][bottom][index][help] */
7307                                          ASC_DVC_VAR asc_ptr_type * asc_dvc,
7308                                          uchar target_ix
7309 )
7310 {
7311         uchar               cur_req;
7312         uchar               tid_no;
7313 
7314         tid_no = ASC_TIX_TO_TID(target_ix);
7315         while (TRUE) {
7316                 if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
7317                         break;
7318                 }
7319                 DvcSleepMilliSecond(1000L);
7320                 if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
7321                         break;
7322                 }
7323         }
7324         return (1);
7325 }
7326 
7327 int
7328 AscWaitISRDone(
     /* [previous][next][first][last][top][bottom][index][help] */
7329                                   ASC_DVC_VAR asc_ptr_type * asc_dvc
7330 )
7331 {
7332         int                 tid;
7333 
7334         for (tid = 0; tid <= ASC_MAX_TID; tid++) {
7335                 AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
7336         }
7337         return (1);
7338 }
7339 
7340 ulong
7341 AscGetOnePhyAddr(
     /* [previous][next][first][last][top][bottom][index][help] */
7342                                         ASC_DVC_VAR asc_ptr_type * asc_dvc,
7343                                         uchar dosfar * buf_addr,
7344                                         ulong buf_size
7345 )
7346 {
7347         ASC_MIN_SG_HEAD     sg_head;
7348 
7349         sg_head.entry_cnt = ASC_MIN_SG_LIST;
7350         if (DvcGetSGList(asc_dvc, (uchar dosfar *) buf_addr,
7351                                   buf_size, (ASC_SG_HEAD dosfar *) & sg_head) != buf_size) {
7352                 return (0L);
7353         }
7354         if (sg_head.entry_cnt > 1) {
7355                 return (0L);
7356         }
7357         return (sg_head.sg_list[0].addr);
7358 }
7359 
7360 ulong
7361 AscGetEisaProductID(
     /* [previous][next][first][last][top][bottom][index][help] */
7362                                            PortAddr iop_base
7363 )
7364 {
7365         PortAddr            eisa_iop;
7366         ushort              product_id_high, product_id_low;
7367         ulong               product_id;
7368 
7369         eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
7370         product_id_low = inpw(eisa_iop);
7371         product_id_high = inpw(eisa_iop + 2);
7372         product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
7373         return (product_id);
7374 }
7375 
7376 PortAddr
7377 AscSearchIOPortAddrEISA(
     /* [previous][next][first][last][top][bottom][index][help] */
7378                                                    PortAddr iop_base
7379 )
7380 {
7381         ulong               eisa_product_id;
7382 
7383         if (iop_base == 0) {
7384                 iop_base = ASC_EISA_MIN_IOP_ADDR;
7385         } else {
7386                 if (iop_base == ASC_EISA_MAX_IOP_ADDR)
7387                         return (0);
7388                 if ((iop_base & 0x0050) == 0x0050) {
7389                         iop_base += ASC_EISA_BIG_IOP_GAP;
7390                 } else {
7391                         iop_base += ASC_EISA_SMALL_IOP_GAP;
7392                 }
7393         }
7394         while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
7395 
7396                 eisa_product_id = AscGetEisaProductID(iop_base);
7397                 if ((eisa_product_id == ASC_EISA_ID_740) ||
7398                         (eisa_product_id == ASC_EISA_ID_750)) {
7399                         if (AscFindSignature(iop_base)) {
7400 
7401                                 inpw(iop_base + 4);
7402                                 return (iop_base);
7403                         }
7404                 }
7405                 if (iop_base == ASC_EISA_MAX_IOP_ADDR)
7406                         return (0);
7407                 if ((iop_base & 0x0050) == 0x0050) {
7408                         iop_base += ASC_EISA_BIG_IOP_GAP;
7409                 } else {
7410                         iop_base += ASC_EISA_SMALL_IOP_GAP;
7411                 }
7412         }
7413         return (0);
7414 }
7415 
7416 int
7417 AscStartChip(
     /* [previous][next][first][last][top][bottom][index][help] */
7418                                 PortAddr iop_base
7419 )
7420 {
7421         AscSetChipControl(iop_base, 0);
7422         if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
7423                 return (0);
7424         }
7425         return (1);
7426 }
7427 
7428 int
7429 AscStopChip(
     /* [previous][next][first][last][top][bottom][index][help] */
7430                            PortAddr iop_base
7431 )
7432 {
7433         uchar               cc_val;
7434 
7435         cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
7436         AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
7437         AscSetChipIH(iop_base, INS_HALT);
7438         AscSetChipIH(iop_base, INS_RFLAG_WTM);
7439         if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
7440                 return (0);
7441         }
7442         return (1);
7443 }
7444 
7445 int
7446 AscIsChipHalted(
     /* [previous][next][first][last][top][bottom][index][help] */
7447                                    PortAddr iop_base
7448 )
7449 {
7450 
7451         if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
7452                 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
7453                         return (1);
7454                 }
7455         }
7456         return (0);
7457 }
7458 
7459 void
7460 AscSetChipIH(
     /* [previous][next][first][last][top][bottom][index][help] */
7461                                 PortAddr iop_base,
7462                                 ushort ins_code
7463 )
7464 {
7465         AscSetBank(iop_base, 1);
7466         AscWriteChipIH(iop_base, ins_code);
7467         AscSetBank(iop_base, 0);
7468         return;
7469 }
7470 
7471 void
7472 AscAckInterrupt(
     /* [previous][next][first][last][top][bottom][index][help] */
7473                                    PortAddr iop_base
7474 )
7475 {
7476 
7477         uchar               host_flag;
7478         uchar               risc_flag;
7479         ushort              loop;
7480 
7481         loop = 0;
7482         do {
7483                 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
7484                 if (loop++ > 0x7FFF) {
7485                         break;
7486                 }
7487         } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
7488 
7489         host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B);
7490         AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
7491                                          (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
7492 
7493         AscSetChipStatus(iop_base, CIW_INT_ACK);
7494         loop = 0;
7495         while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
7496 
7497                 AscSetChipStatus(iop_base, CIW_INT_ACK);
7498                 if (loop++ > 3) {
7499                         break;
7500                 }
7501         }
7502 
7503         AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
7504         return;
7505 }
7506 
7507 void
7508 AscDisableInterrupt(
     /* [previous][next][first][last][top][bottom][index][help] */
7509                                            PortAddr iop_base
7510 )
7511 {
7512         ushort              cfg;
7513 
7514         cfg = AscGetChipCfgLsw(iop_base);
7515         AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
7516         return;
7517 }
7518 
7519 void
7520 AscEnableInterrupt(
     /* [previous][next][first][last][top][bottom][index][help] */
7521                                           PortAddr iop_base
7522 )
7523 {
7524         ushort              cfg;
7525 
7526         cfg = AscGetChipCfgLsw(iop_base);
7527         AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
7528         return;
7529 }
7530 
7531 void
7532 AscSetBank(
     /* [previous][next][first][last][top][bottom][index][help] */
7533                           PortAddr iop_base,
7534                           uchar bank
7535 )
7536 {
7537         uchar               val;
7538 
7539         val = AscGetChipControl(iop_base) &
7540           (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
7541         if (bank == 1) {
7542                 val |= CC_BANK_ONE;
7543         } else if (bank == 2) {
7544                 val |= CC_DIAG | CC_BANK_ONE;
7545         } else {
7546                 val &= ~CC_BANK_ONE;
7547         }
7548         AscSetChipControl(iop_base, val);
7549         return;
7550 }
7551 
7552 int
7553 AscResetChipAndScsiBus(
     /* [previous][next][first][last][top][bottom][index][help] */
7554                                                   PortAddr iop_base
7555 )
7556 {
7557         AscStopChip(iop_base);
7558         AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
7559         DvcSleepMilliSecond(200);
7560 
7561         AscSetChipIH(iop_base, INS_RFLAG_WTM);
7562         AscSetChipIH(iop_base, INS_HALT);
7563 
7564         AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
7565         AscSetChipControl(iop_base, CC_HALT);
7566         DvcSleepMilliSecond(200);
7567         return (AscIsChipHalted(iop_base));
7568 }
7569 
7570 ushort
7571 AscGetIsaDmaChannel(
     /* [previous][next][first][last][top][bottom][index][help] */
7572                                            PortAddr iop_base
7573 )
7574 {
7575         ushort              channel;
7576 
7577         channel = AscGetChipCfgLsw(iop_base) & 0x0003;
7578         if (channel == 0x03)
7579                 return (0);
7580         else if (channel == 0x00)
7581                 return (7);
7582         return (channel + 4);
7583 }
7584 
7585 ushort
7586 AscSetIsaDmaChannel(
     /* [previous][next][first][last][top][bottom][index][help] */
7587                                            PortAddr iop_base,
7588                                            ushort dma_channel
7589 )
7590 {
7591         ushort              cfg_lsw;
7592         uchar               value;
7593 
7594         if ((dma_channel >= 5) && (dma_channel <= 7)) {
7595 
7596                 if (dma_channel == 7)
7597                         value = 0x00;
7598                 else
7599                         value = dma_channel - 4;
7600                 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
7601                 cfg_lsw |= value;
7602                 AscSetChipCfgLsw(iop_base, cfg_lsw);
7603                 return (AscGetIsaDmaChannel(iop_base));
7604         }
7605         return (0);
7606 }
7607 
7608 uchar
7609 AscSetIsaDmaSpeed(
     /* [previous][next][first][last][top][bottom][index][help] */
7610                                          PortAddr iop_base,
7611                                          uchar speed_value
7612 )
7613 {
7614         speed_value &= 0x07;
7615         AscSetBank(iop_base, 1);
7616         AscSetChipDmaSpeed(iop_base, speed_value);
7617         AscSetBank(iop_base, 0);
7618         return (AscGetIsaDmaSpeed(iop_base));
7619 }
7620 
7621 uchar
7622 AscGetIsaDmaSpeed(
     /* [previous][next][first][last][top][bottom][index][help] */
7623                                          PortAddr iop_base
7624 )
7625 {
7626         uchar               speed_value;
7627 
7628         AscSetBank(iop_base, 1);
7629         speed_value = AscGetChipDmaSpeed(iop_base);
7630         speed_value &= 0x07;
7631         AscSetBank(iop_base, 0);
7632         return (speed_value);
7633 }
7634 
7635 ulong
7636 AscGetMaxDmaCount(
     /* [previous][next][first][last][top][bottom][index][help] */
7637                                          ushort bus_type
7638 )
7639 {
7640         if (bus_type & ASC_IS_ISA)
7641                 return (ASC_MAX_ISA_DMA_COUNT);
7642         else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
7643                 return (ASC_MAX_VL_DMA_COUNT);
7644         return (ASC_MAX_PCI_DMA_COUNT);
7645 }
7646 
7647 ushort
7648 AscInitGetConfig(
     /* [previous][next][first][last][top][bottom][index][help] */
7649                                         ASC_DVC_VAR asc_ptr_type * asc_dvc
7650 )
7651 {
7652         ushort              warn_code;
7653 
7654         warn_code = 0;
7655         asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
7656         if (asc_dvc->err_code != 0)
7657                 return (UW_ERR);
7658         if (AscFindSignature(asc_dvc->iop_base)) {
7659                 warn_code |= AscInitAscDvcVar(asc_dvc);
7660                 warn_code |= AscInitFromEEP(asc_dvc);
7661                 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
7662 
7663                 if (asc_dvc->scsi_reset_wait > 10)
7664                         asc_dvc->scsi_reset_wait = 10;
7665 
7666         } else {
7667                 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
7668         }
7669         return (warn_code);
7670 }
7671 
7672 ushort
7673 AscInitSetConfig(
     /* [previous][next][first][last][top][bottom][index][help] */
7674                                         ASC_DVC_VAR asc_ptr_type * asc_dvc
7675 )
7676 {
7677         ushort              warn_code;
7678 
7679         warn_code = 0;
7680         asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
7681         if (asc_dvc->err_code != 0)
7682                 return (UW_ERR);
7683         if (AscFindSignature(asc_dvc->iop_base)) {
7684                 warn_code |= AscInitFromAscDvcVar(asc_dvc);
7685                 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
7686         } else {
7687                 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
7688         }
7689         return (warn_code);
7690 }
7691 
7692 ushort
7693 AscInitAsc1000Driver(
     /* [previous][next][first][last][top][bottom][index][help] */
7694                                                 ASC_DVC_VAR asc_ptr_type * asc_dvc
7695 )
7696 {
7697         ushort              warn_code;
7698         PortAddr            iop_base;
7699 
7700         extern ushort       _mcode_size;
7701         extern ulong        _mcode_chksum;
7702         extern uchar        _mcode_buf[];
7703 
7704         ASC_DBG(3, "AscInitAsc1000Driver: begin\n");
7705         iop_base = asc_dvc->iop_base;
7706         warn_code = 0;
7707 
7708         if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
7709                 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
7710 
7711                 ASC_DBG(3, "AscInitAsc1000Driver: AscResetChipAndScsiBus()\n");
7712                 AscResetChipAndScsiBus(iop_base);
7713                 DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
7714         }
7715         asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
7716         if (asc_dvc->err_code != 0)
7717                 return (UW_ERR);
7718         ASC_DBG(3, "AscInitAsc1000Driver: AscFindSignature()\n");
7719         if (!AscFindSignature(asc_dvc->iop_base)) {
7720                 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
7721                 return (warn_code);
7722         }
7723         ASC_DBG(3, "AscInitAsc1000Driver: AscDisableInterrupt()\n");
7724         AscDisableInterrupt(iop_base);
7725 
7726         ASC_DBG(3, "AscInitAsc1000Driver: AscInitLram()\n");
7727         warn_code |= AscInitLram(asc_dvc);
7728         if (asc_dvc->err_code != 0)
7729                 return (UW_ERR);
7730         ASC_DBG(3, "AscInitAsc1000Driver: AscLoadMicroCode()\n");
7731         if (AscLoadMicroCode(iop_base, 0, (ushort dosfar *) _mcode_buf,
7732                                                  _mcode_size) != _mcode_chksum) {
7733                 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
7734                 return (warn_code);
7735         }
7736         ASC_DBG(3, "AscInitAsc1000Driver: AscInitMicroCodeVar()\n");
7737         warn_code |= AscInitMicroCodeVar(asc_dvc);
7738         asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
7739         ASC_DBG(3, "AscInitAsc1000Driver: AscEnableInterrupt()\n");
7740         AscEnableInterrupt(iop_base);
7741         return (warn_code);
7742 }
7743 
7744 ushort
7745 AscInitAscDvcVar(
     /* [previous][next][first][last][top][bottom][index][help] */
7746                                         ASC_DVC_VAR asc_ptr_type * asc_dvc
7747 )
7748 {
7749         int                 i;
7750         PortAddr            iop_base;
7751         ushort              warn_code;
7752 
7753         iop_base = asc_dvc->iop_base;
7754         warn_code = 0;
7755         asc_dvc->err_code = 0;
7756 
7757         if ((asc_dvc->bus_type &
7758                  (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
7759                 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
7760         }
7761 #if CC_LINK_BUSY_Q
7762         for (i = 0; i <= ASC_MAX_TID; i++) {
7763                 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L;
7764                 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L;
7765         }
7766 #endif
7767 
7768         asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
7769         asc_dvc->bug_fix_cntl = 0;
7770         asc_dvc->pci_fix_asyn_xfer = 0;
7771         asc_dvc->init_sdtr = 0;
7772         asc_dvc->sdtr_done = 0;
7773         asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
7774         asc_dvc->cur_total_qng = 0;
7775         asc_dvc->is_in_int = 0;
7776         asc_dvc->scsi_reset_wait = 3;
7777         asc_dvc->in_critical_cnt = 0;
7778 
7779         asc_dvc->last_q_shortage = 0;
7780         asc_dvc->use_tagged_qng = 0;
7781         asc_dvc->cfg->can_tagged_qng = 0;
7782         asc_dvc->no_scam = 0;
7783         asc_dvc->irq_no = 10;
7784         asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
7785         asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
7786         asc_dvc->cfg->cmd_qng_enabled = ASC_SCSI_WIDTH_BIT_SET;
7787         asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
7788         asc_dvc->cfg->chip_version = AscGetChipVersion(iop_base,
7789                                                                                                    asc_dvc->bus_type);
7790         if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
7791 
7792                 AscPutChipIFC(iop_base, IFC_INIT_DEFAULT);
7793                 asc_dvc->bus_type = ASC_IS_ISAPNP;
7794         }
7795         asc_dvc->unit_not_ready = 0;
7796         asc_dvc->queue_full_or_busy = 0;
7797 
7798         if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
7799                 asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
7800                 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
7801         }
7802         asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
7803         asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
7804           ASC_LIB_VERSION_MINOR;
7805         asc_dvc->int_count = 0L;
7806         asc_dvc->req_count = 0L;
7807         asc_dvc->busy_count = 0L;
7808         asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
7809 
7810         for (i = 0; i <= ASC_MAX_TID; i++) {
7811                 asc_dvc->cfg->sdtr_data[i] =
7812                   (uchar) (ASC_DEF_SDTR_OFFSET | (ASC_DEF_SDTR_INDEX << 4));
7813                 asc_dvc->cur_dvc_qng[i] = 0;
7814                 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
7815                 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L;
7816                 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L;
7817         }
7818         return (warn_code);
7819 }
7820 
7821 ushort
7822 AscInitFromAscDvcVar(
     /* [previous][next][first][last][top][bottom][index][help] */
7823                                                 ASC_DVC_VAR asc_ptr_type * asc_dvc
7824 )
7825 {
7826         PortAddr            iop_base;
7827         ushort              cfg_msw;
7828         ushort              warn_code;
7829 
7830         iop_base = asc_dvc->iop_base;
7831         warn_code = 0;
7832 
7833         cfg_msw = AscGetChipCfgMsw(iop_base);
7834 
7835         if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
7836                 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
7837                 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
7838                 AscSetChipCfgMsw(iop_base, cfg_msw);
7839         }
7840         if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
7841                 warn_code |= ASC_WARN_AUTO_CONFIG;
7842 
7843         }
7844         if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
7845                 asc_dvc->cfg->cmd_qng_enabled) {
7846                 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
7847                 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
7848         }
7849         if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
7850 
7851                 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
7852                         != asc_dvc->irq_no) {
7853                         asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
7854                 }
7855         }
7856         if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
7857                 asc_dvc->cfg->chip_scsi_id) {
7858                 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
7859         }
7860         if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
7861                 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
7862                 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
7863         }
7864         return (warn_code);
7865 }
7866 
7867 ushort
7868 AscInitFromEEP(
     /* [previous][next][first][last][top][bottom][index][help] */
7869                                   ASC_DVC_VAR asc_ptr_type * asc_dvc
7870 )
7871 {
7872         ASCEEP_CONFIG       eep_config_buf;
7873         ASCEEP_CONFIG dosfar *eep_config;
7874         PortAddr            iop_base;
7875         ushort              chksum;
7876         ushort              warn_code;
7877         ushort              cfg_msw, cfg_lsw;
7878         uchar               i;
7879 
7880         iop_base = asc_dvc->iop_base;
7881         warn_code = 0;
7882 
7883         AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
7884 
7885         AscStopQueueExe(iop_base);
7886         if ((AscStopChip(iop_base) == FALSE) ||
7887                 (AscGetChipScsiCtrl(iop_base) != 0)) {
7888                 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
7889                 AscResetChipAndScsiBus(iop_base);
7890                 DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
7891         }
7892         if (AscIsChipHalted(iop_base) == FALSE) {
7893                 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
7894                 return (warn_code);
7895         }
7896         AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
7897         if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
7898                 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
7899                 return (warn_code);
7900         }
7901         eep_config = (ASCEEP_CONFIG dosfar *) & eep_config_buf;
7902 
7903         cfg_msw = AscGetChipCfgMsw(iop_base);
7904         cfg_lsw = AscGetChipCfgLsw(iop_base);
7905 
7906         if (asc_dvc->bus_type & ASC_IS_PCI) {
7907 #if CC_DISABLE_PCI_PARITY_INT
7908                 cfg_msw &= 0xFFC0;
7909                 AscSetChipCfgMsw(iop_base, cfg_msw);
7910 #endif
7911                 if (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) {
7912                         asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ADD_ONE_BYTE;
7913                 }
7914         }
7915         if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
7916                 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
7917                 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
7918                 AscSetChipCfgMsw(iop_base, cfg_msw);
7919         }
7920         chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
7921 
7922         eep_config->cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
7923 
7924         if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
7925                 warn_code |= ASC_WARN_AUTO_CONFIG;
7926 
7927                 if (asc_dvc->cfg->chip_version == 3) {
7928 
7929                         if (eep_config->cfg_lsw != cfg_lsw) {
7930                                 warn_code |= ASC_WARN_EEPROM_RECOVER;
7931                                 eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
7932                         }
7933                         if (eep_config->cfg_msw != cfg_msw) {
7934                                 warn_code |= ASC_WARN_EEPROM_RECOVER;
7935                                 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
7936                         }
7937                 }
7938         }
7939         eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
7940         if (chksum != eep_config->chksum) {
7941                 warn_code |= ASC_WARN_EEPROM_CHKSUM;
7942         }
7943         asc_dvc->init_sdtr = eep_config->init_sdtr;
7944         asc_dvc->cfg->disc_enable = eep_config->disc_enable;
7945 
7946         asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
7947         asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
7948         asc_dvc->start_motor = eep_config->start_motor;
7949         asc_dvc->dvc_cntl = eep_config->cntl;
7950         asc_dvc->no_scam = eep_config->no_scam;
7951 
7952         if ((asc_dvc->bus_type & ASC_IS_PCI) &&
7953                 !(asc_dvc->dvc_cntl & ASC_CNTL_NO_PCI_FIX_ASYN_XFER)) {
7954                 if ((asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
7955                         (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
7956                         asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
7957                 }
7958         } else if ((asc_dvc->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) {
7959 
7960                 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
7961                         == ASC_CHIP_VER_ASYN_BUG) {
7962                         asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
7963                 }
7964         }
7965         if (!AscTestExternalLram(asc_dvc)) {
7966                 if (asc_dvc->bus_type & ASC_IS_PCI) {
7967                         eep_config->cfg_msw |= 0x0800;
7968                         cfg_msw |= 0x0800;
7969                         AscSetChipCfgMsw(iop_base, cfg_msw);
7970                         eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
7971                         eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
7972                 }
7973         } else {
7974 #if CC_TEST_RW_LRAM
7975                 asc_dvc->err_code |= AscTestLramEndian(iop_base);
7976 #endif
7977         }
7978         if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
7979                 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
7980         }
7981         if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
7982                 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
7983         }
7984         if (eep_config->max_tag_qng > eep_config->max_total_qng) {
7985                 eep_config->max_tag_qng = eep_config->max_total_qng;
7986         }
7987         if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
7988                 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
7989         }
7990         asc_dvc->max_total_qng = eep_config->max_total_qng;
7991 
7992         if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
7993                 eep_config->use_cmd_qng) {
7994                 eep_config->disc_enable = eep_config->use_cmd_qng;
7995                 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
7996         }
7997         asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
7998         eep_config->chip_scsi_id &= ASC_MAX_TID;
7999         asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
8000 
8001         for (i = 0; i <= ASC_MAX_TID; i++) {
8002                 asc_dvc->cfg->sdtr_data[i] = eep_config->sdtr_data[i];
8003                 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
8004         }
8005 
8006         eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
8007         if (AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type) != 0) {
8008                 asc_dvc->err_code |= ASC_IERR_WRITE_EEPROM;
8009         }
8010         return (warn_code);
8011 }
8012 
8013 ushort
8014 AscInitMicroCodeVar(
     /* [previous][next][first][last][top][bottom][index][help] */
8015                                            ASC_DVC_VAR asc_ptr_type * asc_dvc
8016 )
8017 {
8018         int                 i;
8019         ushort              warn_code;
8020         PortAddr            iop_base;
8021         ulong               phy_addr;
8022 
8023         iop_base = asc_dvc->iop_base;
8024         warn_code = 0;
8025         for (i = 0; i <= ASC_MAX_TID; i++) {
8026                 AscWriteLramByte(iop_base, (ushort) (ASCV_SDTR_DATA_BEG + i),
8027                                                  asc_dvc->cfg->sdtr_data[i]);
8028         }
8029 
8030         AscInitQLinkVar(asc_dvc);
8031 
8032         AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
8033                                          asc_dvc->cfg->disc_enable);
8034         AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
8035                                          ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
8036         if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
8037                                                                  (uchar dosfar *) asc_dvc->cfg->overrun_buf,
8038                                                                          ASC_OVERRUN_BSIZE)) == 0L) {
8039                 asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
8040         } else {
8041 
8042                 phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
8043                 AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
8044                 AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
8045                                                   ASC_OVERRUN_BSIZE - 8);
8046         }
8047 
8048         asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
8049                                                                                            (ushort) ASCV_MC_DATE_W);
8050         asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
8051                                                                                                   (ushort) ASCV_MC_VER_W);
8052         AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
8053         if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
8054                 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
8055                 return (warn_code);
8056         }
8057         if (AscStartChip(iop_base) != 1) {
8058                 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
8059                 return (warn_code);
8060         }
8061         return (warn_code);
8062 }
8063 
8064 void                dosfar
8065 AscInitPollIsrCallBack(
     /* [previous][next][first][last][top][bottom][index][help] */
8066                                                   ASC_DVC_VAR asc_ptr_type * asc_dvc,
8067                                                   ASC_QDONE_INFO dosfar * scsi_done_q
8068 )
8069 {
8070         ASC_SCSI_REQ_Q dosfar *scsiq_req;
8071         ASC_ISR_CALLBACK    asc_isr_callback;
8072         uchar               cp_sen_len;
8073         uchar               i;
8074 
8075         if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) {
8076                 scsiq_req = (ASC_SCSI_REQ_Q dosfar *) scsi_done_q->d2.srb_ptr;
8077                 ASC_DBG2(3, "AscInitPollIsrCallBack: done_stat %x, host_stat %x\n",
8078                                  scsiq_req->r3.done_stat, scsiq_req->r3.host_stat);
8079                 scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat;
8080                 scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat;
8081                 scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat;
8082                 scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg;
8083                 if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) &&
8084                         (scsi_done_q->d3.host_stat == 0)) {
8085                         cp_sen_len = (uchar) ASC_MIN_SENSE_LEN;
8086                         if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) {
8087                                 cp_sen_len = (uchar) scsiq_req->r1.sense_len;
8088                         }
8089                         for (i = 0; i < cp_sen_len; i++) {
8090                                 scsiq_req->sense[i] = scsiq_req->sense_ptr[i];
8091                         }
8092                 }
8093         } else {
8094                 ASC_DBG1(3, "AscInitPollIsrCallBack: isr_callback %x\n",
8095                                  (unsigned) asc_dvc->isr_callback);
8096                 if (asc_dvc->isr_callback != 0) {
8097                         asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
8098                         (*asc_isr_callback) (asc_dvc, scsi_done_q);
8099                 }
8100         }
8101         return;
8102 }
8103 
8104 int
8105 AscTestExternalLram(
     /* [previous][next][first][last][top][bottom][index][help] */
8106                                            ASC_DVC_VAR asc_ptr_type * asc_dvc
8107 )
8108 {
8109         PortAddr            iop_base;
8110         ushort              q_addr;
8111         ushort              saved_word;
8112         int                 sta;
8113 
8114         iop_base = asc_dvc->iop_base;
8115         sta = 0;
8116 
8117         q_addr = ASC_QNO_TO_QADDR(241);
8118         saved_word = AscReadLramWord(iop_base, q_addr);
8119         if (AscVerWriteLramWord(iop_base, q_addr, 0x55AA) == 0) {
8120                 sta = 1;
8121                 AscWriteLramWord(iop_base, q_addr, saved_word);
8122         }
8123         return (sta);
8124 }
8125 
8126 #if CC_TEST_LRAM_ENDIAN
8127 
8128 #endif
8129 
8130 int
8131 AscWriteEEPCmdReg(
     /* [previous][next][first][last][top][bottom][index][help] */
8132                                          PortAddr iop_base,
8133                                          uchar cmd_reg
8134 )
8135 {
8136         uchar               read_back;
8137         int                 retry;
8138 
8139         retry = 0;
8140         while (TRUE) {
8141                 AscSetChipEEPCmd(iop_base, cmd_reg);
8142                 DvcSleepMilliSecond(1);
8143                 read_back = AscGetChipEEPCmd(iop_base);
8144                 if (read_back == cmd_reg) {
8145                         return (1);
8146                 }
8147                 if (retry++ > ASC_EEP_MAX_RETRY) {
8148                         return (0);
8149                 }
8150         }
8151 }
8152 
8153 int
8154 AscWriteEEPDataReg(
     /* [previous][next][first][last][top][bottom][index][help] */
8155                                           PortAddr iop_base,
8156                                           ushort data_reg
8157 )
8158 {
8159         ushort              read_back;
8160         int                 retry;
8161 
8162         retry = 0;
8163         while (TRUE) {
8164                 AscSetChipEEPData(iop_base, data_reg);
8165                 DvcSleepMilliSecond(1);
8166                 read_back = AscGetChipEEPData(iop_base);
8167                 if (read_back == data_reg) {
8168                         return (1);
8169                 }
8170                 if (retry++ > ASC_EEP_MAX_RETRY) {
8171                         return (0);
8172                 }
8173         }
8174 }
8175 
8176 void
8177 AscWaitEEPRead(
     /* [previous][next][first][last][top][bottom][index][help] */
8178                                   void
8179 )
8180 {
8181         DvcSleepMilliSecond(1);
8182         return;
8183 }
8184 
8185 void
8186 AscWaitEEPWrite(
     /* [previous][next][first][last][top][bottom][index][help] */
8187                                    void
8188 )
8189 {
8190         DvcSleepMilliSecond(20);
8191         return;
8192 }
8193 
8194 ushort
8195 AscReadEEPWord(
     /* [previous][next][first][last][top][bottom][index][help] */
8196                                   PortAddr iop_base,
8197                                   uchar addr
8198 )
8199 {
8200         ushort              read_wval;
8201         uchar               cmd_reg;
8202 
8203         AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
8204         AscWaitEEPRead();
8205         cmd_reg = addr | ASC_EEP_CMD_READ;
8206         AscWriteEEPCmdReg(iop_base, cmd_reg);
8207         AscWaitEEPRead();
8208         read_wval = AscGetChipEEPData(iop_base);
8209         AscWaitEEPRead();
8210         return (read_wval);
8211 }
8212 
8213 ushort
8214 AscWriteEEPWord(
     /* [previous][next][first][last][top][bottom][index][help] */
8215                                    PortAddr iop_base,
8216                                    uchar addr,
8217                                    ushort word_val
8218 )
8219 {
8220         ushort              read_wval;
8221 
8222         read_wval = AscReadEEPWord(iop_base, addr);
8223         if (read_wval != word_val) {
8224                 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
8225                 AscWaitEEPRead();
8226 
8227                 AscWriteEEPDataReg(iop_base, word_val);
8228                 AscWaitEEPRead();
8229 
8230                 AscWriteEEPCmdReg(iop_base,
8231                                                   (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
8232                 AscWaitEEPWrite();
8233 
8234                 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
8235                 AscWaitEEPRead();
8236                 return (AscReadEEPWord(iop_base, addr));
8237         }
8238         return (read_wval);
8239 }
8240 
8241 ushort
8242 AscGetEEPConfig(
     /* [previous][next][first][last][top][bottom][index][help] */
8243                                    PortAddr iop_base,
8244                                    ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
8245 )
8246 {
8247         ushort              wval;
8248         ushort              sum;
8249         ushort dosfar      *wbuf;
8250         int                 cfg_beg;
8251         int                 cfg_end;
8252         int                 s_addr;
8253         int                 isa_pnp_wsize;
8254 
8255         wbuf = (ushort dosfar *) cfg_buf;
8256         sum = 0;
8257 
8258         isa_pnp_wsize = 0;
8259         for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
8260                 wval = AscReadEEPWord(iop_base, (uchar) s_addr);
8261                 sum += wval;
8262                 *wbuf = wval;
8263         }
8264 
8265         if (bus_type & ASC_IS_VL) {
8266                 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
8267                 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
8268         } else {
8269                 cfg_beg = ASC_EEP_DVC_CFG_BEG;
8270                 cfg_end = ASC_EEP_MAX_DVC_ADDR;
8271         }
8272 
8273         for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
8274                  s_addr++, wbuf++) {
8275                 wval = AscReadEEPWord(iop_base, (uchar) s_addr);
8276                 sum += wval;
8277                 *wbuf = wval;
8278         }
8279         *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
8280         return (sum);
8281 }
8282 
8283 int
8284 AscSetEEPConfigOnce(
     /* [previous][next][first][last][top][bottom][index][help] */
8285                                            PortAddr iop_base,
8286                                            ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
8287 )
8288 {
8289         int                 n_error;
8290         ushort dosfar      *wbuf;
8291         ushort              sum;
8292         int                 s_addr;
8293         int                 cfg_beg;
8294         int                 cfg_end;
8295 
8296         wbuf = (ushort dosfar *) cfg_buf;
8297         n_error = 0;
8298         sum = 0;
8299         for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
8300                 sum += *wbuf;
8301                 if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
8302                         n_error++;
8303                 }
8304         }
8305         if (bus_type & ASC_IS_VL) {
8306                 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
8307                 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
8308         } else {
8309                 cfg_beg = ASC_EEP_DVC_CFG_BEG;
8310                 cfg_end = ASC_EEP_MAX_DVC_ADDR;
8311         }
8312         for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
8313                  s_addr++, wbuf++) {
8314                 sum += *wbuf;
8315                 if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
8316                         n_error++;
8317                 }
8318         }
8319         *wbuf = sum;
8320         if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
8321                 n_error++;
8322         }
8323         wbuf = (ushort dosfar *) cfg_buf;
8324         for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
8325                 if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
8326                         n_error++;
8327                 }
8328         }
8329         for (s_addr = cfg_beg; s_addr <= cfg_end;
8330                  s_addr++, wbuf++) {
8331                 if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
8332                         n_error++;
8333                 }
8334         }
8335         return (n_error);
8336 }
8337 
8338 int
8339 AscSetEEPConfig(
     /* [previous][next][first][last][top][bottom][index][help] */
8340                                    PortAddr iop_base,
8341                                    ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
8342 )
8343 {
8344         int                 retry;
8345         int                 n_error;
8346 
8347         retry = 0;
8348         while (TRUE) {
8349                 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
8350                                                                                    bus_type)) == 0) {
8351                         break;
8352                 }
8353                 if (++retry > ASC_EEP_MAX_RETRY) {
8354                         break;
8355                 }
8356         }
8357         return (n_error);
8358 }
8359 
8360 int
8361 AscInitPollBegin(
     /* [previous][next][first][last][top][bottom][index][help] */
8362                                         ASC_DVC_VAR asc_ptr_type * asc_dvc
8363 )
8364 {
8365         PortAddr            iop_base;
8366 
8367         iop_base = asc_dvc->iop_base;
8368 
8369 #if CC_INIT_INQ_DISPLAY
8370         DvcDisplayString((uchar dosfar *) "\r\n");
8371 #endif
8372 
8373         AscDisableInterrupt(iop_base);
8374 
8375         asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY;
8376 
8377         AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00);
8378         asc_dvc->use_tagged_qng = 0;
8379         asc_dvc->cfg->can_tagged_qng = 0;
8380         asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback;
8381         asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack);
8382         return (0);
8383 }
8384 
8385 int
8386 AscInitPollEnd(
     /* [previous][next][first][last][top][bottom][index][help] */
8387                                   ASC_DVC_VAR asc_ptr_type * asc_dvc
8388 )
8389 {
8390         PortAddr            iop_base;
8391         int                 i;
8392 
8393         iop_base = asc_dvc->iop_base;
8394         asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func;
8395         AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
8396                                          asc_dvc->cfg->disc_enable);
8397         AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B,
8398                                          asc_dvc->use_tagged_qng);
8399         AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B,
8400                                          asc_dvc->cfg->can_tagged_qng);
8401 
8402         for (i = 0; i <= ASC_MAX_TID; i++) {
8403                 AscWriteLramByte(iop_base,
8404                                           (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i),
8405                                                  asc_dvc->max_dvc_qng[i]);
8406         }
8407 
8408         AscEnableInterrupt(iop_base);
8409 
8410 #if CC_INIT_INQ_DISPLAY
8411         DvcDisplayString((uchar dosfar *) "\r\n");
8412 #endif
8413         asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY;
8414 
8415         return (0);
8416 }
8417 
8418 int                 _asc_wait_slow_device_ = FALSE;
8419 
8420 int
8421 AscInitPollTarget(
     /* [previous][next][first][last][top][bottom][index][help] */
8422                                          ASC_DVC_VAR asc_ptr_type * asc_dvc,
8423                                          ASC_SCSI_REQ_Q dosfar * scsiq,
8424                                          ASC_SCSI_INQUIRY dosfar * inq,
8425                                          ASC_CAP_INFO dosfar * cap_info
8426 )
8427 {
8428         uchar               tid_no, lun;
8429         uchar               dvc_type;
8430         ASC_SCSI_BIT_ID_TYPE tid_bits;
8431         int                 dvc_found;
8432         int                 support_read_cap;
8433         int                 tmp_disable_init_sdtr;
8434         ulong               phy_addr;
8435 
8436         dvc_found = 0;
8437         tmp_disable_init_sdtr = FALSE;
8438         tid_bits = scsiq->r1.target_id;
8439         lun = scsiq->r1.target_lun;
8440         tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix);
8441         if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
8442                                                                          (uchar dosfar *) scsiq->sense_ptr,
8443                                                                          (ulong) scsiq->r1.sense_len)) == 0L) {
8444                 return (ERR);
8445         }
8446         scsiq->r1.sense_addr = phy_addr;
8447         if (((asc_dvc->init_sdtr & tid_bits) != 0) &&
8448                 ((asc_dvc->sdtr_done & tid_bits) == 0)) {
8449 
8450                 asc_dvc->init_sdtr &= ~tid_bits;
8451                 tmp_disable_init_sdtr = TRUE;
8452         }
8453         ASC_DBG(3, "AscInitPollTarget: PollScsiInquiry()\n");
8454         if (PollScsiInquiry(asc_dvc, scsiq, (uchar dosfar *) inq,
8455                                                 sizeof (ASC_SCSI_INQUIRY)) == 1) {
8456                 dvc_found = 1;
8457                 support_read_cap = TRUE;
8458                 dvc_type = inq->byte0.peri_dvc_type;
8459                 if (dvc_type != SCSI_TYPE_UNKNOWN) {
8460                         if ((dvc_type != SCSI_TYPE_DASD) &&
8461                                 (dvc_type != SCSI_TYPE_WORM) &&
8462                                 (dvc_type != SCSI_TYPE_CDROM) &&
8463                                 (dvc_type != SCSI_TYPE_OPTMEM)) {
8464                                 asc_dvc->start_motor &= ~tid_bits;
8465                                 support_read_cap = FALSE;
8466                         }
8467                         if ((dvc_type != SCSI_TYPE_DASD) ||
8468                                 inq->byte1.rmb) {
8469 
8470                                 if (!_asc_wait_slow_device_) {
8471                                         DvcSleepMilliSecond(3000 - ((int) tid_no * 250));
8472                                         _asc_wait_slow_device_ = TRUE;
8473                                 }
8474                         }
8475 #if CC_INIT_INQ_DISPLAY
8476                         AscDispInquiry(tid_no, lun, inq);
8477 #endif
8478 
8479                         ASC_DBG_PRT_INQUIRY(2, inq, sizeof(ASC_SCSI_INQUIRY));
8480 
8481                         if (lun == 0) {
8482 
8483                                 ASC_DBG1(2, "AscInitPollTarget: vendor_id: \"%.8s\"\n",
8484                                         inq->vendor_id);
8485                                 ASC_DBG1(2, "AscInitPollTarget: product_id: \"%.16s\"\n",
8486                                         inq->product_id);
8487                                 ASC_DBG1(2, "AscInitPollTarget: product_rev_level: \"%.4s\"\n",
8488                                         inq->product_rev_level);
8489 
8490                                 ASC_DBG1(2, "AscInitPollTarget: byte3.rsp_data_fmt %x\n",
8491                                         inq->byte3.rsp_data_fmt);
8492                                 ASC_DBG1(2, "AscInitPollTarget: byte3.ansi_apr_ver %x\n",
8493                                         inq->byte2.ansi_apr_ver);
8494                                         
8495                                 if ((inq->byte3.rsp_data_fmt >= 2) ||
8496                                         (inq->byte2.ansi_apr_ver >= 2)) {
8497 
8498                                         ASC_DBG1(2, "AscInitPollTarget: byte7.CmdQue %x\n",
8499                                                 inq->byte7.CmdQue);
8500 
8501                                         if (inq->byte7.CmdQue) {
8502                                                 asc_dvc->cfg->can_tagged_qng |= tid_bits;
8503                                                 if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) {
8504                                                         asc_dvc->use_tagged_qng |= tid_bits;
8505                                                         asc_dvc->max_dvc_qng[tid_no] =
8506                                                           asc_dvc->cfg->max_tag_qng[tid_no];
8507                                                 }
8508                                         }
8509                                         ASC_DBG1(2, "AscInitPollTarget: byte7.Sync %x\n",
8510                                                 inq->byte7.Sync);
8511 
8512                                         if (!inq->byte7.Sync) {
8513 
8514                                                 asc_dvc->init_sdtr &= ~tid_bits;
8515                                                 asc_dvc->sdtr_done &= ~tid_bits;
8516                                         } else if (tmp_disable_init_sdtr) {
8517 
8518                                                 asc_dvc->init_sdtr |= tid_bits;
8519                                         }
8520                                 } else {
8521 
8522                                         asc_dvc->init_sdtr &= ~tid_bits;
8523                                         asc_dvc->sdtr_done &= ~tid_bits;
8524                                         asc_dvc->use_tagged_qng &= ~tid_bits;
8525                                 }
8526                         }
8527                         if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
8528                                 if (!(asc_dvc->init_sdtr & tid_bits)) {
8529 
8530                                         AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
8531                                                                                         ASYN_SDTR_DATA_FIX_PCI_REV_AB);
8532                                 }
8533                         }
8534                         ASC_DBG(3, "AscInitPollTarget: InitTestUnitReady()\n");
8535                         if (InitTestUnitReady(asc_dvc, scsiq) != 1) {
8536 
8537                         } else {
8538                                 if ((cap_info != 0L) && support_read_cap) {
8539                                         ASC_DBG(3, "AscInitPollTarget: PollScsiReadCapacity()\n");
8540                                         if (PollScsiReadCapacity(asc_dvc, scsiq,
8541                                                                                          cap_info) != 1) {
8542                                                 cap_info->lba = 0L;
8543                                                 cap_info->blk_size = 0x0000;
8544                                         } else {
8545 
8546                                         }
8547                                 }
8548                         }
8549                 } else {
8550                         asc_dvc->start_motor &= ~tid_bits;
8551                 }
8552         } else {
8553 
8554         }
8555         return (dvc_found);
8556 }
8557 
8558 int
8559 PollQueueDone(
     /* [previous][next][first][last][top][bottom][index][help] */
8560                                  ASC_DVC_VAR asc_ptr_type * asc_dvc,
8561                                  ASC_SCSI_REQ_Q dosfar * scsiq,
8562                                  int timeout_sec
8563 )
8564 {
8565         int                 status;
8566         int                 retry;
8567 
8568         retry = 0;
8569         do {
8570                 ASC_DBG(3, "PollQueueDone: AscExeScsiQueue()\n");
8571                 if ((status = AscExeScsiQueue(asc_dvc,
8572                                                                           (ASC_SCSI_Q dosfar *) scsiq)) == 1) {
8573                         ASC_DBG(3, "PollQueueDone: AscPollQDone()\n");
8574                         if ((status = AscPollQDone(asc_dvc, scsiq,
8575                                                                            timeout_sec)) != 1) {
8576                                 ASC_DBG1(3, "PollQueueDone: AscPollQDone() status %x\n", status);
8577                                 if (status == 0x80) {
8578                                         if (retry++ > ASC_MAX_INIT_BUSY_RETRY) {
8579                                                 break;
8580                                         }
8581                                         scsiq->r3.done_stat = 0;
8582                                         scsiq->r3.host_stat = 0;
8583                                         scsiq->r3.scsi_stat = 0;
8584                                         scsiq->r3.scsi_msg = 0;
8585                                         DvcSleepMilliSecond(100);
8586                                         continue;
8587                                 }
8588                                 scsiq->r3.done_stat = 0;
8589                                 scsiq->r3.host_stat = 0;
8590                                 scsiq->r3.scsi_stat = 0;
8591                                 scsiq->r3.scsi_msg = 0;
8592                                 ASC_DBG1(3, "PollQueueDone: AscAbortSRB() scsiq %x\n",
8593                                                  (unsigned) scsiq);
8594 
8595                                 AscAbortSRB(asc_dvc, (ulong) scsiq);
8596                         }
8597                         ASC_DBG1(3, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
8598                         return (scsiq->r3.done_stat);
8599                 }
8600         } while ((status == 0) || (status == 0x80));
8601         ASC_DBG(3, "PollQueueDone: done_stat QD_WITH_ERROR\n");
8602         return (scsiq->r3.done_stat = QD_WITH_ERROR);
8603 }
8604 
8605 int
8606 PollScsiInquiry(
     /* [previous][next][first][last][top][bottom][index][help] */
8607                                    ASC_DVC_VAR asc_ptr_type * asc_dvc,
8608                                    ASC_SCSI_REQ_Q dosfar * scsiq,
8609                                    uchar dosfar * buf,
8610                                    int buf_len
8611 )
8612 {
8613         if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) {
8614                 return (scsiq->r3.done_stat = QD_WITH_ERROR);
8615         }
8616         return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 4));
8617 }
8618 
8619 int
8620 PollScsiReadCapacity(
     /* [previous][next][first][last][top][bottom][index][help] */
8621                                                 ASC_DVC_VAR asc_ptr_type * asc_dvc,
8622                                                 ASC_SCSI_REQ_Q dosfar * scsiq,
8623                                                 ASC_CAP_INFO dosfar * cap_info
8624 )
8625 {
8626         ASC_CAP_INFO        scsi_cap_info;
8627         int                 status;
8628 
8629         if (AscScsiReadCapacity(asc_dvc, scsiq,
8630                                                         (uchar dosfar *) & scsi_cap_info) == ERR) {
8631                 return (scsiq->r3.done_stat = QD_WITH_ERROR);
8632         }
8633         status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 8);
8634         if (status == 1) {
8635 #if CC_LITTLE_ENDIAN_HOST
8636                 cap_info->lba = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.lba);
8637                 cap_info->blk_size = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.blk_size);
8638 #else
8639                 cap_info->lba = scsi_cap_info.lba;
8640                 cap_info->blk_size = scsi_cap_info.blk_size;
8641 #endif
8642                 return (scsiq->r3.done_stat);
8643         }
8644         return (scsiq->r3.done_stat = QD_WITH_ERROR);
8645 }
8646 
8647 ulong dosfar       *
8648 swapfarbuf4(
     /* [previous][next][first][last][top][bottom][index][help] */
8649                            uchar dosfar * buf
8650 )
8651 {
8652         uchar               tmp;
8653 
8654         tmp = buf[3];
8655         buf[3] = buf[0];
8656         buf[0] = tmp;
8657 
8658         tmp = buf[1];
8659         buf[1] = buf[2];
8660         buf[2] = tmp;
8661 
8662         return ((ulong dosfar *) buf);
8663 }
8664 
8665 int
8666 PollScsiTestUnitReady(
     /* [previous][next][first][last][top][bottom][index][help] */
8667                                                  ASC_DVC_VAR asc_ptr_type * asc_dvc,
8668                                                  ASC_SCSI_REQ_Q dosfar * scsiq
8669 )
8670 {
8671         if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) {
8672                 return (scsiq->r3.done_stat = QD_WITH_ERROR);
8673         }
8674         return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 12));
8675 }
8676 
8677 int
8678 PollScsiStartUnit(
     /* [previous][next][first][last][top][bottom][index][help] */
8679                                          ASC_DVC_VAR asc_ptr_type * asc_dvc,
8680                                          ASC_SCSI_REQ_Q dosfar * scsiq
8681 )
8682 {
8683         if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) {
8684                 return (scsiq->r3.done_stat = QD_WITH_ERROR);
8685         }
8686         return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 40));
8687 }
8688 
8689 int
8690 InitTestUnitReady(
     /* [previous][next][first][last][top][bottom][index][help] */
8691                                          ASC_DVC_VAR asc_ptr_type * asc_dvc,
8692                                          ASC_SCSI_REQ_Q dosfar * scsiq
8693 )
8694 {
8695         ASC_SCSI_BIT_ID_TYPE tid_bits;
8696         int                 retry;
8697         ASC_REQ_SENSE dosfar *sen;
8698 
8699         retry = 0;
8700         tid_bits = scsiq->r1.target_id;
8701         while (retry++ < 2) {
8702                 ASC_DBG(3, "InitTestUnitReady: PollScsiTestUnitReady()\n");
8703                 PollScsiTestUnitReady(asc_dvc, scsiq);
8704                 ASC_DBG1(3, "InitTestUnitReady: done_stat %x\n", scsiq->r3.done_stat);
8705                 if (scsiq->r3.done_stat == 0x01) {
8706                         return (1);
8707                 } else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
8708                         DvcSleepMilliSecond(100);
8709 
8710                         sen = (ASC_REQ_SENSE dosfar *) scsiq->sense_ptr;
8711 
8712                         if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) &&
8713                                 ((sen->err_code & 0x70) != 0)) {
8714 
8715                                 if (sen->sense_key == SCSI_SENKEY_NOT_READY) {
8716 
8717                                         if (asc_dvc->start_motor & tid_bits) {
8718                                                 if (PollScsiStartUnit(asc_dvc, scsiq) == 1) {
8719                                                         retry = 0;
8720                                                         continue;
8721                                                 } else {
8722                                                         asc_dvc->start_motor &= ~tid_bits;
8723                                                         break;
8724                                                 }
8725                                         } else {
8726                                                 DvcSleepMilliSecond(100);
8727                                         }
8728                                 } else if (sen->sense_key == SCSI_SENKEY_ATTENSION) {
8729                                         DvcSleepMilliSecond(100);
8730                                 } else {
8731                                         break;
8732                                 }
8733                         } else {
8734                                 break;
8735                         }
8736                 } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) {
8737                         break;
8738                 } else {
8739                         break;
8740                 }
8741         }
8742         return (0);
8743 }
8744 
8745 #if CC_INIT_INQ_DISPLAY
8746 
8747 #endif
8748 
8749 int
8750 AscPollQDone(
     /* [previous][next][first][last][top][bottom][index][help] */
8751                                 ASC_DVC_VAR asc_ptr_type * asc_dvc,
8752                                 ASC_SCSI_REQ_Q dosfar * scsiq,
8753                                 int timeout_sec
8754 )
8755 {
8756         int                 loop, loop_end;
8757         int                 sta;
8758         PortAddr            iop_base;
8759 
8760         iop_base = asc_dvc->iop_base;
8761         loop = 0;
8762         loop_end = timeout_sec * 100;
8763         sta = 1;
8764 
8765         while (TRUE) {
8766                 ASC_DBG4(3,
8767                  "AscPollQDone: loop %d, err_code %x, done_stat %x, scsi_stat %x\n",
8768                  loop, asc_dvc->err_code, scsiq->r3.done_stat, scsiq->r3.scsi_stat);
8769                 if (asc_dvc->err_code != 0) {
8770                         scsiq->r3.done_stat = QD_WITH_ERROR;
8771                         sta = ERR;
8772                         break;
8773                 }
8774                 if (scsiq->r3.done_stat != QD_IN_PROGRESS) {
8775                         if ((scsiq->r3.done_stat == QD_WITH_ERROR) &&
8776                                 (scsiq->r3.scsi_stat == SS_TARGET_BUSY)) {
8777                                 sta = 0x80;
8778                                 break;
8779                         }
8780                         break;
8781                 }
8782                 DvcSleepMilliSecond(10);
8783                 if (loop++ > loop_end) {
8784                         sta = 0;
8785                         break;
8786                 }
8787                 if (AscIsChipHalted(iop_base)) {
8788                         AscISR(asc_dvc);
8789                         loop = 0;
8790                 } else {
8791                         ASC_DBG(3, "AscPollQDone: AscIsIntPending()\n");
8792                         if (AscIsIntPending(iop_base)) {
8793                                 ASC_DBG(3, "AscPollQDone: AscISR()\n");
8794                                 AscISR(asc_dvc);
8795                         }
8796                 }
8797         }
8798         ASC_DBG1(3, "AscPollQDone: sta %x\n", sta);
8799         return (sta);
8800 }
8801 
8802 uchar
8803 AscReadLramByte(
     /* [previous][next][first][last][top][bottom][index][help] */
8804                                    PortAddr iop_base,
8805                                    ushort addr
8806 )
8807 {
8808         uchar               byte_data;
8809         ushort              word_data;
8810 
8811         if (isodd_word(addr)) {
8812                 AscSetChipLramAddr(iop_base, addr - 1);
8813                 word_data = AscGetChipLramData(iop_base);
8814 
8815 #if CC_LITTLE_ENDIAN_HOST
8816                 byte_data = (uchar) ((word_data >> 8) & 0xFF);
8817 #else
8818                 byte_data = (uchar) (word_data & 0xFF);
8819 #endif
8820 
8821         } else {
8822                 AscSetChipLramAddr(iop_base, addr);
8823                 word_data = AscGetChipLramData(iop_base);
8824 
8825 #if CC_LITTLE_ENDIAN_HOST
8826                 byte_data = (uchar) (word_data & 0xFF);
8827 #else
8828                 byte_data = (uchar) ((word_data >> 8) & 0xFF);
8829 #endif
8830 
8831         }
8832         return (byte_data);
8833 }
8834 
8835 ushort
8836 AscReadLramWord(
     /* [previous][next][first][last][top][bottom][index][help] */
8837                                    PortAddr iop_base,
8838                                    ushort addr
8839 )
8840 {
8841         ushort              word_data;
8842 
8843         AscSetChipLramAddr(iop_base, addr);
8844         word_data = AscGetChipLramData(iop_base);
8845         return (word_data);
8846 }
8847 
8848 ulong
8849 AscReadLramDWord(
     /* [previous][next][first][last][top][bottom][index][help] */
8850                                         PortAddr iop_base,
8851                                         ushort addr
8852 )
8853 {
8854         ushort              val_low, val_high;
8855         ulong               dword_data;
8856 
8857         AscSetChipLramAddr(iop_base, addr);
8858 
8859 #if CC_LITTLE_ENDIAN_HOST
8860         val_low = AscGetChipLramData(iop_base);
8861 
8862         val_high = AscGetChipLramData(iop_base);
8863 #else
8864         val_high = AscGetChipLramData(iop_base);
8865         val_low = AscGetChipLramData(iop_base);
8866 #endif
8867 
8868         dword_data = ((ulong) val_high << 16) | (ulong) val_low;
8869         return (dword_data);
8870 }
8871 
8872 void
8873 AscWriteLramWord(
     /* [previous][next][first][last][top][bottom][index][help] */
8874                                         PortAddr iop_base,
8875                                         ushort addr,
8876                                         ushort word_val
8877 )
8878 {
8879         AscSetChipLramAddr(iop_base, addr);
8880         AscPutChipLramData(iop_base, word_val);
8881         return;
8882 }
8883 
8884 void
8885 AscWriteLramDWord(
     /* [previous][next][first][last][top][bottom][index][help] */
8886                                          PortAddr iop_base,
8887                                          ushort addr,
8888                                          ulong dword_val
8889 )
8890 {
8891         ushort              word_val;
8892 
8893         AscSetChipLramAddr(iop_base, addr);
8894 
8895 #if CC_LITTLE_ENDIAN_HOST
8896         word_val = (ushort) dword_val;
8897         AscPutChipLramData(iop_base, word_val);
8898         word_val = (ushort) (dword_val >> 16);
8899         AscPutChipLramData(iop_base, word_val);
8900 #else
8901         word_val = (ushort) (dword_val >> 16);
8902         AscPutChipLramData(iop_base, word_val);
8903         word_val = (ushort) dword_val;
8904         AscPutChipLramData(iop_base, word_val);
8905 #endif
8906         return;
8907 }
8908 
8909 void
8910 AscWriteLramByte(
     /* [previous][next][first][last][top][bottom][index][help] */
8911                                         PortAddr iop_base,
8912                                         ushort addr,
8913                                         uchar byte_val
8914 )
8915 {
8916         ushort              word_data;
8917 
8918         if (isodd_word(addr)) {
8919                 addr--;
8920                 word_data = AscReadLramWord(iop_base, addr);
8921                 word_data &= 0x00FF;
8922                 word_data |= (((ushort) byte_val << 8) & 0xFF00);
8923         } else {
8924                 word_data = AscReadLramWord(iop_base, addr);
8925                 word_data &= 0xFF00;
8926                 word_data |= ((ushort) byte_val & 0x00FF);
8927         }
8928         AscWriteLramWord(iop_base, addr, word_data);
8929         return;
8930 }
8931 
8932 int
8933 AscVerWriteLramWord(
     /* [previous][next][first][last][top][bottom][index][help] */
8934                                            PortAddr iop_base,
8935                                            ushort addr,
8936                                            ushort word_val
8937 )
8938 {
8939         int                 sta;
8940 
8941         sta = 0;
8942         AscSetChipLramAddr(iop_base, addr);
8943         AscPutChipLramData(iop_base, word_val);
8944         AscSetChipLramAddr(iop_base, addr);
8945         if (word_val != AscGetChipLramData(iop_base)) {
8946                 sta = ERR;
8947         }
8948         return (sta);
8949 }
8950 
8951 void
8952 AscMemWordCopyToLram(
     /* [previous][next][first][last][top][bottom][index][help] */
8953                                                 PortAddr iop_base,
8954                                                 ushort s_addr,
8955                                                 ushort dosfar * s_buffer,
8956                                                 int words
8957 )
8958 {
8959         AscSetChipLramAddr(iop_base, s_addr);
8960         DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
8961         return;
8962 }
8963 
8964 void
8965 AscMemDWordCopyToLram(
     /* [previous][next][first][last][top][bottom][index][help] */
8966                                                  PortAddr iop_base,
8967                                                  ushort s_addr,
8968                                                  ulong dosfar * s_buffer,
8969                                                  int dwords
8970 )
8971 {
8972         AscSetChipLramAddr(iop_base, s_addr);
8973         DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
8974         return;
8975 }
8976 
8977 void
8978 AscMemWordCopyFromLram(
     /* [previous][next][first][last][top][bottom][index][help] */
8979                                                   PortAddr iop_base,
8980                                                   ushort s_addr,
8981                                                   ushort dosfar * d_buffer,
8982                                                   int words
8983 )
8984 {
8985         AscSetChipLramAddr(iop_base, s_addr);
8986         DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
8987         return;
8988 }
8989 
8990 ulong
8991 AscMemSumLramWord(
     /* [previous][next][first][last][top][bottom][index][help] */
8992                                          PortAddr iop_base,
8993                                          ushort s_addr,
8994                                          rint words
8995 )
8996 {
8997         ulong               sum;
8998         int                 i;
8999 
9000         sum = 0L;
9001         for (i = 0; i < words; i++, s_addr += 2) {
9002                 sum += AscReadLramWord(iop_base, s_addr);
9003         }
9004         return (sum);
9005 }
9006 
9007 void
9008 AscMemWordSetLram(
     /* [previous][next][first][last][top][bottom][index][help] */
9009                                          PortAddr iop_base,
9010                                          ushort s_addr,
9011                                          ushort set_wval,
9012                                          rint words
9013 )
9014 {
9015         rint                i;
9016 
9017         AscSetChipLramAddr(iop_base, s_addr);
9018         for (i = 0; i < words; i++) {
9019                 AscPutChipLramData(iop_base, set_wval);
9020         }
9021         return;
9022 }
9023 
9024 int
9025 AscScsiInquiry(
     /* [previous][next][first][last][top][bottom][index][help] */
9026                                   ASC_DVC_VAR asc_ptr_type * asc_dvc,
9027                                   ASC_SCSI_REQ_Q dosfar * scsiq,
9028                                   uchar dosfar * buf, int buf_len
9029 )
9030 {
9031         if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf,
9032                                                  (ulong) buf_len) == ERR) {
9033                 return (scsiq->r3.done_stat = QD_WITH_ERROR);
9034         }
9035         scsiq->cdb[0] = (uchar) SCSICMD_Inquiry;
9036         scsiq->cdb[1] = scsiq->r1.target_lun << 5;
9037         scsiq->cdb[2] = 0;
9038         scsiq->cdb[3] = 0;
9039         scsiq->cdb[4] = buf_len;
9040         scsiq->cdb[5] = 0;
9041         scsiq->r2.cdb_len = 6;
9042         return (0);
9043 }
9044 
9045 int
9046 AscScsiReadCapacity(
     /* [previous][next][first][last][top][bottom][index][help] */
9047                                            ASC_DVC_VAR asc_ptr_type * asc_dvc,
9048                                            ASC_SCSI_REQ_Q dosfar * scsiq,
9049                                            uchar dosfar * info
9050 )
9051 {
9052         if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) {
9053                 return (scsiq->r3.done_stat = QD_WITH_ERROR);
9054         }
9055         scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity;
9056         scsiq->cdb[1] = scsiq->r1.target_lun << 5;
9057         scsiq->cdb[2] = 0;
9058         scsiq->cdb[3] = 0;
9059         scsiq->cdb[4] = 0;
9060         scsiq->cdb[5] = 0;
9061         scsiq->cdb[6] = 0;
9062         scsiq->cdb[7] = 0;
9063         scsiq->cdb[8] = 0;
9064         scsiq->cdb[9] = 0;
9065         scsiq->r2.cdb_len = 10;
9066         return (0);
9067 }
9068 
9069 int
9070 AscScsiTestUnitReady(
     /* [previous][next][first][last][top][bottom][index][help] */
9071                                                 ASC_DVC_VAR asc_ptr_type * asc_dvc,
9072                                                 ASC_SCSI_REQ_Q dosfar * scsiq
9073 )
9074 {
9075         if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR,
9076                                                  (ulong) 0L) == ERR) {
9077                 return (scsiq->r3.done_stat = QD_WITH_ERROR);
9078         }
9079         scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
9080         scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady;
9081         scsiq->cdb[1] = scsiq->r1.target_lun << 5;
9082         scsiq->cdb[2] = 0;
9083         scsiq->cdb[3] = 0;
9084         scsiq->cdb[4] = 0;
9085         scsiq->cdb[5] = 0;
9086         scsiq->r2.cdb_len = 6;
9087         return (0);
9088 }
9089 
9090 int
9091 AscScsiStartStopUnit(
     /* [previous][next][first][last][top][bottom][index][help] */
9092                                                 ASC_DVC_VAR asc_ptr_type * asc_dvc,
9093                                                 ASC_SCSI_REQ_Q dosfar * scsiq,
9094                                                 uchar op_mode
9095 )
9096 {
9097         if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) {
9098                 return (scsiq->r3.done_stat = QD_WITH_ERROR);
9099         }
9100         scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
9101         scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit;
9102         scsiq->cdb[1] = scsiq->r1.target_lun << 5;
9103         scsiq->cdb[2] = 0;
9104         scsiq->cdb[3] = 0;
9105         scsiq->cdb[4] = op_mode;
9106 
9107         scsiq->cdb[5] = 0;
9108         scsiq->r2.cdb_len = 6;
9109         return (0);
9110 }

/* [previous][next][first][last][top][bottom][index][help] */