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

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